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