summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp30
-rw-r--r--llvm/test/MC/PowerPC/ppc64-localentry-symbols.s (renamed from llvm/test/MC/PowerPC/ppc64-localentry-symver.s)17
2 files changed, 41 insertions, 6 deletions
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
index 831cf2b1913..395b4236fa8 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
@@ -15,6 +15,7 @@
#include "MCTargetDesc/PPCMCAsmInfo.h"
#include "PPCTargetStreamer.h"
#include "TargetInfo/PowerPCTargetInfo.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/ELF.h"
@@ -182,16 +183,33 @@ public:
void emitAssignment(MCSymbol *S, const MCExpr *Value) override {
auto *Symbol = cast<MCSymbolELF>(S);
+
// When encoding an assignment to set symbol A to symbol B, also copy
// the st_other bits encoding the local entry point offset.
- if (Value->getKind() != MCExpr::SymbolRef)
- return;
- const auto &RhsSym = cast<MCSymbolELF>(
- static_cast<const MCSymbolRefExpr *>(Value)->getSymbol());
- unsigned Other = Symbol->getOther();
+ if (copyLocalEntry(Symbol, Value))
+ UpdateOther.insert(Symbol);
+ else
+ UpdateOther.erase(Symbol);
+ }
+
+ void finish() override {
+ for (auto *Sym : UpdateOther)
+ copyLocalEntry(Sym, Sym->getVariableValue());
+ }
+
+private:
+ SmallPtrSet<MCSymbolELF *, 32> UpdateOther;
+
+ bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) {
+ auto *Ref = dyn_cast<const MCSymbolRefExpr>(S);
+ if (!Ref)
+ return false;
+ const auto &RhsSym = cast<MCSymbolELF>(Ref->getSymbol());
+ unsigned Other = D->getOther();
Other &= ~ELF::STO_PPC64_LOCAL_MASK;
Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK;
- Symbol->setOther(Other);
+ D->setOther(Other);
+ return true;
}
};
diff --git a/llvm/test/MC/PowerPC/ppc64-localentry-symver.s b/llvm/test/MC/PowerPC/ppc64-localentry-symbols.s
index 4c7490646db..f1d5c5d0ab1 100644
--- a/llvm/test/MC/PowerPC/ppc64-localentry-symver.s
+++ b/llvm/test/MC/PowerPC/ppc64-localentry-symbols.s
@@ -4,6 +4,11 @@
# CHECK: 0000000000000000 gw F .text 00000000 0x60 __impl_foo
# CHECK: 0000000000000000 g F .text 00000000 0x60 foo
# CHECK: 0000000000000000 gw F .text 00000000 0x60 foo@FBSD_1.1
+# CHECK: 0000000000000008 g F .text 00000000 0x60 func
+# CHECK: 0000000000000008 gw F .text 00000000 0x60 weak_func
+
+.text
+.abiversion 2
.globl foo
.type foo,@function
@@ -15,3 +20,15 @@ foo:
.symver __impl_foo, foo@FBSD_1.1
.weak __impl_foo
.set __impl_foo, foo
+
+.globl func
+# Mimick FreeBSD weak function/reference
+.weak weak_func
+.equ weak_func, func
+
+.p2align 2
+.type func,@function
+func:
+ nop
+ nop
+ .localentry func, 8
OpenPOWER on IntegriCloud