Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
27 changes: 15 additions & 12 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 Expand Up @@ -240,10 +251,6 @@ class TargetLoweringObjectFileWasm : public TargetLoweringObjectFile {
const MCSymbol *KeySym) const override;
MCSection *getStaticDtorSection(unsigned Priority,
const MCSymbol *KeySym) const override;

const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
const GlobalValue *RHS,
const TargetMachine &TM) const override;
};

class TargetLoweringObjectFileXCOFF : public TargetLoweringObjectFile {
Expand All @@ -269,10 +276,6 @@ class TargetLoweringObjectFileXCOFF : public TargetLoweringObjectFile {
MCSection *getStaticDtorSection(unsigned Priority,
const MCSymbol *KeySym) const override;

const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
const GlobalValue *RHS,
const TargetMachine &TM) const override;

MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
const TargetMachine &TM) const override;

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
Loading
Loading