1 //===- ModuleSymbolTable.cpp - symbol table for in-memory IR --------------===//
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
7 //===----------------------------------------------------------------------===//
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).
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Object/ModuleSymbolTable.h"
16 #include "RecordStreamer.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/IR/DiagnosticInfo.h"
20 #include "llvm/IR/Function.h"
21 #include "llvm/IR/GlobalAlias.h"
22 #include "llvm/IR/GlobalValue.h"
23 #include "llvm/IR/GlobalVariable.h"
24 #include "llvm/IR/InlineAsm.h"
25 #include "llvm/IR/Module.h"
26 #include "llvm/MC/MCAsmInfo.h"
27 #include "llvm/MC/MCContext.h"
28 #include "llvm/MC/MCInstrInfo.h"
29 #include "llvm/MC/MCObjectFileInfo.h"
30 #include "llvm/MC/MCParser/MCAsmParser.h"
31 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
32 #include "llvm/MC/MCRegisterInfo.h"
33 #include "llvm/MC/MCSubtargetInfo.h"
34 #include "llvm/MC/MCSymbol.h"
35 #include "llvm/MC/MCTargetOptions.h"
36 #include "llvm/MC/TargetRegistry.h"
37 #include "llvm/Object/SymbolicFile.h"
38 #include "llvm/Support/Casting.h"
39 #include "llvm/Support/ErrorHandling.h"
40 #include "llvm/Support/MemoryBuffer.h"
41 #include "llvm/Support/SMLoc.h"
42 #include "llvm/Support/SourceMgr.h"
43 #include "llvm/Support/raw_ostream.h"
44 #include "llvm/TargetParser/Triple.h"
52 using namespace object
;
54 void ModuleSymbolTable::addModule(Module
*M
) {
56 assert(FirstMod
->getTargetTriple() == M
->getTargetTriple());
60 for (GlobalValue
&GV
: M
->global_values())
61 SymTab
.push_back(&GV
);
63 CollectAsmSymbols(*M
, [this](StringRef Name
, BasicSymbolRef::Flags Flags
) {
64 SymTab
.push_back(new (AsmSymbols
.Allocate())
65 AsmSymbol(std::string(Name
), Flags
));
70 initializeRecordStreamer(const Module
&M
,
71 function_ref
<void(RecordStreamer
&)> Init
) {
72 // This function may be called twice, once for ModuleSummaryIndexAnalysis and
73 // the other when writing the IR symbol table. If parsing inline assembly has
74 // caused errors in the first run, suppress the second run.
75 if (M
.getContext().getDiagHandlerPtr()->HasErrors
)
77 StringRef InlineAsm
= M
.getModuleInlineAsm();
78 if (InlineAsm
.empty())
82 const Triple
TT(M
.getTargetTriple());
83 const Target
*T
= TargetRegistry::lookupTarget(TT
.str(), Err
);
84 assert(T
&& T
->hasMCAsmParser());
86 std::unique_ptr
<MCRegisterInfo
> MRI(T
->createMCRegInfo(TT
.str()));
90 MCTargetOptions MCOptions
;
91 std::unique_ptr
<MCAsmInfo
> MAI(T
->createMCAsmInfo(*MRI
, TT
.str(), MCOptions
));
95 std::unique_ptr
<MCSubtargetInfo
> STI(
96 T
->createMCSubtargetInfo(TT
.str(), "", ""));
100 std::unique_ptr
<MCInstrInfo
> MCII(T
->createMCInstrInfo());
104 std::unique_ptr
<MemoryBuffer
> Buffer(
105 MemoryBuffer::getMemBuffer(InlineAsm
, "<inline asm>"));
107 SrcMgr
.AddNewSourceBuffer(std::move(Buffer
), SMLoc());
109 MCContext
MCCtx(TT
, MAI
.get(), MRI
.get(), STI
.get(), &SrcMgr
);
110 std::unique_ptr
<MCObjectFileInfo
> MOFI(
111 T
->createMCObjectFileInfo(MCCtx
, /*PIC=*/false));
112 MOFI
->setSDKVersion(M
.getSDKVersion());
113 MCCtx
.setObjectFileInfo(MOFI
.get());
114 RecordStreamer
Streamer(MCCtx
, M
);
115 T
->createNullTargetStreamer(Streamer
);
117 std::unique_ptr
<MCAsmParser
> Parser(
118 createMCAsmParser(SrcMgr
, MCCtx
, Streamer
, *MAI
));
120 std::unique_ptr
<MCTargetAsmParser
> TAP(
121 T
->createMCAsmParser(*STI
, *Parser
, *MCII
, MCOptions
));
125 MCCtx
.setDiagnosticHandler([&](const SMDiagnostic
&SMD
, bool IsInlineAsm
,
126 const SourceMgr
&SrcMgr
,
127 std::vector
<const MDNode
*> &LocInfos
) {
128 M
.getContext().diagnose(
129 DiagnosticInfoSrcMgr(SMD
, M
.getName(), IsInlineAsm
, /*LocCookie=*/0));
132 // Module-level inline asm is assumed to use At&t syntax (see
133 // AsmPrinter::doInitialization()).
134 Parser
->setAssemblerDialect(InlineAsm::AD_ATT
);
136 Parser
->setTargetParser(*TAP
);
137 if (Parser
->Run(false))
143 void ModuleSymbolTable::CollectAsmSymbols(
145 function_ref
<void(StringRef
, BasicSymbolRef::Flags
)> AsmSymbol
) {
146 initializeRecordStreamer(M
, [&](RecordStreamer
&Streamer
) {
147 Streamer
.flushSymverDirectives();
149 for (auto &KV
: Streamer
) {
150 StringRef Key
= KV
.first();
151 RecordStreamer::State Value
= KV
.second
;
152 // FIXME: For now we just assume that all asm symbols are executable.
153 uint32_t Res
= BasicSymbolRef::SF_Executable
;
155 case RecordStreamer::NeverSeen
:
156 llvm_unreachable("NeverSeen should have been replaced earlier");
157 case RecordStreamer::DefinedGlobal
:
158 Res
|= BasicSymbolRef::SF_Global
;
160 case RecordStreamer::Defined
:
162 case RecordStreamer::Global
:
163 case RecordStreamer::Used
:
164 Res
|= BasicSymbolRef::SF_Undefined
;
165 Res
|= BasicSymbolRef::SF_Global
;
167 case RecordStreamer::DefinedWeak
:
168 Res
|= BasicSymbolRef::SF_Weak
;
169 Res
|= BasicSymbolRef::SF_Global
;
171 case RecordStreamer::UndefinedWeak
:
172 Res
|= BasicSymbolRef::SF_Weak
;
173 Res
|= BasicSymbolRef::SF_Undefined
;
175 AsmSymbol(Key
, BasicSymbolRef::Flags(Res
));
179 // In ELF, object code generated for x86-32 and some code models of x86-64 may
180 // reference the special symbol _GLOBAL_OFFSET_TABLE_ that is not used in the
181 // IR. Record it like inline asm symbols.
182 Triple
TT(M
.getTargetTriple());
183 if (!TT
.isOSBinFormatELF() || !TT
.isX86())
185 auto CM
= M
.getCodeModel();
186 if (TT
.getArch() == Triple::x86
|| CM
== CodeModel::Medium
||
187 CM
== CodeModel::Large
) {
188 AsmSymbol("_GLOBAL_OFFSET_TABLE_",
189 BasicSymbolRef::Flags(BasicSymbolRef::SF_Undefined
|
190 BasicSymbolRef::SF_Global
));
194 void ModuleSymbolTable::CollectAsmSymvers(
195 const Module
&M
, function_ref
<void(StringRef
, StringRef
)> AsmSymver
) {
196 initializeRecordStreamer(M
, [&](RecordStreamer
&Streamer
) {
197 for (auto &KV
: Streamer
.symverAliases())
198 for (auto &Alias
: KV
.second
)
199 AsmSymver(KV
.first
->getName(), Alias
);
203 void ModuleSymbolTable::printSymbolName(raw_ostream
&OS
, Symbol S
) const {
204 if (isa
<AsmSymbol
*>(S
)) {
205 OS
<< cast
<AsmSymbol
*>(S
)->first
;
209 auto *GV
= cast
<GlobalValue
*>(S
);
210 if (GV
->hasDLLImportStorageClass())
213 Mang
.getNameWithPrefix(OS
, GV
, false);
216 uint32_t ModuleSymbolTable::getSymbolFlags(Symbol S
) const {
217 if (isa
<AsmSymbol
*>(S
))
218 return cast
<AsmSymbol
*>(S
)->second
;
220 auto *GV
= cast
<GlobalValue
*>(S
);
222 uint32_t Res
= BasicSymbolRef::SF_None
;
223 if (GV
->isDeclarationForLinker())
224 Res
|= BasicSymbolRef::SF_Undefined
;
225 else if (GV
->hasHiddenVisibility() && !GV
->hasLocalLinkage())
226 Res
|= BasicSymbolRef::SF_Hidden
;
227 if (const GlobalVariable
*GVar
= dyn_cast
<GlobalVariable
>(GV
)) {
228 if (GVar
->isConstant())
229 Res
|= BasicSymbolRef::SF_Const
;
231 if (const GlobalObject
*GO
= GV
->getAliaseeObject())
232 if (isa
<Function
>(GO
) || isa
<GlobalIFunc
>(GO
))
233 Res
|= BasicSymbolRef::SF_Executable
;
234 if (isa
<GlobalAlias
>(GV
))
235 Res
|= BasicSymbolRef::SF_Indirect
;
236 if (GV
->hasPrivateLinkage())
237 Res
|= BasicSymbolRef::SF_FormatSpecific
;
238 if (!GV
->hasLocalLinkage())
239 Res
|= BasicSymbolRef::SF_Global
;
240 if (GV
->hasCommonLinkage())
241 Res
|= BasicSymbolRef::SF_Common
;
242 if (GV
->hasLinkOnceLinkage() || GV
->hasWeakLinkage() ||
243 GV
->hasExternalWeakLinkage())
244 Res
|= BasicSymbolRef::SF_Weak
;
246 if (GV
->getName().starts_with("llvm."))
247 Res
|= BasicSymbolRef::SF_FormatSpecific
;
248 else if (auto *Var
= dyn_cast
<GlobalVariable
>(GV
)) {
249 if (Var
->getSection() == "llvm.metadata")
250 Res
|= BasicSymbolRef::SF_FormatSpecific
;