Skip to content

Commit

Permalink
Object: Move attribute calculation into RecordStreamer. NFC
Browse files Browse the repository at this point in the history
Summary: Preparation for D44274

Reviewers: pcc, espindola

Subscribers: hiraditya

Differential Revision: https://reviews.llvm.org/D44276

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@327928 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
vitalybuka committed Mar 20, 2018
1 parent 8827501 commit 32c22cb
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 97 deletions.
80 changes: 2 additions & 78 deletions lib/Object/ModuleSymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -69,81 +68,6 @@ void ModuleSymbolTable::addModule(Module *M) {
});
}

// 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<const GlobalValue *> 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<void(StringRef, BasicSymbolRef::Flags)> AsmSymbol) {
Expand Down Expand Up @@ -176,7 +100,7 @@ void ModuleSymbolTable::CollectAsmSymbols(
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<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm));
Expand All @@ -195,7 +119,7 @@ void ModuleSymbolTable::CollectAsmSymbols(
if (Parser->Run(false))
return;

handleSymverAliases(M, Streamer);
Streamer.flushSymverDirectives();

for (auto &KV : Streamer) {
StringRef Key = KV.first();
Expand Down
85 changes: 80 additions & 5 deletions lib/Object/RecordStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
//===----------------------------------------------------------------------===//

#include "RecordStreamer.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSymbol.h"

Expand Down Expand Up @@ -71,7 +73,8 @@ void RecordStreamer::markUsed(const MCSymbol &Symbol) {

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) {}

RecordStreamer::const_iterator RecordStreamer::begin() {
return Symbols.begin();
Expand Down Expand Up @@ -113,10 +116,82 @@ void RecordStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
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);
const MCExpr *Value = MCSymbolRefExpr::create(Aliasee, getContext());
EmitAssignment(Alias, Value);
SymverAliasMap[Aliasee].push_back(Alias);
SymverAliasMap[Aliasee].push_back(AliasName);
}

void RecordStreamer::flushSymverDirectives() {
// Mapping from mangled name to GV.
StringMap<const GlobalValue *> 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;
}

// 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.
RecordStreamer::State state = 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;
}
if (GV) {
if (GV->hasExternalLinkage())
Attr = MCSA_Global;
else if (GV->hasLocalLinkage())
Attr = MCSA_Local;
else if (GV->isWeakForLinker())
Attr = MCSA_Weak;
}
}
// Set the detected binding on each alias with this aliasee.
for (auto AliasName : Symver.second) {
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);
if (Attr != MCSA_Invalid)
EmitSymbolAttribute(Alias, Attr);
}
}
}
26 changes: 12 additions & 14 deletions lib/Object/RecordStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,32 @@

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<State> 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<const MCSymbol *, std::vector<MCSymbol *>> SymverAliasMap;
DenseMap<const MCSymbol *, std::vector<StringRef>> SymverAliasMap;

/// 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<State>::const_iterator;

Expand All @@ -56,18 +63,9 @@ class RecordStreamer : public MCStreamer {
/// Record .symver aliases for later processing.
void emitELFSymverDirective(StringRef AliasName,
const MCSymbol *Aliasee) override;
/// Return the map of .symver aliasee to associated aliases.
DenseMap<const MCSymbol *, std::vector<MCSymbol *>> &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;
}
// Emit ELF .symver aliases and ensure they have the same binding as the
// defined symbol they alias with.
void flushSymverDirectives();
};

} // end namespace llvm
Expand Down

0 comments on commit 32c22cb

Please sign in to comment.