Index: llvm/lib/Object/ModuleSymbolTable.cpp =================================================================== --- llvm/lib/Object/ModuleSymbolTable.cpp +++ llvm/lib/Object/ModuleSymbolTable.cpp @@ -24,7 +24,6 @@ #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -69,81 +68,6 @@ }); } -// Ensure ELF .symver aliases get the same binding as the defined symbol -// they alias with. -static void handleSymverAliases(const Module &M, RecordStreamer &Streamer) { - if (Streamer.symverAliases().empty()) - return; - - // The name in the assembler will be mangled, but the name in the IR - // might not, so we first compute a mapping from mangled name to GV. - Mangler Mang; - SmallString<64> MangledName; - StringMap MangledNameMap; - auto GetMangledName = [&](const GlobalValue &GV) { - if (!GV.hasName()) - return; - - MangledName.clear(); - MangledName.reserve(GV.getName().size() + 1); - Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false); - MangledNameMap[MangledName] = &GV; - }; - for (const Function &F : M) - GetMangledName(F); - for (const GlobalVariable &GV : M.globals()) - GetMangledName(GV); - for (const GlobalAlias &GA : M.aliases()) - GetMangledName(GA); - - // Walk all the recorded .symver aliases, and set up the binding - // for each alias. - for (auto &Symver : Streamer.symverAliases()) { - const MCSymbol *Aliasee = Symver.first; - MCSymbolAttr Attr = MCSA_Invalid; - - // First check if the aliasee binding was recorded in the asm. - RecordStreamer::State state = Streamer.getSymbolState(Aliasee); - switch (state) { - case RecordStreamer::Global: - case RecordStreamer::DefinedGlobal: - Attr = MCSA_Global; - break; - case RecordStreamer::UndefinedWeak: - case RecordStreamer::DefinedWeak: - Attr = MCSA_Weak; - break; - default: - break; - } - - // If we don't have a symbol attribute from assembly, then check if - // the aliasee was defined in the IR. - if (Attr == MCSA_Invalid) { - const auto *GV = M.getNamedValue(Aliasee->getName()); - if (!GV) { - auto MI = MangledNameMap.find(Aliasee->getName()); - if (MI != MangledNameMap.end()) - GV = MI->second; - else - continue; - } - if (GV->hasExternalLinkage()) - Attr = MCSA_Global; - else if (GV->hasLocalLinkage()) - Attr = MCSA_Local; - else if (GV->isWeakForLinker()) - Attr = MCSA_Weak; - } - if (Attr == MCSA_Invalid) - continue; - - // Set the detected binding on each alias with this aliasee. - for (auto &Alias : Symver.second) - Streamer.EmitSymbolAttribute(Alias, Attr); - } -} - void ModuleSymbolTable::CollectAsmSymbols( const Module &M, function_ref AsmSymbol) { @@ -176,7 +100,7 @@ MCObjectFileInfo MOFI; MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, MCCtx); - RecordStreamer Streamer(MCCtx); + RecordStreamer Streamer(MCCtx, M); T->createNullTargetStreamer(Streamer); std::unique_ptr Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); @@ -195,7 +119,7 @@ if (Parser->Run(false)) return; - handleSymverAliases(M, Streamer); + Streamer.emitSymverAttributes(); for (auto &KV : Streamer) { StringRef Key = KV.first(); Index: llvm/lib/Object/RecordStreamer.h =================================================================== --- llvm/lib/Object/RecordStreamer.h +++ llvm/lib/Object/RecordStreamer.h @@ -20,25 +20,35 @@ namespace llvm { +class GlobalValue; +class Module; + class RecordStreamer : public MCStreamer { public: enum State { NeverSeen, Global, Defined, DefinedGlobal, DefinedWeak, Used, UndefinedWeak}; private: + const Module &M; StringMap Symbols; // Map of aliases created by .symver directives, saved so we can update // their symbol binding after parsing complete. This maps from each // aliasee to its list of aliases. DenseMap> SymverAliasMap; + // Mapping from mangled name to GV. + StringMap MangledNameMap; + + /// Get the state recorded for the given symbol. + State getSymbolState(const MCSymbol *Sym); + void markDefined(const MCSymbol &Symbol); void markGlobal(const MCSymbol &Symbol, MCSymbolAttr Attribute); void markUsed(const MCSymbol &Symbol); void visitUsedSymbol(const MCSymbol &Sym) override; public: - RecordStreamer(MCContext &Context); + RecordStreamer(MCContext &Context, const Module &M); using const_iterator = StringMap::const_iterator; @@ -56,18 +66,9 @@ /// Record .symver aliases for later processing. void emitELFSymverDirective(StringRef AliasName, const MCSymbol *Aliasee) override; - /// Return the map of .symver aliasee to associated aliases. - DenseMap> &symverAliases() { - return SymverAliasMap; - } - - /// Get the state recorded for the given symbol. - State getSymbolState(const MCSymbol *Sym) { - auto SI = Symbols.find(Sym->getName()); - if (SI == Symbols.end()) - return NeverSeen; - return SI->second; - } + // Ensure ELF .symver aliases get the same binding as the defined symbol + // they alias with. + void emitSymverAttributes(); }; } // end namespace llvm Index: llvm/lib/Object/RecordStreamer.cpp =================================================================== --- llvm/lib/Object/RecordStreamer.cpp +++ llvm/lib/Object/RecordStreamer.cpp @@ -8,11 +8,29 @@ //===----------------------------------------------------------------------===// #include "RecordStreamer.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSymbol.h" using namespace llvm; +static void initMangledNameMap(const Module &M, + StringMap &MangledNameMap) { + // The name in the assembler will be mangled, but the name in the IR + // might not, so we first compute a mapping from mangled name to GV. + Mangler Mang; + SmallString<64> MangledName; + for (const GlobalValue &GV : M.global_values()) { + if (!GV.hasName()) + continue; + MangledName.clear(); + MangledName.reserve(GV.getName().size() + 1); + Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false); + MangledNameMap[MangledName] = &GV; + } +} + void RecordStreamer::markDefined(const MCSymbol &Symbol) { State &S = Symbols[Symbol.getName()]; switch (S) { @@ -71,7 +89,10 @@ void RecordStreamer::visitUsedSymbol(const MCSymbol &Sym) { markUsed(Sym); } -RecordStreamer::RecordStreamer(MCContext &Context) : MCStreamer(Context) {} +RecordStreamer::RecordStreamer(MCContext &Context, const Module &M) + : MCStreamer(Context), M(M) { + initMangledNameMap(M, MangledNameMap); +} RecordStreamer::const_iterator RecordStreamer::begin() { return Symbols.begin(); @@ -113,10 +134,66 @@ markDefined(*Symbol); } +RecordStreamer::State RecordStreamer::getSymbolState(const MCSymbol *Sym) { + auto SI = Symbols.find(Sym->getName()); + if (SI == Symbols.end()) + return NeverSeen; + return SI->second; +} + void RecordStreamer::emitELFSymverDirective(StringRef AliasName, const MCSymbol *Aliasee) { MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); + // TODO: Handle "@@@". Depending on SymbolAttribute value it needs to be + // converted into @ or @@. const MCExpr *Value = MCSymbolRefExpr::create(Aliasee, getContext()); EmitAssignment(Alias, Value); SymverAliasMap[Aliasee].push_back(Alias); } + +void RecordStreamer::emitSymverAttributes() { + // Walk all the recorded .symver aliases, and set up the binding + // for each alias. + for (auto &Symver : SymverAliasMap) { + const MCSymbol *Aliasee = Symver.first; + MCSymbolAttr Attr = MCSA_Invalid; + + // First check if the aliasee binding was recorded in the asm. + switch (getSymbolState(Aliasee)) { + case RecordStreamer::Global: + case RecordStreamer::DefinedGlobal: + Attr = MCSA_Global; + break; + case RecordStreamer::UndefinedWeak: + case RecordStreamer::DefinedWeak: + Attr = MCSA_Weak; + break; + default: + break; + } + + // If we don't have a symbol attribute from assembly, then check if + // the aliasee was defined in the IR. + if (Attr == MCSA_Invalid) { + const auto *GV = M.getNamedValue(Aliasee->getName()); + if (!GV) { + auto MI = MangledNameMap.find(Aliasee->getName()); + if (MI != MangledNameMap.end()) + GV = MI->second; + else + continue; + } + if (GV->hasExternalLinkage()) + Attr = MCSA_Global; + else if (GV->hasLocalLinkage()) + Attr = MCSA_Local; + else if (GV->isWeakForLinker()) + Attr = MCSA_Weak; + } + if (Attr == MCSA_Invalid) + continue; + // Set the detected binding on each alias with this aliasee. + for (auto &Alias : Symver.second) + EmitSymbolAttribute(Alias, Attr); + } +}