Index: llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp =================================================================== --- llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp +++ llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp @@ -28,12 +28,29 @@ if (Kind < FirstTargetFixupKind) return Value; + auto handlePCRelFixupValue = [&Value, &Ctx, &Fixup](unsigned W) -> uint64_t { + assert(Value % 2 == 0 && "Non-even PC relative offset."); + int64_t NumHalfWords = (int64_t)Value / 2; + int64_t Max = maxIntN(W); + int64_t Min = minIntN(W); + if (NumHalfWords < Min || NumHalfWords > Max) { + Ctx.reportError(Fixup.getLoc(), "operand out of range (" + + Twine((int64_t) Value) + " not between " + Twine(Min * 2) + + " and " + Twine(Max * 2) + ")"); + return 0; + } + return NumHalfWords; + }; + 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)) { Index: llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp =================================================================== --- llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp +++ llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp @@ -197,7 +197,8 @@ // 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 @@ SmallVectorImpl &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 @@ 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; } Index: llvm/test/MC/SystemZ/fixups-out-of-range-01.s =================================================================== --- llvm/test/MC/SystemZ/fixups-out-of-range-01.s +++ llvm/test/MC/SystemZ/fixups-out-of-range-01.s @@ -2,10 +2,14 @@ .text -# CHECK: error: displacement exceeds uint12 +# CHECK: 8:2: error: displacement exceeds uint12 +# CHECK-NEXT: la %r1, b-a(%r1) +# CHECK-NEXT: ^ la %r1, b-a(%r1) -# CHECK: error: displacement exceeds int20 +# CHECK-NEXT: 13:9: error: displacement exceeds int20 +# CHECK-NEXT: lay %r1, d-c(%r1) +# CHECK-NEXT: ^ lay %r1, d-c(%r1) # CHECK-NOT: error Index: llvm/test/MC/SystemZ/fixups-out-of-range-02.s =================================================================== --- /dev/null +++ llvm/test/MC/SystemZ/fixups-out-of-range-02.s @@ -0,0 +1,60 @@ +# RUN: not llvm-mc -triple s390x-unknown-unknown -filetype=obj -mcpu=zEC12 \ +# RUN: -o /dev/null %s 2>&1 | FileCheck %s + + .text + +# Test fixup ranges, which are encoded as half-words. + +# 12-bit +# CHECK: 15:9: error: operand out of range (4096 not between -4096 and 4094) +# CHECK-NEXT: bprp 0, .Lab1, 0 +# CHECK-NEXT: ^ +# CHECK-NEXT: 22:9: error: operand out of range (-4098 not between -4096 and 4094) +# CHECK-NEXT: bprp 0, .Lab0, 0 +# CHECK-NEXT: ^ + bprp 0, .Lab1, 0 +.Lab0: + bprp 0, .Lab1, 0 + .space 4084 +.Lab1: + nopr + bprp 0, .Lab0, 0 + bprp 0, .Lab0, 0 + +# 24-bit +# CHECK-NEXT: 31:9: error: operand out of range (16777220 not between -16777216 and 16777214) +# CHECK-NEXT: bprp 0, 0, .Lab3 +# CHECK-NEXT: ^ +# CHECK-NEXT: 38:9: error: operand out of range (-16777222 not between -16777216 and 16777214) +# CHECK-NEXT: bprp 0, 0, .Lab2 +# CHECK-NEXT: ^ + bprp 0, 0, .Lab3 +.Lab2: + bprp 0, 0, .Lab3 + .space 16777208 +.Lab3: + nopr + bprp 0, 0, .Lab2 + bprp 0, 0, .Lab2 + +# 16-bit +# CHECK-NEXT: 47:9: error: operand out of range (65540 not between -65536 and 65534) +# CHECK-NEXT: cij %r1, 0, 0, .Lab5 +# CHECK-NEXT: ^ +# CHECK-NEXT: 54:9: error: operand out of range (-65542 not between -65536 and 65534) +# CHECK-NEXT: cij %r1, 0, 0, .Lab4 +# CHECK-NEXT: ^ + cij %r1, 0, 0, .Lab5 +.Lab4: + cij %r1, 0, 0, .Lab5 + .space 65528 +.Lab5: + nopr + cij %r1, 0, 0, .Lab4 + cij %r1, 0, 0, .Lab4 + +# 32-bit +# Unfortunately there is no support for offsets greater than 32 bits, so we have +# to for now assume they are in range. + +# CHECK-NOT: error