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