Index: include/llvm/BinaryFormat/Wasm.h =================================================================== --- include/llvm/BinaryFormat/Wasm.h +++ include/llvm/BinaryFormat/Wasm.h @@ -90,7 +90,7 @@ }; struct WasmFunction { - uint32_t Index; + uint32_t Index; // Wasm Function index space std::vector Locals; ArrayRef Body; uint32_t CodeSectionOffset; Index: include/llvm/Object/Wasm.h =================================================================== --- include/llvm/Object/Wasm.h +++ include/llvm/Object/Wasm.h @@ -42,31 +42,39 @@ }; WasmSymbol(StringRef Name, SymbolType Type, uint32_t Section, - uint32_t ElementIndex, uint32_t FunctionType = 0) - : Name(Name), Type(Type), Section(Section), ElementIndex(ElementIndex), - FunctionType(FunctionType) {} + uint32_t SymbolIndex, uint32_t WasmIndex, + uint32_t FunctionType = 0) + : Name(Name), Type(Type), Section(Section), SymbolIndex(SymbolIndex), + WasmIndex(WasmIndex), FunctionType(FunctionType) {} StringRef Name; SymbolType Type; uint32_t Section; uint32_t Flags = 0; - // Index into either the function or global index space. - uint32_t ElementIndex; + // Index into either the function or global Symbol index space. The Symbol + // index space consists of the imports followed by the exports (each of + // which creates a Symbol). + uint32_t SymbolIndex; + // Index into the the function or global Wasm index space. This is the + // index space used by the Wasm format for referring to a function or + // global, and consists of the imports followed by the function/global + // definitions. + // To be crystal clear, the following Wasm file has three linker symbols, + // and two Wasm callable items: + // (import "env" "externalFn" ...) + // (export "exportedFn" (func $exportedFnBody)) + // (export "exportedFnAlias" (func $exportedFnBody)) + // (func $exportedFnBody ...) + // Symbol index space = + // [ 0: import externalFn, 1: export exportedFn, 2: export exportedFnAlias ] + // Wasm index space = + // [ 0: import externalFn, 1: definition exportedFnBody ] + uint32_t WasmIndex; // For function, the type index uint32_t FunctionType; - // Symbols can be both exported and imported (in the case of the weakly - // defined symbol). In this the import index is stored as AltIndex. - uint32_t AltIndex = 0; - bool HasAltIndex = false; - - void setAltIndex(uint32_t Index) { - HasAltIndex = true; - AltIndex = Index; - } - bool isFunction() const { return Type == WasmSymbol::SymbolType::FUNCTION_IMPORT || Type == WasmSymbol::SymbolType::FUNCTION_EXPORT; @@ -99,7 +107,8 @@ void print(raw_ostream &Out) const { Out << "Name=" << Name << ", Type=" << static_cast(Type) - << ", Flags=" << Flags << " ElemIndex=" << ElementIndex; + << ", Flags=" << Flags << " SymbolIndex=" << SymbolIndex + << ", WasmIndex=" << WasmIndex; } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) @@ -143,13 +152,18 @@ ArrayRef globals() const { return Globals; } ArrayRef exports() const { return Exports; } const wasm::WasmLinkingData& linkingData() const { return LinkingData; } - uint32_t getNumberOfSymbols() const { return Symbols.size(); } + uint32_t getNumberOfSymbols() const + { return FunctionSymbols.size() + GlobalSymbols.size(); } ArrayRef elements() const { return ElemSegments; } ArrayRef dataSegments() const { return DataSegments; } ArrayRef functions() const { return Functions; } ArrayRef comdats() const { return Comdats; } ArrayRef debugNames() const { return DebugNames; } uint32_t startFunction() const { return StartFunction; } + uint32_t getNumImportedGlobals() const { return NumImportedGlobals; } + uint32_t getNumImportedFunctions() const { return NumImportedFunctions; } + uint32_t getNumExportedGlobals() const { return NumExportedGlobals; } + uint32_t getNumExportedFunctions() const { return NumExportedFunctions; } void moveSymbolNext(DataRefImpl &Symb) const override; @@ -204,7 +218,9 @@ bool isRelocatableObject() const override; private: - bool isValidFunctionIndex(uint32_t Index) const; + bool isValidFunctionWasmIndex(uint32_t Index) const; + bool isValidFunctionSymbolIndex(uint32_t Index) const; + bool isValidGlobalWasmIndex(uint32_t Index) const; const WasmSection &getWasmSection(DataRefImpl Ref) const; const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const; @@ -236,7 +252,7 @@ Error parseRelocSection(StringRef Name, const uint8_t *Ptr, const uint8_t *End); - void populateSymbolTable(); + Error populateSymbolTable(); wasm::WasmObjectHeader Header; std::vector Sections; @@ -250,7 +266,8 @@ std::vector ElemSegments; std::vector DataSegments; std::vector Functions; - std::vector Symbols; + std::vector FunctionSymbols; + std::vector GlobalSymbols; std::vector Comdats; std::vector DebugNames; uint32_t StartFunction = -1; @@ -258,10 +275,13 @@ wasm::WasmLinkingData LinkingData; uint32_t NumImportedGlobals = 0; uint32_t NumImportedFunctions = 0; + uint32_t NumExportedGlobals = 0; + uint32_t NumExportedFunctions = 0; uint32_t ImportSection = 0; uint32_t ExportSection = 0; - StringMap SymbolMap; + // TODO: will get rid of this map in next commit + StringMap> SymbolMap; // name to pair(kind,index) }; } // end namespace object Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -211,8 +211,10 @@ // Index values to use for fixing up call_indirect type indices. // Maps function symbols to the index of the type of the function DenseMap TypeIndices; - // Maps function/global symbols to the function/global index space. + // Maps function/global symbols to the function/global Symbol index space. DenseMap SymbolIndices; + // Maps function/global symbols to the function/global Wasm index space. + DenseMap WasmIndices; // Maps function symbol indices to the table element index space. Used // for TABLE_INDEX relocation types (i.e. address taken functions). SmallVector TableIndices; @@ -508,7 +510,7 @@ if (!Sym->isDefined()) return 0; - uint32_t GlobalIndex = SymbolIndices[Sym]; + uint32_t GlobalIndex = WasmIndices[Sym]; const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports]; uint64_t Address = Global.InitialValue + RelEntry.Addend; @@ -526,11 +528,11 @@ const WasmRelocationEntry &RelEntry) { const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol); assert(Sym->isFunction()); - if (!SymbolIndices.count(Sym)) + if (!WasmIndices.count(Sym)) report_fatal_error("symbol not found in function/global index space: " + RelEntry.Symbol->getName()); - uint32_t SymbolIndex = SymbolIndices[Sym]; - int32_t TableIndex = TableIndices[SymbolIndex]; + uint32_t WasmIndex = WasmIndices[Sym]; + int32_t TableIndex = TableIndices[WasmIndex]; if (TableIndex < 0) report_fatal_error("symbol not found in table index space: " + Sym->getName()); @@ -1020,6 +1022,16 @@ return Pair.first->second; } +static void addFlags(SmallVector, 4> &SymbolFlags, + const MCSymbolWasm &WS) { + uint32_t Flags = (WS.isWeak() ? wasm::WASM_SYMBOL_BINDING_WEAK : 0) | + (WS.isHidden() ? wasm::WASM_SYMBOL_VISIBILITY_HIDDEN : 0) | + (!WS.isExternal() && WS.isDefined() ? wasm::WASM_SYMBOL_BINDING_LOCAL : 0); + if (Flags != 0) { + SymbolFlags.emplace_back(WS.getName(), Flags); + } +} + void WasmObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { DEBUG(dbgs() << "WasmObjectWriter::writeObject\n"); @@ -1034,6 +1046,8 @@ SmallVector, 4> SymbolFlags; SmallVector, 2> InitFuncs; std::map> Comdats; + unsigned NumFuncExports = 0; + unsigned NumGlobalExports = 0; SmallVector DataSegments; uint32_t DataSize = 0; @@ -1131,8 +1145,7 @@ continue; // If the symbol is not defined in this translation unit, import it. - if ((!WS.isDefined() && !WS.isComdat()) || - WS.isVariable()) { + if (!WS.isDefined() && !WS.isComdat()) { WasmImport Import; Import.ModuleName = WS.getModuleName(); Import.FieldName = WS.getName(); @@ -1140,19 +1153,22 @@ if (WS.isFunction()) { Import.Kind = wasm::WASM_EXTERNAL_FUNCTION; Import.Type = getFunctionType(WS); - SymbolIndices[&WS] = NumFunctionImports; + WasmIndices[&WS] = SymbolIndices[&WS] = NumFunctionImports; ++NumFunctionImports; } else { Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; Import.Type = int32_t(PtrType); Import.IsMutable = false; - SymbolIndices[&WS] = NumGlobalImports; + unsigned SymbolIndex = NumGlobalImports; + WasmIndices[&WS] = SymbolIndices[&WS] = SymbolIndex; // If this global is the stack pointer, make it mutable. if (WS.getName() == "__stack_pointer") Import.IsMutable = true; ++NumGlobalImports; + + addFlags(SymbolFlags, WS); } Imports.push_back(Import); @@ -1196,23 +1212,18 @@ const auto &WS = static_cast(S); DEBUG(dbgs() << "MCSymbol: '" << S << "'" - << " isDefined=" << S.isDefined() << " isExternal=" - << S.isExternal() << " isTemporary=" << S.isTemporary() + << " isDefined=" << S.isDefined() + << " isExternal=" << S.isExternal() + << " isTemporary=" << S.isTemporary() << " isFunction=" << WS.isFunction() << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden() << " isVariable=" << WS.isVariable() << "\n"); - if (WS.isWeak() || WS.isHidden()) { - uint32_t Flags = (WS.isWeak() ? wasm::WASM_SYMBOL_BINDING_WEAK : 0) | - (WS.isHidden() ? wasm::WASM_SYMBOL_VISIBILITY_HIDDEN : 0); - SymbolFlags.emplace_back(WS.getName(), Flags); - } - if (WS.isVariable()) continue; - unsigned Index; + unsigned WasmIndex, SymbolIndex; if (WS.isFunction()) { if (WS.isDefined()) { @@ -1225,21 +1236,24 @@ "function symbols must have a size set with .size"); // A definition. Take the next available index. - Index = NumFunctionImports + Functions.size(); + WasmIndex = NumFunctionImports + Functions.size(); + SymbolIndex = NumFunctionImports + NumFuncExports; + ++NumFuncExports; // Prepare the function. WasmFunction Func; Func.Type = getFunctionType(WS); Func.Sym = &WS; - SymbolIndices[&WS] = Index; + SymbolIndices[&WS] = SymbolIndex; + WasmIndices[&WS] = WasmIndex; Functions.push_back(Func); } else { // An import; the index was assigned above. - Index = SymbolIndices.find(&WS)->second; + WasmIndex = SymbolIndex = SymbolIndices.find(&WS)->second; } - DEBUG(dbgs() << " -> function index: " << Index << "\n"); - } else { + DEBUG(dbgs() << " -> function index: " << WasmIndex << "\n"); + } else { if (WS.isTemporary() && !WS.getSize()) continue; @@ -1256,7 +1270,9 @@ // For each global, prepare a corresponding wasm global holding its // address. For externals these will also be named exports. - Index = NumGlobalImports + Globals.size(); + WasmIndex = NumGlobalImports + Globals.size(); + SymbolIndex = NumGlobalImports + NumGlobalExports; + ++NumGlobalExports; auto &DataSection = static_cast(WS.getSection()); assert(DataSection.isWasmData()); @@ -1266,16 +1282,19 @@ Global.HasImport = false; Global.InitialValue = DataSection.getMemoryOffset() + Layout.getSymbolOffset(WS); Global.ImportIndex = 0; - SymbolIndices[&WS] = Index; - DEBUG(dbgs() << " -> global index: " << Index << "\n"); + SymbolIndices[&WS] = SymbolIndex; + WasmIndices[&WS] = WasmIndex; + DEBUG(dbgs() << " -> global index: " << WasmIndex << "\n"); Globals.push_back(Global); } + addFlags(SymbolFlags, WS); + // If the symbol is visible outside this translation unit, export it. if (WS.isDefined()) { WasmExport Export; Export.FieldName = WS.getName(); - Export.Index = Index; + Export.Index = WasmIndex; if (WS.isFunction()) Export.Kind = wasm::WASM_EXTERNAL_FUNCTION; else @@ -1283,14 +1302,11 @@ DEBUG(dbgs() << " -> export " << Exports.size() << "\n"); Exports.push_back(Export); - if (!WS.isExternal()) - SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL); - if (WS.isFunction()) { auto &Section = static_cast(WS.getSection()); if (const MCSymbolWasm *C = Section.getGroup()) Comdats[C->getName()].emplace_back( - WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index}); + WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, WasmIndex}); } } } @@ -1308,22 +1324,32 @@ const auto &WS = static_cast(S); const MCSymbolWasm *ResolvedSym = ResolveSymbol(WS); DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym << "'\n"); - assert(SymbolIndices.count(ResolvedSym) > 0); - uint32_t Index = SymbolIndices.find(ResolvedSym)->second; - DEBUG(dbgs() << " -> index:" << Index << "\n"); + assert(WasmIndices.count(ResolvedSym) > 0); + uint32_t WasmIndex = WasmIndices.find(ResolvedSym)->second; + DEBUG(dbgs() << " -> index:" << WasmIndex << "\n"); + + unsigned SymbolIndex; + if (WS.isFunction()) { + SymbolIndex = NumFunctionImports + NumFuncExports; + ++NumFuncExports; + } else { + SymbolIndex = NumGlobalImports + NumGlobalExports; + ++NumGlobalExports; + } + SymbolIndices[&WS] = SymbolIndex; + WasmIndices[&WS] = WasmIndex; + + addFlags(SymbolFlags, WS); WasmExport Export; Export.FieldName = WS.getName(); - Export.Index = Index; + Export.Index = WasmIndex; if (WS.isFunction()) Export.Kind = wasm::WASM_EXTERNAL_FUNCTION; else Export.Kind = wasm::WASM_EXTERNAL_GLOBAL; DEBUG(dbgs() << " -> export " << Exports.size() << "\n"); Exports.push_back(Export); - - if (!WS.isExternal()) - SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL); } { @@ -1337,11 +1363,11 @@ return; assert(Rel.Symbol->isFunction()); const MCSymbolWasm* WS = ResolveSymbol(*Rel.Symbol); - uint32_t SymbolIndex = SymbolIndices[WS]; - if (TableIndices[SymbolIndex] == -1) { - TableIndices[SymbolIndex] = TableElems.size() + InitialTableOffset; + uint32_t WasmIndex = WasmIndices[WS]; + if (TableIndices[WasmIndex] == -1) { + TableIndices[WasmIndex] = TableElems.size() + InitialTableOffset; DEBUG(dbgs() << " -> adding to table: " << TableElems.size() << "\n"); - TableElems.push_back(SymbolIndex); + TableElems.push_back(WasmIndex); } }; Index: lib/Object/WasmObjectFile.cpp =================================================================== --- lib/Object/WasmObjectFile.cpp +++ lib/Object/WasmObjectFile.cpp @@ -288,7 +288,7 @@ return make_error("Function named more than once", object_error::parse_failed); StringRef Name = readString(Ptr); - if (!isValidFunctionIndex(Index) || Name.empty()) + if (!isValidFunctionWasmIndex(Index) || Name.empty()) return make_error("Invalid name entry", object_error::parse_failed); DebugNames.push_back(wasm::WasmFunctionName{Index, Name}); @@ -317,67 +317,86 @@ return Error::success(); } -void WasmObjectFile::populateSymbolTable() { +Error WasmObjectFile::populateSymbolTable() { + FunctionSymbols.reserve(NumImportedFunctions + NumExportedFunctions); + GlobalSymbols.reserve(NumImportedGlobals + NumExportedGlobals); + // Add imports to symbol table - size_t GlobalIndex = 0; - size_t FunctionIndex = 0; for (const wasm::WasmImport& Import : Imports) { + WasmSymbol::SymbolType ImportType; + std::vector *Symbols; + unsigned FunctionType = 0; switch (Import.Kind) { case wasm::WASM_EXTERNAL_GLOBAL: assert(Import.Global.Type == wasm::WASM_TYPE_I32); - SymbolMap.try_emplace(Import.Field, Symbols.size()); - Symbols.emplace_back(Import.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT, - ImportSection, GlobalIndex++); - DEBUG(dbgs() << "Adding import: " << Symbols.back() - << " sym index:" << Symbols.size() << "\n"); + Symbols = &GlobalSymbols; + ImportType = WasmSymbol::SymbolType::GLOBAL_IMPORT; break; case wasm::WASM_EXTERNAL_FUNCTION: - SymbolMap.try_emplace(Import.Field, Symbols.size()); - Symbols.emplace_back(Import.Field, - WasmSymbol::SymbolType::FUNCTION_IMPORT, - ImportSection, FunctionIndex++, Import.SigIndex); - DEBUG(dbgs() << "Adding import: " << Symbols.back() - << " sym index:" << Symbols.size() << "\n"); + Symbols = &FunctionSymbols; + ImportType = WasmSymbol::SymbolType::FUNCTION_IMPORT; + FunctionType = Import.SigIndex; break; default: - break; + continue; } + if (!SymbolMap.try_emplace(Import.Field, Import.Kind, Symbols->size()).second) + return make_error( + "Duplicate symbol name " + Import.Field, + object_error::parse_failed); + unsigned SymbolIndex = Symbols->size(); + unsigned WasmIndex = SymbolIndex; + Symbols->emplace_back(Import.Field, ImportType, ImportSection, SymbolIndex, + WasmIndex, FunctionType); + DEBUG(dbgs() << "Adding import: " << Symbols->back() + << " sym index:" << SymbolIndex << "\n"); } // Add exports to symbol table for (const wasm::WasmExport& Export : Exports) { - if (Export.Kind == wasm::WASM_EXTERNAL_FUNCTION || - Export.Kind == wasm::WASM_EXTERNAL_GLOBAL) { - WasmSymbol::SymbolType ExportType = - Export.Kind == wasm::WASM_EXTERNAL_FUNCTION - ? WasmSymbol::SymbolType::FUNCTION_EXPORT - : WasmSymbol::SymbolType::GLOBAL_EXPORT; - auto Pair = SymbolMap.try_emplace(Export.Name, Symbols.size()); - if (Pair.second) { - Symbols.emplace_back(Export.Name, ExportType, - ExportSection, Export.Index); - DEBUG(dbgs() << "Adding export: " << Symbols.back() - << " sym index:" << Symbols.size() << "\n"); - } else { - uint32_t SymIndex = Pair.first->second; - const WasmSymbol &OldSym = Symbols[SymIndex]; - WasmSymbol NewSym(Export.Name, ExportType, ExportSection, Export.Index); - NewSym.setAltIndex(OldSym.ElementIndex); - Symbols[SymIndex] = NewSym; - - DEBUG(dbgs() << "Replacing existing symbol: " << NewSym - << " sym index:" << SymIndex << "\n"); - } - } - if (Export.Kind == wasm::WASM_EXTERNAL_FUNCTION) { + WasmSymbol::SymbolType ExportType; + std::vector *Symbols; + unsigned FunctionType = 0; + switch (Export.Kind) { + case wasm::WASM_EXTERNAL_GLOBAL: + assert(isValidGlobalWasmIndex(Export.Index)); + if (Export.Index < NumImportedGlobals) + return make_error("symbol cannot export an import", + object_error::parse_failed); + Symbols = &GlobalSymbols; + ExportType = WasmSymbol::SymbolType::GLOBAL_EXPORT; + break; + case wasm::WASM_EXTERNAL_FUNCTION: { + if (Export.Index < NumImportedFunctions) + return make_error("symbol cannot export an import", + object_error::parse_failed); + Symbols = &FunctionSymbols; + ExportType = WasmSymbol::SymbolType::FUNCTION_EXPORT; + FunctionType = FunctionTypes[Export.Index - NumImportedFunctions]; auto &Function = Functions[Export.Index - NumImportedFunctions]; if (Function.Name.empty()) { // Use the export's name to set a name for the Function, but only if one // hasn't already been set. Function.Name = Export.Name; } + break; } + default: + continue; + } + if (!SymbolMap.try_emplace(Export.Name, Export.Kind, Symbols->size()).second) + return make_error( + "Duplicate symbol name " + Export.Name, + object_error::parse_failed); + unsigned SymbolIndex = Symbols->size(); + unsigned WasmIndex = Export.Index; + Symbols->emplace_back(Export.Name, ExportType, ExportSection, SymbolIndex, + WasmIndex, FunctionType); + DEBUG(dbgs() << "Adding export: " << Symbols->back() + << " sym index:" << SymbolIndex << "\n"); } + + return Error::success(); } Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr, @@ -391,7 +410,8 @@ // Only populate the symbol table with imports and exports if the object // has a linking section (i.e. its a relocatable object file). Otherwise // the global might not represent symbols at all. - populateSymbolTable(); + if (Error Err = populateSymbolTable()) + return Err; while (Ptr < End) { uint8_t Type = readVarint7(Ptr); @@ -409,7 +429,10 @@ "Invalid symbol name in linking section: " + Symbol, object_error::parse_failed); } - uint32_t SymIndex = iter->second; + uint32_t Kind = iter->second.first; + uint32_t SymIndex = iter->second.second; + std::vector &Symbols = + Kind == wasm::WASM_EXTERNAL_FUNCTION ? FunctionSymbols : GlobalSymbols; assert(SymIndex < Symbols.size()); Symbols[SymIndex].Flags = Flags; DEBUG(dbgs() << "Set symbol flags index:" @@ -441,7 +464,7 @@ wasm::WasmInitFunc Init; Init.Priority = readVaruint32(Ptr); Init.FunctionIndex = readVaruint32(Ptr); - if (!isValidFunctionIndex(Init.FunctionIndex)) + if (!isValidFunctionSymbolIndex(Init.FunctionIndex)) return make_error("Invalid function index: " + Twine(Init.FunctionIndex), object_error::parse_failed); @@ -501,7 +524,7 @@ DataSegments[Index].Data.Comdat = Name; break; case wasm::WASM_COMDAT_FUNCTION: - if (Index < NumImportedFunctions || !isValidFunctionIndex(Index)) + if (Index < NumImportedFunctions || !isValidFunctionWasmIndex(Index)) return make_error("COMDAT function index out of range", object_error::parse_failed); Index -= NumImportedFunctions; @@ -736,16 +759,17 @@ Ex.Index = readVaruint32(Ptr); switch (Ex.Kind) { case wasm::WASM_EXTERNAL_FUNCTION: - if (Ex.Index >= FunctionTypes.size() + NumImportedFunctions) + ++NumExportedFunctions; + if (!isValidFunctionWasmIndex(Ex.Index)) return make_error("Invalid function export", object_error::parse_failed); break; - case wasm::WASM_EXTERNAL_GLOBAL: { - if (Ex.Index >= Globals.size() + NumImportedGlobals) + case wasm::WASM_EXTERNAL_GLOBAL: + ++NumExportedGlobals; + if (!isValidGlobalWasmIndex(Ex.Index)) return make_error("Invalid global export", object_error::parse_failed); break; - } case wasm::WASM_EXTERNAL_MEMORY: case wasm::WASM_EXTERNAL_TABLE: break; @@ -761,13 +785,21 @@ return Error::success(); } -bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const { - return Index < FunctionTypes.size() + NumImportedFunctions; +bool WasmObjectFile::isValidFunctionWasmIndex(uint32_t Index) const { + return Index < NumImportedFunctions + FunctionTypes.size(); +} + +bool WasmObjectFile::isValidFunctionSymbolIndex(uint32_t Index) const { + return Index < NumImportedFunctions + NumExportedFunctions; +} + +bool WasmObjectFile::isValidGlobalWasmIndex(uint32_t Index) const { + return Index < NumImportedGlobals + Globals.size(); } Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) { StartFunction = readVaruint32(Ptr); - if (!isValidFunctionIndex(StartFunction)) + if (!isValidFunctionWasmIndex(StartFunction)) return make_error("Invalid start function", object_error::parse_failed); return Error::success(); @@ -906,12 +938,15 @@ basic_symbol_iterator WasmObjectFile::symbol_end() const { DataRefImpl Ref; - Ref.d.a = Symbols.size(); + Ref.d.a = FunctionSymbols.size() + GlobalSymbols.size(); return BasicSymbolRef(Ref, this); } const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const { - return Symbols[Symb.d.a]; + unsigned Index = Symb.d.a; + return Index >= FunctionSymbols.size() + ? GlobalSymbols[Index - FunctionSymbols.size()] + : FunctionSymbols[Index]; } const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const { @@ -931,9 +966,9 @@ case WasmSymbol::SymbolType::FUNCTION_IMPORT: case WasmSymbol::SymbolType::GLOBAL_IMPORT: case WasmSymbol::SymbolType::FUNCTION_EXPORT: - return Sym.ElementIndex; + return Sym.WasmIndex; case WasmSymbol::SymbolType::GLOBAL_EXPORT: { - uint32_t GlobalIndex = Sym.ElementIndex - NumImportedGlobals; + uint32_t GlobalIndex = Sym.WasmIndex - NumImportedGlobals; assert(GlobalIndex < Globals.size()); const wasm::WasmGlobal &Global = Globals[GlobalIndex]; // WasmSymbols correspond only to I32_CONST globals Index: test/MC/WebAssembly/global-ctor-dtor.ll =================================================================== --- test/MC/WebAssembly/global-ctor-dtor.ll +++ test/MC/WebAssembly/global-ctor-dtor.ll @@ -161,8 +161,6 @@ ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 4 ; CHECK-NEXT: SymbolInfo: -; CHECK-NEXT: - Name: __dso_handle -; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] ; CHECK-NEXT: - Name: .Lcall_dtors.42 ; CHECK-NEXT: Flags: [ BINDING_LOCAL ] ; CHECK-NEXT: - Name: .Lregister_call_dtors.42 @@ -171,6 +169,8 @@ ; CHECK-NEXT: Flags: [ BINDING_LOCAL ] ; CHECK-NEXT: - Name: .Lregister_call_dtors ; CHECK-NEXT: Flags: [ BINDING_LOCAL ] +; CHECK-NEXT: - Name: __dso_handle +; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: .data.global1 Index: test/MC/WebAssembly/weak-alias.ll =================================================================== --- test/MC/WebAssembly/weak-alias.ll +++ test/MC/WebAssembly/weak-alias.ll @@ -63,32 +63,23 @@ ; CHECK-NEXT: ElemType: ANYFUNC ; CHECK-NEXT: Limits: ; CHECK-NEXT: Initial: 0x00000001 -; CHECK-NEXT: - Module: env -; CHECK-NEXT: Field: foo_alias -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: SigIndex: 0 -; CHECK-NEXT: - Module: env -; CHECK-NEXT: Field: bar_alias -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: GlobalType: I32 -; CHECK-NEXT: GlobalMutable: false ; CHECK-NEXT: - Type: FUNCTION ; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0 ] ; CHECK-NEXT: - Type: GLOBAL ; CHECK-NEXT: Globals: -; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 -; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 16 -; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: @@ -98,83 +89,83 @@ ; CHECK-NEXT: Exports: ; CHECK-NEXT: - Name: foo ; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: - Name: call_direct ; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 2 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Name: call_alias ; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 3 +; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: call_direct_ptr ; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 4 +; CHECK-NEXT: Index: 3 ; CHECK-NEXT: - Name: direct_address ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: - Name: call_alias_ptr ; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 5 +; CHECK-NEXT: Index: 4 ; CHECK-NEXT: - Name: alias_address ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 2 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Name: bar ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 3 +; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Name: foo_alias ; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: - Name: bar_alias ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: Index: 3 +; CHECK-NEXT: Index: 2 ; CHECK-NEXT: - Type: ELEM ; CHECK-NEXT: Segments: ; CHECK-NEXT: - Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1 -; CHECK-NEXT: Functions: [ 1 ] +; CHECK-NEXT: Functions: [ 0 ] ; CHECK-NEXT: - Type: CODE ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Offset: 0x00000009 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 5 ; CHECK-NEXT: Offset: 0x00000012 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Offset: 0x0000001E ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TYPE_INDEX_LEB ; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Offset: 0x00000024 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB -; CHECK-NEXT: Index: 2 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x00000031 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TYPE_INDEX_LEB ; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Offset: 0x00000037 ; CHECK-NEXT: Functions: -; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 41000B -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 1081808080000B -; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 1080808080000B -; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 1085808080000B +; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 410028028880808000118080808000000B -; CHECK-NEXT: - Index: 5 +; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 410028029080808000118080808000000B ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Offset: 0x0000000F ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 5 ; CHECK-NEXT: Offset: 0x00000018 ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 @@ -199,25 +190,19 @@ ; CHECK-NEXT: Name: name ; CHECK-NEXT: FunctionNames: ; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Name: foo_alias -; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Name: foo -; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Name: call_direct -; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Name: call_alias -; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: Name: call_direct_ptr -; CHECK-NEXT: - Index: 5 +; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Name: call_alias_ptr ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 20 ; CHECK-NEXT: SymbolInfo: -; CHECK-NEXT: - Name: foo_alias -; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] -; CHECK-NEXT: - Name: bar_alias -; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] ; CHECK-NEXT: - Name: foo ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] ; CHECK-NEXT: - Name: call_direct @@ -228,6 +213,10 @@ ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] ; CHECK-NEXT: - Name: call_alias_ptr ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; CHECK-NEXT: - Name: foo_alias +; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] +; CHECK-NEXT: - Name: bar_alias +; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: .data.bar @@ -244,13 +233,13 @@ ; CHECK-NEXT: ... ; CHECK-SYMS: SYMBOL TABLE: -; CHECK-SYMS-NEXT: 00000001 gw F EXPORT .hidden foo_alias -; CHECK-SYMS-NEXT: 00000000 gw EXPORT .hidden bar_alias -; CHECK-SYMS-NEXT: 00000001 g F EXPORT .hidden foo -; CHECK-SYMS-NEXT: 00000002 g F EXPORT .hidden call_direct -; CHECK-SYMS-NEXT: 00000003 g F EXPORT .hidden call_alias -; CHECK-SYMS-NEXT: 00000004 g F EXPORT .hidden call_direct_ptr -; CHECK-SYMS-NEXT: 00000008 g EXPORT direct_address -; CHECK-SYMS-NEXT: 00000005 g F EXPORT .hidden call_alias_ptr -; CHECK-SYMS-NEXT: 00000010 g EXPORT alias_address -; CHECK-SYMS-NEXT: 00000000 g EXPORT bar +; CHECK-SYMS-NEXT: 00000000 g F EXPORT .hidden foo +; CHECK-SYMS-NEXT: 00000001 g F EXPORT .hidden call_direct +; CHECK-SYMS-NEXT: 00000002 g F EXPORT .hidden call_alias +; CHECK-SYMS-NEXT: 00000003 g F EXPORT .hidden call_direct_ptr +; CHECK-SYMS-NEXT: 00000004 g F EXPORT .hidden call_alias_ptr +; CHECK-SYMS-NEXT: 00000000 gw F EXPORT .hidden foo_alias +; CHECK-SYMS-NEXT: 00000008 g EXPORT direct_address +; CHECK-SYMS-NEXT: 00000010 g EXPORT alias_address +; CHECK-SYMS-NEXT: 00000000 g EXPORT bar +; CHECK-SYMS-NEXT: 00000000 gw EXPORT .hidden bar_alias Index: test/MC/WebAssembly/weak.ll =================================================================== --- test/MC/WebAssembly/weak.ll +++ test/MC/WebAssembly/weak.ll @@ -32,8 +32,8 @@ ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 0 ; CHECK-NEXT: SymbolInfo: -; CHECK-NEXT: - Name: weak_external_data -; CHECK-NEXT: Flags: [ BINDING_WEAK ] ; CHECK-NEXT: - Name: weak_function ; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] +; CHECK-NEXT: - Name: weak_external_data +; CHECK-NEXT: Flags: [ BINDING_WEAK ] ; CHECK-NEXT: ...