xref: /freebsd/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp (revision 5916ae1fb14a28c69818f16ed2903248e08d50b3)
1  //===- ModuleSymbolTable.cpp - symbol table for in-memory IR --------------===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // This class represents a symbol table built from in-memory IR. It provides
10  // access to GlobalValues and should only be used if such access is required
11  // (e.g. in the LTO implementation).
12  //
13  //===----------------------------------------------------------------------===//
14  
15  #include "llvm/Object/ModuleSymbolTable.h"
16  #include "RecordStreamer.h"
17  #include "llvm/ADT/STLExtras.h"
18  #include "llvm/ADT/SmallString.h"
19  #include "llvm/ADT/StringMap.h"
20  #include "llvm/ADT/StringRef.h"
21  #include "llvm/ADT/Triple.h"
22  #include "llvm/IR/Function.h"
23  #include "llvm/IR/GlobalAlias.h"
24  #include "llvm/IR/GlobalValue.h"
25  #include "llvm/IR/GlobalVariable.h"
26  #include "llvm/IR/InlineAsm.h"
27  #include "llvm/IR/Module.h"
28  #include "llvm/MC/MCAsmInfo.h"
29  #include "llvm/MC/MCContext.h"
30  #include "llvm/MC/MCDirectives.h"
31  #include "llvm/MC/MCInstrInfo.h"
32  #include "llvm/MC/MCObjectFileInfo.h"
33  #include "llvm/MC/MCParser/MCAsmParser.h"
34  #include "llvm/MC/MCParser/MCTargetAsmParser.h"
35  #include "llvm/MC/MCRegisterInfo.h"
36  #include "llvm/MC/MCSubtargetInfo.h"
37  #include "llvm/MC/MCSymbol.h"
38  #include "llvm/MC/MCTargetOptions.h"
39  #include "llvm/Object/SymbolicFile.h"
40  #include "llvm/Support/Casting.h"
41  #include "llvm/Support/CodeGen.h"
42  #include "llvm/Support/ErrorHandling.h"
43  #include "llvm/Support/MemoryBuffer.h"
44  #include "llvm/Support/SMLoc.h"
45  #include "llvm/Support/SourceMgr.h"
46  #include "llvm/Support/TargetRegistry.h"
47  #include "llvm/Support/raw_ostream.h"
48  #include <algorithm>
49  #include <cassert>
50  #include <cstdint>
51  #include <memory>
52  #include <string>
53  
54  using namespace llvm;
55  using namespace object;
56  
57  void ModuleSymbolTable::addModule(Module *M) {
58    if (FirstMod)
59      assert(FirstMod->getTargetTriple() == M->getTargetTriple());
60    else
61      FirstMod = M;
62  
63    for (GlobalValue &GV : M->global_values())
64      SymTab.push_back(&GV);
65  
66    CollectAsmSymbols(*M, [this](StringRef Name, BasicSymbolRef::Flags Flags) {
67      SymTab.push_back(new (AsmSymbols.Allocate())
68                           AsmSymbol(std::string(Name), Flags));
69    });
70  }
71  
72  static void
73  initializeRecordStreamer(const Module &M,
74                           function_ref<void(RecordStreamer &)> Init) {
75    StringRef InlineAsm = M.getModuleInlineAsm();
76    if (InlineAsm.empty())
77      return;
78  
79    std::string Err;
80    const Triple TT(M.getTargetTriple());
81    const Target *T = TargetRegistry::lookupTarget(TT.str(), Err);
82    assert(T && T->hasMCAsmParser());
83  
84    std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str()));
85    if (!MRI)
86      return;
87  
88    MCTargetOptions MCOptions;
89    std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str(), MCOptions));
90    if (!MAI)
91      return;
92  
93    std::unique_ptr<MCSubtargetInfo> STI(
94        T->createMCSubtargetInfo(TT.str(), "", ""));
95    if (!STI)
96      return;
97  
98    std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
99    if (!MCII)
100      return;
101  
102    std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm));
103    SourceMgr SrcMgr;
104    SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
105  
106    MCContext MCCtx(TT, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
107    std::unique_ptr<MCObjectFileInfo> MOFI(
108        T->createMCObjectFileInfo(MCCtx, /*PIC=*/false));
109    MOFI->setSDKVersion(M.getSDKVersion());
110    MCCtx.setObjectFileInfo(MOFI.get());
111    RecordStreamer Streamer(MCCtx, M);
112    T->createNullTargetStreamer(Streamer);
113  
114    std::unique_ptr<MCAsmParser> Parser(
115        createMCAsmParser(SrcMgr, MCCtx, Streamer, *MAI));
116  
117    std::unique_ptr<MCTargetAsmParser> TAP(
118        T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
119    if (!TAP)
120      return;
121  
122    // Module-level inline asm is assumed to use At&t syntax (see
123    // AsmPrinter::doInitialization()).
124    Parser->setAssemblerDialect(InlineAsm::AD_ATT);
125  
126    Parser->setTargetParser(*TAP);
127    if (Parser->Run(false))
128      return;
129  
130    Init(Streamer);
131  }
132  
133  void ModuleSymbolTable::CollectAsmSymbols(
134      const Module &M,
135      function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmSymbol) {
136    initializeRecordStreamer(M, [&](RecordStreamer &Streamer) {
137      Streamer.flushSymverDirectives();
138  
139      for (auto &KV : Streamer) {
140        StringRef Key = KV.first();
141        RecordStreamer::State Value = KV.second;
142        // FIXME: For now we just assume that all asm symbols are executable.
143        uint32_t Res = BasicSymbolRef::SF_Executable;
144        switch (Value) {
145        case RecordStreamer::NeverSeen:
146          llvm_unreachable("NeverSeen should have been replaced earlier");
147        case RecordStreamer::DefinedGlobal:
148          Res |= BasicSymbolRef::SF_Global;
149          break;
150        case RecordStreamer::Defined:
151          break;
152        case RecordStreamer::Global:
153        case RecordStreamer::Used:
154          Res |= BasicSymbolRef::SF_Undefined;
155          Res |= BasicSymbolRef::SF_Global;
156          break;
157        case RecordStreamer::DefinedWeak:
158          Res |= BasicSymbolRef::SF_Weak;
159          Res |= BasicSymbolRef::SF_Global;
160          break;
161        case RecordStreamer::UndefinedWeak:
162          Res |= BasicSymbolRef::SF_Weak;
163          Res |= BasicSymbolRef::SF_Undefined;
164        }
165        AsmSymbol(Key, BasicSymbolRef::Flags(Res));
166      }
167    });
168  }
169  
170  void ModuleSymbolTable::CollectAsmSymvers(
171      const Module &M, function_ref<void(StringRef, StringRef)> AsmSymver) {
172    initializeRecordStreamer(M, [&](RecordStreamer &Streamer) {
173      for (auto &KV : Streamer.symverAliases())
174        for (auto &Alias : KV.second)
175          AsmSymver(KV.first->getName(), Alias);
176    });
177  }
178  
179  void ModuleSymbolTable::printSymbolName(raw_ostream &OS, Symbol S) const {
180    if (S.is<AsmSymbol *>()) {
181      OS << S.get<AsmSymbol *>()->first;
182      return;
183    }
184  
185    auto *GV = S.get<GlobalValue *>();
186    if (GV->hasDLLImportStorageClass())
187      OS << "__imp_";
188  
189    Mang.getNameWithPrefix(OS, GV, false);
190  }
191  
192  uint32_t ModuleSymbolTable::getSymbolFlags(Symbol S) const {
193    if (S.is<AsmSymbol *>())
194      return S.get<AsmSymbol *>()->second;
195  
196    auto *GV = S.get<GlobalValue *>();
197  
198    uint32_t Res = BasicSymbolRef::SF_None;
199    if (GV->isDeclarationForLinker())
200      Res |= BasicSymbolRef::SF_Undefined;
201    else if (GV->hasHiddenVisibility() && !GV->hasLocalLinkage())
202      Res |= BasicSymbolRef::SF_Hidden;
203    if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
204      if (GVar->isConstant())
205        Res |= BasicSymbolRef::SF_Const;
206    }
207    if (dyn_cast_or_null<Function>(GV->getBaseObject()))
208      Res |= BasicSymbolRef::SF_Executable;
209    if (isa<GlobalAlias>(GV))
210      Res |= BasicSymbolRef::SF_Indirect;
211    if (GV->hasPrivateLinkage())
212      Res |= BasicSymbolRef::SF_FormatSpecific;
213    if (!GV->hasLocalLinkage())
214      Res |= BasicSymbolRef::SF_Global;
215    if (GV->hasCommonLinkage())
216      Res |= BasicSymbolRef::SF_Common;
217    if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
218        GV->hasExternalWeakLinkage())
219      Res |= BasicSymbolRef::SF_Weak;
220  
221    if (GV->getName().startswith("llvm."))
222      Res |= BasicSymbolRef::SF_FormatSpecific;
223    else if (auto *Var = dyn_cast<GlobalVariable>(GV)) {
224      if (Var->getSection() == "llvm.metadata")
225        Res |= BasicSymbolRef::SF_FormatSpecific;
226    }
227  
228    return Res;
229  }
230