1321369Sdim//===- ModuleSymbolTable.cpp - symbol table for in-memory IR --------------===//
2311116Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6311116Sdim//
7311116Sdim//===----------------------------------------------------------------------===//
8311116Sdim//
9311116Sdim// This class represents a symbol table built from in-memory IR. It provides
10311116Sdim// access to GlobalValues and should only be used if such access is required
11311116Sdim// (e.g. in the LTO implementation).
12311116Sdim//
13311116Sdim//===----------------------------------------------------------------------===//
14311116Sdim
15321369Sdim#include "llvm/Object/ModuleSymbolTable.h"
16311116Sdim#include "RecordStreamer.h"
17311116Sdim#include "llvm/ADT/STLExtras.h"
18321369Sdim#include "llvm/ADT/SmallString.h"
19321369Sdim#include "llvm/ADT/StringMap.h"
20321369Sdim#include "llvm/ADT/StringRef.h"
21321369Sdim#include "llvm/ADT/Triple.h"
22321369Sdim#include "llvm/IR/Function.h"
23321369Sdim#include "llvm/IR/GlobalAlias.h"
24321369Sdim#include "llvm/IR/GlobalValue.h"
25321369Sdim#include "llvm/IR/GlobalVariable.h"
26311116Sdim#include "llvm/IR/Module.h"
27311116Sdim#include "llvm/MC/MCAsmInfo.h"
28311116Sdim#include "llvm/MC/MCContext.h"
29321369Sdim#include "llvm/MC/MCDirectives.h"
30311116Sdim#include "llvm/MC/MCInstrInfo.h"
31311116Sdim#include "llvm/MC/MCObjectFileInfo.h"
32311116Sdim#include "llvm/MC/MCParser/MCAsmParser.h"
33311116Sdim#include "llvm/MC/MCParser/MCTargetAsmParser.h"
34311116Sdim#include "llvm/MC/MCRegisterInfo.h"
35311116Sdim#include "llvm/MC/MCSubtargetInfo.h"
36321369Sdim#include "llvm/MC/MCSymbol.h"
37321369Sdim#include "llvm/MC/MCTargetOptions.h"
38321369Sdim#include "llvm/Object/SymbolicFile.h"
39321369Sdim#include "llvm/Support/Casting.h"
40321369Sdim#include "llvm/Support/CodeGen.h"
41321369Sdim#include "llvm/Support/ErrorHandling.h"
42311116Sdim#include "llvm/Support/MemoryBuffer.h"
43321369Sdim#include "llvm/Support/SMLoc.h"
44311116Sdim#include "llvm/Support/SourceMgr.h"
45311116Sdim#include "llvm/Support/TargetRegistry.h"
46311116Sdim#include "llvm/Support/raw_ostream.h"
47321369Sdim#include <algorithm>
48321369Sdim#include <cassert>
49321369Sdim#include <cstdint>
50321369Sdim#include <memory>
51321369Sdim#include <string>
52321369Sdim
53311116Sdimusing namespace llvm;
54311116Sdimusing namespace object;
55311116Sdim
56311116Sdimvoid ModuleSymbolTable::addModule(Module *M) {
57311116Sdim  if (FirstMod)
58311116Sdim    assert(FirstMod->getTargetTriple() == M->getTargetTriple());
59311116Sdim  else
60311116Sdim    FirstMod = M;
61311116Sdim
62321369Sdim  for (GlobalValue &GV : M->global_values())
63311116Sdim    SymTab.push_back(&GV);
64311116Sdim
65321369Sdim  CollectAsmSymbols(*M, [this](StringRef Name, BasicSymbolRef::Flags Flags) {
66321369Sdim    SymTab.push_back(new (AsmSymbols.Allocate()) AsmSymbol(Name, Flags));
67321369Sdim  });
68311116Sdim}
69311116Sdim
70341825Sdimstatic void
71341825SdiminitializeRecordStreamer(const Module &M,
72341825Sdim                         function_ref<void(RecordStreamer &)> Init) {
73321369Sdim  StringRef InlineAsm = M.getModuleInlineAsm();
74311116Sdim  if (InlineAsm.empty())
75311116Sdim    return;
76311116Sdim
77311116Sdim  std::string Err;
78321369Sdim  const Triple TT(M.getTargetTriple());
79311116Sdim  const Target *T = TargetRegistry::lookupTarget(TT.str(), Err);
80311116Sdim  assert(T && T->hasMCAsmParser());
81311116Sdim
82311116Sdim  std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str()));
83311116Sdim  if (!MRI)
84311116Sdim    return;
85311116Sdim
86360784Sdim  MCTargetOptions MCOptions;
87360784Sdim  std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str(), MCOptions));
88311116Sdim  if (!MAI)
89311116Sdim    return;
90311116Sdim
91311116Sdim  std::unique_ptr<MCSubtargetInfo> STI(
92311116Sdim      T->createMCSubtargetInfo(TT.str(), "", ""));
93311116Sdim  if (!STI)
94311116Sdim    return;
95311116Sdim
96311116Sdim  std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
97311116Sdim  if (!MCII)
98311116Sdim    return;
99311116Sdim
100311116Sdim  MCObjectFileInfo MOFI;
101311116Sdim  MCContext MCCtx(MAI.get(), MRI.get(), &MOFI);
102327952Sdim  MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, MCCtx);
103344779Sdim  MOFI.setSDKVersion(M.getSDKVersion());
104331366Sdim  RecordStreamer Streamer(MCCtx, M);
105311116Sdim  T->createNullTargetStreamer(Streamer);
106311116Sdim
107311116Sdim  std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm));
108311116Sdim  SourceMgr SrcMgr;
109311116Sdim  SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
110311116Sdim  std::unique_ptr<MCAsmParser> Parser(
111311116Sdim      createMCAsmParser(SrcMgr, MCCtx, Streamer, *MAI));
112311116Sdim
113311116Sdim  std::unique_ptr<MCTargetAsmParser> TAP(
114311116Sdim      T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
115311116Sdim  if (!TAP)
116311116Sdim    return;
117311116Sdim
118311116Sdim  Parser->setTargetParser(*TAP);
119311116Sdim  if (Parser->Run(false))
120311116Sdim    return;
121311116Sdim
122341825Sdim  Init(Streamer);
123341825Sdim}
124321369Sdim
125341825Sdimvoid ModuleSymbolTable::CollectAsmSymbols(
126341825Sdim    const Module &M,
127341825Sdim    function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmSymbol) {
128341825Sdim  initializeRecordStreamer(M, [&](RecordStreamer &Streamer) {
129341825Sdim    Streamer.flushSymverDirectives();
130341825Sdim
131341825Sdim    for (auto &KV : Streamer) {
132341825Sdim      StringRef Key = KV.first();
133341825Sdim      RecordStreamer::State Value = KV.second;
134341825Sdim      // FIXME: For now we just assume that all asm symbols are executable.
135341825Sdim      uint32_t Res = BasicSymbolRef::SF_Executable;
136341825Sdim      switch (Value) {
137341825Sdim      case RecordStreamer::NeverSeen:
138341825Sdim        llvm_unreachable("NeverSeen should have been replaced earlier");
139341825Sdim      case RecordStreamer::DefinedGlobal:
140341825Sdim        Res |= BasicSymbolRef::SF_Global;
141341825Sdim        break;
142341825Sdim      case RecordStreamer::Defined:
143341825Sdim        break;
144341825Sdim      case RecordStreamer::Global:
145341825Sdim      case RecordStreamer::Used:
146341825Sdim        Res |= BasicSymbolRef::SF_Undefined;
147341825Sdim        Res |= BasicSymbolRef::SF_Global;
148341825Sdim        break;
149341825Sdim      case RecordStreamer::DefinedWeak:
150341825Sdim        Res |= BasicSymbolRef::SF_Weak;
151341825Sdim        Res |= BasicSymbolRef::SF_Global;
152341825Sdim        break;
153341825Sdim      case RecordStreamer::UndefinedWeak:
154341825Sdim        Res |= BasicSymbolRef::SF_Weak;
155341825Sdim        Res |= BasicSymbolRef::SF_Undefined;
156341825Sdim      }
157341825Sdim      AsmSymbol(Key, BasicSymbolRef::Flags(Res));
158311116Sdim    }
159341825Sdim  });
160311116Sdim}
161311116Sdim
162341825Sdimvoid ModuleSymbolTable::CollectAsmSymvers(
163341825Sdim    const Module &M, function_ref<void(StringRef, StringRef)> AsmSymver) {
164341825Sdim  initializeRecordStreamer(M, [&](RecordStreamer &Streamer) {
165341825Sdim    for (auto &KV : Streamer.symverAliases())
166341825Sdim      for (auto &Alias : KV.second)
167341825Sdim        AsmSymver(KV.first->getName(), Alias);
168341825Sdim  });
169341825Sdim}
170341825Sdim
171311116Sdimvoid ModuleSymbolTable::printSymbolName(raw_ostream &OS, Symbol S) const {
172311116Sdim  if (S.is<AsmSymbol *>()) {
173311116Sdim    OS << S.get<AsmSymbol *>()->first;
174311116Sdim    return;
175311116Sdim  }
176311116Sdim
177311116Sdim  auto *GV = S.get<GlobalValue *>();
178311116Sdim  if (GV->hasDLLImportStorageClass())
179311116Sdim    OS << "__imp_";
180311116Sdim
181311116Sdim  Mang.getNameWithPrefix(OS, GV, false);
182311116Sdim}
183311116Sdim
184311116Sdimuint32_t ModuleSymbolTable::getSymbolFlags(Symbol S) const {
185311116Sdim  if (S.is<AsmSymbol *>())
186311116Sdim    return S.get<AsmSymbol *>()->second;
187311116Sdim
188311116Sdim  auto *GV = S.get<GlobalValue *>();
189311116Sdim
190311116Sdim  uint32_t Res = BasicSymbolRef::SF_None;
191311116Sdim  if (GV->isDeclarationForLinker())
192311116Sdim    Res |= BasicSymbolRef::SF_Undefined;
193311116Sdim  else if (GV->hasHiddenVisibility() && !GV->hasLocalLinkage())
194311116Sdim    Res |= BasicSymbolRef::SF_Hidden;
195311116Sdim  if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
196311116Sdim    if (GVar->isConstant())
197311116Sdim      Res |= BasicSymbolRef::SF_Const;
198311116Sdim  }
199311116Sdim  if (dyn_cast_or_null<Function>(GV->getBaseObject()))
200311116Sdim    Res |= BasicSymbolRef::SF_Executable;
201311116Sdim  if (isa<GlobalAlias>(GV))
202311116Sdim    Res |= BasicSymbolRef::SF_Indirect;
203311116Sdim  if (GV->hasPrivateLinkage())
204311116Sdim    Res |= BasicSymbolRef::SF_FormatSpecific;
205311116Sdim  if (!GV->hasLocalLinkage())
206311116Sdim    Res |= BasicSymbolRef::SF_Global;
207311116Sdim  if (GV->hasCommonLinkage())
208311116Sdim    Res |= BasicSymbolRef::SF_Common;
209311116Sdim  if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
210311116Sdim      GV->hasExternalWeakLinkage())
211311116Sdim    Res |= BasicSymbolRef::SF_Weak;
212311116Sdim
213311116Sdim  if (GV->getName().startswith("llvm."))
214311116Sdim    Res |= BasicSymbolRef::SF_FormatSpecific;
215311116Sdim  else if (auto *Var = dyn_cast<GlobalVariable>(GV)) {
216311116Sdim    if (Var->getSection() == "llvm.metadata")
217311116Sdim      Res |= BasicSymbolRef::SF_FormatSpecific;
218311116Sdim  }
219311116Sdim
220311116Sdim  return Res;
221311116Sdim}
222