Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RISCVAsmParser: Don't treat operands with relocation specifier as parse-time constants #133377

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 37 additions & 78 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,15 +524,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
bool isGPRAsFPR32() const { return isGPRF32() && Reg.IsGPRAsFPR; }
bool isGPRPairAsFPR64() const { return isGPRPair() && Reg.IsGPRAsFPR; }

static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
RISCVMCExpr::Specifier &VK) {
if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
VK = RE->getSpecifier();
return RE->evaluateAsConstant(Imm);
}

static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
VK = RISCVMCExpr::VK_None;
Imm = CE->getValue();
return true;
}
Expand All @@ -547,7 +540,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
bool IsValid;
if (!IsConstantImm)
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
Expand All @@ -562,7 +555,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
// Must be of 'immediate' type but not a constant.
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
if (!isImm() || evaluateConstantImm(getImm(), Imm))
return false;
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
VK == RISCVMCExpr::VK_None;
Expand All @@ -572,7 +565,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
// Must be of 'immediate' type but not a constant.
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
if (!isImm() || evaluateConstantImm(getImm(), Imm))
return false;
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
(VK == RISCVMCExpr::VK_CALL || VK == RISCVMCExpr::VK_CALL_PLT);
Expand All @@ -582,7 +575,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
// Must be of 'immediate' type but not a constant.
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
if (!isImm() || evaluateConstantImm(getImm(), Imm))
return false;
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
VK == RISCVMCExpr::VK_CALL;
Expand All @@ -592,7 +585,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
// Must be of 'immediate' type but not a constant.
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
if (!isImm() || evaluateConstantImm(getImm(), Imm))
return false;
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
VK == RISCVMCExpr::VK_TPREL_ADD;
Expand All @@ -602,7 +595,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
// Must be of 'immediate' type but not a constant.
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
if (!isImm() || evaluateConstantImm(getImm(), Imm))
return false;
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
VK == RISCVMCExpr::VK_TLSDESC_CALL;
Expand Down Expand Up @@ -647,61 +640,48 @@ struct RISCVOperand final : public MCParsedAsmOperand {

bool isImmXLenLI() const {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
if (VK == RISCVMCExpr::VK_LO || VK == RISCVMCExpr::VK_PCREL_LO ||
VK == RISCVMCExpr::VK_TLSDESC_LOAD_LO ||
VK == RISCVMCExpr::VK_TLSDESC_ADD_LO)
return true;
// Given only Imm, ensuring that the actually specified constant is either
// a signed or unsigned 64-bit number is unfortunately impossible.
if (IsConstantImm) {
return VK == RISCVMCExpr::VK_None &&
(isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
}
if (evaluateConstantImm(getImm(), Imm))
return isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm));

return RISCVAsmParser::isSymbolDiff(getImm());
}

bool isImmXLenLI_Restricted() const {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
// 'la imm' supports constant immediates only.
return IsConstantImm && (VK == RISCVMCExpr::VK_None) &&
return IsConstantImm &&
(isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
}

template <unsigned N> bool isUImm() const {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_None;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
return IsConstantImm && isUInt<N>(Imm);
}

template <unsigned N, unsigned S> bool isUImmShifted() const {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
return IsConstantImm && isShiftedUInt<N, S>(Imm) &&
VK == RISCVMCExpr::VK_None;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
return IsConstantImm && isShiftedUInt<N, S>(Imm);
}

template <class Pred> bool isUImmPred(Pred p) const {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
return IsConstantImm && p(Imm) && VK == RISCVMCExpr::VK_None;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
return IsConstantImm && p(Imm);
}

bool isUImmLog2XLen() const {
Expand Down Expand Up @@ -789,22 +769,18 @@ struct RISCVOperand final : public MCParsedAsmOperand {

template <unsigned N> bool isSImm() const {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
return IsConstantImm && isInt<N>(fixImmediateForRV32(Imm, isRV64Imm())) &&
VK == RISCVMCExpr::VK_None;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
return IsConstantImm && isInt<N>(fixImmediateForRV32(Imm, isRV64Imm()));
}

template <class Pred> bool isSImmPred(Pred p) const {
int64_t Imm;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
return IsConstantImm && p(fixImmediateForRV32(Imm, isRV64Imm())) &&
VK == RISCVMCExpr::VK_None;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
return IsConstantImm && p(fixImmediateForRV32(Imm, isRV64Imm()));
}

bool isSImm5() const { return isSImm<5>(); }
Expand Down Expand Up @@ -865,15 +841,14 @@ struct RISCVOperand final : public MCParsedAsmOperand {
bool IsValid;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
if (!IsConstantImm)
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
else
IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
return IsValid &&
((IsConstantImm && VK == RISCVMCExpr::VK_None) ||
VK == RISCVMCExpr::VK_LO || VK == RISCVMCExpr::VK_PCREL_LO ||
VK == RISCVMCExpr::VK_TPREL_LO ||
(IsConstantImm || VK == RISCVMCExpr::VK_LO ||
VK == RISCVMCExpr::VK_PCREL_LO || VK == RISCVMCExpr::VK_TPREL_LO ||
VK == RISCVMCExpr::VK_TLSDESC_LOAD_LO ||
VK == RISCVMCExpr::VK_TLSDESC_ADD_LO);
}
Expand All @@ -898,40 +873,27 @@ struct RISCVOperand final : public MCParsedAsmOperand {
bool isUImm20LUI() const {
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
int64_t Imm;
bool IsValid;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
if (!IsConstantImm) {
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
return IsValid &&
(VK == RISCVMCExpr::VK_HI || VK == RISCVMCExpr::VK_TPREL_HI);
} else {
return isUInt<20>(Imm) &&
(VK == RISCVMCExpr::VK_None || VK == RISCVMCExpr::VK_HI ||
VK == RISCVMCExpr::VK_TPREL_HI);
}
bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
if (IsConstantImm)
return isUInt<20>(Imm);
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
(VK == RISCVMCExpr::VK_HI || VK == RISCVMCExpr::VK_TPREL_HI);
}

bool isUImm20AUIPC() const {
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
int64_t Imm;
bool IsValid;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
if (!IsConstantImm) {
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
return IsValid &&
(VK == RISCVMCExpr::VK_PCREL_HI || VK == RISCVMCExpr::VK_GOT_HI ||
VK == RISCVMCExpr::VK_TLS_GOT_HI ||
VK == RISCVMCExpr::VK_TLS_GD_HI ||
VK == RISCVMCExpr::VK_TLSDESC_HI);
}
bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
if (IsConstantImm)
return isUInt<20>(Imm);

return isUInt<20>(Imm) &&
(VK == RISCVMCExpr::VK_None || VK == RISCVMCExpr::VK_PCREL_HI ||
VK == RISCVMCExpr::VK_GOT_HI || VK == RISCVMCExpr::VK_TLS_GOT_HI ||
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
(VK == RISCVMCExpr::VK_PCREL_HI || VK == RISCVMCExpr::VK_GOT_HI ||
VK == RISCVMCExpr::VK_TLS_GOT_HI ||
VK == RISCVMCExpr::VK_TLS_GD_HI ||
VK == RISCVMCExpr::VK_TLSDESC_HI);
}
Expand Down Expand Up @@ -1157,8 +1119,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
assert(Expr && "Expr shouldn't be null!");
int64_t Imm = 0;
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
bool IsConstant = evaluateConstantImm(Expr, Imm);

if (IsConstant)
Inst.addOperand(
Expand Down Expand Up @@ -1207,9 +1168,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
assert(N == 1 && "Invalid number of operands!");
int64_t Imm = 0;
if (Kind == KindTy::Immediate) {
RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
[[maybe_unused]] bool IsConstantImm =
evaluateConstantImm(getImm(), Imm, VK);
[[maybe_unused]] bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
assert(IsConstantImm && "Invalid VTypeI Operand!");
} else {
Imm = getVType();
Expand Down
27 changes: 0 additions & 27 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,30 +164,3 @@ StringRef RISCVMCExpr::getSpecifierName(Specifier S) {
}
llvm_unreachable("Invalid ELF symbol kind");
}

bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
MCValue Value;
if (specifier != VK_LO && specifier != VK_HI)
return false;

if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr))
return false;

if (!Value.isAbsolute())
return false;

Res = evaluateAsInt64(Value.getConstant());
return true;
}

int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const {
switch (specifier) {
default:
llvm_unreachable("Invalid kind");
case VK_LO:
return SignExtend64<12>(Value);
case VK_HI:
// Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
return ((Value + 0x800) >> 12) & 0xfffff;
}
}
8 changes: 4 additions & 4 deletions llvm/test/MC/RISCV/insn.s
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,12 @@ target:
# CHECK-OBJ: fmadd.s fa0, fa1, fa2, fa3, rne
.insn r4 MADD, 0, 0, fa0, fa1, fa2, fa3

# CHECK-ASM: .insn i 3, 5, t1, -2048(t2)
# CHECK-ASM: encoding: [0x03,0xd3,0x03,0x80]
# CHECK-ASM: .insn i 3, 5, t1, %lo(2048)(t2)
# CHECK-ASM: encoding: [0x03,0xd3,0bAAAA0011,A]
# CHECK-OBJ: lhu t1, -0x800(t2)
.insn i 0x3, 0x5, x6, %lo(2048)(x7)
# CHECK-ASM: .insn i 3, 5, t1, -2048(t2)
# CHECK-ASM: encoding: [0x03,0xd3,0x03,0x80]
# CHECK-ASM: .insn i 3, 5, t1, %lo(2048)(t2)
# CHECK-ASM: encoding: [0x03,0xd3,0bAAAA0011,A]
# CHECK-OBJ: lhu t1, -0x800(t2)
.insn i LOAD, 0x5, x6, %lo(2048)(x7)

Expand Down
14 changes: 12 additions & 2 deletions llvm/test/MC/RISCV/linker-relaxation.s
Original file line number Diff line number Diff line change
Expand Up @@ -137,18 +137,28 @@ sb t1, %pcrel_lo(2b)(a2)
# RELAX-FIXUP: fixup A - offset: 0, value: %pcrel_lo(.Ltmp1), kind: fixup_riscv_pcrel_lo12_s
# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax

## %hi/%lo on an absolute symbol (not yet defined) leads to relocations when relaxation is enabled.
lui t2, %hi(abs)
# NORELAX-RELOC-NOT: R_RISCV_
# RELAX-RELOC: R_RISCV_HI20 - 0x12345
# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0
# RELAX-FIXUP: fixup A - offset: 0, value: %hi(abs), kind: fixup_riscv_hi20
# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax

addi t2, t2, %lo(abs)
# NORELAX-RELOC-NOT: R_RISCV_
# RELAX-RELOC: R_RISCV_LO12_I - 0x12345
# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0
# RELAX-FIXUP: fixup A - offset: 0, value: %lo(abs), kind: fixup_riscv_lo12_i
# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax

.set abs, 0x12345

lui t3, %hi(abs)
# RELAX-RELOC-NOT: R_RISCV_
# RELAX-FIXUP-NOT: fixup
# RELAX-RELOC: R_RISCV_HI20 - 0x12345
# RELAX-RELOC-NEXT: R_RISCV_RELAX - 0x0
# RELAX-FIXUP: fixup A - offset: 0, value: %hi(74565), kind: fixup_riscv_hi20
# RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax

# Check that a relocation is not emitted for a symbol difference which has
# been folded to a fixup with an absolute value. This can happen when a
Expand Down
5 changes: 3 additions & 2 deletions llvm/test/MC/RISCV/rv32i-aliases-valid.s
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ li x12, 0x80000000
# CHECK-ALIAS: li a2, -1
li x12, 0xFFFFFFFF

# CHECK-INST: addi a0, zero, 1110
# CHECK-ALIAS: li a0, 1110
# CHECK-ASM-NOALIAS: addi a0, zero, %lo(1193046)
# CHECK-OBJ-NOALIAS: addi a0, zero, 1110
# CHECK-ASM: addi a0, zero, %lo(1193046)
li a0, %lo(0x123456)

# CHECK-OBJ-NOALIAS: addi a0, zero, 0
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/MC/RISCV/rv64i-aliases-valid.s
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ li x13, 0xffffffff55555556
# CHECK-S-OBJ-NEXT: addi t0, t0, -1365
li x5, -2147485013

# CHECK-INST: addi a0, zero, 1110
# CHECK-ALIAS: li a0, 1110
# CHECK-ASM: addi a0, zero, %lo(1193046)
# CHECK-OBJ: addi a0, zero, %lo(1193046)
li a0, %lo(0x123456)

# CHECK-OBJ-NOALIAS: addi a0, zero, 0
Expand Down
12 changes: 6 additions & 6 deletions llvm/test/MC/RISCV/rv64i-valid.s
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ lwu x2, +4(x3)
# CHECK-ASM-AND-OBJ: lwu tp, -2048(t0)
# CHECK-ASM: encoding: [0x03,0xe2,0x02,0x80]
lwu x4, -2048(x5)
# CHECK-ASM-AND-OBJ: lwu t1, -2048(t2)
# CHECK-ASM: encoding: [0x03,0xe3,0x03,0x80]
# CHECK-ASM: lwu t1, %lo(2048)(t2) # encoding: [0x03,0xe3,0bAAAA0011,A]
# CHECK-OBJ: lwu t1, -2048(t2)
lwu x6, %lo(2048)(x7)
# CHECK-ASM-AND-OBJ: lwu s0, 2047(s1)
# CHECK-ASM: encoding: [0x03,0xe4,0xf4,0x7f]
Expand All @@ -25,8 +25,8 @@ lwu x8, 2047(x9)
# CHECK-ASM-AND-OBJ: ld a0, -2048(a1)
# CHECK-ASM: encoding: [0x03,0xb5,0x05,0x80]
ld x10, -2048(x11)
# CHECK-ASM-AND-OBJ: ld a2, -2048(a3)
# CHECK-ASM: encoding: [0x03,0xb6,0x06,0x80]
# CHECK-ASM: ld a2, %lo(2048)(a3) # encoding: [0x03,0xb6,0bAAAA0110,A]
# CHECK-OBJ: ld a2, -2048(a3)
ld x12, %lo(2048)(x13)
# CHECK-ASM-AND-OBJ: ld a4, 2047(a5)
# CHECK-ASM: encoding: [0x03,0xb7,0xf7,0x7f]
Expand All @@ -35,8 +35,8 @@ ld x14, 2047(x15)
# CHECK-ASM-AND-OBJ: sd a6, -2048(a7)
# CHECK-ASM: encoding: [0x23,0xb0,0x08,0x81]
sd x16, -2048(x17)
# CHECK-ASM-AND-OBJ: sd s2, -2048(s3)
# CHECK-ASM: encoding: [0x23,0xb0,0x29,0x81]
# CHECK-ASM: sd s2, %lo(2048)(s3) # encoding: [0x23'A',0xb0'A',0x29'A',0x01'A']
# CHECK-OBJ: sd s2, -2048(s3)
sd x18, %lo(2048)(x19)
# CHECK-ASM-AND-OBJ: sd s4, 2047(s5)
# CHECK-ASM: encoding: [0xa3,0xbf,0x4a,0x7f]
Expand Down
Loading
Loading