forked from OSchip/llvm-project
[SystemZ] Add range checks for PC-relative fixups.
The AsmParser checks the range of a PC-relative operand, but only if it is immediate. This patch adds range checks for operands in applyFixup(), at which point the offset to a label is known. The diagnostic message for an operand that is out of range is explicit (with given value and min/max limits). This is now also done for displacement fixups. Review: Ulrich Weigand Differential Revision: https://reviews.llvm.org/D114194
This commit is contained in:
parent
fd722c5959
commit
5bf4f2acb8
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
|
||||
.text
|
||||
|
||||
# CHECK: error: displacement exceeds uint12
|
||||
# CHECK: error: operand out of range (4096 not between 0 and 4095)
|
||||
# CHECK-NEXT: la %r1, b-a(%r1)
|
||||
# CHECK-NEXT: ^
|
||||
la %r1, b-a(%r1)
|
||||
|
||||
# CHECK: error: displacement exceeds int20
|
||||
# CHECK-NEXT: error: operand out of range (524288 not between -524288 and 524287)
|
||||
# CHECK-NEXT: lay %r1, d-c(%r1)
|
||||
# CHECK-NEXT: ^
|
||||
lay %r1, d-c(%r1)
|
||||
|
||||
# CHECK-NOT: error
|
|
@ -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: error: operand out of range (4096 not between -4096 and 4094)
|
||||
# CHECK-NEXT: bprp 0, .Lab1, 0
|
||||
# CHECK-NEXT: ^
|
||||
# CHECK-NEXT: 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: error: operand out of range (16777220 not between -16777216 and 16777214)
|
||||
# CHECK-NEXT: bprp 0, 0, .Lab3
|
||||
# CHECK-NEXT: ^
|
||||
# CHECK-NEXT: 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: error: operand out of range (65540 not between -65536 and 65534)
|
||||
# CHECK-NEXT: cij %r1, 0, 0, .Lab5
|
||||
# CHECK-NEXT: ^
|
||||
# CHECK-NEXT: 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
|
Loading…
Reference in New Issue