forked from OSchip/llvm-project
[LTO] Fix the logic for dropping unnamed_addr.
Differential Revision: https://reviews.llvm.org/D24037 llvm-svn: 280144
This commit is contained in:
parent
c943d72d94
commit
35af5b3d21
|
@ -382,12 +382,13 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
|
|||
case SHN_UNDEF:
|
||||
return elf::Symtab<ELFT>::X
|
||||
->addUndefined(Name, Binding, Sym->st_other, Sym->getType(),
|
||||
/*CanOmitFromDynSym*/ false, this)
|
||||
/*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false,
|
||||
this)
|
||||
->body();
|
||||
case SHN_COMMON:
|
||||
return elf::Symtab<ELFT>::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 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
|
|||
if (Sec == &InputSection<ELFT>::Discarded)
|
||||
return elf::Symtab<ELFT>::X
|
||||
->addUndefined(Name, Binding, Sym->st_other, Sym->getType(),
|
||||
/*CanOmitFromDynSym*/ false, this)
|
||||
/*CanOmitFromDynSym*/ false,
|
||||
/*HasUnnamedAddr*/ false, this)
|
||||
->body();
|
||||
return elf::Symtab<ELFT>::X->addRegular(Name, *Sym, Sec)->body();
|
||||
}
|
||||
|
@ -646,23 +648,29 @@ Symbol *BitcodeFile::createSymbol(const DenseSet<const Comdat *> &KeptComdats,
|
|||
}
|
||||
|
||||
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<ELFT>::X->addUndefined(NameRef, Binding, Visibility, Type,
|
||||
CanOmitFromDynSym, this);
|
||||
CanOmitFromDynSym, HasUnnamedAddr,
|
||||
this);
|
||||
|
||||
const Module &M = Obj.getModule();
|
||||
if (Flags & BasicSymbolRef::SF_Undefined)
|
||||
return Symtab<ELFT>::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 @@ Symbol *BitcodeFile::createSymbol(const DenseSet<const Comdat *> &KeptComdats,
|
|||
const DataLayout &DL = M.getDataLayout();
|
||||
uint64_t Size = DL.getTypeAllocSize(GV->getValueType());
|
||||
return Symtab<ELFT>::X->addCommon(NameRef, Size, GV->getAlignment(),
|
||||
Binding, Visibility, STT_OBJECT, this);
|
||||
Binding, Visibility, STT_OBJECT,
|
||||
HasUnnamedAddr, this);
|
||||
}
|
||||
return Symtab<ELFT>::X->addBitcode(NameRef, IsWeak, Visibility, Type,
|
||||
CanOmitFromDynSym, this);
|
||||
CanOmitFromDynSym, HasUnnamedAddr, this);
|
||||
}
|
||||
|
||||
bool BitcodeFile::shouldSkip(uint32_t Flags) {
|
||||
|
|
|
@ -194,6 +194,12 @@ void BitcodeCompiler::add(BitcodeFile &F) {
|
|||
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;
|
||||
|
|
|
@ -219,6 +219,7 @@ std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef &Name) {
|
|||
Sym->Binding = STB_WEAK;
|
||||
Sym->Visibility = STV_DEFAULT;
|
||||
Sym->IsUsedInRegularObj = false;
|
||||
Sym->HasUnnamedAddr = true;
|
||||
Sym->ExportDynamic = false;
|
||||
Sym->Traced = V.Traced;
|
||||
std::tie(Name, Sym->VersionId) = getSymbolVersion(Name);
|
||||
|
@ -234,12 +235,14 @@ std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef &Name) {
|
|||
template <class ELFT>
|
||||
std::pair<Symbol *, bool>
|
||||
SymbolTable<ELFT>::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.
|
||||
S->HasUnnamedAddr &= HasUnnamedAddr;
|
||||
// Merge in the new symbol's visibility.
|
||||
S->Visibility = getMinVisibility(S->Visibility, Visibility);
|
||||
if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic))
|
||||
|
@ -268,18 +271,19 @@ std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Existing,
|
|||
|
||||
template <class ELFT> Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name) {
|
||||
return addUndefined(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0,
|
||||
/*CanOmitFromDynSym*/ false, /*File*/ nullptr);
|
||||
/*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false,
|
||||
/*File*/ nullptr);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Symbol *SymbolTable<ELFT>::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<BitcodeFile>(File), File);
|
||||
if (WasInserted) {
|
||||
S->Binding = Binding;
|
||||
|
@ -343,11 +347,11 @@ template <class ELFT>
|
|||
Symbol *SymbolTable<ELFT>::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 +391,10 @@ Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, const Elf_Sym &Sym,
|
|||
InputSectionBase<ELFT> *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<ELFT>(S, WasInserted, Sym.getBinding());
|
||||
if (Cmp > 0)
|
||||
replaceBody<DefinedRegular<ELFT>>(S, Name, Sym, Section);
|
||||
|
@ -406,7 +410,7 @@ Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t Binding,
|
|||
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<ELFT>(S, WasInserted, Binding);
|
||||
if (Cmp > 0)
|
||||
replaceBody<DefinedRegular<ELFT>>(S, Name, StOther);
|
||||
|
@ -423,6 +427,7 @@ Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N,
|
|||
bool WasInserted;
|
||||
std::tie(S, WasInserted) = insert(N, STT_NOTYPE, /*Visibility*/ StOther & 0x3,
|
||||
/*CanOmitFromDynSym*/ false,
|
||||
/*HasUnnamedAddr*/ false,
|
||||
/*IsUsedInRegularObj*/ true, nullptr);
|
||||
int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, STB_GLOBAL);
|
||||
if (Cmp > 0)
|
||||
|
@ -443,7 +448,7 @@ void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name,
|
|||
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 +462,13 @@ void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name,
|
|||
template <class ELFT>
|
||||
Symbol *SymbolTable<ELFT>::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<ELFT>(S, WasInserted,
|
||||
IsWeak ? STB_WEAK : STB_GLOBAL);
|
||||
if (Cmp > 0)
|
||||
|
|
|
@ -59,7 +59,8 @@ public:
|
|||
|
||||
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<ELFT> *Section);
|
||||
|
@ -72,11 +73,12 @@ public:
|
|||
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 @@ private:
|
|||
std::pair<Symbol *, bool> insert(StringRef &Name);
|
||||
std::pair<Symbol *, bool> 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);
|
||||
|
|
|
@ -413,6 +413,9 @@ struct Symbol {
|
|||
// 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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue