Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -382,12 +382,13 @@ case SHN_UNDEF: return elf::Symtab::X ->addUndefined(Name, Binding, Sym->st_other, Sym->getType(), - /*CanOmitFromDynSym*/ false, this) + /*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false, + this) ->body(); case SHN_COMMON: return elf::Symtab::X ->addCommon(Name, Sym->st_size, Sym->st_value, Binding, Sym->st_other, - Sym->getType(), this) + Sym->getType(), /*HasUnnamedAddr*/ false, this) ->body(); } @@ -400,7 +401,8 @@ if (Sec == &InputSection::Discarded) return elf::Symtab::X ->addUndefined(Name, Binding, Sym->st_other, Sym->getType(), - /*CanOmitFromDynSym*/ false, this) + /*CanOmitFromDynSym*/ false, + /*HasUnnamedAddr*/ false, this) ->body(); return elf::Symtab::X->addRegular(Name, *Sym, Sec)->body(); } @@ -646,23 +648,29 @@ } uint8_t Visibility; - if (GV) + bool HasUnnamedAddr = false; + if (GV) { Visibility = getGvVisibility(GV); - else + HasUnnamedAddr = + GV->getUnnamedAddr() == llvm::GlobalValue::UnnamedAddr::Global; + } else { // FIXME: Set SF_Hidden flag correctly for module asm symbols, and expose // protected visibility. Visibility = STV_DEFAULT; + } if (GV) if (const Comdat *C = GV->getComdat()) if (!KeptComdats.count(C)) return Symtab::X->addUndefined(NameRef, Binding, Visibility, Type, - CanOmitFromDynSym, this); + CanOmitFromDynSym, HasUnnamedAddr, + this); const Module &M = Obj.getModule(); if (Flags & BasicSymbolRef::SF_Undefined) return Symtab::X->addUndefined(NameRef, Binding, Visibility, Type, - CanOmitFromDynSym, this); + CanOmitFromDynSym, HasUnnamedAddr, + this); if (Flags & BasicSymbolRef::SF_Common) { // FIXME: Set SF_Common flag correctly for module asm symbols, and expose // size and alignment. @@ -670,10 +678,11 @@ const DataLayout &DL = M.getDataLayout(); uint64_t Size = DL.getTypeAllocSize(GV->getValueType()); return Symtab::X->addCommon(NameRef, Size, GV->getAlignment(), - Binding, Visibility, STT_OBJECT, this); + Binding, Visibility, STT_OBJECT, + HasUnnamedAddr, this); } return Symtab::X->addBitcode(NameRef, IsWeak, Visibility, Type, - CanOmitFromDynSym, this); + CanOmitFromDynSym, HasUnnamedAddr, this); } bool BitcodeFile::shouldSkip(uint32_t Flags) { Index: ELF/LTO.cpp =================================================================== --- ELF/LTO.cpp +++ ELF/LTO.cpp @@ -194,6 +194,12 @@ if (BitcodeFile::shouldSkip(Flags)) continue; Symbol *S = Syms[BodyIndex++]; + if (GV) { + if (S->HasUnnamedAddr) + GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); + else + GV->setUnnamedAddr(GlobalValue::UnnamedAddr::None); + } if (Flags & BasicSymbolRef::SF_Undefined) { handleUndefinedAsmRefs(Sym, GV, AsmUndefinedRefs); continue; Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -59,7 +59,8 @@ Symbol *addUndefined(StringRef Name); Symbol *addUndefined(StringRef Name, uint8_t Binding, uint8_t StOther, - uint8_t Type, bool CanOmitFromDynSym, InputFile *File); + uint8_t Type, bool CanOmitFromDynSym, + bool HasUnnamedAddr, InputFile *File); Symbol *addRegular(StringRef Name, const Elf_Sym &Sym, InputSectionBase *Section); @@ -72,11 +73,12 @@ void addLazyArchive(ArchiveFile *F, const llvm::object::Archive::Symbol S); void addLazyObject(StringRef Name, LazyObjectFile &Obj); Symbol *addBitcode(StringRef Name, bool IsWeak, uint8_t StOther, uint8_t Type, - bool CanOmitFromDynSym, BitcodeFile *File); + bool CanOmitFromDynSym, bool HasUnnamedAddr, + BitcodeFile *File); Symbol *addCommon(StringRef N, uint64_t Size, uint64_t Alignment, uint8_t Binding, uint8_t StOther, uint8_t Type, - InputFile *File); + bool HasUnnamedAddr, InputFile *File); void scanUndefinedFlags(); void scanShlibUndefined(); @@ -93,7 +95,8 @@ std::pair insert(StringRef &Name); std::pair insert(StringRef &Name, uint8_t Type, uint8_t Visibility, bool CanOmitFromDynSym, - bool IsUsedInRegularObj, InputFile *File); + bool HasUnnamedAddr, bool IsUsedInRegularObj, + InputFile *File); std::string conflictMsg(SymbolBody *Existing, InputFile *NewFile); void reportDuplicate(SymbolBody *Existing, InputFile *NewFile); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -219,6 +219,7 @@ Sym->Binding = STB_WEAK; Sym->Visibility = STV_DEFAULT; Sym->IsUsedInRegularObj = false; + Sym->HasUnnamedAddr = false; Sym->ExportDynamic = false; Sym->Traced = V.Traced; std::tie(Name, Sym->VersionId) = getSymbolVersion(Name); @@ -234,12 +235,18 @@ template std::pair SymbolTable::insert(StringRef &Name, uint8_t Type, uint8_t Visibility, - bool CanOmitFromDynSym, bool IsUsedInRegularObj, - InputFile *File) { + bool CanOmitFromDynSym, bool HasUnnamedAddr, + bool IsUsedInRegularObj, InputFile *File) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); + // Merge in the new unnamed_addr attribute. + if (WasInserted) + S->HasUnnamedAddr = HasUnnamedAddr; + else + S->HasUnnamedAddr &= HasUnnamedAddr; + // Merge in the new symbol's visibility. S->Visibility = getMinVisibility(S->Visibility, Visibility); if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic)) @@ -268,18 +275,19 @@ template Symbol *SymbolTable::addUndefined(StringRef Name) { return addUndefined(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0, - /*CanOmitFromDynSym*/ false, /*File*/ nullptr); + /*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false, + /*File*/ nullptr); } template Symbol *SymbolTable::addUndefined(StringRef Name, uint8_t Binding, uint8_t StOther, uint8_t Type, bool CanOmitFromDynSym, - InputFile *File) { + bool HasUnnamedAddr, InputFile *File) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = - insert(Name, Type, StOther & 3, CanOmitFromDynSym, + insert(Name, Type, StOther & 3, CanOmitFromDynSym, HasUnnamedAddr, /*IsUsedInRegularObj*/ !File || !isa(File), File); if (WasInserted) { S->Binding = Binding; @@ -343,11 +351,11 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint64_t Alignment, uint8_t Binding, uint8_t StOther, uint8_t Type, - InputFile *File) { + bool HasUnnamedAddr, InputFile *File) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = - insert(N, Type, StOther & 3, /*CanOmitFromDynSym*/ false, + insert(N, Type, StOther & 3, /*CanOmitFromDynSym*/ false, HasUnnamedAddr, /*IsUsedInRegularObj*/ true, File); int Cmp = compareDefined(S, WasInserted, Binding); if (Cmp > 0) { @@ -387,10 +395,10 @@ InputSectionBase *Section) { Symbol *S; bool WasInserted; - std::tie(S, WasInserted) = - insert(Name, Sym.getType(), Sym.getVisibility(), - /*CanOmitFromDynSym*/ false, /*IsUsedInRegularObj*/ true, - Section ? Section->getFile() : nullptr); + std::tie(S, WasInserted) = insert( + Name, Sym.getType(), Sym.getVisibility(), + /*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false, + /*IsUsedInRegularObj*/ true, Section ? Section->getFile() : nullptr); int Cmp = compareDefinedNonCommon(S, WasInserted, Sym.getBinding()); if (Cmp > 0) replaceBody>(S, Name, Sym, Section); @@ -406,7 +414,7 @@ bool WasInserted; std::tie(S, WasInserted) = insert(Name, STT_NOTYPE, StOther & 3, /*CanOmitFromDynSym*/ false, - /*IsUsedInRegularObj*/ true, nullptr); + /*HasUnnamedAddr*/ false, /*IsUsedInRegularObj*/ true, nullptr); int Cmp = compareDefinedNonCommon(S, WasInserted, Binding); if (Cmp > 0) replaceBody>(S, Name, StOther); @@ -423,6 +431,7 @@ bool WasInserted; std::tie(S, WasInserted) = insert(N, STT_NOTYPE, /*Visibility*/ StOther & 0x3, /*CanOmitFromDynSym*/ false, + /*HasUnnamedAddr*/ false, /*IsUsedInRegularObj*/ true, nullptr); int Cmp = compareDefinedNonCommon(S, WasInserted, STB_GLOBAL); if (Cmp > 0) @@ -443,7 +452,7 @@ bool WasInserted; std::tie(S, WasInserted) = insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true, - /*IsUsedInRegularObj*/ false, F); + /*HasUnnamedAddr*/ false, /*IsUsedInRegularObj*/ false, F); // Make sure we preempt DSO symbols with default visibility. if (Sym.getVisibility() == STV_DEFAULT) S->ExportDynamic = true; @@ -457,11 +466,13 @@ template Symbol *SymbolTable::addBitcode(StringRef Name, bool IsWeak, uint8_t StOther, uint8_t Type, - bool CanOmitFromDynSym, BitcodeFile *F) { + bool CanOmitFromDynSym, + bool HasUnnamedAddr, BitcodeFile *F) { Symbol *S; bool WasInserted; - std::tie(S, WasInserted) = insert(Name, Type, StOther & 3, CanOmitFromDynSym, - /*IsUsedInRegularObj*/ false, F); + std::tie(S, WasInserted) = + insert(Name, Type, StOther & 3, CanOmitFromDynSym, HasUnnamedAddr, + /*IsUsedInRegularObj*/ false, F); int Cmp = compareDefinedNonCommon(S, WasInserted, IsWeak ? STB_WEAK : STB_GLOBAL); if (Cmp > 0) Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -413,6 +413,9 @@ // observed non-DSO symbols. unsigned Visibility : 2; + // True if the symbol has unnamed_addr. + unsigned HasUnnamedAddr : 1; + // True if the symbol was used for linking and thus need to be added to the // output file's symbol table. This is true for all symbols except for // unreferenced DSO symbols and bitcode symbols that are unreferenced except Index: test/ELF/lto/Inputs/unnamed-addr-drop.ll =================================================================== --- test/ELF/lto/Inputs/unnamed-addr-drop.ll +++ test/ELF/lto/Inputs/unnamed-addr-drop.ll @@ -0,0 +1,4 @@ +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +@foo = unnamed_addr constant i32 42 Index: test/ELF/lto/unnamed-addr-drop.ll =================================================================== --- test/ELF/lto/unnamed-addr-drop.ll +++ test/ELF/lto/unnamed-addr-drop.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as %s -o %t1.o +; RUN: llvm-as %S/Inputs/unnamed-addr-drop.ll -o %t2.o +; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t.so -save-temps -shared +; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +@foo = weak constant i32 41 + +; Check that unnamed_addr is dropped during the merge. +; CHECK: @foo = constant i32 42 Index: test/ELF/lto/unnamed-addr-lib.ll =================================================================== --- test/ELF/lto/unnamed-addr-lib.ll +++ test/ELF/lto/unnamed-addr-lib.ll @@ -11,8 +11,8 @@ ; We could add one extra bit for ODR so that we know that preemption is not ; necessary, but that is probably not worth it. -; CHECK: @foo = internal unnamed_addr constant i8 42 -; CHECK: @bar = weak_odr unnamed_addr constant i8 42 +; CHECK: @foo = internal constant i8 42 +; CHECK: @bar = weak_odr constant i8 42 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu"