1c94d393aSSam Clegg //===- SymbolTable.cpp ----------------------------------------------------===//
2c94d393aSSam Clegg //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c94d393aSSam Clegg //
7c94d393aSSam Clegg //===----------------------------------------------------------------------===//
8c94d393aSSam Clegg 
9c94d393aSSam Clegg #include "SymbolTable.h"
10c94d393aSSam Clegg #include "Config.h"
115fa274beSSam Clegg #include "InputChunks.h"
12e915a71fSHeejin Ahn #include "InputEvent.h"
1393102974SSam Clegg #include "InputGlobal.h"
14b8621596SSam Clegg #include "WriterUtils.h"
15c94d393aSSam Clegg #include "lld/Common/ErrorHandler.h"
162017d52bSRui Ueyama #include "lld/Common/Memory.h"
177d67dd11SRui Ueyama #include "llvm/ADT/SetVector.h"
18c94d393aSSam Clegg 
19c94d393aSSam Clegg #define DEBUG_TYPE "lld"
20c94d393aSSam Clegg 
21c94d393aSSam Clegg using namespace llvm;
2220db381bSSam Clegg using namespace llvm::wasm;
2345218f4aSSam Clegg using namespace llvm::object;
24c94d393aSSam Clegg using namespace lld;
25c94d393aSSam Clegg using namespace lld::wasm;
26c94d393aSSam Clegg 
27c94d393aSSam Clegg SymbolTable *lld::wasm::Symtab;
28c94d393aSSam Clegg 
29c94d393aSSam Clegg void SymbolTable::addFile(InputFile *File) {
30c94d393aSSam Clegg   log("Processing: " + toString(File));
31c94d393aSSam Clegg   File->parse();
32c94d393aSSam Clegg 
33c729c1b4SSam Clegg   // LLVM bitcode file
34c729c1b4SSam Clegg   if (auto *F = dyn_cast<BitcodeFile>(File))
35c729c1b4SSam Clegg     BitcodeFiles.push_back(F);
36c729c1b4SSam Clegg   else if (auto *F = dyn_cast<ObjFile>(File))
37c94d393aSSam Clegg     ObjectFiles.push_back(F);
38c94d393aSSam Clegg }
39c94d393aSSam Clegg 
40c729c1b4SSam Clegg // This function is where all the optimizations of link-time
41c729c1b4SSam Clegg // optimization happens. When LTO is in use, some input files are
42c729c1b4SSam Clegg // not in native object file format but in the LLVM bitcode format.
43c729c1b4SSam Clegg // This function compiles bitcode files into a few big native files
44c729c1b4SSam Clegg // using LLVM functions and replaces bitcode symbols with the results.
45c729c1b4SSam Clegg // Because all bitcode files that the program consists of are passed
46c729c1b4SSam Clegg // to the compiler at once, it can do whole-program optimization.
47c729c1b4SSam Clegg void SymbolTable::addCombinedLTOObject() {
48c729c1b4SSam Clegg   if (BitcodeFiles.empty())
49c729c1b4SSam Clegg     return;
50c729c1b4SSam Clegg 
51c729c1b4SSam Clegg   // Compile bitcode files and replace bitcode symbols.
52c729c1b4SSam Clegg   LTO.reset(new BitcodeCompiler);
53c729c1b4SSam Clegg   for (BitcodeFile *F : BitcodeFiles)
54c729c1b4SSam Clegg     LTO->add(*F);
55c729c1b4SSam Clegg 
56c729c1b4SSam Clegg   for (StringRef Filename : LTO->compile()) {
57c729c1b4SSam Clegg     auto *Obj = make<ObjFile>(MemoryBufferRef(Filename, "lto.tmp"));
58c729c1b4SSam Clegg     Obj->parse();
59c729c1b4SSam Clegg     ObjectFiles.push_back(Obj);
60c729c1b4SSam Clegg   }
61c729c1b4SSam Clegg }
62c729c1b4SSam Clegg 
63c94d393aSSam Clegg void SymbolTable::reportRemainingUndefines() {
6474fe0ba1SSam Clegg   for (Symbol *Sym : SymVector) {
65c729c1b4SSam Clegg     if (!Sym->isUndefined() || Sym->isWeak())
66c729c1b4SSam Clegg       continue;
67c729c1b4SSam Clegg     if (Config->AllowUndefinedSymbols.count(Sym->getName()) != 0)
68c729c1b4SSam Clegg       continue;
69c729c1b4SSam Clegg     if (!Sym->IsUsedInRegularObj)
70c729c1b4SSam Clegg       continue;
7147e2b6b2SSam Clegg     error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym));
72c94d393aSSam Clegg   }
73c94d393aSSam Clegg }
74c94d393aSSam Clegg 
75c94d393aSSam Clegg Symbol *SymbolTable::find(StringRef Name) {
7667d6908fSRui Ueyama   return SymMap.lookup(CachedHashStringRef(Name));
77c94d393aSSam Clegg }
78c94d393aSSam Clegg 
794c2cbfe6SSam Clegg std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, InputFile *File) {
804c2cbfe6SSam Clegg   bool Inserted = false;
81a80d94d5SSam Clegg   Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
824c2cbfe6SSam Clegg   if (!Sym) {
83dfb0b2c7SSam Clegg     Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
84c729c1b4SSam Clegg     Sym->IsUsedInRegularObj = false;
8574fe0ba1SSam Clegg     SymVector.emplace_back(Sym);
864c2cbfe6SSam Clegg     Inserted = true;
874c2cbfe6SSam Clegg   }
884c2cbfe6SSam Clegg   if (!File || File->kind() == InputFile::ObjectKind)
894c2cbfe6SSam Clegg     Sym->IsUsedInRegularObj = true;
904c2cbfe6SSam Clegg   return {Sym, Inserted};
91c94d393aSSam Clegg }
92c94d393aSSam Clegg 
93e3498ec5SRui Ueyama static void reportTypeError(const Symbol *Existing, const InputFile *File,
943876d89aSSam Clegg                             llvm::wasm::WasmSymbolType Type) {
95e3498ec5SRui Ueyama   error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " +
96e3498ec5SRui Ueyama         toString(Existing->getWasmType()) + " in " +
973876d89aSSam Clegg         toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) +
983876d89aSSam Clegg         " in " + toString(File));
99e3498ec5SRui Ueyama }
100e3498ec5SRui Ueyama 
1016f4286fbSHeejin Ahn // Check the type of new symbol matches that of the symbol is replacing.
1026f4286fbSHeejin Ahn // For functions this can also involve verifying that the signatures match.
103cefbf9acSSam Clegg static void checkFunctionType(Symbol *Existing, const InputFile *File,
104e3498ec5SRui Ueyama                               const WasmSignature *NewSig) {
10565d6380cSSam Clegg   auto ExistingFunction = dyn_cast<FunctionSymbol>(Existing);
10665d6380cSSam Clegg   if (!ExistingFunction) {
1073876d89aSSam Clegg     reportTypeError(Existing, File, WASM_SYMBOL_TYPE_FUNCTION);
108e3498ec5SRui Ueyama     return;
109e3498ec5SRui Ueyama   }
110e3498ec5SRui Ueyama 
111cefbf9acSSam Clegg   if (!NewSig)
112cefbf9acSSam Clegg     return;
113cefbf9acSSam Clegg 
114e915a71fSHeejin Ahn   const WasmSignature *OldSig = ExistingFunction->Signature;
115cefbf9acSSam Clegg   if (!OldSig) {
116e915a71fSHeejin Ahn     ExistingFunction->Signature = NewSig;
117cefbf9acSSam Clegg     return;
118cefbf9acSSam Clegg   }
119cefbf9acSSam Clegg 
120cefbf9acSSam Clegg   if (*NewSig != *OldSig)
121ffd0aaf8SSam Clegg     warn("function signature mismatch: " + Existing->getName() +
122e3498ec5SRui Ueyama          "\n>>> defined as " + toString(*OldSig) + " in " +
123e3498ec5SRui Ueyama          toString(Existing->getFile()) + "\n>>> defined as " +
124ffd0aaf8SSam Clegg          toString(*NewSig) + " in " + toString(File));
125e3498ec5SRui Ueyama }
126e3498ec5SRui Ueyama 
127e3498ec5SRui Ueyama static void checkGlobalType(const Symbol *Existing, const InputFile *File,
128e3498ec5SRui Ueyama                             const WasmGlobalType *NewType) {
129e3498ec5SRui Ueyama   if (!isa<GlobalSymbol>(Existing)) {
1303876d89aSSam Clegg     reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL);
131b8621596SSam Clegg     return;
132b8621596SSam Clegg   }
133b8621596SSam Clegg 
134e3498ec5SRui Ueyama   const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType();
135e3498ec5SRui Ueyama   if (*NewType != *OldType) {
136e3498ec5SRui Ueyama     error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " +
137e3498ec5SRui Ueyama           toString(*OldType) + " in " + toString(Existing->getFile()) +
138e3498ec5SRui Ueyama           "\n>>> defined as " + toString(*NewType) + " in " + toString(File));
139c94d393aSSam Clegg   }
14024b3dcd4SSam Clegg }
14124b3dcd4SSam Clegg 
142e915a71fSHeejin Ahn static void checkEventType(const Symbol *Existing, const InputFile *File,
143e915a71fSHeejin Ahn                            const WasmEventType *NewType,
144e915a71fSHeejin Ahn                            const WasmSignature *NewSig) {
145e915a71fSHeejin Ahn   auto ExistingEvent = dyn_cast<EventSymbol>(Existing);
146e915a71fSHeejin Ahn   if (!isa<EventSymbol>(Existing)) {
147e915a71fSHeejin Ahn     reportTypeError(Existing, File, WASM_SYMBOL_TYPE_EVENT);
148e915a71fSHeejin Ahn     return;
149e915a71fSHeejin Ahn   }
150e915a71fSHeejin Ahn 
151e915a71fSHeejin Ahn   const WasmEventType *OldType = cast<EventSymbol>(Existing)->getEventType();
152e915a71fSHeejin Ahn   const WasmSignature *OldSig = ExistingEvent->Signature;
153e915a71fSHeejin Ahn   if (NewType->Attribute != OldType->Attribute)
154e915a71fSHeejin Ahn     error("Event type mismatch: " + Existing->getName() + "\n>>> defined as " +
155e915a71fSHeejin Ahn           toString(*OldType) + " in " + toString(Existing->getFile()) +
156e915a71fSHeejin Ahn           "\n>>> defined as " + toString(*NewType) + " in " + toString(File));
157e915a71fSHeejin Ahn   if (*NewSig != *OldSig)
158e915a71fSHeejin Ahn     warn("Event signature mismatch: " + Existing->getName() +
159e915a71fSHeejin Ahn          "\n>>> defined as " + toString(*OldSig) + " in " +
160e915a71fSHeejin Ahn          toString(Existing->getFile()) + "\n>>> defined as " +
161e915a71fSHeejin Ahn          toString(*NewSig) + " in " + toString(File));
162e915a71fSHeejin Ahn }
163e915a71fSHeejin Ahn 
164e3498ec5SRui Ueyama static void checkDataType(const Symbol *Existing, const InputFile *File) {
165e3498ec5SRui Ueyama   if (!isa<DataSymbol>(Existing))
1663876d89aSSam Clegg     reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA);
167e3498ec5SRui Ueyama }
168e3498ec5SRui Ueyama 
169dfb0b2c7SSam Clegg DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
170ebda41f8SNicholas Wilson                                                    uint32_t Flags,
171ebda41f8SNicholas Wilson                                                    InputFunction *Function) {
172e7245b42SNicola Zaghen   LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n");
173b961abc8SRui Ueyama   assert(!find(Name));
174ebda41f8SNicholas Wilson   SyntheticFunctions.emplace_back(Function);
1754c2cbfe6SSam Clegg   return replaceSymbol<DefinedFunction>(insert(Name, nullptr).first, Name,
1764c2cbfe6SSam Clegg                                         Flags, nullptr, Function);
17750686856SSam Clegg }
17850686856SSam Clegg 
17900245539SSam Clegg DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name,
18000245539SSam Clegg                                                  uint32_t Flags) {
181e7245b42SNicola Zaghen   LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n");
182b961abc8SRui Ueyama   assert(!find(Name));
1834c2cbfe6SSam Clegg   return replaceSymbol<DefinedData>(insert(Name, nullptr).first, Name, Flags);
184c94d393aSSam Clegg }
185c94d393aSSam Clegg 
18693102974SSam Clegg DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags,
18793102974SSam Clegg                                                InputGlobal *Global) {
188e7245b42SNicola Zaghen   LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global
189e7245b42SNicola Zaghen                     << "\n");
190b961abc8SRui Ueyama   assert(!find(Name));
191ebda41f8SNicholas Wilson   SyntheticGlobals.emplace_back(Global);
1924c2cbfe6SSam Clegg   return replaceSymbol<DefinedGlobal>(insert(Name, nullptr).first, Name, Flags,
1934c2cbfe6SSam Clegg                                       nullptr, Global);
19493102974SSam Clegg }
19593102974SSam Clegg 
196e3498ec5SRui Ueyama static bool shouldReplace(const Symbol *Existing, InputFile *NewFile,
197e3498ec5SRui Ueyama                           uint32_t NewFlags) {
198c03c9040SRui Ueyama   // If existing symbol is undefined, replace it.
199e3498ec5SRui Ueyama   if (!Existing->isDefined()) {
200e7245b42SNicola Zaghen     LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: "
201e3498ec5SRui Ueyama                       << Existing->getName() << "\n");
202c03c9040SRui Ueyama     return true;
203c03c9040SRui Ueyama   }
204c03c9040SRui Ueyama 
205c03c9040SRui Ueyama   // Now we have two defined symbols. If the new one is weak, we can ignore it.
206c03c9040SRui Ueyama   if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
207e7245b42SNicola Zaghen     LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n");
208c03c9040SRui Ueyama     return false;
209c03c9040SRui Ueyama   }
210c03c9040SRui Ueyama 
211c03c9040SRui Ueyama   // If the existing symbol is weak, we should replace it.
212e3498ec5SRui Ueyama   if (Existing->isWeak()) {
213e7245b42SNicola Zaghen     LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n");
214c03c9040SRui Ueyama     return true;
215c03c9040SRui Ueyama   }
216c03c9040SRui Ueyama 
217c03c9040SRui Ueyama   // Neither symbol is week. They conflict.
218e3498ec5SRui Ueyama   error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " +
219e3498ec5SRui Ueyama         toString(Existing->getFile()) + "\n>>> defined in " +
220e3498ec5SRui Ueyama         toString(NewFile));
221c03c9040SRui Ueyama   return true;
222b8621596SSam Clegg }
22393e559b1SSam Clegg 
22493e559b1SSam Clegg Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags,
225e3498ec5SRui Ueyama                                         InputFile *File,
226e3498ec5SRui Ueyama                                         InputFunction *Function) {
2278b0b48f3SSam Clegg   LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " ["
2288b0b48f3SSam Clegg                     << (Function ? toString(Function->Signature) : "none")
2298b0b48f3SSam Clegg                     << "]\n");
23093e559b1SSam Clegg   Symbol *S;
23193e559b1SSam Clegg   bool WasInserted;
2324c2cbfe6SSam Clegg   std::tie(S, WasInserted) = insert(Name, File);
233c729c1b4SSam Clegg 
234e3498ec5SRui Ueyama   if (WasInserted || S->isLazy()) {
235e3498ec5SRui Ueyama     replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function);
236e3498ec5SRui Ueyama     return S;
237e3498ec5SRui Ueyama   }
238e3498ec5SRui Ueyama 
239c729c1b4SSam Clegg   if (Function)
240e3498ec5SRui Ueyama     checkFunctionType(S, File, &Function->Signature);
241e3498ec5SRui Ueyama 
2428b0b48f3SSam Clegg   if (shouldReplace(S, File, Flags)) {
2438b0b48f3SSam Clegg     // If the new defined function doesn't have signture (i.e. bitcode
24437b4ee52SSam Clegg     // functions) but the old symbol does then preserve the old signature
2458b0b48f3SSam Clegg     const WasmSignature *OldSig = nullptr;
2468b0b48f3SSam Clegg     if (auto* F = dyn_cast<FunctionSymbol>(S))
247e915a71fSHeejin Ahn       OldSig = F->Signature;
24837b4ee52SSam Clegg     if (auto *L = dyn_cast<LazySymbol>(S))
24937b4ee52SSam Clegg       OldSig = L->Signature;
2508b0b48f3SSam Clegg     auto NewSym = replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function);
251e915a71fSHeejin Ahn     if (!NewSym->Signature)
252e915a71fSHeejin Ahn       NewSym->Signature = OldSig;
2538b0b48f3SSam Clegg   }
25493e559b1SSam Clegg   return S;
25593e559b1SSam Clegg }
25693e559b1SSam Clegg 
25700245539SSam Clegg Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags,
258e3498ec5SRui Ueyama                                     InputFile *File, InputSegment *Segment,
25993102974SSam Clegg                                     uint32_t Address, uint32_t Size) {
260e7245b42SNicola Zaghen   LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address
261e7245b42SNicola Zaghen                     << "\n");
26293e559b1SSam Clegg   Symbol *S;
26393e559b1SSam Clegg   bool WasInserted;
2644c2cbfe6SSam Clegg   std::tie(S, WasInserted) = insert(Name, File);
265c729c1b4SSam Clegg 
266e3498ec5SRui Ueyama   if (WasInserted || S->isLazy()) {
267e3498ec5SRui Ueyama     replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size);
268e3498ec5SRui Ueyama     return S;
269e3498ec5SRui Ueyama   }
270e3498ec5SRui Ueyama 
271e3498ec5SRui Ueyama   checkDataType(S, File);
272e3498ec5SRui Ueyama 
273e3498ec5SRui Ueyama   if (shouldReplace(S, File, Flags))
274e3498ec5SRui Ueyama     replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size);
275c94d393aSSam Clegg   return S;
276c94d393aSSam Clegg }
277c94d393aSSam Clegg 
27893102974SSam Clegg Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags,
279e3498ec5SRui Ueyama                                       InputFile *File, InputGlobal *Global) {
280e7245b42SNicola Zaghen   LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n");
2814c2cbfe6SSam Clegg 
28293102974SSam Clegg   Symbol *S;
28393102974SSam Clegg   bool WasInserted;
2844c2cbfe6SSam Clegg   std::tie(S, WasInserted) = insert(Name, File);
285c729c1b4SSam Clegg 
286e3498ec5SRui Ueyama   if (WasInserted || S->isLazy()) {
287e3498ec5SRui Ueyama     replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global);
28893102974SSam Clegg     return S;
28993102974SSam Clegg   }
29093102974SSam Clegg 
291e3498ec5SRui Ueyama   checkGlobalType(S, File, &Global->getType());
292e3498ec5SRui Ueyama 
293e3498ec5SRui Ueyama   if (shouldReplace(S, File, Flags))
294e3498ec5SRui Ueyama     replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global);
295e3498ec5SRui Ueyama   return S;
296e3498ec5SRui Ueyama }
297e3498ec5SRui Ueyama 
298e915a71fSHeejin Ahn Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags,
299e915a71fSHeejin Ahn                                      InputFile *File, InputEvent *Event) {
300e915a71fSHeejin Ahn   LLVM_DEBUG(dbgs() << "addDefinedEvent:" << Name << "\n");
301e915a71fSHeejin Ahn 
302e915a71fSHeejin Ahn   Symbol *S;
303e915a71fSHeejin Ahn   bool WasInserted;
304e915a71fSHeejin Ahn   std::tie(S, WasInserted) = insert(Name, File);
305e915a71fSHeejin Ahn 
306e915a71fSHeejin Ahn   if (WasInserted || S->isLazy()) {
307e915a71fSHeejin Ahn     replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event);
308e915a71fSHeejin Ahn     return S;
309e915a71fSHeejin Ahn   }
310e915a71fSHeejin Ahn 
311e915a71fSHeejin Ahn   checkEventType(S, File, &Event->getType(), &Event->Signature);
312e915a71fSHeejin Ahn 
313e915a71fSHeejin Ahn   if (shouldReplace(S, File, Flags))
314e915a71fSHeejin Ahn     replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event);
315e915a71fSHeejin Ahn   return S;
316e915a71fSHeejin Ahn }
317e915a71fSHeejin Ahn 
318*7cc07531SSam Clegg Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef Module,
319*7cc07531SSam Clegg                                           uint32_t Flags, InputFile *File,
320e3498ec5SRui Ueyama                                           const WasmSignature *Sig) {
3218b0b48f3SSam Clegg   LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name <<
3228b0b48f3SSam Clegg              " [" << (Sig ? toString(*Sig) : "none") << "]\n");
323c03c9040SRui Ueyama 
324c94d393aSSam Clegg   Symbol *S;
325c94d393aSSam Clegg   bool WasInserted;
3264c2cbfe6SSam Clegg   std::tie(S, WasInserted) = insert(Name, File);
327c729c1b4SSam Clegg 
328e3498ec5SRui Ueyama   if (WasInserted)
329*7cc07531SSam Clegg     replaceSymbol<UndefinedFunction>(S, Name, Module, Flags, File, Sig);
330e3498ec5SRui Ueyama   else if (auto *Lazy = dyn_cast<LazySymbol>(S))
331b961abc8SRui Ueyama     Lazy->fetch();
332cefbf9acSSam Clegg   else
333e3498ec5SRui Ueyama     checkFunctionType(S, File, Sig);
334cefbf9acSSam Clegg 
335c03c9040SRui Ueyama   return S;
336c03c9040SRui Ueyama }
337c03c9040SRui Ueyama 
338e3498ec5SRui Ueyama Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags,
339e3498ec5SRui Ueyama                                       InputFile *File) {
340e7245b42SNicola Zaghen   LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n");
34193102974SSam Clegg 
342e3498ec5SRui Ueyama   Symbol *S;
343e3498ec5SRui Ueyama   bool WasInserted;
3444c2cbfe6SSam Clegg   std::tie(S, WasInserted) = insert(Name, File);
345f989a92dSSam Clegg 
346e3498ec5SRui Ueyama   if (WasInserted)
347e3498ec5SRui Ueyama     replaceSymbol<UndefinedData>(S, Name, Flags, File);
348e3498ec5SRui Ueyama   else if (auto *Lazy = dyn_cast<LazySymbol>(S))
349b961abc8SRui Ueyama     Lazy->fetch();
350e3498ec5SRui Ueyama   else if (S->isDefined())
351e3498ec5SRui Ueyama     checkDataType(S, File);
352c94d393aSSam Clegg   return S;
353c94d393aSSam Clegg }
354c94d393aSSam Clegg 
355e3498ec5SRui Ueyama Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags,
356e3498ec5SRui Ueyama                                         InputFile *File,
357e3498ec5SRui Ueyama                                         const WasmGlobalType *Type) {
358e7245b42SNicola Zaghen   LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n");
359e3498ec5SRui Ueyama 
360e3498ec5SRui Ueyama   Symbol *S;
361e3498ec5SRui Ueyama   bool WasInserted;
3624c2cbfe6SSam Clegg   std::tie(S, WasInserted) = insert(Name, File);
363c729c1b4SSam Clegg 
364e3498ec5SRui Ueyama   if (WasInserted)
365e3498ec5SRui Ueyama     replaceSymbol<UndefinedGlobal>(S, Name, Flags, File, Type);
366e3498ec5SRui Ueyama   else if (auto *Lazy = dyn_cast<LazySymbol>(S))
367b961abc8SRui Ueyama     Lazy->fetch();
368e3498ec5SRui Ueyama   else if (S->isDefined())
369e3498ec5SRui Ueyama     checkGlobalType(S, File, Type);
370e3498ec5SRui Ueyama   return S;
371e3498ec5SRui Ueyama }
372e3498ec5SRui Ueyama 
373e3498ec5SRui Ueyama void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) {
374e7245b42SNicola Zaghen   LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");
375c94d393aSSam Clegg   StringRef Name = Sym->getName();
376c03c9040SRui Ueyama 
377c94d393aSSam Clegg   Symbol *S;
378c94d393aSSam Clegg   bool WasInserted;
3794c2cbfe6SSam Clegg   std::tie(S, WasInserted) = insert(Name, nullptr);
380c03c9040SRui Ueyama 
381c94d393aSSam Clegg   if (WasInserted) {
38237b4ee52SSam Clegg     replaceSymbol<LazySymbol>(S, Name, 0, File, *Sym);
383c03c9040SRui Ueyama     return;
384c03c9040SRui Ueyama   }
385c03c9040SRui Ueyama 
38637b4ee52SSam Clegg   if (!S->isUndefined())
38737b4ee52SSam Clegg     return;
38837b4ee52SSam Clegg 
38937b4ee52SSam Clegg   // The existing symbol is undefined, load a new one from the archive,
39037b4ee52SSam Clegg   // unless the the existing symbol is weak in which case replace the undefined
39137b4ee52SSam Clegg   // symbols with a LazySymbol.
39237b4ee52SSam Clegg   if (S->isWeak()) {
39337b4ee52SSam Clegg     const WasmSignature *OldSig = nullptr;
39437b4ee52SSam Clegg     // In the case of an UndefinedFunction we need to preserve the expected
39537b4ee52SSam Clegg     // signature.
39637b4ee52SSam Clegg     if (auto *F = dyn_cast<UndefinedFunction>(S))
39737b4ee52SSam Clegg       OldSig = F->Signature;
39837b4ee52SSam Clegg     LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n");
39937b4ee52SSam Clegg     auto NewSym = replaceSymbol<LazySymbol>(S, Name, WASM_SYMBOL_BINDING_WEAK,
40037b4ee52SSam Clegg                                             File, *Sym);
40137b4ee52SSam Clegg     NewSym->Signature = OldSig;
40237b4ee52SSam Clegg     return;
40337b4ee52SSam Clegg   }
40437b4ee52SSam Clegg 
405e7245b42SNicola Zaghen   LLVM_DEBUG(dbgs() << "replacing existing undefined\n");
406e3498ec5SRui Ueyama   File->addMember(Sym);
407c94d393aSSam Clegg }
408e0f6fcd0SSam Clegg 
409c4d9aa1bSNicholas Wilson bool SymbolTable::addComdat(StringRef Name) {
410c4d9aa1bSNicholas Wilson   return Comdats.insert(CachedHashStringRef(Name)).second;
411e0f6fcd0SSam Clegg }
412