Index: wasm/InputFiles.h =================================================================== --- wasm/InputFiles.h +++ wasm/InputFiles.h @@ -99,7 +99,6 @@ uint32_t getRelocatedAddress(uint32_t Index) const; size_t getNumFunctionImports() const { return NumFunctionImports; } - size_t getNumGlobalImports() const { return NumGlobalImports; } const WasmSection *CodeSection = nullptr; @@ -113,12 +112,14 @@ private: Symbol *createDefined(const WasmSymbol &Sym, const InputSegment *Segment = nullptr, - InputFunction *Function = nullptr); + InputFunction *Function = nullptr, + uint32_t Address = 0); Symbol *createUndefined(const WasmSymbol &Sym, const WasmSignature *Signature = nullptr); void initializeSymbols(); InputSegment *getSegment(const WasmSymbol &WasmSym) const; const WasmSignature *getFunctionSig(const WasmSymbol &Sym) const; + uint32_t getGlobalValue(const WasmSymbol &Sym) const; InputFunction *getFunction(const WasmSymbol &Sym) const; // List of all symbols referenced or defined by this file. Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -136,6 +136,12 @@ To.push_back(R); } +uint32_t ObjFile::getGlobalValue(const WasmSymbol &Sym) const { + const WasmGlobal &Global = getWasmObj()->globals()[Sym.ElementIndex - NumGlobalImports]; + assert(Global.Type == llvm::wasm::WASM_TYPE_I32); + return Global.InitExpr.Value.Int32; +} + // Get the signature for a given function symbol, either by looking // it up in function sections (for defined functions), of the imports section // (for imported functions). @@ -206,7 +212,7 @@ S = createUndefined(WasmSym); break; case WasmSymbol::SymbolType::GLOBAL_EXPORT: - S = createDefined(WasmSym, getSegment(WasmSym), nullptr); + S = createDefined(WasmSym, getSegment(WasmSym), nullptr, getGlobalValue(WasmSym)); break; case WasmSymbol::SymbolType::FUNCTION_EXPORT: S = createDefined(WasmSym, nullptr, getFunction(WasmSym)); @@ -252,26 +258,35 @@ Symbol *ObjFile::createUndefined(const WasmSymbol &Sym, const WasmSignature *Signature) { - return Symtab->addUndefined(this, &Sym, Signature); + Symbol::Kind Kind; + if (Sym.Type == WasmSymbol::SymbolType::FUNCTION_IMPORT) + Kind = Symbol::Kind::UndefinedFunctionKind; + else if (Sym.Type == WasmSymbol::SymbolType::GLOBAL_IMPORT) + Kind = Symbol::Kind::UndefinedGlobalKind; + else + llvm_unreachable("invalid undefined symbol type"); + return Symtab->addUndefined(Sym.Name, Kind, Sym.Flags, this, Signature); } Symbol *ObjFile::createDefined(const WasmSymbol &Sym, const InputSegment *Segment, - InputFunction *Function) { + InputFunction *Function, uint32_t Address) { + Symbol::Kind Kind; + if (Sym.Type == WasmSymbol::SymbolType::FUNCTION_EXPORT) + Kind = Symbol::Kind::DefinedFunctionKind; + else if (Sym.Type == WasmSymbol::SymbolType::GLOBAL_EXPORT) + Kind = Symbol::Kind::DefinedGlobalKind; + else + llvm_unreachable("invalid defined symbol type"); + Symbol *S; if (Sym.isLocal()) { S = make(Sym.Name, true); - Symbol::Kind Kind; - if (Sym.Type == WasmSymbol::SymbolType::FUNCTION_EXPORT) - Kind = Symbol::Kind::DefinedFunctionKind; - else if (Sym.Type == WasmSymbol::SymbolType::GLOBAL_EXPORT) - Kind = Symbol::Kind::DefinedGlobalKind; - else - llvm_unreachable("invalid local symbol type"); - S->update(Kind, this, &Sym, Segment, Function); + S->update(Kind, this, Sym.Flags, Segment, Function, Address); return S; } - return Symtab->addDefined(this, &Sym, Segment, Function); + return Symtab->addDefined(Sym.Name, Kind, Sym.Flags, this, Segment, Function, + Address); } void ArchiveFile::parse() { Index: wasm/SymbolTable.h =================================================================== --- wasm/SymbolTable.h +++ wasm/SymbolTable.h @@ -17,7 +17,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/Support/raw_ostream.h" -using llvm::object::WasmSymbol; using llvm::wasm::WasmSignature; namespace lld { @@ -49,11 +48,11 @@ ArrayRef getSymbols() const { return SymVector; } Symbol *find(StringRef Name); - Symbol *addDefined(InputFile *F, const WasmSymbol *Sym, - const InputSegment *Segment = nullptr, - InputFunction *Function = nullptr); - Symbol *addUndefined(InputFile *F, const WasmSymbol *Sym, - const WasmSignature *Signature = nullptr); + Symbol *addDefined(StringRef Name, Symbol::Kind Kind, uint32_t Flags, + InputFile *F, const InputSegment *Segment = nullptr, + InputFunction *Function = 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); Symbol *addDefinedGlobal(StringRef Name); void addLazy(ArchiveFile *F, const Archive::Symbol *Sym); Index: wasm/SymbolTable.cpp =================================================================== --- wasm/SymbolTable.cpp +++ wasm/SymbolTable.cpp @@ -20,6 +20,7 @@ #define DEBUG_TYPE "lld" using namespace llvm; +using namespace llvm::wasm; using namespace lld; using namespace lld::wasm; @@ -80,18 +81,18 @@ // 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, - const WasmSymbol &New, + Symbol::Kind Kind, const WasmSignature *NewSig) { if (Existing.isLazy()) return; - bool NewIsFunction = New.Type == WasmSymbol::SymbolType::FUNCTION_EXPORT || - New.Type == WasmSymbol::SymbolType::FUNCTION_IMPORT; + bool NewIsFunction = Kind == Symbol::Kind::UndefinedFunctionKind || + Kind == Symbol::Kind::DefinedFunctionKind; // First check the symbol types match (i.e. either both are function // symbols or both are data symbols). if (Existing.isFunction() != NewIsFunction) { - error("symbol type mismatch: " + New.Name + "\n>>> defined as " + + error("symbol type mismatch: " + Existing.getName() + "\n>>> defined as " + (Existing.isFunction() ? "Function" : "Global") + " in " + toString(Existing.getFile()) + "\n>>> defined as " + (NewIsFunction ? "Function" : "Global") + " in " + F.getName()); @@ -106,16 +107,17 @@ if (!Existing.hasFunctionType()) return; - DEBUG(dbgs() << "checkSymbolTypes: " << New.Name << "\n"); + DEBUG(dbgs() << "checkSymbolTypes: " << Existing.getName() << "\n"); assert(NewSig); const WasmSignature &OldSig = Existing.getFunctionType(); if (*NewSig == OldSig) return; - error("function signature mismatch: " + New.Name + "\n>>> defined as " + - toString(OldSig) + " in " + toString(Existing.getFile()) + - "\n>>> defined as " + toString(*NewSig) + " in " + F.getName()); + error("function signature mismatch: " + Existing.getName() + + "\n>>> defined as " + toString(OldSig) + " in " + + toString(Existing.getFile()) + "\n>>> defined as " + toString(*NewSig) + + " in " + F.getName()); } Symbol *SymbolTable::addDefinedGlobal(StringRef Name) { @@ -130,40 +132,38 @@ return S; } -Symbol *SymbolTable::addDefined(InputFile *F, const WasmSymbol *Sym, +Symbol *SymbolTable::addDefined(StringRef Name, Symbol::Kind Kind, + uint32_t Flags, InputFile *F, const InputSegment *Segment, - InputFunction *Function) { - DEBUG(dbgs() << "addDefined: " << Sym->Name << "\n"); + InputFunction *Function, uint32_t Address) { + DEBUG(dbgs() << "addDefined: " << Name << "\n"); Symbol *S; bool WasInserted; - Symbol::Kind Kind = Symbol::DefinedFunctionKind; - if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_EXPORT) - Kind = Symbol::DefinedGlobalKind; - std::tie(S, WasInserted) = insert(Sym->Name); + std::tie(S, WasInserted) = insert(Name); if (WasInserted) { - S->update(Kind, F, Sym, Segment, Function); + S->update(Kind, F, Flags, Segment, Function, Address); } else if (S->isLazy()) { // The existing symbol is lazy. Replace it without checking types since // lazy symbols don't have any type information. - DEBUG(dbgs() << "replacing existing lazy symbol: " << Sym->Name << "\n"); - S->update(Kind, F, Sym, Segment, Function); + DEBUG(dbgs() << "replacing existing lazy symbol: " << Name << "\n"); + S->update(Kind, F, Flags, Segment, Function); } else if (!S->isDefined()) { // The existing symbol table entry is undefined. The new symbol replaces // it, after checking the type matches - DEBUG(dbgs() << "resolving existing undefined symbol: " << Sym->Name + DEBUG(dbgs() << "resolving existing undefined symbol: " << Name << "\n"); - checkSymbolTypes(*S, *F, *Sym, Function ? &Function->Signature : nullptr); - S->update(Kind, F, Sym, Segment, Function); - } else if (Sym->isWeak()) { + checkSymbolTypes(*S, *F, Kind, Function ? &Function->Signature : nullptr); + S->update(Kind, F, Flags, Segment, Function, Address); + } else if ((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"); } else if (S->isWeak()) { // the new symbol is not weak and the existing symbol is, so we replace // it DEBUG(dbgs() << "replacing existing weak symbol\n"); - checkSymbolTypes(*S, *F, *Sym, Function ? &Function->Signature : nullptr); - S->update(Kind, F, Sym, Segment, Function); + checkSymbolTypes(*S, *F, Kind, Function ? &Function->Signature : nullptr); + S->update(Kind, F, Flags, Segment, Function, Address); } else { // neither symbol is week. They conflict. reportDuplicate(S, F); @@ -185,17 +185,14 @@ return S; } -Symbol *SymbolTable::addUndefined(InputFile *F, const WasmSymbol *Sym, - const WasmSignature *Type) { - DEBUG(dbgs() << "addUndefined: " << Sym->Name << "\n"); +Symbol *SymbolTable::addUndefined(StringRef Name, Symbol::Kind Kind, uint32_t Flags, + InputFile *F, const WasmSignature *Type) { + DEBUG(dbgs() << "addUndefined: " << Name << "\n"); Symbol *S; bool WasInserted; - Symbol::Kind Kind = Symbol::UndefinedFunctionKind; - if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_IMPORT) - Kind = Symbol::UndefinedGlobalKind; - std::tie(S, WasInserted) = insert(Sym->Name); + std::tie(S, WasInserted) = insert(Name); if (WasInserted) { - S->update(Kind, F, Sym); + S->update(Kind, F, Flags); if (Type) S->setFunctionType(Type); } else if (S->isLazy()) { @@ -204,7 +201,7 @@ AF->addMember(&S->getArchiveSymbol()); } else if (S->isDefined()) { DEBUG(dbgs() << "resolved by existing\n"); - checkSymbolTypes(*S, *F, *Sym, Type); + checkSymbolTypes(*S, *F, Kind, Type); } return S; } Index: wasm/Symbols.h =================================================================== --- wasm/Symbols.h +++ wasm/Symbols.h @@ -15,9 +15,6 @@ #include "llvm/Object/Wasm.h" using llvm::object::Archive; -using llvm::object::WasmSymbol; -using llvm::wasm::WasmExport; -using llvm::wasm::WasmImport; using llvm::wasm::WasmSignature; namespace lld { @@ -41,8 +38,8 @@ InvalidKind, }; - Symbol(StringRef Name, bool IsLocal) - : WrittenToSymtab(0), WrittenToNameSec(0), IsLocal(IsLocal), Name(Name) {} + Symbol(StringRef Name, uint32_t Flags) + : WrittenToSymtab(0), WrittenToNameSec(0), Flags(Flags), Name(Name) {} Kind getKind() const { return SymbolKind; } @@ -57,7 +54,7 @@ SymbolKind == UndefinedFunctionKind; } bool isGlobal() const { return !isFunction(); } - bool isLocal() const { return IsLocal; } + bool isLocal() const; bool isWeak() const; bool isHidden() const; @@ -89,9 +86,9 @@ void setVirtualAddress(uint32_t VA); - void update(Kind K, InputFile *F = nullptr, const WasmSymbol *Sym = nullptr, + void update(Kind K, InputFile *F = nullptr, uint32_t Flags = 0, const InputSegment *Segment = nullptr, - const InputFunction *Function = nullptr); + const InputFunction *Function = nullptr, uint32_t Address = 0); void setArchiveSymbol(const Archive::Symbol &Sym) { ArchiveSymbol = Sym; } const Archive::Symbol &getArchiveSymbol() { return ArchiveSymbol; } @@ -102,18 +99,17 @@ unsigned WrittenToNameSec : 1; protected: - unsigned IsLocal : 1; + uint32_t Flags; + uint32_t VirtualAddress; StringRef Name; Archive::Symbol ArchiveSymbol = {nullptr, 0, 0}; Kind SymbolKind = InvalidKind; InputFile *File = nullptr; - const WasmSymbol *Sym = nullptr; const InputSegment *Segment = nullptr; const InputFunction *Function = nullptr; llvm::Optional OutputIndex; llvm::Optional TableIndex; - llvm::Optional VirtualAddress; const WasmSignature *FunctionType = nullptr; }; Index: wasm/Symbols.cpp =================================================================== --- wasm/Symbols.cpp +++ wasm/Symbols.cpp @@ -19,6 +19,7 @@ #define DEBUG_TYPE "lld" using namespace llvm; +using namespace llvm::wasm; using namespace lld; using namespace lld::wasm; @@ -41,17 +42,7 @@ DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n"); if (isUndefined()) return UINT32_MAX; - if (VirtualAddress.hasValue()) - return VirtualAddress.getValue(); - - ObjFile *Obj = cast(File); - assert(Sym != nullptr); - const WasmGlobal &Global = - Obj->getWasmObj() - ->globals()[Sym->ElementIndex - Obj->getNumGlobalImports()]; - assert(Global.Type == llvm::wasm::WASM_TYPE_I32); - assert(Segment); - return Segment->translateVA(Global.InitExpr.Value.Int32); + return Segment ? Segment->translateVA(VirtualAddress) : VirtualAddress; } uint32_t Symbol::getOutputIndex() const { @@ -64,7 +55,7 @@ void Symbol::setVirtualAddress(uint32_t Value) { DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n"); - assert(!VirtualAddress.hasValue()); + assert(isGlobal()); VirtualAddress = Value; } @@ -81,18 +72,29 @@ TableIndex = Index; } -void Symbol::update(Kind K, InputFile *F, const WasmSymbol *WasmSym, - const InputSegment *Seg, const InputFunction *Func) { +void Symbol::update(Kind K, InputFile *F, uint32_t Flags_, + const InputSegment *Seg, const InputFunction *Func, + uint32_t Address) { SymbolKind = K; File = F; - Sym = WasmSym; + Flags = Flags_; Segment = Seg; Function = Func; + if (Address) + setVirtualAddress(Address); } -bool Symbol::isWeak() const { return Sym && Sym->isWeak(); } +bool Symbol::isWeak() const { + return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK; +} -bool Symbol::isHidden() const { return Sym && Sym->isHidden(); } +bool Symbol::isLocal() const { + return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL; +} + +bool Symbol::isHidden() const { + return (Flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN; +} std::string lld::toString(const wasm::Symbol &Sym) { if (Config->Demangle)