diff options
Diffstat (limited to 'llvm/lib/Target/SystemZ/MCTargetDesc')
-rw-r--r-- | llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp | 32 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp | 10 |
2 files changed, 31 insertions, 11 deletions
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp index 0f5e0b9672a9..538380263c3c 100644 --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp @@ -28,25 +28,43 @@ static uint64_t extractBitsForFixup(MCFixupKind Kind, uint64_t Value, if (Kind < FirstTargetFixupKind) return Value; + auto checkFixupInRange = [&](int64_t Min, int64_t Max) -> bool { + int64_t SVal = int64_t(Value); + if (SVal < Min || SVal > Max) { + Ctx.reportError(Fixup.getLoc(), "operand out of range (" + Twine(SVal) + + " not between " + Twine(Min) + + " and " + Twine(Max) + ")"); + return false; + } + return true; + }; + + auto handlePCRelFixupValue = [&](unsigned W) -> uint64_t { + if (Value % 2 != 0) + Ctx.reportError(Fixup.getLoc(), "Non-even PC relative offset."); + if (!checkFixupInRange(minIntN(W) * 2, maxIntN(W) * 2)) + return 0; + return (int64_t)Value / 2; + }; + switch (unsigned(Kind)) { case SystemZ::FK_390_PC12DBL: + return handlePCRelFixupValue(12); case SystemZ::FK_390_PC16DBL: + return handlePCRelFixupValue(16); case SystemZ::FK_390_PC24DBL: + return handlePCRelFixupValue(24); case SystemZ::FK_390_PC32DBL: - return (int64_t)Value / 2; + return handlePCRelFixupValue(32); case SystemZ::FK_390_12: - if (!isUInt<12>(Value)) { - Ctx.reportError(Fixup.getLoc(), "displacement exceeds uint12"); + if (!checkFixupInRange(0, maxUIntN(12))) return 0; - } return Value; case SystemZ::FK_390_20: { - if (!isInt<20>(Value)) { - Ctx.reportError(Fixup.getLoc(), "displacement exceeds int20"); + if (!checkFixupInRange(minIntN(20), maxIntN(20))) return 0; - } // The high byte of a 20 bit displacement value comes first. uint64_t DLo = Value & 0xfff; uint64_t DHi = (Value >> 12) & 0xff; diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp index e280e4aaf3d8..c83796b8579b 100644 --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp @@ -197,7 +197,8 @@ getDispOpValue(const MCInst &MI, unsigned OpNum, // All instructions follow the pattern where the first displacement has a // 2 bytes offset, and the second one 4 bytes. unsigned ByteOffs = Fixups.size() == 0 ? 2 : 4; - Fixups.push_back(MCFixup::create(ByteOffs, MO.getExpr(), (MCFixupKind)Kind)); + Fixups.push_back(MCFixup::create(ByteOffs, MO.getExpr(), (MCFixupKind)Kind, + MI.getLoc())); assert(Fixups.size() <= 2 && "More than two memory operands in MI?"); return 0; } @@ -296,6 +297,7 @@ SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum, SmallVectorImpl<MCFixup> &Fixups, unsigned Kind, int64_t Offset, bool AllowTLS) const { + SMLoc Loc = MI.getLoc(); const MCOperand &MO = MI.getOperand(OpNum); const MCExpr *Expr; if (MO.isImm()) @@ -311,13 +313,13 @@ SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum, Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx); } } - Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind)); + Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind, Loc)); // Output the fixup for the TLS marker if present. if (AllowTLS && OpNum + 1 < MI.getNumOperands()) { const MCOperand &MOTLS = MI.getOperand(OpNum + 1); - Fixups.push_back(MCFixup::create(0, MOTLS.getExpr(), - (MCFixupKind)SystemZ::FK_390_TLS_CALL)); + Fixups.push_back(MCFixup::create( + 0, MOTLS.getExpr(), (MCFixupKind)SystemZ::FK_390_TLS_CALL, Loc)); } return 0; } |