Skip to content

[RISCV] Replace @plt/@gotpcrel in data directives with %pltpcrel %gotpcrel #132569

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

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
6 changes: 3 additions & 3 deletions lld/test/ELF/riscv-reloc-plt32.s
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
.globl _start
_start:
.data
.word foo@PLT - .
.word foo@PLT - . + 1
.word foo@PLT - . - 1
.word %pltpcrel(foo)
.word %pltpcrel(foo + 1)
.word %pltpcrel(foo - 1)
2 changes: 1 addition & 1 deletion lld/test/ELF/riscv-undefined-weak.s
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,4 @@ branch:
# PC-NOT: .plt:
# PLT: .plt:

.word target@plt - .
.word %pltpcrel(target)
16 changes: 8 additions & 8 deletions lld/test/ELF/riscv64-reloc-got32-pcrel.s
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ bar:

.globl _start
_start: // PC = 0x33a8
// bar@GOTPCREL = 0x2398 (got entry for `bar`) - 0x33a8 (.) = 0xf0efffff
// bar@GOTPCREL+4 = 0x2398 (got entry for `bar`) - 0x33ac (.) + 4 = 0xf0efffff
// bar@GOTPCREL-4 = 0x2398 (got entry for `bar`) - 0x33b0 (.) - 4 = 0xe4efffff
// %gotpcrel(bar) = 0x2398 (got entry for `bar`) - 0x33a8 (.) = 0xf0efffff
// %gotpcrel(bar+4) = 0x2398 (got entry for `bar`) - 0x33ac (.) + 4 = 0xf0efffff
// %gotpcrel(bar-4) = 0x2398 (got entry for `bar`) - 0x33b0 (.) - 4 = 0xe4efffff
// CHECK: Contents of section .data:
// CHECK-NEXT: {{.*}} f0efffff f0efffff e4efffff
.word bar@GOTPCREL
.word bar@GOTPCREL+4
.word bar@GOTPCREL-4
.word %gotpcrel(bar)
.word %gotpcrel(bar+4)
.word %gotpcrel(bar-4)

// WARN: relocation R_RISCV_GOT32_PCREL out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz'
// WARN: relocation R_RISCV_GOT32_PCREL out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz'
.word baz@GOTPCREL+0xffffffff
.word baz@GOTPCREL-0xffffffff
.word %gotpcrel(baz+0xffffffff)
.word %gotpcrel(baz-0xffffffff)
5 changes: 4 additions & 1 deletion llvm/include/llvm/CodeGen/AsmPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,10 @@ class AsmPrinter : public MachineFunctionPass {
unsigned MaxBytesToEmit = 0) const;

/// Lower the specified LLVM Constant to an MCExpr.
virtual const MCExpr *lowerConstant(const Constant *CV);
/// When BaseCV is present, we are lowering the element at BaseCV plus Offset.
virtual const MCExpr *lowerConstant(const Constant *CV,
const Constant *BaseCV = nullptr,
uint64_t Offset = 0);

/// Print a general LLVM constant to the .s file.
/// On AIX, when an alias refers to a sub-element of a global variable, the
Expand Down
19 changes: 15 additions & 4 deletions llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
uint8_t PLTRelativeSpecifier = 0;

public:
TargetLoweringObjectFileELF();
~TargetLoweringObjectFileELF() override = default;

void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
Expand Down Expand Up @@ -112,11 +111,22 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
MCSection *getStaticDtorSection(unsigned Priority,
const MCSymbol *KeySym) const override;

virtual const MCExpr *createTargetMCExpr(const MCExpr *Expr,
uint8_t Specifier) const {
return nullptr;
}
const MCExpr *
lowerSymbolDifference(const MCSymbol *LHS, const MCSymbol *RHS,
int64_t Addend,
std::optional<int64_t> PCRelativeOffset) const;
const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
const GlobalValue *RHS,
const GlobalValue *RHS, int64_t Addend,
std::optional<int64_t> PCRelativeOffset,
const TargetMachine &TM) const override;

const MCExpr *lowerDSOLocalEquivalent(const DSOLocalEquivalent *Equiv,
const MCExpr *lowerDSOLocalEquivalent(const MCSymbol *LHS,
const MCSymbol *RHS, int64_t Addend,
std::optional<int64_t> PCRelativeOffset,
const TargetMachine &TM) const override;

MCSection *getSectionForCommandLines() const override;
Expand Down Expand Up @@ -206,7 +216,8 @@ class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
const MCSymbol *KeySym) const override;

const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
const GlobalValue *RHS,
const GlobalValue *RHS, int64_t Addend,
std::optional<int64_t> PCRelativeOffset,
const TargetMachine &TM) const override;

/// Given a mergeable constant with the specified size and relocation
Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,12 @@ class MCTargetAsmParser : public MCAsmParserExtension {
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
return getParser().parsePrimaryExpr(Res, EndLoc, nullptr);
}
// Parse an expression in a data directive, possibly with a relocation
// specifier.
virtual bool parseDataExpr(const MCExpr *&Res) {
SMLoc EndLoc;
return getParser().parseExpression(Res, EndLoc);
}

virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc,
SMLoc &EndLoc) = 0;
Expand Down
21 changes: 10 additions & 11 deletions llvm/include/llvm/Target/TargetLoweringObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
bool SupportIndirectSymViaGOTPCRel = false;
bool SupportGOTPCRelWithOffset = true;
bool SupportDebugThreadLocalLocation = true;
bool SupportDSOLocalEquivalentLowering = false;
uint32_t PLTPCRelativeSpecifier = 0;

/// PersonalityEncoding, LSDAEncoding, TTypeEncoding - Some encoding values
/// for EH.
Expand Down Expand Up @@ -196,20 +196,19 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
/// emitting the address in debug info.
virtual const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const;

virtual const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
const GlobalValue *RHS,
const TargetMachine &TM) const {
virtual const MCExpr *lowerRelativeReference(
const GlobalValue *LHS, const GlobalValue *RHS, int64_t Addend,
std::optional<int64_t> PCRelativeOffset, const TargetMachine &TM) const {
return nullptr;
}

/// Target supports a native lowering of a dso_local_equivalent constant
/// without needing to replace it with equivalent IR.
bool supportDSOLocalEquivalentLowering() const {
return SupportDSOLocalEquivalentLowering;
}
/// Target supports a PC-relative relocation that references the PLT of a
/// function.
bool hasPLTPCRelative() const { return PLTPCRelativeSpecifier; }

virtual const MCExpr *lowerDSOLocalEquivalent(const DSOLocalEquivalent *Equiv,
const TargetMachine &TM) const {
virtual const MCExpr *lowerDSOLocalEquivalent(
const MCSymbol *LHS, const MCSymbol *RHS, int64_t Addend,
std::optional<int64_t> PCRelativeOffset, const TargetMachine &TM) const {
return nullptr;
}

Expand Down
66 changes: 39 additions & 27 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down
77 changes: 51 additions & 26 deletions llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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())
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/MC/MCAssembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/MC/MCParser/AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
Loading
Loading