Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -306,14 +306,14 @@ InputFunction *Function) { if (Sym.isBindingLocal()) return make(Sym.Name, Sym.Flags, this, Function); - return Symtab->addDefined(true, Sym.Name, Sym.Flags, this, Function); + return Symtab->addDefinedFunction(Sym.Name, Sym.Flags, this, Function); } Symbol *ObjFile::createDefinedGlobal(const WasmSymbol &Sym, InputSegment *Segment, uint32_t Address) { if (Sym.isBindingLocal()) return make(Sym.Name, Sym.Flags, this, Segment, Address); - return Symtab->addDefined(false, Sym.Name, Sym.Flags, this, Segment, Address); + return Symtab->addDefinedGlobal(Sym.Name, Sym.Flags, this, Segment, Address); } void ArchiveFile::parse() { Index: wasm/SymbolTable.h =================================================================== --- wasm/SymbolTable.h +++ wasm/SymbolTable.h @@ -42,16 +42,17 @@ std::vector ObjectFiles; - void reportDuplicate(Symbol *Existing, InputFile *NewFile); void reportRemainingUndefines(); ArrayRef getSymbols() const { return SymVector; } Symbol *find(StringRef Name); ObjFile *findComdat(StringRef Name) const; - Symbol *addDefined(bool IsFunction, StringRef Name, uint32_t Flags, - InputFile *F, InputChunk *Chunk = nullptr, - uint32_t Address = 0); + Symbol *addDefinedFunction(StringRef Name, uint32_t Flags, InputFile *F, + InputFunction *Function = nullptr); + Symbol *addDefinedGlobal(StringRef Name, uint32_t Flags, InputFile *F, + InputSegment *Segment = nullptr, + uint32_t Address = 0); Symbol *addUndefined(StringRef Name, Symbol::Kind Kind, uint32_t Flags, InputFile *F, const WasmSignature *Signature = nullptr); Symbol *addUndefinedFunction(StringRef Name, const WasmSignature *Type); Index: wasm/SymbolTable.cpp =================================================================== --- wasm/SymbolTable.cpp +++ wasm/SymbolTable.cpp @@ -71,12 +71,6 @@ return {Sym, true}; } -void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) { - error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " + - toString(Existing->getFile()) + "\n>>> defined in " + - toString(NewFile)); -} - // Check the type of new symbol matches that of the symbol is replacing. // For functions this can also involve verifying that the signatures match. static void checkSymbolTypes(const Symbol &Existing, const InputFile &F, @@ -146,56 +140,73 @@ return replaceSymbol(S, Name, Flags); } -Symbol *SymbolTable::addDefined(bool IsFunction, StringRef Name, uint32_t Flags, - InputFile *F, InputChunk *Chunk, - uint32_t Address) { - if (IsFunction) - DEBUG(dbgs() << "addDefined: func:" << Name << "\n"); - else - DEBUG(dbgs() << "addDefined: global:" << Name << " addr:" << Address - << "\n"); - Symbol *S; - bool WasInserted; +struct NewSymbol { + InputFile *File; + uint32_t Flags; + InputChunk *Chunk; + bool IsFunction; +}; + +static bool shouldReplace(const Symbol &Existing, const NewSymbol &New) { bool Replace = false; bool CheckTypes = false; - std::tie(S, WasInserted) = insert(Name); - if (WasInserted) { - Replace = true; - } else if (S->isLazy()) { + if (Existing.isLazy()) { // Existing symbol is lazy. Replace it without checking types since // lazy symbols don't have any type information. - DEBUG(dbgs() << "replacing existing lazy symbol: " << Name << "\n"); + DEBUG(dbgs() << "replacing existing lazy symbol: " << Existing.getName() + << "\n"); Replace = true; - } else if (!S->isDefined()) { + } else if (!Existing.isDefined()) { // Existing symbol is undefined: replace it, while check types. - DEBUG(dbgs() << "resolving existing undefined symbol: " << Name << "\n"); + DEBUG(dbgs() << "resolving existing undefined symbol: " + << Existing.getName() << "\n"); Replace = true; CheckTypes = true; - } else if ((Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { + } else if ((New.Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { // the new symbol is weak we can ignore it DEBUG(dbgs() << "existing symbol takes precedence\n"); CheckTypes = true; - } else if (S->isWeak()) { + } else if (Existing.isWeak()) { // the existing symbol is, so we replace it DEBUG(dbgs() << "replacing existing weak symbol\n"); Replace = true; CheckTypes = true; } else { // neither symbol is week. They conflict. - reportDuplicate(S, F); + error("duplicate symbol: " + toString(Existing) + "\n>>> defined in " + + toString(Existing.getFile()) + "\n>>> defined in " + + toString(New.File)); } - if (Replace) { - if (CheckTypes) - checkSymbolTypes(*S, *F, IsFunction, Chunk); - if (IsFunction) - replaceSymbol(S, Name, Flags, F, - cast(Chunk)); - else - replaceSymbol(S, Name, Flags, F, cast(Chunk), - Address); - } + if (CheckTypes) + checkSymbolTypes(Existing, *New.File, New.IsFunction, New.Chunk); + + return Replace; +} + +Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, + InputFile *F, InputFunction *Function) { + DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n"); + Symbol *S; + bool WasInserted; + std::tie(S, WasInserted) = insert(Name); + NewSymbol New{F, Flags, Function, true}; + if (WasInserted || shouldReplace(*S, New)) + replaceSymbol(S, Name, Flags, F, Function); + return S; +} + +Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, + InputFile *F, InputSegment *Segment, + uint32_t Address) { + DEBUG(dbgs() << "addDefinedGlobal:" << Name << " addr:" << Address << "\n"); + Symbol *S; + bool WasInserted; + std::tie(S, WasInserted) = insert(Name); + NewSymbol New{F, Flags, Segment, false}; + if (WasInserted || shouldReplace(*S, New)) + replaceSymbol(S, Name, Flags, F, Segment, Address); return S; }