Index: test/wasm/data-layout.ll =================================================================== --- test/wasm/data-layout.ll +++ test/wasm/data-layout.ll @@ -23,27 +23,27 @@ ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1024 +; CHECK-NEXT: Value: 1052 ; CHECK-NEXT: - Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1040 +; CHECK-NEXT: Value: 1024 ; CHECK-NEXT: - Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1048 +; CHECK-NEXT: Value: 1040 ; CHECK-NEXT: - Type: I32 ; CHECK-NEXT: Mutable: false ; CHECK-NEXT: InitExpr: ; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 1052 +; CHECK-NEXT: Value: 1048 ; CHECK: - Type: DATA ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 -; CHECK-NEXT: Index: 4 +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000001F ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 Index: test/wasm/relocatable.ll =================================================================== --- test/wasm/relocatable.ll +++ test/wasm/relocatable.ll @@ -93,6 +93,18 @@ ; CHECK-NEXT: - Name: my_func ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 3 +; CHECK-NEXT: - Name: hello_str +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: Index: 1 +; CHECK-NEXT: - Name: func_addr1 +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: Index: 2 +; CHECK-NEXT: - Name: func_addr2 +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: Index: 3 +; CHECK-NEXT: - Name: data_addr1 +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: Index: 4 ; CHECK-NEXT: - Type: ELEM ; CHECK-NEXT: Segments: ; CHECK-NEXT: - Offset: Index: wasm/Driver.cpp =================================================================== --- wasm/Driver.cpp +++ wasm/Driver.cpp @@ -142,7 +142,6 @@ log("injecting global: " + Name); Symbol *S = Symtab->addDefinedGlobal(Name); S->setVirtualAddress(Value); - S->setOutputIndex(Config->SyntheticGlobals.size()); Config->SyntheticGlobals.emplace_back(S); return S; } Index: wasm/InputFiles.h =================================================================== --- wasm/InputFiles.h +++ wasm/InputFiles.h @@ -103,7 +103,6 @@ size_t NumGlobalImports() const { return GlobalImports; } int32_t FunctionIndexOffset = 0; - int32_t GlobalIndexOffset = 0; int32_t TableIndexOffset = 0; const WasmSection *CodeSection = nullptr; std::vector CodeRelocations; Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -48,7 +48,6 @@ " FunctionIndexOffset : " + Twine(FunctionIndexOffset) + "\n" + " NumFunctionImports : " + Twine(NumFunctionImports()) + "\n" + " TableIndexOffset : " + Twine(TableIndexOffset) + "\n" + - " GlobalIndexOffset : " + Twine(GlobalIndexOffset) + "\n" + " NumGlobalImports : " + Twine(NumGlobalImports()) + "\n"); } @@ -69,15 +68,10 @@ } uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const { - DEBUG(dbgs() << "relocateFunctionIndex: " << Original); const Symbol *Sym = getFunctionSymbol(Original); - uint32_t Index; - if (Sym) - Index = Sym->getOutputIndex(); - else - Index = Original + FunctionIndexOffset; - - DEBUG(dbgs() << " -> " << Index << "\n"); + uint32_t Index = Sym->getOutputIndex(); + DEBUG(dbgs() << "relocateFunctionIndex: " << toString(*Sym) << ": " + << Original << " -> " << Index << "\n"); return Index; } @@ -90,15 +84,10 @@ } uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const { - DEBUG(dbgs() << "relocateGlobalIndex: " << Original); - uint32_t Index; - const Symbol *Sym = getGlobalSymbol(Original); - if (Sym) - Index = Sym->getOutputIndex(); - else - Index = Original + GlobalIndexOffset; - - DEBUG(dbgs() << " -> " << Index << "\n"); + const Symbol* Sym = getGlobalSymbol(Original); + uint32_t Index = Sym->getOutputIndex(); + DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original + << " -> " << Index << "\n"); return Index; } Index: wasm/OutputSections.cpp =================================================================== --- wasm/OutputSections.cpp +++ wasm/OutputSections.cpp @@ -72,9 +72,8 @@ static void applyRelocation(uint8_t *Buf, const OutputRelocation &Reloc) { DEBUG(dbgs() << "write reloc: type=" << Reloc.Reloc.Type - << " index=" << Reloc.Reloc.Index << " new=" << Reloc.NewIndex - << " value=" << Reloc.Value << " offset=" << Reloc.Reloc.Offset - << "\n"); + << " index=" << Reloc.Reloc.Index << " value=" << Reloc.Value + << " offset=" << Reloc.Reloc.Offset << "\n"); Buf += Reloc.Reloc.Offset; int64_t ExistingValue; switch (Reloc.Reloc.Type) { @@ -149,15 +148,18 @@ int32_t OutputOffset) { log("calcRelocations: " + File.getName() + " offset=" + Twine(OutputOffset)); for (const WasmRelocation &Reloc : Relocs) { - int64_t NewIndex = calcNewIndex(File, Reloc); OutputRelocation NewReloc; NewReloc.Reloc = Reloc; NewReloc.Reloc.Offset += OutputOffset; - NewReloc.NewIndex = NewIndex; DEBUG(dbgs() << "reloc: type=" << Reloc.Type << " index=" << Reloc.Index - << " offset=" << Reloc.Offset << " new=" << NewIndex + << " offset=" << Reloc.Offset << " newOffset=" << NewReloc.Reloc.Offset << "\n"); + if (Config->EmitRelocs) + NewReloc.NewIndex = calcNewIndex(File, Reloc); + else + NewReloc.NewIndex = UINT32_MAX; + switch (Reloc.Type) { case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: case R_WEBASSEMBLY_MEMORY_ADDR_I32: @@ -167,7 +169,8 @@ NewReloc.Value += Reloc.Addend; break; default: - NewReloc.Value = NewIndex; + NewReloc.Value = calcNewIndex(File, Reloc); + break; } OutputRelocs.emplace_back(NewReloc); Index: wasm/SymbolTable.h =================================================================== --- wasm/SymbolTable.h +++ wasm/SymbolTable.h @@ -47,6 +47,7 @@ void reportDuplicate(Symbol *Existing, InputFile *NewFile); void reportRemainingUndefines(); + ArrayRef getSymbols() const { return SymVector; } Symbol *find(StringRef Name); Symbol *addDefined(InputFile *F, const WasmSymbol *Sym, @@ -60,6 +61,7 @@ std::pair insert(StringRef Name); llvm::DenseMap SymMap; + std::vector SymVector; }; extern SymbolTable *Symtab; Index: wasm/SymbolTable.cpp =================================================================== --- wasm/SymbolTable.cpp +++ wasm/SymbolTable.cpp @@ -35,8 +35,7 @@ void SymbolTable::reportRemainingUndefines() { std::unordered_set Undefs; - for (auto &I : SymMap) { - Symbol *Sym = I.second; + for (Symbol *Sym : SymVector) { if (Sym->isUndefined() && !Sym->isWeak() && Config->AllowUndefinedSymbols.count(Sym->getName()) == 0) { Undefs.insert(Sym); @@ -68,6 +67,7 @@ if (Sym) return {Sym, false}; Sym = make(Name, false); + SymVector.emplace_back(Sym); return {Sym, true}; } Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -111,8 +111,9 @@ std::vector Types; DenseMap TypeIndices; - std::vector FunctionImports; - std::vector GlobalImports; + std::vector FunctionImports; + std::vector GlobalImports; + std::vector DefinedGlobals; // Elements that are used to construct the final output std::string Header; @@ -217,11 +218,14 @@ } void Writer::createGlobalSection() { + if (DefinedGlobals.empty()) + return; + SyntheticSection *Section = createSyntheticSection(WASM_SEC_GLOBAL); raw_ostream &OS = Section->getStream(); - writeUleb128(OS, NumGlobals, "global count"); - for (const Symbol *Sym : Config->SyntheticGlobals) { + writeUleb128(OS, DefinedGlobals.size(), "global count"); + for (const Symbol *Sym : DefinedGlobals) { WasmGlobal Global; Global.Type = WASM_TYPE_I32; Global.Mutable = Sym == Config->StackPointerSymbol; @@ -229,24 +233,6 @@ Global.InitExpr.Value.Int32 = Sym->getVirtualAddress(); writeGlobal(OS, Global); } - - if (Config->EmitRelocs) { - for (ObjFile *File : Symtab->ObjectFiles) { - uint32_t GlobalIndex = File->NumGlobalImports(); - for (const WasmGlobal &Global : File->getWasmObj()->globals()) { - WasmGlobal RelocatedGlobal(Global); - if (Global.Type != WASM_TYPE_I32) - fatal("unsupported global type: " + Twine(Global.Type)); - if (Global.InitExpr.Opcode != WASM_OPCODE_I32_CONST) - fatal("unsupported global init opcode: " + - Twine(Global.InitExpr.Opcode)); - RelocatedGlobal.InitExpr.Value.Int32 = - File->getRelocatedAddress(GlobalIndex); - writeGlobal(OS, RelocatedGlobal); - ++GlobalIndex; - } - } - } } void Writer::createTableSection() { @@ -261,35 +247,36 @@ } void Writer::createExportSection() { - // Memory is and main function are exported for executables. bool ExportMemory = !Config->Relocatable && !Config->ImportMemory; - bool ExportOther = true; // ??? TODO Config->Relocatable; - bool ExportHidden = Config->Relocatable; Symbol *EntrySym = Symtab->find(Config->Entry); bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined(); + bool ExportHidden = Config->EmitRelocs; - uint32_t NumExports = 0; - - if (ExportMemory) - ++NumExports; + uint32_t NumExports = ExportMemory ? 1 : 0; + std::vector SymbolExports; if (ExportEntry) - ++NumExports; - - if (ExportOther) { - for (ObjFile *File : Symtab->ObjectFiles) { - for (Symbol *Sym : File->getSymbols()) { - if (!Sym->isFunction() || Sym->isLocal() || Sym->isUndefined() || - (Sym->isHidden() && !ExportHidden) || Sym->WrittenToSymtab) - continue; - if (Sym == EntrySym) - continue; - Sym->WrittenToSymtab = true; - ++NumExports; - } - } + SymbolExports.emplace_back(EntrySym); + + for (const Symbol *Sym : Symtab->getSymbols()) { + if (Sym->isUndefined() || Sym->isGlobal()) + continue; + if (Sym->isHidden() && !ExportHidden) + continue; + if (ExportEntry && Sym == EntrySym) + continue; + SymbolExports.emplace_back(Sym); } + for (const Symbol *Sym : DefinedGlobals) { + // Can't export the SP right now because it mutable and mutable globals + // connot be exported. + if (Sym == Config->StackPointerSymbol) + continue; + SymbolExports.emplace_back(Sym); + } + + NumExports += SymbolExports.size(); if (!NumExports) return; @@ -306,34 +293,16 @@ writeExport(OS, MemoryExport); } - if (ExportEntry) { - WasmExport EntryExport; - EntryExport.Name = Config->Entry; - EntryExport.Kind = WASM_EXTERNAL_FUNCTION; - EntryExport.Index = EntrySym->getOutputIndex(); - writeExport(OS, EntryExport); - } - - if (ExportOther) { - for (ObjFile *File : Symtab->ObjectFiles) { - for (Symbol *Sym : File->getSymbols()) { - if (!Sym->isFunction() || Sym->isLocal() || Sym->isUndefined() || - (Sym->isHidden() && !ExportHidden) || !Sym->WrittenToSymtab) - continue; - if (Sym == EntrySym) - continue; - Sym->WrittenToSymtab = false; - log("Export: " + Sym->getName()); - WasmExport Export; - Export.Name = Sym->getName(); - Export.Index = Sym->getOutputIndex(); - if (Sym->isFunction()) - Export.Kind = WASM_EXTERNAL_FUNCTION; - else - Export.Kind = WASM_EXTERNAL_GLOBAL; - writeExport(OS, Export); - } - } + for (const Symbol *Sym : SymbolExports) { + log("Export: " + Sym->getName()); + WasmExport Export; + Export.Name = Sym->getName(); + Export.Index = Sym->getOutputIndex(); + if (Sym->isFunction()) + Export.Kind = WASM_EXTERNAL_FUNCTION; + else + Export.Kind = WASM_EXTERNAL_GLOBAL; + writeExport(OS, Export); } } @@ -557,7 +526,6 @@ } void Writer::calculateOffsets() { - NumGlobals = Config->SyntheticGlobals.size(); NumTableElems = InitialTableOffset; for (ObjFile *File : Symtab->ObjectFiles) { @@ -568,13 +536,6 @@ FunctionImports.size() - File->NumFunctionImports() + NumFunctions; NumFunctions += WasmFile->functions().size(); - // Global Index - if (Config->EmitRelocs) { - File->GlobalIndexOffset = - GlobalImports.size() - File->NumGlobalImports() + NumGlobals; - NumGlobals += WasmFile->globals().size(); - } - // Memory if (WasmFile->memories().size()) { if (WasmFile->memories().size() > 1) { @@ -640,19 +601,31 @@ } void Writer::assignSymbolIndexes() { + uint32_t GlobalIndex = GlobalImports.size(); + + if (Config->StackPointerSymbol) { + DefinedGlobals.emplace_back(Config->StackPointerSymbol); + Config->StackPointerSymbol->setOutputIndex(GlobalIndex++); + } + + if (Config->EmitRelocs) + DefinedGlobals.reserve(Symtab->getSymbols().size()); + for (ObjFile *File : Symtab->ObjectFiles) { DEBUG(dbgs() << "assignSymbolIndexes: " << File->getName() << "\n"); for (Symbol *Sym : File->getSymbols()) { if (Sym->hasOutputIndex() || !Sym->isDefined()) continue; - if (Sym->getFile() && isa(Sym->getFile())) { - auto *Obj = cast(Sym->getFile()); - if (Sym->isFunction()) - Sym->setOutputIndex(Obj->FunctionIndexOffset + - Sym->getFunctionIndex()); - else - Sym->setOutputIndex(Obj->GlobalIndexOffset + Sym->getGlobalIndex()); + if (Sym->isFunction()) { + if (Sym->getFile() && isa(Sym->getFile())) { + auto *Obj = cast(Sym->getFile()); + Sym->setOutputIndex(Obj->FunctionIndexOffset + + Sym->getFunctionIndex()); + } + } else if (Config->EmitRelocs) { + DefinedGlobals.emplace_back(Sym); + Sym->setOutputIndex(GlobalIndex++); } } }