diff options
author | Fangrui Song <i@maskray.me> | 2025-03-29 11:08:13 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-29 11:08:13 -0700 |
commit | fe6fb910df9d1b9a9e2e7a6e8228d020668e0129 (patch) | |
tree | b03e644f0516ae2281f3354235c81e48f8ac891d /llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | |
parent | 666faa7fd98b7a58e089a38083f33c067ed5b955 (diff) | |
download | llvm-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/CodeGen/TargetLoweringObjectFileImpl.cpp')
-rw-r--r-- | llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 77 |
1 files changed, 51 insertions, 26 deletions
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) { |