10b57cec5SDimitry Andric //===-- RecordStreamer.cpp - Record asm defined and used symbols ----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "RecordStreamer.h"
100b57cec5SDimitry Andric #include "llvm/IR/Mangler.h"
110b57cec5SDimitry Andric #include "llvm/IR/Module.h"
120b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric using namespace llvm;
160b57cec5SDimitry Andric
markDefined(const MCSymbol & Symbol)170b57cec5SDimitry Andric void RecordStreamer::markDefined(const MCSymbol &Symbol) {
180b57cec5SDimitry Andric State &S = Symbols[Symbol.getName()];
190b57cec5SDimitry Andric switch (S) {
200b57cec5SDimitry Andric case DefinedGlobal:
210b57cec5SDimitry Andric case Global:
220b57cec5SDimitry Andric S = DefinedGlobal;
230b57cec5SDimitry Andric break;
240b57cec5SDimitry Andric case NeverSeen:
250b57cec5SDimitry Andric case Defined:
260b57cec5SDimitry Andric case Used:
270b57cec5SDimitry Andric S = Defined;
280b57cec5SDimitry Andric break;
290b57cec5SDimitry Andric case DefinedWeak:
300b57cec5SDimitry Andric break;
310b57cec5SDimitry Andric case UndefinedWeak:
320b57cec5SDimitry Andric S = DefinedWeak;
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric
markGlobal(const MCSymbol & Symbol,MCSymbolAttr Attribute)360b57cec5SDimitry Andric void RecordStreamer::markGlobal(const MCSymbol &Symbol,
370b57cec5SDimitry Andric MCSymbolAttr Attribute) {
380b57cec5SDimitry Andric State &S = Symbols[Symbol.getName()];
390b57cec5SDimitry Andric switch (S) {
400b57cec5SDimitry Andric case DefinedGlobal:
410b57cec5SDimitry Andric case Defined:
420b57cec5SDimitry Andric S = (Attribute == MCSA_Weak) ? DefinedWeak : DefinedGlobal;
430b57cec5SDimitry Andric break;
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric case NeverSeen:
460b57cec5SDimitry Andric case Global:
470b57cec5SDimitry Andric case Used:
480b57cec5SDimitry Andric S = (Attribute == MCSA_Weak) ? UndefinedWeak : Global;
490b57cec5SDimitry Andric break;
500b57cec5SDimitry Andric case UndefinedWeak:
510b57cec5SDimitry Andric case DefinedWeak:
520b57cec5SDimitry Andric break;
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric
markUsed(const MCSymbol & Symbol)560b57cec5SDimitry Andric void RecordStreamer::markUsed(const MCSymbol &Symbol) {
570b57cec5SDimitry Andric State &S = Symbols[Symbol.getName()];
580b57cec5SDimitry Andric switch (S) {
590b57cec5SDimitry Andric case DefinedGlobal:
600b57cec5SDimitry Andric case Defined:
610b57cec5SDimitry Andric case Global:
620b57cec5SDimitry Andric case DefinedWeak:
630b57cec5SDimitry Andric case UndefinedWeak:
640b57cec5SDimitry Andric break;
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric case NeverSeen:
670b57cec5SDimitry Andric case Used:
680b57cec5SDimitry Andric S = Used;
690b57cec5SDimitry Andric break;
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric
visitUsedSymbol(const MCSymbol & Sym)730b57cec5SDimitry Andric void RecordStreamer::visitUsedSymbol(const MCSymbol &Sym) { markUsed(Sym); }
740b57cec5SDimitry Andric
RecordStreamer(MCContext & Context,const Module & M)750b57cec5SDimitry Andric RecordStreamer::RecordStreamer(MCContext &Context, const Module &M)
760b57cec5SDimitry Andric : MCStreamer(Context), M(M) {}
770b57cec5SDimitry Andric
begin()780b57cec5SDimitry Andric RecordStreamer::const_iterator RecordStreamer::begin() {
790b57cec5SDimitry Andric return Symbols.begin();
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric
end()820b57cec5SDimitry Andric RecordStreamer::const_iterator RecordStreamer::end() { return Symbols.end(); }
830b57cec5SDimitry Andric
emitLabel(MCSymbol * Symbol,SMLoc Loc)845ffd83dbSDimitry Andric void RecordStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
855ffd83dbSDimitry Andric MCStreamer::emitLabel(Symbol);
860b57cec5SDimitry Andric markDefined(*Symbol);
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric
emitAssignment(MCSymbol * Symbol,const MCExpr * Value)895ffd83dbSDimitry Andric void RecordStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
900b57cec5SDimitry Andric markDefined(*Symbol);
915ffd83dbSDimitry Andric MCStreamer::emitAssignment(Symbol, Value);
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric
emitSymbolAttribute(MCSymbol * Symbol,MCSymbolAttr Attribute)945ffd83dbSDimitry Andric bool RecordStreamer::emitSymbolAttribute(MCSymbol *Symbol,
950b57cec5SDimitry Andric MCSymbolAttr Attribute) {
960b57cec5SDimitry Andric if (Attribute == MCSA_Global || Attribute == MCSA_Weak)
970b57cec5SDimitry Andric markGlobal(*Symbol, Attribute);
980b57cec5SDimitry Andric if (Attribute == MCSA_LazyReference)
990b57cec5SDimitry Andric markUsed(*Symbol);
1000b57cec5SDimitry Andric return true;
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric
emitZerofill(MCSection * Section,MCSymbol * Symbol,uint64_t Size,Align ByteAlignment,SMLoc Loc)1035ffd83dbSDimitry Andric void RecordStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
104bdd1243dSDimitry Andric uint64_t Size, Align ByteAlignment,
1050b57cec5SDimitry Andric SMLoc Loc) {
1060b57cec5SDimitry Andric markDefined(*Symbol);
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric
emitCommonSymbol(MCSymbol * Symbol,uint64_t Size,Align ByteAlignment)1095ffd83dbSDimitry Andric void RecordStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
110bdd1243dSDimitry Andric Align ByteAlignment) {
1110b57cec5SDimitry Andric markDefined(*Symbol);
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric
getSymbolState(const MCSymbol * Sym)1140b57cec5SDimitry Andric RecordStreamer::State RecordStreamer::getSymbolState(const MCSymbol *Sym) {
1150b57cec5SDimitry Andric auto SI = Symbols.find(Sym->getName());
1160b57cec5SDimitry Andric if (SI == Symbols.end())
1170b57cec5SDimitry Andric return NeverSeen;
1180b57cec5SDimitry Andric return SI->second;
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric
emitELFSymverDirective(const MCSymbol * OriginalSym,StringRef Name,bool KeepOriginalSym)121fe6060f1SDimitry Andric void RecordStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
122fe6060f1SDimitry Andric StringRef Name,
123fe6060f1SDimitry Andric bool KeepOriginalSym) {
124fe6060f1SDimitry Andric SymverAliasMap[OriginalSym].push_back(Name);
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric iterator_range<RecordStreamer::const_symver_iterator>
symverAliases()1280b57cec5SDimitry Andric RecordStreamer::symverAliases() {
1290b57cec5SDimitry Andric return {SymverAliasMap.begin(), SymverAliasMap.end()};
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric
flushSymverDirectives()1320b57cec5SDimitry Andric void RecordStreamer::flushSymverDirectives() {
1330b57cec5SDimitry Andric // Mapping from mangled name to GV.
1340b57cec5SDimitry Andric StringMap<const GlobalValue *> MangledNameMap;
1350b57cec5SDimitry Andric // The name in the assembler will be mangled, but the name in the IR
1360b57cec5SDimitry Andric // might not, so we first compute a mapping from mangled name to GV.
1370b57cec5SDimitry Andric Mangler Mang;
1380b57cec5SDimitry Andric SmallString<64> MangledName;
1390b57cec5SDimitry Andric for (const GlobalValue &GV : M.global_values()) {
1400b57cec5SDimitry Andric if (!GV.hasName())
1410b57cec5SDimitry Andric continue;
1420b57cec5SDimitry Andric MangledName.clear();
1430b57cec5SDimitry Andric MangledName.reserve(GV.getName().size() + 1);
1440b57cec5SDimitry Andric Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false);
1450b57cec5SDimitry Andric MangledNameMap[MangledName] = &GV;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric
1480b57cec5SDimitry Andric // Walk all the recorded .symver aliases, and set up the binding
1490b57cec5SDimitry Andric // for each alias.
1500b57cec5SDimitry Andric for (auto &Symver : SymverAliasMap) {
1510b57cec5SDimitry Andric const MCSymbol *Aliasee = Symver.first;
1520b57cec5SDimitry Andric MCSymbolAttr Attr = MCSA_Invalid;
1530b57cec5SDimitry Andric bool IsDefined = false;
1540b57cec5SDimitry Andric
1550b57cec5SDimitry Andric // First check if the aliasee binding was recorded in the asm.
1560b57cec5SDimitry Andric RecordStreamer::State state = getSymbolState(Aliasee);
1570b57cec5SDimitry Andric switch (state) {
1580b57cec5SDimitry Andric case RecordStreamer::Global:
1590b57cec5SDimitry Andric case RecordStreamer::DefinedGlobal:
1600b57cec5SDimitry Andric Attr = MCSA_Global;
1610b57cec5SDimitry Andric break;
1620b57cec5SDimitry Andric case RecordStreamer::UndefinedWeak:
1630b57cec5SDimitry Andric case RecordStreamer::DefinedWeak:
1640b57cec5SDimitry Andric Attr = MCSA_Weak;
1650b57cec5SDimitry Andric break;
1660b57cec5SDimitry Andric default:
1670b57cec5SDimitry Andric break;
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric
1700b57cec5SDimitry Andric switch (state) {
1710b57cec5SDimitry Andric case RecordStreamer::Defined:
1720b57cec5SDimitry Andric case RecordStreamer::DefinedGlobal:
1730b57cec5SDimitry Andric case RecordStreamer::DefinedWeak:
1740b57cec5SDimitry Andric IsDefined = true;
1750b57cec5SDimitry Andric break;
1760b57cec5SDimitry Andric case RecordStreamer::NeverSeen:
1770b57cec5SDimitry Andric case RecordStreamer::Global:
1780b57cec5SDimitry Andric case RecordStreamer::Used:
1790b57cec5SDimitry Andric case RecordStreamer::UndefinedWeak:
1800b57cec5SDimitry Andric break;
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric
1830b57cec5SDimitry Andric if (Attr == MCSA_Invalid || !IsDefined) {
1840b57cec5SDimitry Andric const GlobalValue *GV = M.getNamedValue(Aliasee->getName());
1850b57cec5SDimitry Andric if (!GV) {
1860b57cec5SDimitry Andric auto MI = MangledNameMap.find(Aliasee->getName());
1870b57cec5SDimitry Andric if (MI != MangledNameMap.end())
1880b57cec5SDimitry Andric GV = MI->second;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric if (GV) {
1910b57cec5SDimitry Andric // If we don't have a symbol attribute from assembly, then check if
1920b57cec5SDimitry Andric // the aliasee was defined in the IR.
1930b57cec5SDimitry Andric if (Attr == MCSA_Invalid) {
1940b57cec5SDimitry Andric if (GV->hasExternalLinkage())
1950b57cec5SDimitry Andric Attr = MCSA_Global;
1960b57cec5SDimitry Andric else if (GV->hasLocalLinkage())
1970b57cec5SDimitry Andric Attr = MCSA_Local;
1980b57cec5SDimitry Andric else if (GV->isWeakForLinker())
1990b57cec5SDimitry Andric Attr = MCSA_Weak;
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric IsDefined = IsDefined || !GV->isDeclarationForLinker();
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric // Set the detected binding on each alias with this aliasee.
2060b57cec5SDimitry Andric for (auto AliasName : Symver.second) {
2070b57cec5SDimitry Andric std::pair<StringRef, StringRef> Split = AliasName.split("@@@");
2080b57cec5SDimitry Andric SmallString<128> NewName;
209*5f757f3fSDimitry Andric if (!Split.second.empty() && !Split.second.starts_with("@")) {
2100b57cec5SDimitry Andric // Special processing for "@@@" according
2110b57cec5SDimitry Andric // https://sourceware.org/binutils/docs/as/Symver.html
2120b57cec5SDimitry Andric const char *Separator = IsDefined ? "@@" : "@";
2130b57cec5SDimitry Andric AliasName =
2140b57cec5SDimitry Andric (Split.first + Separator + Split.second).toStringRef(NewName);
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
2170b57cec5SDimitry Andric // TODO: Handle "@@@". Depending on SymbolAttribute value it needs to be
2180b57cec5SDimitry Andric // converted into @ or @@.
2190b57cec5SDimitry Andric const MCExpr *Value = MCSymbolRefExpr::create(Aliasee, getContext());
2200b57cec5SDimitry Andric if (IsDefined)
2210b57cec5SDimitry Andric markDefined(*Alias);
2220b57cec5SDimitry Andric // Don't use EmitAssignment override as it always marks alias as defined.
2235ffd83dbSDimitry Andric MCStreamer::emitAssignment(Alias, Value);
2240b57cec5SDimitry Andric if (Attr != MCSA_Invalid)
2255ffd83dbSDimitry Andric emitSymbolAttribute(Alias, Attr);
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric }
229