diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp @@ -92,33 +92,16 @@ bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const { - bool IsSymbolicDifference = false; - if (const auto *MBE = dyn_cast(getSubExpr())) { - if (isa(MBE->getLHS()) && isa(MBE->getRHS())) - MBE = cast(MBE->getLHS()); - IsSymbolicDifference = isa(MBE->getLHS()) && - isa(MBE->getRHS()); - } + // Explicitly drop the layout and assembler to prevent any symbolic folding in + // the expression handling. This is required to preserve symbolic difference + // expressions to emit the paired relocations. + if (!getSubExpr()->evaluateAsRelocatable(Res, nullptr, nullptr)) + return false; - // Some custom fixup types are not valid with symbol difference expressions - if (IsSymbolicDifference) { - switch (getKind()) { - default: - break; - case VK_RISCV_LO: - case VK_RISCV_HI: - case VK_RISCV_PCREL_LO: - case VK_RISCV_PCREL_HI: - case VK_RISCV_GOT_HI: - case VK_RISCV_TPREL_LO: - case VK_RISCV_TPREL_HI: - case VK_RISCV_TPREL_ADD: - case VK_RISCV_TLS_GOT_HI: - case VK_RISCV_TLS_GD_HI: - return false; - } - } - return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); + Res = + MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind()); + // Custom fixup types are not valid with symbol difference expressions. + return Res.getSymB() ? getKind() == VK_RISCV_None : true; } void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const { diff --git a/llvm/test/MC/RISCV/expressions.s b/llvm/test/MC/RISCV/expressions.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/expressions.s @@ -0,0 +1,29 @@ +# RUN: not llvm-mc -triple riscv32 -filetype obj %s -o /dev/null 2>&1 | FileCheck %s + +.Ltmp1: + .quad tls + + lui a0, %hi(tls+0-.Ltmp1) +# CHECK: :6:2: error: expected relocatable expression + lw a0, %lo(tls+0-.Ltmp1)(t0) +# CHECK: :8:2: error: expected relocatable expression + lui a0, %tprel_hi(tls+0-.Ltmp1) +# CHECK: :10:2: error: expected relocatable expression + add a0, a0, tp, %tprel_add(tls+0-.Ltmp1) +# CHECK: :12:2: error: expected relocatable expression + addi a0, a0, %tprel_lo(tls+0-.Ltmp1) +# CHECK: :14:2: error: expected relocatable expression + auipc a0, %tls_ie_pcrel_hi(tls+0-.Ltmp1) +# CHECK: :16:2: error: expected relocatable expression + auipc a0, %tls_gd_pcrel_hi(tls+0-.Ltmp1) +# CHECK: :18:2: error: expected relocatable expression + auipc a0, %pcrel_hi(tls-.Ltmp1) +# CHECK: :20:2: error: expected relocatable expression + auipc a0, %got_pcrel_hi(tls-.Ltmp1) +# CHECK: :22:2: error: expected relocatable expression + addi a0, a0, %pcrel_lo(tls-.Ltmp1) +# CHECK: :24:2: error: expected relocatable expression + +# tail tls+32 +# tail tls-tls +# _ :28:2: error: expected relocatable expression