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