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
51using namespace llvm;
52using namespace object;
53
54void 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
69static void
70initializeRecordStreamer(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
130void 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
167void 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
176void 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
189uint32_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