xref: /freebsd-src/contrib/llvm-project/llvm/lib/Object/RecordStreamer.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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