1276989f5SEric Christopher //===-- RecordStreamer.cpp - Record asm defined and used symbols ----------===//
213b69d63SRafael Espindola //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
613b69d63SRafael Espindola //
713b69d63SRafael Espindola //===----------------------------------------------------------------------===//
813b69d63SRafael Espindola
9ba79dba8SRafael Espindola #include "RecordStreamer.h"
100d03881eSVitaly Buka #include "llvm/IR/Mangler.h"
110d03881eSVitaly Buka #include "llvm/IR/Module.h"
1247b4d6baSRafael Espindola #include "llvm/MC/MCContext.h"
1313b69d63SRafael Espindola #include "llvm/MC/MCSymbol.h"
141df42facSEugene Zelenko
1513b69d63SRafael Espindola using namespace llvm;
1613b69d63SRafael Espindola
markDefined(const MCSymbol & Symbol)1713b69d63SRafael Espindola void RecordStreamer::markDefined(const MCSymbol &Symbol) {
1813b69d63SRafael Espindola State &S = Symbols[Symbol.getName()];
1913b69d63SRafael Espindola switch (S) {
2013b69d63SRafael Espindola case DefinedGlobal:
2113b69d63SRafael Espindola case Global:
2213b69d63SRafael Espindola S = DefinedGlobal;
2313b69d63SRafael Espindola break;
2413b69d63SRafael Espindola case NeverSeen:
2513b69d63SRafael Espindola case Defined:
2613b69d63SRafael Espindola case Used:
2713b69d63SRafael Espindola S = Defined;
2813b69d63SRafael Espindola break;
29f7518498SDavide Italiano case DefinedWeak:
30ec7e29e9SDavide Italiano break;
31f7518498SDavide Italiano case UndefinedWeak:
32f7518498SDavide Italiano S = DefinedWeak;
3313b69d63SRafael Espindola }
3413b69d63SRafael Espindola }
3513b69d63SRafael Espindola
markGlobal(const MCSymbol & Symbol,MCSymbolAttr Attribute)36ec7e29e9SDavide Italiano void RecordStreamer::markGlobal(const MCSymbol &Symbol,
37ec7e29e9SDavide Italiano MCSymbolAttr Attribute) {
3813b69d63SRafael Espindola State &S = Symbols[Symbol.getName()];
3913b69d63SRafael Espindola switch (S) {
4013b69d63SRafael Espindola case DefinedGlobal:
4113b69d63SRafael Espindola case Defined:
42f7518498SDavide Italiano S = (Attribute == MCSA_Weak) ? DefinedWeak : DefinedGlobal;
4313b69d63SRafael Espindola break;
4413b69d63SRafael Espindola
4513b69d63SRafael Espindola case NeverSeen:
4613b69d63SRafael Espindola case Global:
4713b69d63SRafael Espindola case Used:
48f7518498SDavide Italiano S = (Attribute == MCSA_Weak) ? UndefinedWeak : Global;
49ec7e29e9SDavide Italiano break;
50f7518498SDavide Italiano case UndefinedWeak:
51f7518498SDavide Italiano case DefinedWeak:
5213b69d63SRafael Espindola break;
5313b69d63SRafael Espindola }
5413b69d63SRafael Espindola }
5513b69d63SRafael Espindola
markUsed(const MCSymbol & Symbol)5613b69d63SRafael Espindola void RecordStreamer::markUsed(const MCSymbol &Symbol) {
5713b69d63SRafael Espindola State &S = Symbols[Symbol.getName()];
5813b69d63SRafael Espindola switch (S) {
5913b69d63SRafael Espindola case DefinedGlobal:
6013b69d63SRafael Espindola case Defined:
6113b69d63SRafael Espindola case Global:
62f7518498SDavide Italiano case DefinedWeak:
63f7518498SDavide Italiano case UndefinedWeak:
6413b69d63SRafael Espindola break;
6513b69d63SRafael Espindola
6613b69d63SRafael Espindola case NeverSeen:
6713b69d63SRafael Espindola case Used:
6813b69d63SRafael Espindola S = Used;
6913b69d63SRafael Espindola break;
7013b69d63SRafael Espindola }
7113b69d63SRafael Espindola }
7213b69d63SRafael Espindola
visitUsedSymbol(const MCSymbol & Sym)7313b69d63SRafael Espindola void RecordStreamer::visitUsedSymbol(const MCSymbol &Sym) { markUsed(Sym); }
7413b69d63SRafael Espindola
RecordStreamer(MCContext & Context,const Module & M)750d03881eSVitaly Buka RecordStreamer::RecordStreamer(MCContext &Context, const Module &M)
760d03881eSVitaly Buka : MCStreamer(Context), M(M) {}
771df42facSEugene Zelenko
begin()7813b69d63SRafael Espindola RecordStreamer::const_iterator RecordStreamer::begin() {
7913b69d63SRafael Espindola return Symbols.begin();
8013b69d63SRafael Espindola }
8113b69d63SRafael Espindola
end()8213b69d63SRafael Espindola RecordStreamer::const_iterator RecordStreamer::end() { return Symbols.end(); }
8313b69d63SRafael Espindola
emitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)84bcd24b2dSFangrui Song void RecordStreamer::emitInstruction(const MCInst &Inst,
85edbf06a7SAndrea Di Biagio const MCSubtargetInfo &STI) {
86bcd24b2dSFangrui Song MCStreamer::emitInstruction(Inst, STI);
8713b69d63SRafael Espindola }
8813b69d63SRafael Espindola
emitLabel(MCSymbol * Symbol,SMLoc Loc)896d2d589bSFangrui Song void RecordStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
906d2d589bSFangrui Song MCStreamer::emitLabel(Symbol);
9113b69d63SRafael Espindola markDefined(*Symbol);
9213b69d63SRafael Espindola }
9313b69d63SRafael Espindola
emitAssignment(MCSymbol * Symbol,const MCExpr * Value)94a55daa14SFangrui Song void RecordStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
9513b69d63SRafael Espindola markDefined(*Symbol);
96a55daa14SFangrui Song MCStreamer::emitAssignment(Symbol, Value);
9713b69d63SRafael Espindola }
9813b69d63SRafael Espindola
emitSymbolAttribute(MCSymbol * Symbol,MCSymbolAttr Attribute)99a55daa14SFangrui Song bool RecordStreamer::emitSymbolAttribute(MCSymbol *Symbol,
100395c8bedSFangrui Song MCSymbolAttr Attribute) {
10116bfa13aSDavide Italiano if (Attribute == MCSA_Global || Attribute == MCSA_Weak)
102ec7e29e9SDavide Italiano markGlobal(*Symbol, Attribute);
103f9721ba5SMehdi Amini if (Attribute == MCSA_LazyReference)
104f9721ba5SMehdi Amini markUsed(*Symbol);
10513b69d63SRafael Espindola return true;
10613b69d63SRafael Espindola }
10713b69d63SRafael Espindola
emitZerofill(MCSection * Section,MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment,SMLoc Loc)108a55daa14SFangrui Song void RecordStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
1094d5b1073SFrancis Visoiu Mistrih uint64_t Size, unsigned ByteAlignment,
1104d5b1073SFrancis Visoiu Mistrih SMLoc Loc) {
11113b69d63SRafael Espindola markDefined(*Symbol);
11213b69d63SRafael Espindola }
11313b69d63SRafael Espindola
emitCommonSymbol(MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment)114a55daa14SFangrui Song void RecordStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
11513b69d63SRafael Espindola unsigned ByteAlignment) {
11613b69d63SRafael Espindola markDefined(*Symbol);
11713b69d63SRafael Espindola }
118d8204472STeresa Johnson
getSymbolState(const MCSymbol * Sym)1190d03881eSVitaly Buka RecordStreamer::State RecordStreamer::getSymbolState(const MCSymbol *Sym) {
1200d03881eSVitaly Buka auto SI = Symbols.find(Sym->getName());
1210d03881eSVitaly Buka if (SI == Symbols.end())
1220d03881eSVitaly Buka return NeverSeen;
1230d03881eSVitaly Buka return SI->second;
1240d03881eSVitaly Buka }
1250d03881eSVitaly Buka
emitELFSymverDirective(const MCSymbol * OriginalSym,StringRef Name,bool KeepOriginalSym)126*d96af2edSFangrui Song void RecordStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
127*d96af2edSFangrui Song StringRef Name,
128*d96af2edSFangrui Song bool KeepOriginalSym) {
129*d96af2edSFangrui Song SymverAliasMap[OriginalSym].push_back(Name);
1300d03881eSVitaly Buka }
1310d03881eSVitaly Buka
132230b2567SVlad Tsyrklevich iterator_range<RecordStreamer::const_symver_iterator>
symverAliases()133230b2567SVlad Tsyrklevich RecordStreamer::symverAliases() {
134230b2567SVlad Tsyrklevich return {SymverAliasMap.begin(), SymverAliasMap.end()};
135230b2567SVlad Tsyrklevich }
136230b2567SVlad Tsyrklevich
flushSymverDirectives()1370d03881eSVitaly Buka void RecordStreamer::flushSymverDirectives() {
1380d03881eSVitaly Buka // Mapping from mangled name to GV.
1390d03881eSVitaly Buka StringMap<const GlobalValue *> MangledNameMap;
1400d03881eSVitaly Buka // The name in the assembler will be mangled, but the name in the IR
1410d03881eSVitaly Buka // might not, so we first compute a mapping from mangled name to GV.
1420d03881eSVitaly Buka Mangler Mang;
1430d03881eSVitaly Buka SmallString<64> MangledName;
1440d03881eSVitaly Buka for (const GlobalValue &GV : M.global_values()) {
1450d03881eSVitaly Buka if (!GV.hasName())
1460d03881eSVitaly Buka continue;
1470d03881eSVitaly Buka MangledName.clear();
1480d03881eSVitaly Buka MangledName.reserve(GV.getName().size() + 1);
1490d03881eSVitaly Buka Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false);
1500d03881eSVitaly Buka MangledNameMap[MangledName] = &GV;
1510d03881eSVitaly Buka }
1520d03881eSVitaly Buka
1530d03881eSVitaly Buka // Walk all the recorded .symver aliases, and set up the binding
1540d03881eSVitaly Buka // for each alias.
1550d03881eSVitaly Buka for (auto &Symver : SymverAliasMap) {
1560d03881eSVitaly Buka const MCSymbol *Aliasee = Symver.first;
1570d03881eSVitaly Buka MCSymbolAttr Attr = MCSA_Invalid;
158849217abSVitaly Buka bool IsDefined = false;
1590d03881eSVitaly Buka
1600d03881eSVitaly Buka // First check if the aliasee binding was recorded in the asm.
1610d03881eSVitaly Buka RecordStreamer::State state = getSymbolState(Aliasee);
1620d03881eSVitaly Buka switch (state) {
1630d03881eSVitaly Buka case RecordStreamer::Global:
1640d03881eSVitaly Buka case RecordStreamer::DefinedGlobal:
1650d03881eSVitaly Buka Attr = MCSA_Global;
1660d03881eSVitaly Buka break;
1670d03881eSVitaly Buka case RecordStreamer::UndefinedWeak:
1680d03881eSVitaly Buka case RecordStreamer::DefinedWeak:
1690d03881eSVitaly Buka Attr = MCSA_Weak;
1700d03881eSVitaly Buka break;
1710d03881eSVitaly Buka default:
1720d03881eSVitaly Buka break;
1730d03881eSVitaly Buka }
1740d03881eSVitaly Buka
175849217abSVitaly Buka switch (state) {
176849217abSVitaly Buka case RecordStreamer::Defined:
177849217abSVitaly Buka case RecordStreamer::DefinedGlobal:
178849217abSVitaly Buka case RecordStreamer::DefinedWeak:
179849217abSVitaly Buka IsDefined = true;
180849217abSVitaly Buka break;
181849217abSVitaly Buka case RecordStreamer::NeverSeen:
182849217abSVitaly Buka case RecordStreamer::Global:
183849217abSVitaly Buka case RecordStreamer::Used:
184849217abSVitaly Buka case RecordStreamer::UndefinedWeak:
185849217abSVitaly Buka break;
186849217abSVitaly Buka }
187849217abSVitaly Buka
188849217abSVitaly Buka if (Attr == MCSA_Invalid || !IsDefined) {
189849217abSVitaly Buka const GlobalValue *GV = M.getNamedValue(Aliasee->getName());
1900d03881eSVitaly Buka if (!GV) {
1910d03881eSVitaly Buka auto MI = MangledNameMap.find(Aliasee->getName());
1920d03881eSVitaly Buka if (MI != MangledNameMap.end())
1930d03881eSVitaly Buka GV = MI->second;
1940d03881eSVitaly Buka }
1950d03881eSVitaly Buka if (GV) {
196849217abSVitaly Buka // If we don't have a symbol attribute from assembly, then check if
197849217abSVitaly Buka // the aliasee was defined in the IR.
198849217abSVitaly Buka if (Attr == MCSA_Invalid) {
1990d03881eSVitaly Buka if (GV->hasExternalLinkage())
2000d03881eSVitaly Buka Attr = MCSA_Global;
2010d03881eSVitaly Buka else if (GV->hasLocalLinkage())
2020d03881eSVitaly Buka Attr = MCSA_Local;
2030d03881eSVitaly Buka else if (GV->isWeakForLinker())
2040d03881eSVitaly Buka Attr = MCSA_Weak;
2050d03881eSVitaly Buka }
206849217abSVitaly Buka IsDefined = IsDefined || !GV->isDeclarationForLinker();
2070d03881eSVitaly Buka }
208849217abSVitaly Buka }
209849217abSVitaly Buka
2100d03881eSVitaly Buka // Set the detected binding on each alias with this aliasee.
2110d03881eSVitaly Buka for (auto AliasName : Symver.second) {
212849217abSVitaly Buka std::pair<StringRef, StringRef> Split = AliasName.split("@@@");
213849217abSVitaly Buka SmallString<128> NewName;
214849217abSVitaly Buka if (!Split.second.empty() && !Split.second.startswith("@")) {
215849217abSVitaly Buka // Special processing for "@@@" according
216849217abSVitaly Buka // https://sourceware.org/binutils/docs/as/Symver.html
217849217abSVitaly Buka const char *Separator = IsDefined ? "@@" : "@";
218849217abSVitaly Buka AliasName =
219849217abSVitaly Buka (Split.first + Separator + Split.second).toStringRef(NewName);
220849217abSVitaly Buka }
22147b4d6baSRafael Espindola MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
2220d03881eSVitaly Buka // TODO: Handle "@@@". Depending on SymbolAttribute value it needs to be
2230d03881eSVitaly Buka // converted into @ or @@.
22481e911cdSRafael Espindola const MCExpr *Value = MCSymbolRefExpr::create(Aliasee, getContext());
2256c05a3bbSVitaly Buka if (IsDefined)
2266c05a3bbSVitaly Buka markDefined(*Alias);
2276c05a3bbSVitaly Buka // Don't use EmitAssignment override as it always marks alias as defined.
228a55daa14SFangrui Song MCStreamer::emitAssignment(Alias, Value);
2290d03881eSVitaly Buka if (Attr != MCSA_Invalid)
230395c8bedSFangrui Song emitSymbolAttribute(Alias, Attr);
2310d03881eSVitaly Buka }
2320d03881eSVitaly Buka }
233d8204472STeresa Johnson }
234