Index: llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ llvm/trunk/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 @@ void emitAssignment(MCSymbol *S, const MCExpr *Value) override { auto *Symbol = cast(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( - static_cast(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 UpdateOther; + + bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) { + auto *Ref = dyn_cast(S); + if (!Ref) + return false; + const auto &RhsSym = cast(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; } }; Index: llvm/trunk/test/MC/PowerPC/ppc64-localentry-symbols.s =================================================================== --- llvm/trunk/test/MC/PowerPC/ppc64-localentry-symbols.s +++ llvm/trunk/test/MC/PowerPC/ppc64-localentry-symbols.s @@ -0,0 +1,34 @@ +# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-freebsd13.0 %s -o %t +# RUN: llvm-objdump -t %t | FileCheck %s + +# 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 +foo: + nop + nop + .localentry foo, 8 + +.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 Index: llvm/trunk/test/MC/PowerPC/ppc64-localentry-symver.s =================================================================== --- llvm/trunk/test/MC/PowerPC/ppc64-localentry-symver.s +++ llvm/trunk/test/MC/PowerPC/ppc64-localentry-symver.s @@ -1,17 +0,0 @@ -# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-freebsd13.0 %s -o %t -# RUN: llvm-objdump -t %t | FileCheck %s - -# 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 - -.globl foo -.type foo,@function -foo: - nop - nop - .localentry foo, 8 - -.symver __impl_foo, foo@FBSD_1.1 -.weak __impl_foo -.set __impl_foo, foo