Skip to content

AsmPrinter: Remove ELF's special lowerRelativeReference for unnamed_addr function; use lowerDSOLocalEquivalent in more cases #134781

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
4 changes: 0 additions & 4 deletions llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,6 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
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, int64_t Addend,
std::optional<int64_t> PCRelativeOffset,
const TargetMachine &TM) const override;

const MCExpr *lowerDSOLocalEquivalent(const MCSymbol *LHS,
const MCSymbol *RHS, int64_t Addend,
Expand Down
10 changes: 6 additions & 4 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3496,10 +3496,12 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV,
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()))
// LHS is a dso_local_equivalent of a function, reference the PLT entry
// instead. Note: A default visibility symbol is by default preemptible
// during linking, and should not be referenced with PC-relative
// relocations. Therefore, use a PLT relocation even if the function is
// dso_local.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For AArch64, this change makes relocations for relative vtable entries always be PLT32, though PREL32 relocation also works (for dso_local) and its target symbol could get changed from function to section-plus-offset (in hope to omit the function symbol in local symbol table).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you talking about the ld -r/--emit-reelocs --discard-all or objcopy --discard-all behavior?
It's true that the PLT-generating relocation, if present, keeps the symbol alive under --discard-all.
However, the advantage is that even in the object file, the dso_local_equivalent semantics are retained: we don't take the address of the symbol.

% cat x.s
f1:
f2:

.data
.long f1@plt - .
.long f2 - .
% llvm-mc -triple=aarch64 -filetype=obj x.s -o x.o && ld.lld x.o -o x -r --discard-all && readelf -W -s x
Symbol table '.symtab' contains 4 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    1 f1
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 .text
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 .data

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was referring to the logic in this function, where if it is PREL32 and the target symbol is dso_local, we may update relocation target from "func + vtable_slot_offset" to "section + offset". So if the dso_local function is not referenced elsewhere, we can omit its emission in local symtab.

if (DSOEquiv && TM.getTargetTriple().isOSBinFormatELF())
Res = getObjFileLowering().lowerDSOLocalEquivalent(
LHSSym, RHSSym, Addend, PCRelativeOffset, TM);

Expand Down
18 changes: 0 additions & 18 deletions llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1233,24 +1233,6 @@ const MCExpr *TargetLoweringObjectFileELF::lowerSymbolDifference(
return Res;
}

const MCExpr *TargetLoweringObjectFileELF::lowerRelativeReference(
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())
return nullptr;

// Basic correctness checks.
if (LHS->getType()->getPointerAddressSpace() != 0 ||
RHS->getType()->getPointerAddressSpace() != 0 || LHS->isThreadLocal() ||
RHS->isThreadLocal())
return nullptr;

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 MCSymbol *LHS, const MCSymbol *RHS, int64_t Addend,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ declare void @fn1() unnamed_addr
declare void @fn2() unnamed_addr
declare void @fn3()

;; Create a PC-relative relocation that the linker might decline if the addend symbol is preemptible.
; CHECK: .long 0
; CHECK-NEXT: .long fn1(prel31)-vtable-4
; CHECK-NEXT: .long fn2(prel31)-vtable-4
; CHECK-NEXT: .long fn1-vtable-4
; CHECK-NEXT: .long fn2-vtable-4
; CHECK-NEXT: .long fn3-vtable-4
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/RISCV/dso_local_equivalent.ll
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ declare void @extern_func()
; CHECK-NEXT: .word 0 # 0x0
; CHECK-NEXT: .word %pltpcrel(f0)
; CHECK-NEXT: .word %pltpcrel(f1+4)
; CHECK-NEXT: .word f2-_ZTV1B-8
; CHECK-NEXT: .word %pltpcrel(f2+8)
; CHECK-NEXT: .word %pltpcrel(f3+12)
; CHECK-NEXT: .word f4-_ZTV1B-8
; CHECK-NEXT: .word %pltpcrel(f4+16)
; CHECK-NEXT: .size _ZTV1B, 28
declare void @f0()
declare void @f1()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ declare void @fn2() unnamed_addr
declare void @fn3()
@global4 = external unnamed_addr global i8

;; Create a PC-relative relocation that the linker might decline if the addend symbol is preemptible.
; CHECK: vtable:
; CHECK-NEXT: .word 0 # 0x0
; CHECK-NEXT: .word %pltpcrel(fn1)
; CHECK-NEXT: .word %pltpcrel(fn2+4)
; CHECK-NEXT: .word fn1-vtable-4
; CHECK-NEXT: .word fn2-vtable-4
; CHECK-NEXT: .word fn3-vtable-4
; CHECK-NEXT: .word global4-vtable-4
; CHECK-NEXT: .size vtable, 20
26 changes: 21 additions & 5 deletions llvm/test/CodeGen/X86/dso_local_equivalent.ll
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,27 @@ define void @call_no_name_extern() {

declare hidden void @0()
declare void @1()
declare void @forward_extern_func()

;; Note that we keep this at the very end because llc emits this after all the
;; functions.
; CHECK: const:
; CHECK: .long forward_extern_func@PLT
@const = constant i32 trunc (i64 ptrtoint (ptr dso_local_equivalent @forward_extern_func to i64) to i32)

declare void @forward_extern_func()
; CHECK-LABEL: _ZTV1B:
; CHECK: .long 0
; CHECK-NEXT: .long 0
; CHECK-NEXT: .long f0@PLT-_ZTV1B-8
; CHECK-NEXT: .long f1@PLT-_ZTV1B-8
; CHECK-NEXT: .long f2@PLT-_ZTV1B-8

@_ZTV1B = dso_local constant { [5 x i32] } { [5 x i32] [
i32 0,
i32 0,
i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @f0 to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [7 x i32] }, ptr @_ZTV1B, i32 0, i32 0, i32 2) to i64)) to i32),
i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @f1 to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [7 x i32] }, ptr @_ZTV1B, i32 0, i32 0, i32 2) to i64)) to i32),
i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @f2 to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [7 x i32] }, ptr @_ZTV1B, i32 0, i32 0, i32 2) to i64)) to i32)
] }

declare void @f0()
declare void @f1()
define dso_local void @f2() {
ret void
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ declare void @fn2() unnamed_addr
declare void @fn3()

; CHECK: .long 0
; CHECK-NEXT: .long fn1@PLT-vtable-4
; CHECK-NEXT: .long fn2@PLT-vtable-4
; CHECK-NEXT: .long fn1-vtable-4
; CHECK-NEXT: .long fn2-vtable-4
; CHECK-NEXT: .long fn3-vtable-4
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ declare void @fn2() unnamed_addr
declare void @fn3()
@global4 = external unnamed_addr global i8

;; Create a PC-relative relocation that the linker might decline if the addend symbol is preemptible.
; CHECK: .long 0
; CHECK-NEXT: .long fn1@PLT-vtable-4
; CHECK-NEXT: .long fn2@PLT-vtable-4
; CHECK-NEXT: .long fn1-vtable-4
; CHECK-NEXT: .long fn2-vtable-4
; CHECK-NEXT: .long fn3-vtable-4
; CHECK-NEXT: .long global4-vtable-4
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/X86/relptr-rodata.ll
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ target triple = "x86_64-unknown-linux-gnu"
; CHECK-NEXT: .globl obj
; CHECK: obj:
; CHECK: .long 0
; CHECK: .long hidden_func-obj-4
; CHECK: .long hidden_func@PLT-obj-4

declare hidden void @hidden_func()

Expand Down