[BOLT] Replace list of Names with Symbols for BinaryFunction

Summary:
BinaryFunction used to have a list of Names associated with its main
entry point. However, the function is primarily identified by its
corresponding symbol or symbols, and these symbols are available as we
are creating them for a corresponding BinaryData object.

There's also no reason to emit symbols for alternative function names
(aliases), so change the code to only emit needed symbols.

When we emit a cold fragment for a function, only emit one cold symbol
for the fragment instead of one per every main entry symbol/name.

When we match a symbol to an entry point in the function, with this
change we can first go through the list of main entry symbols (now that
they are available).

(cherry picked from FBD19426709)
This commit is contained in:
Maksim Panchenko 2020-01-13 11:56:59 -08:00
parent 7a59783d7a
commit ac697b7d3a
13 changed files with 171 additions and 141 deletions

View File

@ -740,7 +740,7 @@ std::string BinaryContext::generateJumpTableName(const BinaryFunction &BF,
} else {
Id = JumpTableIds[Address] = BF.JumpTables.size();
}
return ("JUMP_TABLE/" + BF.Names[0] + "." + std::to_string(Id) +
return ("JUMP_TABLE/" + BF.getOneName().str() + "." + std::to_string(Id) +
(Offset ? ("." + std::to_string(Offset)) : ""));
}
@ -1096,31 +1096,30 @@ void BinaryContext::postProcessSymbolTable() {
void BinaryContext::foldFunction(BinaryFunction &ChildBF,
BinaryFunction &ParentBF) {
std::shared_lock<std::shared_timed_mutex> ReadCtxLock(CtxMutex,
std::defer_lock);
assert(!ChildBF.isMultiEntry() && !ParentBF.isMultiEntry() &&
"cannot merge functions with multiple entry points");
std::unique_lock<std::shared_timed_mutex> WriteCtxLock(CtxMutex,
std::defer_lock);
std::unique_lock<std::shared_timed_mutex> WriteSymbolMapLock(
SymbolToFunctionMapMutex, std::defer_lock);
// Copy name list.
ParentBF.addNewNames(ChildBF.getNames());
// Update internal bookkeeping info.
for (auto &Name : ChildBF.getNames()) {
ReadCtxLock.lock();
// Calls to functions are handled via symbols, and we keep the lookup table
// that we need to update.
auto *Symbol = Ctx->lookupSymbol(Name);
ReadCtxLock.unlock();
assert(Symbol && "symbol cannot be NULL at this point");
const auto ChildName = ChildBF.getOneName();
// Move symbols over and update bookkeeping info.
for (auto *Symbol : ChildBF.getSymbols()) {
ParentBF.getSymbols().push_back(Symbol);
WriteSymbolMapLock.lock();
SymbolToFunctionMap[Symbol] = &ParentBF;
WriteSymbolMapLock.unlock();
// NB: there's no need to update BinaryDataMap and GlobalSymbols.
}
ChildBF.getSymbols().clear();
// Move other names the child function is known under.
std::move(ChildBF.Aliases.begin(), ChildBF.Aliases.end(),
std::back_inserter(ParentBF.Aliases));
ChildBF.Aliases.clear();
// Merge execution counts of ChildBF into those of ParentBF.
ChildBF.mergeProfileDataInto(ParentBF);
@ -1144,12 +1143,10 @@ void BinaryContext::foldFunction(BinaryFunction &ChildBF,
} else {
// In non-relocation mode we keep the function, but rename it.
std::string NewName = "__ICF_" + ChildBF.getSymbol()->getName().str();
ChildBF.Names.clear();
ChildBF.Names.push_back(NewName);
std::string NewName = "__ICF_" + ChildName.str();
WriteCtxLock.lock();
ChildBF.OutputSymbol = Ctx->getOrCreateSymbol(NewName);
ChildBF.getSymbols().push_back(Ctx->getOrCreateSymbol(NewName));
WriteCtxLock.unlock();
ChildBF.setFolded();

View File

@ -239,18 +239,19 @@ SMLoc findDebugLineInformationForInstructionAt(
uint64_t BinaryFunction::Count = 0;
const std::string *
Optional<StringRef>
BinaryFunction::hasNameRegex(const StringRef Name) const {
const auto RegexName = (Twine("^") + StringRef(Name) + "$").str();
Regex MatchName(RegexName);
for (auto &Name : Names)
if (MatchName.match(Name))
return &Name;
return nullptr;
auto Match = forEachName([&MatchName](StringRef Name) {
return MatchName.match(Name);
});
return Match;
}
std::string BinaryFunction::getDemangledName() const {
StringRef MangledName = Names.back();
StringRef MangledName = getOneName();
MangledName = MangledName.substr(0, MangledName.find_first_of('/'));
int Status = 0;
char *const Name =
@ -403,11 +404,12 @@ void BinaryFunction::print(raw_ostream &OS, std::string Annotation,
StringRef SectionName =
IsInjected ? "<no input section>" : InputSection->getName();
OS << "Binary Function \"" << *this << "\" " << Annotation << " {";
if (Names.size() > 1) {
OS << "\n Other names : ";
auto AllNames = getNames();
if (AllNames.size() > 1) {
OS << "\n All names : ";
auto Sep = "";
for (unsigned i = 0; i < Names.size() - 1; ++i) {
OS << Sep << Names[i];
for (const auto Name : AllNames) {
OS << Sep << Name;
Sep = "\n ";
}
}
@ -3388,30 +3390,27 @@ uint64_t BinaryFunction::getEntryForSymbol(const MCSymbol *EntrySymbol) const {
if (!isMultiEntry())
return 0;
if (getSymbol() == EntrySymbol)
return 0;
for (const auto *Symbol : getSymbols())
if (Symbol == EntrySymbol)
return 0;
// The function might have multiple symbols associated with its main entry
// point. Check EntrySymbol against all secondary entry points and return 0
// corresponding to the main entry point if no match is found.
// Check all secondary entries available as either basic blocks or lables.
uint64_t NumEntries = 0;
if (hasCFG()) {
for (const auto *BB : BasicBlocks) {
if (!BB->isEntryPoint())
continue;
if (BB->getLabel() == EntrySymbol)
return NumEntries;
++NumEntries;
}
} else {
for (auto &KV : Labels) {
if (KV.second == EntrySymbol)
return NumEntries;
++NumEntries;
}
for (const auto *BB : BasicBlocks) {
if (!BB->isEntryPoint())
continue;
if (BB->getLabel() == EntrySymbol)
return NumEntries;
++NumEntries;
}
NumEntries = 0;
for (auto &KV : Labels) {
if (KV.second == EntrySymbol)
return NumEntries;
++NumEntries;
}
return 0;
llvm_unreachable("symbol not found");
}
BinaryFunction::BasicBlockOrderType BinaryFunction::dfs() const {

View File

@ -153,8 +153,16 @@ private:
/// Current state of the function.
State CurrentState{State::Empty};
/// A list of function names.
std::vector<std::string> Names;
/// A list of symbols associated with the function entry point.
///
/// Multiple symbols would typically result from identical code-folding
/// optimization.
typedef SmallVector<MCSymbol *, 1> SymbolListTy;
SymbolListTy Symbols;
/// The list of names this function is known under. Used for fuzzy-matching
/// the function to its name in a profile, command line, etc.
std::vector<std::string> Aliases;
/// Containing section
BinarySection *InputSection = nullptr;
@ -517,12 +525,6 @@ private:
};
std::vector<BasicBlockOffset> BasicBlockOffsets;
/// Symbol in the output.
///
/// NB: function can have multiple symbols associated with it. We will emit
/// all symbols for the function
MCSymbol *OutputSymbol;
MCSymbol *ColdSymbol{nullptr};
/// Symbol at the end of the function.
@ -547,7 +549,7 @@ private:
private:
/// Register alternative function name.
void addAlternativeName(std::string NewName) {
Names.emplace_back(NewName);
Aliases.emplace_back(NewName);
}
/// Return label at a given \p Address in the function. If the label does
@ -653,21 +655,21 @@ private:
BinaryFunction(const std::string &Name, BinarySection &Section,
uint64_t Address, uint64_t Size, BinaryContext &BC,
bool IsSimple) :
Names({Name}), InputSection(&Section), Address(Address),
InputSection(&Section), Address(Address),
Size(Size), BC(BC), IsSimple(IsSimple),
CodeSectionName(".local.text." + Name),
ColdCodeSectionName(".local.cold.text." + Name),
FunctionNumber(++Count) {
OutputSymbol = BC.Ctx->getOrCreateSymbol(Name);
Symbols.push_back(BC.Ctx->getOrCreateSymbol(Name));
}
/// This constructor is used to create an injected function
BinaryFunction(const std::string &Name, BinaryContext &BC, bool IsSimple)
: Names({Name}), Address(0), Size(0), BC(BC), IsSimple(IsSimple),
: Address(0), Size(0), BC(BC), IsSimple(IsSimple),
CodeSectionName(".local.text." + Name),
ColdCodeSectionName(".local.cold.text." + Name),
FunctionNumber(++Count) {
OutputSymbol = BC.Ctx->getOrCreateSymbol(Name);
Symbols.push_back(BC.Ctx->getOrCreateSymbol(Name));
IsInjected = true;
}
@ -925,40 +927,74 @@ public:
getJumpTableContainingAddress(Address);
}
/// Return the name of the function as extracted from the binary file.
/// If the function has multiple names - return the last one
/// followed by "(*#<numnames>)".
/// We should preferably only use getName() for diagnostics and use
/// Return the name of the function if the function has just one name.
/// If the function has multiple names - return one followed
/// by "(*#<numnames>)".
///
/// We should use getPrintName() for diagnostics and use
/// hasName() to match function name against a given string.
///
/// We pick the last name from the list to match the name of the function
/// in profile data for easier manual analysis.
/// NOTE: for disambiguating names of local symbols we use the following
/// naming schemes:
/// primary: <function>/<id>
/// alternative: <function>/<file>/<id2>
std::string getPrintName() const {
return Names.size() == 1 ?
Names.back() :
(Names.back() + "(*" + std::to_string(Names.size()) + ")");
const auto NumNames = Symbols.size() + Aliases.size();
return NumNames == 1
? getOneName().str()
: (getOneName().str() + "(*" + std::to_string(NumNames) + ")");
}
/// The function may have many names. For that reason, we avoid having
/// getName() method as most of the time the user needs a different
/// interface, such as forEachName(), hasName(), hasNameRegex(), etc.
/// In some cases though, we need just a name uniquely identifying
/// the function, and that's what this method is for.
StringRef getOneName() const {
return Symbols[0]->getName();
}
/// Return the name of the function as getPrintName(), but also trying
/// to demangle it.
std::string getDemangledName() const;
/// Check if (possibly one out of many) function name matches the given
/// string. Use this member function instead of direct name comparison.
bool hasName(const std::string &FunctionName) const {
for (auto &Name : Names)
if (Name == FunctionName)
return true;
return false;
/// Call \p Callback for every name of this function as long as the Callback
/// returns false. Stop if Callback returns true or all names have been used.
/// Return the name for which the Callback returned true if any.
template <typename FType>
Optional<StringRef> forEachName(FType Callback) const {
for (auto *Symbol : Symbols)
if (Callback(Symbol->getName()))
return Symbol->getName();
for (auto &Name : Aliases)
if (Callback(StringRef(Name)))
return StringRef(Name);
return NoneType();
}
/// Check if (possibly one out of many) function name matches the given
/// regex.
const std::string *hasNameRegex(const StringRef NameRegex) const;
/// string. Use this member function instead of direct name comparison.
bool hasName(const std::string &FunctionName) const {
auto Res = forEachName([&](StringRef Name) {
return Name == FunctionName;
});
return Res.hasValue();
}
/// Check if of function names matches the given regex.
Optional<StringRef> hasNameRegex(const StringRef NameRegex) const;
/// Return a vector of all possible names for the function.
const std::vector<std::string> &getNames() const {
return Names;
const std::vector<StringRef> getNames() const {
std::vector<StringRef> AllNames;
forEachName([&AllNames] (StringRef Name) {
AllNames.push_back(Name);
return false;
});
return AllNames;
}
/// Return a state the function is in (see BinaryFunction::State definition
@ -1055,15 +1091,19 @@ public:
/// Return MC symbol associated with the function.
/// All references to the function should use this symbol.
MCSymbol *getSymbol() {
return OutputSymbol;
return Symbols[0];
}
/// Return MC symbol associated with the function (const version).
/// All references to the function should use this symbol.
const MCSymbol *getSymbol() const {
return OutputSymbol;
return Symbols[0];
}
/// Return a list of symbols associated with the main entry of the function.
SymbolListTy &getSymbols() { return Symbols; }
const SymbolListTy &getSymbols() const { return Symbols; }
/// Return MC symbol corresponding to an enumerated entry for multiple-entry
/// functions.
const MCSymbol *getSymbolForEntry(uint64_t EntryNum) const;
@ -1333,13 +1373,6 @@ public:
return Address <= PC && PC < Address + Size;
}
/// Add new names this function is known under.
template <class ContainterTy>
void addNewNames(const ContainterTy &NewNames) {
Names.insert(Names.begin(), NewNames.begin(), NewNames.end());
std::sort(Names.begin(), Names.end());
}
/// Create a basic block at a given \p Offset in the
/// function.
/// If \p DeriveAlignment is true, set the alignment of the block based

View File

@ -217,7 +217,7 @@ class RewriteInstanceDiff {
const auto &Function = BFI.second;
const auto Score = getNormalizedScore(Function, RI1);
LargestBin1.insert(std::make_pair<>(Score, &Function));
for (const auto &Name : Function.getNames()) {
for (const auto Name : Function.getNames()) {
if (auto OptionalLTOName = getLTOCommonName(Name))
LTOName = *OptionalLTOName;
NameLookup[Name] = &Function;
@ -237,7 +237,7 @@ class RewriteInstanceDiff {
const auto &Function = BFI.second;
const auto Score = getNormalizedScore(Function, RI2);
LargestBin2.insert(std::make_pair<>(Score, &Function));
for (const auto &Name : Function.getNames()) {
for (const auto Name : Function.getNames()) {
if (auto OptionalLTOName = getLTOCommonName(Name))
LTOName = *OptionalLTOName;
}
@ -259,7 +259,7 @@ class RewriteInstanceDiff {
const auto &Function2 = BFI2.second;
StringRef LTOName;
bool Match = false;
for (const auto &Name : Function2.getNames()) {
for (const auto Name : Function2.getNames()) {
auto Iter = NameLookup.find(Name);
if (auto OptionalLTOName = getLTOCommonName(Name))
LTOName = *OptionalLTOName;

View File

@ -650,7 +650,7 @@ DataAggregator::getBinaryFunctionContainingAddress(uint64_t Address) const {
StringRef DataAggregator::getLocationName(BinaryFunction &Func,
uint64_t Count) {
if (!BAT)
return Func.getNames()[0];
return Func.getOneName();
const auto *OrigFunc = &Func;
if (const auto HotAddr = BAT->fetchParentAddress(Func.getAddress())) {
@ -659,11 +659,9 @@ StringRef DataAggregator::getLocationName(BinaryFunction &Func,
if (HotFunc)
OrigFunc = HotFunc;
}
const auto &Names = OrigFunc->getNames();
// If it is a local function, prefer the name containing the file name where
// the local function was declared
for (const auto &Name : Names) {
StringRef AlternativeName = Name;
for (auto AlternativeName : OrigFunc->getNames()) {
size_t FileNameIdx = AlternativeName.find('/');
// Confirm the alternative name has the pattern Symbol/FileName/1 before
// using it
@ -672,17 +670,17 @@ StringRef DataAggregator::getLocationName(BinaryFunction &Func,
continue;
return AlternativeName;
}
return Names[0];
return Func.getOneName();
}
bool DataAggregator::doSample(BinaryFunction &Func, uint64_t Address,
uint64_t Count) {
auto I = FuncsToSamples.find(Func.getNames()[0]);
auto I = FuncsToSamples.find(Func.getOneName());
if (I == FuncsToSamples.end()) {
bool Success;
StringRef LocName = getLocationName(Func, Count);
std::tie(I, Success) = FuncsToSamples.insert(std::make_pair(
Func.getNames()[0],
Func.getOneName(),
FuncSampleData(LocName, FuncSampleData::ContainerTy())));
}
@ -699,7 +697,7 @@ bool DataAggregator::doIntraBranch(BinaryFunction &Func, uint64_t From,
uint64_t Mispreds) {
FuncBranchData *AggrData = Func.getBranchData();
if (!AggrData) {
AggrData = &FuncsToBranches[Func.getNames()[0]];
AggrData = &FuncsToBranches[Func.getOneName()];
AggrData->Name = getLocationName(Func, Count);
Func.setBranchData(AggrData);
}
@ -735,7 +733,7 @@ bool DataAggregator::doInterBranch(BinaryFunction *FromFunc,
SrcFunc = getLocationName(*FromFunc, Count);
FromAggrData = FromFunc->getBranchData();
if (!FromAggrData) {
FromAggrData = &FuncsToBranches[FromFunc->getNames()[0]];
FromAggrData = &FuncsToBranches[FromFunc->getOneName()];
FromAggrData->Name = SrcFunc;
FromFunc->setBranchData(FromAggrData);
}
@ -749,7 +747,7 @@ bool DataAggregator::doInterBranch(BinaryFunction *FromFunc,
DstFunc = getLocationName(*ToFunc, 0);
ToAggrData = ToFunc->getBranchData();
if (!ToAggrData) {
ToAggrData = &FuncsToBranches[ToFunc->getNames()[0]];
ToAggrData = &FuncsToBranches[ToFunc->getOneName()];
ToAggrData->Name = DstFunc;
ToFunc->setBranchData(ToAggrData);
}
@ -1519,14 +1517,14 @@ void DataAggregator::processMemEvents() {
// Try to resolve symbol for PC
auto *Func = getBinaryFunctionContainingAddress(PC);
if (Func) {
FuncName = Func->getNames()[0];
FuncName = Func->getOneName();
PC -= Func->getAddress();
}
// Try to resolve symbol for memory load
auto *MemFunc = getBinaryFunctionContainingAddress(Addr);
if (MemFunc) {
MemName = MemFunc->getNames()[0];
MemName = MemFunc->getOneName();
Addr -= MemFunc->getAddress();
} else if (Addr) {
if (auto *BD = BC->getBinaryDataContainingAddress(Addr)) {

View File

@ -751,7 +751,7 @@ fetchMapEntry(MapTy &Map, const std::vector<MCSymbol *> &Symbols) {
template <typename MapTy>
decltype(MapTy::MapEntryTy::second) *
fetchMapEntry(MapTy &Map, const std::vector<std::string> &FuncNames) {
fetchMapEntry(MapTy &Map, const std::vector<StringRef> &FuncNames) {
// Do a reverse order iteration since the name in profile has a higher chance
// of matching a name at the end of the list.
for (auto FI = FuncNames.rbegin(), FE = FuncNames.rend(); FI != FE; ++FI) {
@ -767,7 +767,7 @@ std::vector<decltype(MapTy::MapEntryTy::second) *>
fetchMapEntriesRegex(
MapTy &Map,
const StringMap<std::vector<decltype(MapTy::MapEntryTy::second) *>> &LTOCommonNameMap,
const std::vector<std::string> &FuncNames) {
const std::vector<StringRef> &FuncNames) {
std::vector<decltype(MapTy::MapEntryTy::second) *> AllData;
// Do a reverse order iteration since the name in profile has a higher chance
// of matching a name at the end of the list.
@ -794,7 +794,7 @@ fetchMapEntriesRegex(
}
FuncBranchData *
DataReader::getFuncBranchData(const std::vector<std::string> &FuncNames) {
DataReader::getFuncBranchData(const std::vector<StringRef> &FuncNames) {
return fetchMapEntry<FuncsToBranchesMapTy>(FuncsToBranches, FuncNames);
}
@ -804,22 +804,22 @@ DataReader::getFuncBranchData(const std::vector<MCSymbol *> &Symbols) {
}
FuncMemData *
DataReader::getFuncMemData(const std::vector<std::string> &FuncNames) {
DataReader::getFuncMemData(const std::vector<StringRef> &FuncNames) {
return fetchMapEntry<FuncsToMemEventsMapTy>(FuncsToMemEvents, FuncNames);
}
FuncSampleData *
DataReader::getFuncSampleData(const std::vector<std::string> &FuncNames) {
DataReader::getFuncSampleData(const std::vector<StringRef> &FuncNames) {
return fetchMapEntry<FuncsToSamplesMapTy>(FuncsToSamples, FuncNames);
}
std::vector<FuncBranchData *>
DataReader::getFuncBranchDataRegex(const std::vector<std::string> &FuncNames) {
DataReader::getFuncBranchDataRegex(const std::vector<StringRef> &FuncNames) {
return fetchMapEntriesRegex(FuncsToBranches, LTOCommonNameMap, FuncNames);
}
std::vector<FuncMemData *>
DataReader::getFuncMemDataRegex(const std::vector<std::string> &FuncNames) {
DataReader::getFuncMemDataRegex(const std::vector<StringRef> &FuncNames) {
return fetchMapEntriesRegex(FuncsToMemEvents, LTOCommonNameMemMap, FuncNames);
}

View File

@ -360,28 +360,28 @@ public:
/// Return branch data matching one of the names in \p FuncNames.
FuncBranchData *
getFuncBranchData(const std::vector<std::string> &FuncNames);
getFuncBranchData(const std::vector<StringRef> &FuncNames);
/// Return branch data matching one of the \p Symbols.
FuncBranchData *getFuncBranchData(const std::vector<MCSymbol *> &Symbols);
/// Return mem data matching one of the names in \p FuncNames.
FuncMemData *getFuncMemData(const std::vector<std::string> &FuncNames);
FuncMemData *getFuncMemData(const std::vector<StringRef> &FuncNames);
FuncSampleData *
getFuncSampleData(const std::vector<std::string> &FuncNames);
getFuncSampleData(const std::vector<StringRef> &FuncNames);
/// Return a vector of all FuncBranchData matching the list of names.
/// Internally use fuzzy matching to match special names like LTO-generated
/// function names.
std::vector<FuncBranchData *>
getFuncBranchDataRegex(const std::vector<std::string> &FuncNames);
getFuncBranchDataRegex(const std::vector<StringRef> &FuncNames);
/// Return a vector of all FuncMemData matching the list of names.
/// Internally use fuzzy matching to match special names like LTO-generated
/// function names.
std::vector<FuncMemData *>
getFuncMemDataRegex(const std::vector<std::string> &FuncNames);
getFuncMemDataRegex(const std::vector<StringRef> &FuncNames);
using FuncsToBranchesMapTy = StringMap<FuncBranchData>;
using FuncsToSamplesMapTy = StringMap<FuncSampleData>;

View File

@ -495,7 +495,7 @@ IndirectCallPromotion::maybeGetHotJumpTableTargets(
if (MI.Addr.IsSymbol) {
// Deal with bad/stale data
if (!MI.Addr.Name.startswith("JUMP_TABLE/" + Function.getNames().front()))
if (!MI.Addr.Name.startswith("JUMP_TABLE/" + Function.getOneName().str()))
return JumpTableInfoType();
Index = (MI.Addr.Offset - (ArrayStart - JT->getAddress())) / JT->EntrySize;
} else {

View File

@ -75,7 +75,7 @@ uint32_t Instrumentation::getFunctionNameIndex(const BinaryFunction &Function) {
return Iter->second;
auto Idx = StringTable.size();
FuncToStringIdx.emplace(std::make_pair(&Function, Idx));
StringTable.append(Function.getNames()[0]);
StringTable.append(Function.getOneName());
StringTable.append(1, '\0');
return Idx;
}

View File

@ -223,10 +223,10 @@ void ReorderFunctions::reorder(std::vector<Cluster> &&Clusters,
TotalSize += Cg.size(FuncId);
if (PrintDetailed) {
outs() << format("BOLT-INFO: start = %6u : avgCallDist = %lu : %s\n",
outs() << format("BOLT-INFO: start = %6u : avgCallDist = %lu : ",
TotalSize,
Calls ? Dist / Calls : 0,
Cg.nodeIdToFunc(FuncId)->getPrintName().c_str());
Calls ? Dist / Calls : 0)
<< Cg.nodeIdToFunc(FuncId)->getPrintName() << '\n';
const auto NewPage = TotalSize / HugePageSize;
if (NewPage != CurPage) {
CurPage = NewPage;
@ -457,11 +457,13 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) {
continue;
if (FuncsFile)
*FuncsFile << Func->getSymbol()->getName().data() << "\n";
*FuncsFile << Func->getOneName().data() << "\n";
if (LinkSectionsFile) {
const char *Indent = "";
for (auto Name : Func->getNames()) {
auto AllNames = Func->getNames();
std::sort(AllNames.begin(), AllNames.end());
for (auto Name : AllNames) {
const auto SlashPos = Name.find('/');
if (SlashPos != std::string::npos) {
// Avoid duplicates for local functions.
@ -469,7 +471,7 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) {
continue;
Name = Name.substr(0, SlashPos);
}
*LinkSectionsFile << Indent << ".text." << Name << "\n";
*LinkSectionsFile << Indent << ".text." << Name.data() << "\n";
Indent = " ";
}
}

View File

@ -52,7 +52,7 @@ void VeneerElimination::runOnFunctions(BinaryContext &BC) {
BC.MIB->getTargetSymbol(FirstInstruction, 1);
// Functions can have multiple symbols
for (auto &Name : VeneerFunction.getNames()) {
for (auto Name : VeneerFunction.getNames()) {
auto *Symbol = BC.Ctx->lookupSymbol(Name);
VeneerDestinations[Symbol] = VeneerTargetSymbol;
BC.SymbolToFunctionMap.erase(Symbol);

View File

@ -50,7 +50,7 @@ ProfileReader::buildNameMaps(std::map<uint64_t, BinaryFunction> &Functions) {
}
for (auto &BFI : Functions) {
const auto &Function = BFI.second;
for (auto &Name : Function.getNames()) {
for (auto Name : Function.getNames()) {
if (const auto CommonName = getLTOCommonName(Name)) {
LTOCommonNameFunctionMap[*CommonName].insert(&Function);
}
@ -284,7 +284,7 @@ ProfileReader::readProfile(const std::string &FileName,
if (!opts::IgnoreHash)
Function.hash(/*Recompute = */true, true);
for (auto &FunctionName : Function.getNames()) {
for (auto FunctionName : Function.getNames()) {
auto PI = ProfileNameToProfile.find(FunctionName);
if (PI == ProfileNameToProfile.end()) {
continue;
@ -301,7 +301,7 @@ ProfileReader::readProfile(const std::string &FileName,
if (ProfiledFunctions.count(&Function))
continue;
for (auto &FunctionName : Function.getNames()) {
for (auto FunctionName : Function.getNames()) {
const auto CommonName = getLTOCommonName(FunctionName);
if (CommonName) {
auto I = LTOCommonNameMap.find(*CommonName);

View File

@ -942,7 +942,6 @@ void RewriteInstance::discoverFileObjects() {
BC->getBinaryFunctions().clear();
BC->clearBinaryData();
// For local symbols we want to keep track of associated FILE symbol name for
// disambiguation by combined name.
StringRef FileSymbolName;
@ -1507,7 +1506,7 @@ void RewriteInstance::adjustFunctionBoundaries() {
NextFunction = &std::next(BFI)->second;
// Check if it's a fragment of a function.
const auto *FragName = Function.hasNameRegex(".*\\.cold\\..*");
auto FragName = Function.hasNameRegex(".*\\.cold\\..*");
if (!FragName)
FragName = Function.hasNameRegex(".*\\.cold");
if (FragName) {
@ -2646,14 +2645,16 @@ bool RewriteInstance::emitFunction(MCStreamer &Streamer,
MCContext &Context = Streamer.getContext();
const MCAsmInfo *MAI = Context.getAsmInfo();
// Emit all names the function is known under.
for (const auto &Name : Function.getNames()) {
Twine EmitName = EmitColdPart ? Twine(Name).concat(".cold") : Name;
auto *EmitSymbol = BC->Ctx->getOrCreateSymbol(EmitName);
Streamer.EmitSymbolAttribute(EmitSymbol, MCSA_ELF_TypeFunction);
DEBUG(dbgs() << "emitting symbol " << EmitSymbol->getName()
<< " for function " << Function << '\n');
Streamer.EmitLabel(EmitSymbol);
// Emit all symbols associated with the main function entry.
if (!EmitColdPart) {
for (auto *Symbol : Function.getSymbols()) {
Streamer.EmitSymbolAttribute(Symbol, MCSA_ELF_TypeFunction);
Streamer.EmitLabel(Symbol);
}
} else {
auto *Symbol = Function.getColdSymbol();
Streamer.EmitSymbolAttribute(Symbol, MCSA_ELF_TypeFunction);
Streamer.EmitLabel(Symbol);
}
// Emit CFI start
@ -3973,7 +3974,7 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
Elf_Sym NewSymbol;
NewSymbol.st_shndx = Function->getCodeSection()->getIndex();
NewSymbol.st_value = Function->getOutputAddress();
NewSymbol.st_name = AddToStrTab(Function->getPrintName());
NewSymbol.st_name = AddToStrTab(Function->getOneName());
NewSymbol.st_size = Function->getOutputSize();
NewSymbol.st_other = 0;
NewSymbol.setBindingAndType(ELF::STB_LOCAL, ELF::STT_FUNC);