aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2025-03-29 11:08:13 -0700
committerGitHub <noreply@github.com>2025-03-29 11:08:13 -0700
commitfe6fb910df9d1b9a9e2e7a6e8228d020668e0129 (patch)
treeb03e644f0516ae2281f3354235c81e48f8ac891d /llvm/lib
parent666faa7fd98b7a58e089a38083f33c067ed5b955 (diff)
downloadllvm-fe6fb910df9d1b9a9e2e7a6e8228d020668e0129.zip
llvm-fe6fb910df9d1b9a9e2e7a6e8228d020668e0129.tar.gz
llvm-fe6fb910df9d1b9a9e2e7a6e8228d020668e0129.tar.bz2
[RISCV] Replace @plt/@gotpcrel in data directives with %pltpcrel %gotpcrel
clang -fexperimental-relative-c++-abi-vtables might generate `@plt` and `@gotpcrel` specifiers in data directives. The syntax is not used in humand-written assembly code, and is not supported by GNU assembler. Note: the `@plt` in `.word foo@plt` is different from the legacy `call func@plt` (where `@plt` is simply ignored). The `@plt` syntax was selected was simply due to a quirk of AsmParser: the syntax was supported by all targets until I updated it to be an opt-in feature in a0671758eb6e52a758bd1b096a9b421eec60204c RISC-V favors the `%specifier(expr)` syntax following MIPS and Sparc, and we should follow this convention. This PR adds support for `.word %pltpcrel(foo+offset)` and `.word %gotpcrel(foo)`, and drops `@plt` and `@gotpcrel`. * MCValue::SymA can no longer have a SymbolVariant. Add an assert similar to that of AArch64ELFObjectWriter.cpp before https://reviews.llvm.org/D81446 (see my analysis at https://maskray.me/blog/2025-03-16-relocation-generation-in-assemblers if intrigued) * `jump foo@plt, x31` now has a different diagnostic. Pull Request: https://github.com/llvm/llvm-project/pull/132569
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp66
-rw-r--r--llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp77
-rw-r--r--llvm/lib/MC/MCAssembler.cpp2
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp2
-rw-r--r--llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp10
-rw-r--r--llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h3
-rw-r--r--llvm/lib/Target/AMDGPU/AMDGPUMCInstLower.cpp9
-rw-r--r--llvm/lib/Target/AMDGPU/R600AsmPrinter.h3
-rw-r--r--llvm/lib/Target/AMDGPU/R600MCInstLower.cpp6
-rw-r--r--llvm/lib/Target/AVR/AVRAsmPrinter.cpp9
-rw-r--r--llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp33
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp37
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp7
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp2
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp9
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h2
-rw-r--r--llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp19
-rw-r--r--llvm/lib/Target/RISCV/RISCVTargetObjectFile.h3
18 files changed, 197 insertions, 102 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 40abe28..c626202 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -3363,7 +3363,9 @@ void AsmPrinter::emitAlignment(Align Alignment, const GlobalObject *GV,
// Constant emission.
//===----------------------------------------------------------------------===//
-const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) {
+const MCExpr *AsmPrinter::lowerConstant(const Constant *CV,
+ const Constant *BaseCV,
+ uint64_t Offset) {
MCContext &Ctx = OutContext;
if (CV->isNullValue() || isa<UndefValue>(CV))
@@ -3382,7 +3384,8 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) {
return lowerBlockAddressConstant(*BA);
if (const auto *Equiv = dyn_cast<DSOLocalEquivalent>(CV))
- return getObjFileLowering().lowerDSOLocalEquivalent(Equiv, TM);
+ return getObjFileLowering().lowerDSOLocalEquivalent(
+ getSymbol(Equiv->getGlobalValue()), nullptr, 0, std::nullopt, TM);
if (const NoCFIValue *NC = dyn_cast<NoCFIValue>(CV))
return MCSymbolRefExpr::create(getSymbol(NC->getGlobalValue()), Ctx);
@@ -3428,7 +3431,7 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) {
// is reasonable to treat their delta as a 32-bit value.
[[fallthrough]];
case Instruction::BitCast:
- return lowerConstant(CE->getOperand(0));
+ return lowerConstant(CE->getOperand(0), BaseCV, Offset);
case Instruction::IntToPtr: {
const DataLayout &DL = getDataLayout();
@@ -3467,33 +3470,42 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) {
}
case Instruction::Sub: {
- GlobalValue *LHSGV;
- APInt LHSOffset;
+ GlobalValue *LHSGV, *RHSGV;
+ APInt LHSOffset, RHSOffset;
DSOLocalEquivalent *DSOEquiv;
if (IsConstantOffsetFromGlobal(CE->getOperand(0), LHSGV, LHSOffset,
- getDataLayout(), &DSOEquiv)) {
- GlobalValue *RHSGV;
- APInt RHSOffset;
- if (IsConstantOffsetFromGlobal(CE->getOperand(1), RHSGV, RHSOffset,
- getDataLayout())) {
- const MCExpr *RelocExpr =
- getObjFileLowering().lowerRelativeReference(LHSGV, RHSGV, TM);
- if (!RelocExpr) {
- const MCExpr *LHSExpr =
- MCSymbolRefExpr::create(getSymbol(LHSGV), Ctx);
- if (DSOEquiv &&
- getObjFileLowering().supportDSOLocalEquivalentLowering())
- LHSExpr =
- getObjFileLowering().lowerDSOLocalEquivalent(DSOEquiv, TM);
- RelocExpr = MCBinaryExpr::createSub(
- LHSExpr, MCSymbolRefExpr::create(getSymbol(RHSGV), Ctx), Ctx);
- }
- int64_t Addend = (LHSOffset - RHSOffset).getSExtValue();
+ getDataLayout(), &DSOEquiv) &&
+ IsConstantOffsetFromGlobal(CE->getOperand(1), RHSGV, RHSOffset,
+ getDataLayout())) {
+ auto *LHSSym = getSymbol(LHSGV);
+ auto *RHSSym = getSymbol(RHSGV);
+ int64_t Addend = (LHSOffset - RHSOffset).getSExtValue();
+ std::optional<int64_t> PCRelativeOffset;
+ if (getObjFileLowering().hasPLTPCRelative() && RHSGV == BaseCV)
+ PCRelativeOffset = Offset;
+
+ // Try the generic symbol difference first.
+ const MCExpr *Res = getObjFileLowering().lowerRelativeReference(
+ LHSGV, RHSGV, Addend, PCRelativeOffset, TM);
+
+ // (ELF-specific) If the generic symbol difference does not apply, and
+ // LHS is a dso_local_equivalent of a dso_preemptable function,
+ // reference the PLT entry instead.
+ if (DSOEquiv && TM.getTargetTriple().isOSBinFormatELF() &&
+ !(LHSGV->isDSOLocal() || LHSGV->isImplicitDSOLocal()))
+ Res = getObjFileLowering().lowerDSOLocalEquivalent(
+ LHSSym, RHSSym, Addend, PCRelativeOffset, TM);
+
+ // Otherwise, return LHS-RHS+Addend.
+ if (!Res) {
+ Res =
+ MCBinaryExpr::createSub(MCSymbolRefExpr::create(LHSSym, Ctx),
+ MCSymbolRefExpr::create(RHSSym, Ctx), Ctx);
if (Addend != 0)
- RelocExpr = MCBinaryExpr::createAdd(
- RelocExpr, MCConstantExpr::create(Addend, Ctx), Ctx);
- return RelocExpr;
+ Res = MCBinaryExpr::createAdd(
+ Res, MCConstantExpr::create(Addend, Ctx), Ctx);
}
+ return Res;
}
const MCExpr *LHS = lowerConstant(CE->getOperand(0));
@@ -4023,7 +4035,7 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
// Otherwise, it must be a ConstantExpr. Lower it to an MCExpr, then emit it
// thread the streamer with EmitValue.
- const MCExpr *ME = AP.lowerConstant(CV);
+ const MCExpr *ME = AP.lowerConstant(CV, BaseCV, Offset);
// Since lowerConstant already folded and got rid of all IR pointer and
// integer casts, detect GOT equivalent accesses by looking into the MCExpr
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 0e44acd..dd6d85e 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -115,10 +115,6 @@ static void GetObjCImageInfo(Module &M, unsigned &Version, unsigned &Flags,
// ELF
//===----------------------------------------------------------------------===//
-TargetLoweringObjectFileELF::TargetLoweringObjectFileELF() {
- SupportDSOLocalEquivalentLowering = true;
-}
-
void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx,
const TargetMachine &TgtM) {
TargetLoweringObjectFile::Initialize(Ctx, TgtM);
@@ -1174,9 +1170,37 @@ MCSection *TargetLoweringObjectFileELF::getStaticDtorSection(
KeySym);
}
+const MCExpr *TargetLoweringObjectFileELF::lowerSymbolDifference(
+ const MCSymbol *LHS, const MCSymbol *RHS, int64_t Addend,
+ std::optional<int64_t> PCRelativeOffset) const {
+ auto &Ctx = getContext();
+ const MCExpr *Res;
+ // Return a relocatable expression with the PLT specifier, %plt(GV) or
+ // %plt(GV-RHS).
+ if (PCRelativeOffset && PLTPCRelativeSpecifier) {
+ Res = MCSymbolRefExpr::create(LHS, Ctx);
+ // The current location is RHS plus *PCRelativeOffset. Compensate for it.
+ Addend += *PCRelativeOffset;
+ if (Addend)
+ Res = MCBinaryExpr::createAdd(Res, MCConstantExpr::create(Addend, Ctx),
+ Ctx);
+ return createTargetMCExpr(Res, PLTPCRelativeSpecifier);
+ }
+
+ if (!PLTRelativeSpecifier)
+ return nullptr;
+ Res = MCBinaryExpr::createSub(
+ MCSymbolRefExpr::create(LHS, PLTRelativeSpecifier, Ctx),
+ MCSymbolRefExpr::create(RHS, Ctx), Ctx);
+ if (Addend)
+ Res =
+ MCBinaryExpr::createAdd(Res, MCConstantExpr::create(Addend, Ctx), Ctx);
+ return Res;
+}
+
const MCExpr *TargetLoweringObjectFileELF::lowerRelativeReference(
- const GlobalValue *LHS, const GlobalValue *RHS,
- const TargetMachine &TM) const {
+ const GlobalValue *LHS, const GlobalValue *RHS, int64_t Addend,
+ std::optional<int64_t> PCRelativeOffset, const TargetMachine &TM) const {
// We may only use a PLT-relative relocation to refer to unnamed_addr
// functions.
if (!LHS->hasGlobalUnnamedAddr() || !LHS->getValueType()->isFunctionTy())
@@ -1188,24 +1212,22 @@ const MCExpr *TargetLoweringObjectFileELF::lowerRelativeReference(
RHS->isThreadLocal())
return nullptr;
- return MCBinaryExpr::createSub(
- MCSymbolRefExpr::create(TM.getSymbol(LHS), PLTRelativeSpecifier,
- getContext()),
- MCSymbolRefExpr::create(TM.getSymbol(RHS), getContext()), getContext());
+ return lowerSymbolDifference(TM.getSymbol(LHS), TM.getSymbol(RHS), Addend,
+ PCRelativeOffset);
}
+// Reference the PLT entry of a function, optionally with a subtrahend (`RHS`).
const MCExpr *TargetLoweringObjectFileELF::lowerDSOLocalEquivalent(
- const DSOLocalEquivalent *Equiv, const TargetMachine &TM) const {
- assert(supportDSOLocalEquivalentLowering());
-
- const auto *GV = Equiv->getGlobalValue();
-
- // A PLT entry is not needed for dso_local globals.
- if (GV->isDSOLocal() || GV->isImplicitDSOLocal())
- return MCSymbolRefExpr::create(TM.getSymbol(GV), getContext());
-
- return MCSymbolRefExpr::create(TM.getSymbol(GV), PLTRelativeSpecifier,
- getContext());
+ const MCSymbol *LHS, const MCSymbol *RHS, int64_t Addend,
+ std::optional<int64_t> PCRelativeOffset, const TargetMachine &TM) const {
+ if (RHS)
+ return lowerSymbolDifference(LHS, RHS, Addend, PCRelativeOffset);
+
+ // Only the legacy MCSymbolRefExpr::VariantKind approach is implemented.
+ // Reference LHS@plt or LHS@plt - RHS.
+ if (PLTRelativeSpecifier)
+ return MCSymbolRefExpr::create(LHS, PLTRelativeSpecifier, getContext());
+ return nullptr;
}
MCSection *TargetLoweringObjectFileELF::getSectionForCommandLines() const {
@@ -2044,8 +2066,8 @@ MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection(
}
const MCExpr *TargetLoweringObjectFileCOFF::lowerRelativeReference(
- const GlobalValue *LHS, const GlobalValue *RHS,
- const TargetMachine &TM) const {
+ const GlobalValue *LHS, const GlobalValue *RHS, int64_t Addend,
+ std::optional<int64_t> PCRelativeOffset, const TargetMachine &TM) const {
const Triple &T = TM.getTargetTriple();
if (T.isOSCygMing())
return nullptr;
@@ -2069,9 +2091,12 @@ const MCExpr *TargetLoweringObjectFileCOFF::lowerRelativeReference(
cast<GlobalVariable>(RHS)->hasInitializer() || RHS->hasSection())
return nullptr;
- return MCSymbolRefExpr::create(TM.getSymbol(LHS),
- MCSymbolRefExpr::VK_COFF_IMGREL32,
- getContext());
+ const MCExpr *Res = MCSymbolRefExpr::create(
+ TM.getSymbol(LHS), MCSymbolRefExpr::VK_COFF_IMGREL32, getContext());
+ if (Addend != 0)
+ Res = MCBinaryExpr::createAdd(
+ Res, MCConstantExpr::create(Addend, getContext()), getContext());
+ return Res;
}
static std::string APIntToHexString(const APInt &AI) {
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index 6ae99ec..1c79af4 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -237,7 +237,7 @@ bool MCAssembler::evaluateFixup(const MCFixup &Fixup, const MCFragment *DF,
// A linker relaxation target may emit ADD/SUB relocations for A-B+C. Let
// recordRelocation handle non-VK_None cases like A@plt-B+C.
if (!IsResolved && Target.getSymA() && Target.getSubSym() &&
- Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None &&
+ Target.getRefKind() == 0 &&
getBackend().handleAddSubRelocations(*this, *DF, Fixup, Target, Value))
return true;
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 9448e7b..65a3800 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -3144,7 +3144,7 @@ bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
auto parseOp = [&]() -> bool {
const MCExpr *Value;
SMLoc ExprLoc = getLexer().getLoc();
- if (checkForValidSection() || parseExpression(Value))
+ if (checkForValidSection() || getTargetParser().parseDataExpr(Value))
return true;
// Special case constant expressions to match code generator.
if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index e3ad085..ff1aee9 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -254,7 +254,9 @@ public:
return false;
}
- const MCExpr *lowerConstant(const Constant *CV) override;
+ const MCExpr *lowerConstant(const Constant *CV,
+ const Constant *BaseCV = nullptr,
+ uint64_t Offset = 0) override;
private:
void printOperand(const MachineInstr *MI, unsigned OpNum, raw_ostream &O);
@@ -3496,13 +3498,15 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
.addReg(AArch64::X16));
}
-const MCExpr *AArch64AsmPrinter::lowerConstant(const Constant *CV) {
+const MCExpr *AArch64AsmPrinter::lowerConstant(const Constant *CV,
+ const Constant *BaseCV,
+ uint64_t Offset) {
if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
return MCSymbolRefExpr::create(MCInstLowering.GetGlobalValueSymbol(GV, 0),
OutContext);
}
- return AsmPrinter::lowerConstant(CV);
+ return AsmPrinter::lowerConstant(CV, BaseCV, Offset);
}
// Force static initialization.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h
index 2c959d7..4183bb6 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h
@@ -107,7 +107,8 @@ public:
/// Lower the specified LLVM Constant to an MCExpr.
/// The AsmPrinter::lowerConstantof does not know how to lower
/// addrspacecast, therefore they should be lowered by this function.
- const MCExpr *lowerConstant(const Constant *CV) override;
+ const MCExpr *lowerConstant(const Constant *CV, const Constant *BaseCV,
+ uint64_t Offset) override;
/// tblgen'erated driver function for lowering simple MI->MC pseudo
/// instructions.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMCInstLower.cpp b/llvm/lib/Target/AMDGPU/AMDGPUMCInstLower.cpp
index 895d1e7..6fa97d8 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUMCInstLower.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUMCInstLower.cpp
@@ -223,20 +223,23 @@ bool AMDGPUAsmPrinter::lowerOperand(const MachineOperand &MO,
return MCInstLowering.lowerOperand(MO, MCOp);
}
-const MCExpr *AMDGPUAsmPrinter::lowerConstant(const Constant *CV) {
+const MCExpr *AMDGPUAsmPrinter::lowerConstant(const Constant *CV,
+ const Constant *BaseCV,
+ uint64_t Offset) {
// Intercept LDS variables with known addresses
if (const GlobalVariable *GV = dyn_cast<const GlobalVariable>(CV)) {
if (std::optional<uint32_t> Address =
AMDGPUMachineFunction::getLDSAbsoluteAddress(*GV)) {
auto *IntTy = Type::getInt32Ty(CV->getContext());
- return AsmPrinter::lowerConstant(ConstantInt::get(IntTy, *Address));
+ return AsmPrinter::lowerConstant(ConstantInt::get(IntTy, *Address),
+ BaseCV, Offset);
}
}
if (const MCExpr *E = lowerAddrSpaceCast(TM, CV, OutContext))
return E;
- return AsmPrinter::lowerConstant(CV);
+ return AsmPrinter::lowerConstant(CV, BaseCV, Offset);
}
void AMDGPUAsmPrinter::emitInstruction(const MachineInstr *MI) {
diff --git a/llvm/lib/Target/AMDGPU/R600AsmPrinter.h b/llvm/lib/Target/AMDGPU/R600AsmPrinter.h
index 552d01f..936fe9bc 100644
--- a/llvm/lib/Target/AMDGPU/R600AsmPrinter.h
+++ b/llvm/lib/Target/AMDGPU/R600AsmPrinter.h
@@ -30,7 +30,8 @@ public:
/// Lower the specified LLVM Constant to an MCExpr.
/// The AsmPrinter::lowerConstantof does not know how to lower
/// addrspacecast, therefore they should be lowered by this function.
- const MCExpr *lowerConstant(const Constant *CV) override;
+ const MCExpr *lowerConstant(const Constant *CV, const Constant *BaseCV,
+ uint64_t Offset) override;
private:
void EmitProgramInfoR600(const MachineFunction &MF);
diff --git a/llvm/lib/Target/AMDGPU/R600MCInstLower.cpp b/llvm/lib/Target/AMDGPU/R600MCInstLower.cpp
index 6da5456..6d7e834 100644
--- a/llvm/lib/Target/AMDGPU/R600MCInstLower.cpp
+++ b/llvm/lib/Target/AMDGPU/R600MCInstLower.cpp
@@ -72,8 +72,10 @@ void R600AsmPrinter::emitInstruction(const MachineInstr *MI) {
}
}
-const MCExpr *R600AsmPrinter::lowerConstant(const Constant *CV) {
+const MCExpr *R600AsmPrinter::lowerConstant(const Constant *CV,
+ const Constant *BaseCV,
+ uint64_t Offset) {
if (const MCExpr *E = lowerAddrSpaceCast(TM, CV, OutContext))
return E;
- return AsmPrinter::lowerConstant(CV);
+ return AsmPrinter::lowerConstant(CV, BaseCV, Offset);
}
diff --git a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
index a63aa542..a8621ab 100644
--- a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
+++ b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
@@ -59,7 +59,8 @@ public:
void emitInstruction(const MachineInstr *MI) override;
- const MCExpr *lowerConstant(const Constant *CV) override;
+ const MCExpr *lowerConstant(const Constant *CV, const Constant *BaseCV,
+ uint64_t Offset) override;
void emitXXStructor(const DataLayout &DL, const Constant *CV) override;
@@ -199,7 +200,9 @@ void AVRAsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, I);
}
-const MCExpr *AVRAsmPrinter::lowerConstant(const Constant *CV) {
+const MCExpr *AVRAsmPrinter::lowerConstant(const Constant *CV,
+ const Constant *BaseCV,
+ uint64_t Offset) {
MCContext &Ctx = OutContext;
if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
@@ -210,7 +213,7 @@ const MCExpr *AVRAsmPrinter::lowerConstant(const Constant *CV) {
}
}
- return AsmPrinter::lowerConstant(CV);
+ return AsmPrinter::lowerConstant(CV, BaseCV, Offset);
}
void AVRAsmPrinter::emitXXStructor(const DataLayout &DL, const Constant *CV) {
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index b4365cd..861ccde 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -232,6 +232,8 @@ class RISCVAsmParser : public MCTargetAsmParser {
}
bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
+ bool parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E);
+ bool parseDataExpr(const MCExpr *&Res) override;
bool parseDirectiveOption();
bool parseDirectiveAttribute();
@@ -2019,8 +2021,17 @@ ParseStatus RISCVAsmParser::parseOperandWithSpecifier(OperandVector &Operands) {
SMLoc S = getLoc();
SMLoc E;
- if (!parseOptionalToken(AsmToken::Percent) ||
- getLexer().getKind() != AsmToken::Identifier)
+ if (parseToken(AsmToken::Percent, "expected '%' relocation specifier"))
+ return ParseStatus::Failure;
+ const MCExpr *Expr = nullptr;
+ bool Failed = parseExprWithSpecifier(Expr, E);
+ if (!Failed)
+ Operands.push_back(RISCVOperand::createImm(Expr, S, E, isRV64()));
+ return Failed;
+}
+
+bool RISCVAsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) {
+ if (getLexer().getKind() != AsmToken::Identifier)
return Error(getLoc(), "expected '%' relocation specifier");
StringRef Identifier = getParser().getTok().getIdentifier();
auto Spec = RISCVMCExpr::getSpecifierForName(Identifier);
@@ -2029,15 +2040,21 @@ ParseStatus RISCVAsmParser::parseOperandWithSpecifier(OperandVector &Operands) {
getParser().Lex(); // Eat the identifier
if (parseToken(AsmToken::LParen, "expected '('"))
- return ParseStatus::Failure;
+ return true;
const MCExpr *SubExpr;
if (getParser().parseParenExpression(SubExpr, E))
- return ParseStatus::Failure;
+ return true;
- const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, *Spec, getContext());
- Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
- return ParseStatus::Success;
+ Res = RISCVMCExpr::create(SubExpr, *Spec, getContext());
+ return false;
+}
+
+bool RISCVAsmParser::parseDataExpr(const MCExpr *&Res) {
+ SMLoc E;
+ if (parseOptionalToken(AsmToken::Percent))
+ return parseExprWithSpecifier(Res, E);
+ return getParser().parseExpression(Res);
}
ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
@@ -2129,7 +2146,7 @@ ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
return ParseStatus::Failure;
if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||
- getSpecifier(cast<MCSymbolRefExpr>(Res)) == RISCVMCExpr::VK_PLT)
+ getSpecifier(cast<MCSymbolRefExpr>(Res)) == RISCVMCExpr::VK_PLTPCREL)
return Error(S, "operand must be a valid jump target");
Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_CALL, getContext());
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
index f8841dd..5faeb98 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
@@ -50,13 +50,17 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
const MCValue &Target,
const MCFixup &Fixup,
bool IsPCRel) const {
+ assert((!Target.getSymA() ||
+ Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) &&
+ "sym@specifier should have been rejected");
const MCExpr *Expr = Fixup.getValue();
// Determine the type of the relocation
unsigned Kind = Fixup.getTargetKind();
if (Kind >= FirstLiteralRelocationKind)
return Kind - FirstLiteralRelocationKind;
- switch (Target.getRefKind()) {
+ auto Spec = RISCVMCExpr::Specifier(Target.getRefKind());
+ switch (Spec) {
case RISCVMCExpr::VK_TPREL_HI:
case RISCVMCExpr::VK_TLS_GOT_HI:
case RISCVMCExpr::VK_TLS_GD_HI:
@@ -64,6 +68,16 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
if (auto *S = Target.getSymA())
cast<MCSymbolELF>(S->getSymbol()).setType(ELF::STT_TLS);
break;
+ case RISCVMCExpr::VK_PLTPCREL:
+ case RISCVMCExpr::VK_GOTPCREL:
+ if (Kind == FK_Data_4)
+ break;
+ Ctx.reportError(Fixup.getLoc(),
+ "%" + RISCVMCExpr::getSpecifierName(Spec) +
+ " can only be used in a .word directive");
+ return ELF::R_RISCV_NONE;
+ default:
+ break;
}
if (IsPCRel) {
@@ -73,9 +87,7 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
return ELF::R_RISCV_NONE;
case FK_Data_4:
case FK_PCRel_4:
- return uint8_t(Target.getAccessVariant()) == RISCVMCExpr::VK_PLT
- ? ELF::R_RISCV_PLT32
- : ELF::R_RISCV_32_PCREL;
+ return ELF::R_RISCV_32_PCREL;
case RISCV::fixup_riscv_pcrel_hi20:
return ELF::R_RISCV_PCREL_HI20;
case RISCV::fixup_riscv_pcrel_lo12_i:
@@ -129,11 +141,18 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
Ctx.reportError(Fixup.getLoc(), "2-byte data relocations not supported");
return ELF::R_RISCV_NONE;
case FK_Data_4:
- if (Expr->getKind() == MCExpr::Target &&
- cast<RISCVMCExpr>(Expr)->getSpecifier() == RISCVMCExpr::VK_32_PCREL)
- return ELF::R_RISCV_32_PCREL;
- if (getSpecifier(Target.getSymA()) == RISCVMCExpr::VK_GOTPCREL)
- return ELF::R_RISCV_GOT32_PCREL;
+ if (Expr->getKind() == MCExpr::Target) {
+ switch (cast<RISCVMCExpr>(Expr)->getSpecifier()) {
+ case RISCVMCExpr::VK_32_PCREL:
+ return ELF::R_RISCV_32_PCREL;
+ case RISCVMCExpr::VK_GOTPCREL:
+ return ELF::R_RISCV_GOT32_PCREL;
+ case RISCVMCExpr::VK_PLTPCREL:
+ return ELF::R_RISCV_PLT32;
+ default:
+ break;
+ }
+ }
return ELF::R_RISCV_32;
case FK_Data_8:
return ELF::R_RISCV_64;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
index c327f9d..7e9b312 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
@@ -18,11 +18,6 @@
#include "llvm/TargetParser/Triple.h"
using namespace llvm;
-const MCAsmInfo::VariantKindDesc variantKindDescs[] = {
- {RISCVMCExpr::VK_GOTPCREL, "GOTPCREL"},
- {RISCVMCExpr::VK_PLT, "PLT"},
-};
-
void RISCVMCAsmInfo::anchor() {}
RISCVMCAsmInfo::RISCVMCAsmInfo(const Triple &TT) {
@@ -33,8 +28,6 @@ RISCVMCAsmInfo::RISCVMCAsmInfo(const Triple &TT) {
ExceptionsType = ExceptionHandling::DwarfCFI;
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";
-
- initializeVariantKinds(variantKindDescs);
}
const MCExpr *RISCVMCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index f333ffe..b27f13e 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -479,7 +479,7 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
case RISCVMCExpr::VK_None:
case RISCVMCExpr::VK_32_PCREL:
case RISCVMCExpr::VK_GOTPCREL:
- case RISCVMCExpr::VK_PLT:
+ case RISCVMCExpr::VK_PLTPCREL:
llvm_unreachable("unhandled specifier");
case RISCVMCExpr::VK_TPREL_ADD:
// tprel_add is only used to indicate that a relocation should be emitted
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
index b73496b..e7c0f95 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
@@ -118,14 +118,15 @@ RISCVMCExpr::getSpecifierForName(StringRef name) {
.Case("tlsdesc_load_lo", VK_TLSDESC_LOAD_LO)
.Case("tlsdesc_add_lo", VK_TLSDESC_ADD_LO)
.Case("tlsdesc_call", VK_TLSDESC_CALL)
+ // Used in data directives
+ .Case("pltpcrel", VK_PLTPCREL)
+ .Case("gotpcrel", VK_GOTPCREL)
.Default(std::nullopt);
}
StringRef RISCVMCExpr::getSpecifierName(Specifier S) {
switch (S) {
case VK_None:
- case VK_PLT:
- case VK_GOTPCREL:
llvm_unreachable("not used as %specifier()");
case VK_LO:
return "lo";
@@ -161,6 +162,10 @@ StringRef RISCVMCExpr::getSpecifierName(Specifier S) {
return "call_plt";
case VK_32_PCREL:
return "32_pcrel";
+ case VK_GOTPCREL:
+ return "gotpcrel";
+ case VK_PLTPCREL:
+ return "pltpcrel";
}
llvm_unreachable("Invalid ELF symbol kind");
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h
index af178ff..604d2eb 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h
@@ -38,7 +38,7 @@ public:
VK_CALL_PLT,
VK_32_PCREL,
VK_GOTPCREL,
- VK_PLT,
+ VK_PLTPCREL,
VK_TLSDESC_HI,
VK_TLSDESC_LOAD_LO,
VK_TLSDESC_ADD_LO,
diff --git a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp
index e546815..57c0af7 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp
@@ -27,7 +27,7 @@ void RISCVELFTargetObjectFile::Initialize(MCContext &Ctx,
const TargetMachine &TM) {
TargetLoweringObjectFileELF::Initialize(Ctx, TM);
- PLTRelativeSpecifier = RISCVMCExpr::VK_PLT;
+ PLTPCRelativeSpecifier = RISCVMCExpr::VK_PLTPCREL;
SupportIndirectSymViaGOTPCRel = true;
SmallDataSection = getContext().getELFSection(
@@ -49,11 +49,11 @@ void RISCVELFTargetObjectFile::Initialize(MCContext &Ctx,
const MCExpr *RISCVELFTargetObjectFile::getIndirectSymViaGOTPCRel(
const GlobalValue *GV, const MCSymbol *Sym, const MCValue &MV,
int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const {
- int64_t FinalOffset = Offset + MV.getConstant();
- const MCExpr *Res =
- MCSymbolRefExpr::create(Sym, RISCVMCExpr::VK_GOTPCREL, getContext());
- const MCExpr *Off = MCConstantExpr::create(FinalOffset, getContext());
- return MCBinaryExpr::createAdd(Res, Off, getContext());
+ auto &Ctx = getContext();
+ const MCExpr *Res = MCSymbolRefExpr::create(Sym, Ctx);
+ Res = MCBinaryExpr::createAdd(
+ Res, MCConstantExpr::create(Offset + MV.getConstant(), Ctx), Ctx);
+ return RISCVMCExpr::create(Res, RISCVMCExpr::VK_GOTPCREL, Ctx);
}
// A address must be loaded from a small section if its size is less than the
@@ -180,3 +180,10 @@ MCSection *RISCVELFTargetObjectFile::getSectionForConstant(
return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C,
Alignment);
}
+
+const MCExpr *
+RISCVELFTargetObjectFile::createTargetMCExpr(const MCExpr *Expr,
+ uint8_t Specifier) const {
+ return RISCVMCExpr::create(Expr, RISCVMCExpr::Specifier(Specifier),
+ getContext());
+}
diff --git a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h
index ff7e3e4..b6da3f4 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h
+++ b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h
@@ -48,6 +48,9 @@ public:
bool isInSmallSection(uint64_t Size) const;
+ const MCExpr *createTargetMCExpr(const MCExpr *Expr,
+ uint8_t Specifier) const override;
+
const MCExpr *getIndirectSymViaGOTPCRel(const GlobalValue *GV,
const MCSymbol *Sym,
const MCValue &MV, int64_t Offset,