xref: /llvm-project-15.0.7/lld/wasm/Symbols.cpp (revision 44a40046)
1 //===- Symbols.cpp --------------------------------------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "Symbols.h"
11 #include "Config.h"
12 #include "InputChunks.h"
13 #include "InputFiles.h"
14 #include "InputGlobal.h"
15 #include "OutputSegment.h"
16 #include "lld/Common/ErrorHandler.h"
17 #include "lld/Common/Strings.h"
18 
19 #define DEBUG_TYPE "lld"
20 
21 using namespace llvm;
22 using namespace llvm::wasm;
23 using namespace lld;
24 using namespace lld::wasm;
25 
26 DefinedFunction *WasmSym::CallCtors;
27 DefinedData *WasmSym::DsoHandle;
28 DefinedData *WasmSym::DataEnd;
29 DefinedData *WasmSym::HeapBase;
30 GlobalSymbol *WasmSym::StackPointer;
31 UndefinedGlobal *WasmSym::TableBase;
32 UndefinedGlobal *WasmSym::MemoryBase;
33 
34 WasmSymbolType Symbol::getWasmType() const {
35   if (isa<FunctionSymbol>(this))
36     return WASM_SYMBOL_TYPE_FUNCTION;
37   if (isa<DataSymbol>(this))
38     return WASM_SYMBOL_TYPE_DATA;
39   if (isa<GlobalSymbol>(this))
40     return WASM_SYMBOL_TYPE_GLOBAL;
41   if (isa<SectionSymbol>(this))
42     return WASM_SYMBOL_TYPE_SECTION;
43   llvm_unreachable("invalid symbol kind");
44 }
45 
46 InputChunk *Symbol::getChunk() const {
47   if (auto *F = dyn_cast<DefinedFunction>(this))
48     return F->Function;
49   if (auto *D = dyn_cast<DefinedData>(this))
50     return D->Segment;
51   return nullptr;
52 }
53 
54 bool Symbol::isLive() const {
55   if (auto *G = dyn_cast<DefinedGlobal>(this))
56     return G->Global->Live;
57   if (InputChunk *C = getChunk())
58     return C->Live;
59   return Referenced;
60 }
61 
62 void Symbol::markLive() {
63   if (auto *G = dyn_cast<DefinedGlobal>(this))
64     G->Global->Live = true;
65   if (InputChunk *C = getChunk())
66     C->Live = true;
67   Referenced = true;
68 }
69 
70 uint32_t Symbol::getOutputSymbolIndex() const {
71   assert(OutputSymbolIndex != INVALID_INDEX);
72   return OutputSymbolIndex;
73 }
74 
75 void Symbol::setOutputSymbolIndex(uint32_t Index) {
76   LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << Name << " -> " << Index
77                     << "\n");
78   assert(OutputSymbolIndex == INVALID_INDEX);
79   OutputSymbolIndex = Index;
80 }
81 
82 bool Symbol::isWeak() const {
83   return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK;
84 }
85 
86 bool Symbol::isLocal() const {
87   return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL;
88 }
89 
90 bool Symbol::isHidden() const {
91   return (Flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN;
92 }
93 
94 void Symbol::setHidden(bool IsHidden) {
95   LLVM_DEBUG(dbgs() << "setHidden: " << Name << " -> " << IsHidden << "\n");
96   Flags &= ~WASM_SYMBOL_VISIBILITY_MASK;
97   if (IsHidden)
98     Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
99   else
100     Flags |= WASM_SYMBOL_VISIBILITY_DEFAULT;
101 }
102 
103 bool Symbol::isExported() const {
104   if (!isDefined() || isLocal())
105     return false;
106 
107   if (ForceExport || Config->ExportAll)
108     return true;
109 
110   if (Config->ExportDynamic && !isHidden())
111     return true;
112 
113   return false;
114 }
115 
116 uint32_t FunctionSymbol::getFunctionIndex() const {
117   if (auto *F = dyn_cast<DefinedFunction>(this))
118     return F->Function->getFunctionIndex();
119   assert(FunctionIndex != INVALID_INDEX);
120   return FunctionIndex;
121 }
122 
123 void FunctionSymbol::setFunctionIndex(uint32_t Index) {
124   LLVM_DEBUG(dbgs() << "setFunctionIndex " << Name << " -> " << Index << "\n");
125   assert(FunctionIndex == INVALID_INDEX);
126   FunctionIndex = Index;
127 }
128 
129 bool FunctionSymbol::hasFunctionIndex() const {
130   if (auto *F = dyn_cast<DefinedFunction>(this))
131     return F->Function->hasFunctionIndex();
132   return FunctionIndex != INVALID_INDEX;
133 }
134 
135 uint32_t FunctionSymbol::getTableIndex() const {
136   if (auto *F = dyn_cast<DefinedFunction>(this))
137     return F->Function->getTableIndex();
138   assert(TableIndex != INVALID_INDEX);
139   return TableIndex;
140 }
141 
142 bool FunctionSymbol::hasTableIndex() const {
143   if (auto *F = dyn_cast<DefinedFunction>(this))
144     return F->Function->hasTableIndex();
145   return TableIndex != INVALID_INDEX;
146 }
147 
148 void FunctionSymbol::setTableIndex(uint32_t Index) {
149   // For imports, we set the table index here on the Symbol; for defined
150   // functions we set the index on the InputFunction so that we don't export
151   // the same thing twice (keeps the table size down).
152   if (auto *F = dyn_cast<DefinedFunction>(this)) {
153     F->Function->setTableIndex(Index);
154     return;
155   }
156   LLVM_DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n");
157   assert(TableIndex == INVALID_INDEX);
158   TableIndex = Index;
159 }
160 
161 DefinedFunction::DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F,
162                                  InputFunction *Function)
163     : FunctionSymbol(Name, DefinedFunctionKind, Flags, F,
164                      Function ? &Function->Signature : nullptr),
165       Function(Function) {}
166 
167 uint32_t DefinedData::getVirtualAddress() const {
168   LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
169   if (Segment)
170     return Segment->OutputSeg->StartVA + Segment->OutputSegmentOffset + Offset;
171   return Offset;
172 }
173 
174 void DefinedData::setVirtualAddress(uint32_t Value) {
175   LLVM_DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n");
176   assert(!Segment);
177   Offset = Value;
178 }
179 
180 uint32_t DefinedData::getOutputSegmentOffset() const {
181   LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n");
182   return Segment->OutputSegmentOffset + Offset;
183 }
184 
185 uint32_t DefinedData::getOutputSegmentIndex() const {
186   LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n");
187   return Segment->OutputSeg->Index;
188 }
189 
190 uint32_t GlobalSymbol::getGlobalIndex() const {
191   if (auto *F = dyn_cast<DefinedGlobal>(this))
192     return F->Global->getGlobalIndex();
193   assert(GlobalIndex != INVALID_INDEX);
194   return GlobalIndex;
195 }
196 
197 void GlobalSymbol::setGlobalIndex(uint32_t Index) {
198   LLVM_DEBUG(dbgs() << "setGlobalIndex " << Name << " -> " << Index << "\n");
199   assert(GlobalIndex == INVALID_INDEX);
200   GlobalIndex = Index;
201 }
202 
203 bool GlobalSymbol::hasGlobalIndex() const {
204   if (auto *F = dyn_cast<DefinedGlobal>(this))
205     return F->Global->hasGlobalIndex();
206   return GlobalIndex != INVALID_INDEX;
207 }
208 
209 DefinedGlobal::DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File,
210                              InputGlobal *Global)
211     : GlobalSymbol(Name, DefinedGlobalKind, Flags, File,
212                    Global ? &Global->getType() : nullptr),
213       Global(Global) {}
214 
215 uint32_t SectionSymbol::getOutputSectionIndex() const {
216   LLVM_DEBUG(dbgs() << "getOutputSectionIndex: " << getName() << "\n");
217   assert(OutputSectionIndex != INVALID_INDEX);
218   return OutputSectionIndex;
219 }
220 
221 void SectionSymbol::setOutputSectionIndex(uint32_t Index) {
222   LLVM_DEBUG(dbgs() << "setOutputSectionIndex: " << getName() << " -> " << Index
223                     << "\n");
224   assert(Index != INVALID_INDEX);
225   OutputSectionIndex = Index;
226 }
227 
228 void LazySymbol::fetch() { cast<ArchiveFile>(File)->addMember(&ArchiveSymbol); }
229 
230 std::string lld::toString(const wasm::Symbol &Sym) {
231   return lld::maybeDemangleSymbol(Sym.getName());
232 }
233 
234 std::string lld::maybeDemangleSymbol(StringRef Name) {
235   if (Config->Demangle)
236     if (Optional<std::string> S = demangleItanium(Name))
237       return *S;
238   return Name;
239 }
240 
241 std::string lld::toString(wasm::Symbol::Kind Kind) {
242   switch (Kind) {
243   case wasm::Symbol::DefinedFunctionKind:
244     return "DefinedFunction";
245   case wasm::Symbol::DefinedDataKind:
246     return "DefinedData";
247   case wasm::Symbol::DefinedGlobalKind:
248     return "DefinedGlobal";
249   case wasm::Symbol::UndefinedFunctionKind:
250     return "UndefinedFunction";
251   case wasm::Symbol::UndefinedDataKind:
252     return "UndefinedData";
253   case wasm::Symbol::UndefinedGlobalKind:
254     return "UndefinedGlobal";
255   case wasm::Symbol::LazyKind:
256     return "LazyKind";
257   case wasm::Symbol::SectionKind:
258     return "SectionKind";
259   }
260   llvm_unreachable("invalid symbol kind");
261 }
262