Index: test/wasm/call-indirect.ll =================================================================== --- test/wasm/call-indirect.ll +++ test/wasm/call-indirect.ll @@ -52,7 +52,7 @@ ; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - I64 ; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 0, 2 ] +; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 0, 2, 1 ] ; CHECK-NEXT: - Type: TABLE ; CHECK-NEXT: Tables: ; CHECK-NEXT: - ElemType: ANYFUNC @@ -114,6 +114,9 @@ ; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 42012000118380808000001A0B +; CHECK-NEXT: - Index: 5 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 0B ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 Index: test/wasm/function-imports-first.ll =================================================================== --- test/wasm/function-imports-first.ll +++ test/wasm/function-imports-first.ll @@ -22,7 +22,7 @@ ; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - F32 ; CHECK: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 1 ] +; CHECK-NEXT: FunctionTypes: [ 0, 1, 0 ] ; CHECK: - Type: CODE ; CHECK-NEXT: Functions: ; CHECK-NEXT: - Index: 0 @@ -31,6 +31,9 @@ ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 41000B +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 0B ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 0 @@ -41,4 +44,6 @@ ; CHECK-NEXT: Name: _start ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Name: ret32 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Name: __wasm_call_ctors ; CHECK-NEXT: ... Index: test/wasm/function-imports.ll =================================================================== --- test/wasm/function-imports.ll +++ test/wasm/function-imports.ll @@ -23,15 +23,18 @@ ; CHECK-NEXT: ReturnType: NORESULT ; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 1 ] +; CHECK-NEXT: FunctionTypes: [ 0, 1, 1 ] ; CHECK: - Type: CODE ; CHECK-NEXT: Functions: ; CHECK: - Index: 0 ; CHECK: - Index: 1 +; CHECK: - Index: 2 ; CHECK: Name: name ; CHECK-NEXT: FunctionNames: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: ret32 ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Name: _start +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Name: __wasm_call_ctors ; CHECK-NEXT: ... Index: test/wasm/init-fini.ll =================================================================== --- test/wasm/init-fini.ll +++ test/wasm/init-fini.ll @@ -27,7 +27,16 @@ ; RUN: lld -flavor wasm %t.o %t.global-ctor-dtor.o -o %t.wasm ; RUN: obj2yaml %t.wasm | FileCheck %s -; CHECK: Name: linking +; CHECK: - Type: ELEM +; CHECK-NEXT: Segments: +; CHECK-NEXT: - Offset: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 1 +; CHECK-NEXT: Functions: [ 4, 9 ] + +; CHECK: Body: 100010051007100A0B +; CHECK-NEXT: - Type: CUSTOM +; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 0 ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: name @@ -54,6 +63,8 @@ ; CHECK-NEXT: Name: .Lcall_dtors ; CHECK-NEXT: - Index: 10 ; CHECK-NEXT: Name: .Lregister_call_dtors +; CHECK-NEXT: - Index: 11 +; CHECK-NEXT: Name: __wasm_call_ctors ; CHECK-NEXT: ... Index: test/wasm/local-symbols.ll =================================================================== --- test/wasm/local-symbols.ll +++ test/wasm/local-symbols.ll @@ -24,8 +24,11 @@ ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: ReturnType: I32 ; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: ReturnType: NORESULT +; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 0 ] +; CHECK-NEXT: FunctionTypes: [ 0, 0, 1 ] ; CHECK-NEXT: - Type: TABLE ; CHECK-NEXT: Tables: ; CHECK-NEXT: - ElemType: ANYFUNC @@ -60,6 +63,9 @@ ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 41010B +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 0B ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 @@ -78,4 +84,6 @@ ; CHECK-NEXT: Name: baz ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Name: _start +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Name: __wasm_call_ctors ; CHECK-NEXT: ... Index: test/wasm/stack-pointer.ll =================================================================== --- test/wasm/stack-pointer.ll +++ test/wasm/stack-pointer.ll @@ -18,8 +18,11 @@ ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: ReturnType: I32 ; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: ReturnType: NORESULT +; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0 ] +; CHECK-NEXT: FunctionTypes: [ 0, 1 ] ; CHECK-NEXT: - Type: TABLE ; CHECK-NEXT: Tables: ; CHECK-NEXT: - ElemType: ANYFUNC @@ -46,6 +49,9 @@ ; CHECK-NEXT: - Name: _start ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Index: 0 +; CHECK-NEXT: - Name: __wasm_call_ctors +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 1 ; CHECK-NEXT: - Type: CODE ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB @@ -55,6 +61,9 @@ ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 23808080800041106B1A41000B +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 0B ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 0 @@ -63,4 +72,6 @@ ; CHECK-NEXT: FunctionNames: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: _start +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: __wasm_call_ctors ; CHECK-NEXT: ... Index: test/wasm/weak-alias-overide.ll =================================================================== --- test/wasm/weak-alias-overide.ll +++ test/wasm/weak-alias-overide.ll @@ -30,7 +30,7 @@ ; CHECK-NEXT: ReturnType: NORESULT ; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 0, 0, 0, 0 ] +; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 0, 0, 0, 0, 1 ] ; CHECK-NEXT: - Type: TABLE ; CHECK-NEXT: Tables: ; CHECK-NEXT: - ElemType: ANYFUNC @@ -108,6 +108,9 @@ ; CHECK-NEXT: - Type: I32 ; CHECK-NEXT: Count: 2 ; CHECK-NEXT: Body: 23808080800041106B220024808080800020004182808080003602081082808080002101200041106A24808080800020010B +; CHECK-NEXT: - Index: 7 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 0B ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 0 @@ -128,4 +131,6 @@ ; CHECK-NEXT: Name: call_alias_ptr ; CHECK-NEXT: - Index: 6 ; CHECK-NEXT: Name: call_direct_ptr +; CHECK-NEXT: - Index: 7 +; CHECK-NEXT: Name: __wasm_call_ctors ; CHECK-NEXT: ... Index: test/wasm/weak-alias.ll =================================================================== --- test/wasm/weak-alias.ll +++ test/wasm/weak-alias.ll @@ -23,8 +23,11 @@ ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: ReturnType: I32 ; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: ReturnType: NORESULT +; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 0 ] +; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 0, 1 ] ; CHECK-NEXT: - Type: TABLE ; CHECK-NEXT: Tables: ; CHECK-NEXT: - ElemType: ANYFUNC @@ -99,6 +102,9 @@ ; CHECK-NEXT: - Type: I32 ; CHECK-NEXT: Count: 2 ; CHECK-NEXT: Body: 23808080800041106B220024808080800020004182808080003602081081808080002101200041106A24808080800020010B +; CHECK-NEXT: - Index: 6 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 0B ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 0 @@ -117,4 +123,6 @@ ; CHECK-NEXT: Name: call_alias_ptr ; CHECK-NEXT: - Index: 5 ; CHECK-NEXT: Name: call_direct_ptr +; CHECK-NEXT: - Index: 6 +; CHECK-NEXT: Name: __wasm_call_ctors ; CHECK-NEXT: ... Index: test/wasm/weak-symbols.ll =================================================================== --- test/wasm/weak-symbols.ll +++ test/wasm/weak-symbols.ll @@ -23,8 +23,11 @@ ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: ReturnType: I32 ; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: ReturnType: NORESULT +; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0 ] +; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 1 ] ; CHECK-NEXT: - Type: TABLE ; CHECK-NEXT: Tables: ; CHECK-NEXT: - ElemType: ANYFUNC @@ -83,6 +86,9 @@ ; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 4181808080000B +; CHECK-NEXT: - Index: 5 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 0B ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 @@ -103,4 +109,6 @@ ; CHECK-NEXT: Name: exportWeak1 ; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Name: exportWeak2 +; CHECK-NEXT: - Index: 5 +; CHECK-NEXT: Name: __wasm_call_ctors ; CHECK-NEXT: ... Index: test/wasm/weak-undefined.ll =================================================================== --- test/wasm/weak-undefined.ll +++ test/wasm/weak-undefined.ll @@ -33,8 +33,11 @@ ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: ReturnType: I32 ; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: ReturnType: NORESULT +; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 0, 0 ] +; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 1 ] ; CHECK-NEXT: - Type: TABLE ; CHECK-NEXT: Tables: ; CHECK-NEXT: - ElemType: ANYFUNC @@ -78,6 +81,9 @@ ; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 4100280280808080000B +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Locals: +; CHECK-NEXT: Body: 0B ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 0 Index: wasm/Config.h =================================================================== --- wasm/Config.h +++ wasm/Config.h @@ -35,11 +35,13 @@ uint32_t MaxMemory; uint32_t ZStackSize; llvm::StringRef Entry; + llvm::StringRef CtorFunction = "__wasm_call_ctors"; llvm::StringRef OutputFile; llvm::StringSet<> AllowUndefinedSymbols; std::vector SearchPaths; Symbol *StackPointerSymbol = nullptr; + Symbol *CtorSymbol = nullptr; }; // The only instance of Configuration struct. Index: wasm/Driver.cpp =================================================================== --- wasm/Driver.cpp +++ wasm/Driver.cpp @@ -273,15 +273,16 @@ error("undefined symbols specified for relocatable output file"); if (!Config->Relocatable) { - if (!Config->Entry.empty()) { - static WasmSignature Signature = {{}, WASM_TYPE_NORESULT}; + static WasmSignature Signature = {{}, WASM_TYPE_NORESULT}; + if (!Config->Entry.empty()) addSyntheticUndefinedFunction(Config->Entry, &Signature); - } // Handle the `--undefined ` options. for (StringRef S : args::getStrings(Args, OPT_undefined)) addSyntheticUndefinedFunction(S, nullptr); + Config->CtorSymbol = Symtab->addDefinedFunction( + Config->CtorFunction, &Signature, WASM_SYMBOL_VISIBILITY_HIDDEN); Config->StackPointerSymbol = Symtab->addDefinedGlobal("__stack_pointer"); } Index: wasm/InputChunks.h =================================================================== --- wasm/InputChunks.h +++ wasm/InputChunks.h @@ -50,7 +50,7 @@ std::vector OutRelocations; protected: - InputChunk(const ObjFile &F) : File(F) {} + InputChunk(const ObjFile *F) : File(F) {} virtual ~InputChunk() = default; void calcRelocations(); virtual const uint8_t *getData() const = 0; @@ -58,7 +58,7 @@ std::vector Relocations; int32_t OutputOffset = 0; - const ObjFile &File; + const ObjFile *File; }; // Represents a WebAssembly data segment which can be included as part of @@ -71,7 +71,7 @@ // each global variable. class InputSegment : public InputChunk { public: - InputSegment(const WasmSegment &Seg, const ObjFile &F) + InputSegment(const WasmSegment &Seg, const ObjFile *F) : InputChunk(F), Segment(Seg) {} // Translate an offset in the input segment to an offset in the output @@ -108,13 +108,13 @@ // combined to create the final output CODE section. class InputFunction : public InputChunk { public: - InputFunction(const WasmSignature &S, const WasmFunction &Func, - const ObjFile &F) + InputFunction(const WasmSignature &S, const WasmFunction *Func, + const ObjFile *F) : InputChunk(F), Signature(S), Function(Func) {} - uint32_t getSize() const override { return Function.Size; } + uint32_t getSize() const override { return Function->Size; } const uint8_t *getData() const override { - return File.CodeSection->Content.data() + getInputSectionOffset(); + return File->CodeSection->Content.data() + getInputSectionOffset(); } uint32_t getOutputIndex() const { return OutputIndex.getValue(); }; @@ -128,12 +128,26 @@ protected: uint32_t getInputSectionOffset() const override { - return Function.CodeSectionOffset; + return Function->CodeSectionOffset; } - const WasmFunction &Function; + const WasmFunction *Function; llvm::Optional OutputIndex; }; +class SyntheticFunction : public InputFunction { +public: + SyntheticFunction(const WasmSignature &S, StringRef Body) + : InputFunction(S, nullptr, nullptr), Body(Body) {} + + uint32_t getSize() const override { return Body.size(); } + const uint8_t *getData() const override { + return reinterpret_cast(Body.data()); + } + +protected: + StringRef Body; +}; + } // namespace wasm } // namespace lld Index: wasm/InputChunks.cpp =================================================================== --- wasm/InputChunks.cpp +++ wasm/InputChunks.cpp @@ -30,6 +30,8 @@ } void InputChunk::copyRelocations(const WasmSection &Section) { + if (Section.Relocations.empty()) + return; size_t Start = getInputSectionOffset(); size_t Size = getSize(); for (const WasmRelocation &R : Section.Relocations) @@ -92,8 +94,10 @@ // output section. Calculates the updated index and offset for each relocation // as well as the value to write out in the final binary. void InputChunk::calcRelocations() { + if (Relocations.empty()) + return; int32_t Off = getOutputOffset() - getInputSectionOffset(); - log("calcRelocations: " + File.getName() + " offset=" + Twine(Off)); + log("calcRelocations: " + File->getName() + " offset=" + Twine(Off)); for (const WasmRelocation &Reloc : Relocations) { OutputRelocation NewReloc; NewReloc.Reloc = Reloc; @@ -104,16 +108,16 @@ << " newOffset=" << NewReloc.Reloc.Offset << "\n"); if (Config->EmitRelocs) - NewReloc.NewIndex = File.calcNewIndex(Reloc); + NewReloc.NewIndex = File->calcNewIndex(Reloc); switch (Reloc.Type) { case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: case R_WEBASSEMBLY_MEMORY_ADDR_I32: case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - NewReloc.Value = File.getRelocatedAddress(Reloc.Index) + Reloc.Addend; + NewReloc.Value = File->getRelocatedAddress(Reloc.Index) + Reloc.Addend; break; default: - NewReloc.Value = File.calcNewIndex(Reloc); + NewReloc.Value = File->calcNewIndex(Reloc); break; } Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -188,7 +188,7 @@ GlobalSymbols.resize(NumGlobalImports + WasmObj->globals().size()); for (const WasmSegment &S : WasmObj->dataSegments()) { - InputSegment *Seg = make(S, *this); + InputSegment *Seg = make(S, this); Seg->copyRelocations(*DataSection); Segments.emplace_back(Seg); } @@ -199,7 +199,7 @@ for (size_t I = 0; I < Funcs.size(); ++I) { const WasmFunction &Func = Funcs[I]; const WasmSignature &Sig = Types[FuncTypes[I]]; - InputFunction *F = make(Sig, Func, *this); + InputFunction *F = make(Sig, &Func, this); F->copyRelocations(*CodeSection); Functions.emplace_back(F); } Index: wasm/SymbolTable.h =================================================================== --- wasm/SymbolTable.h +++ wasm/SymbolTable.h @@ -55,6 +55,8 @@ InputFile *F, const WasmSignature *Signature = nullptr); Symbol *addUndefinedFunction(StringRef Name, const WasmSignature *Type); Symbol *addDefinedGlobal(StringRef Name); + Symbol *addDefinedFunction(StringRef Name, const WasmSignature *Type, + uint32_t Flags); void addLazy(ArchiveFile *F, const Archive::Symbol *Sym); private: Index: wasm/SymbolTable.cpp =================================================================== --- wasm/SymbolTable.cpp +++ wasm/SymbolTable.cpp @@ -119,6 +119,22 @@ " in " + F.getName()); } +Symbol *SymbolTable::addDefinedFunction(StringRef Name, + const WasmSignature *Type, + uint32_t Flags) { + DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n"); + Symbol *S; + bool WasInserted; + std::tie(S, WasInserted) = insert(Name); + if (WasInserted) { + S->update(Symbol::DefinedFunctionKind, nullptr, Flags); + S->setFunctionType(Type); + } else if (!S->isFunction()) { + error("symbol type mismatch: " + Name); + } + return S; +} + Symbol *SymbolTable::addDefinedGlobal(StringRef Name) { DEBUG(dbgs() << "addDefinedGlobal: " << Name << "\n"); Symbol *S; Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -68,7 +68,10 @@ private: void openFile(); - uint32_t getTypeIndex(const WasmSignature &Sig); + uint32_t lookupType(const WasmSignature &Sig); + uint32_t registerType(const WasmSignature &Sig); + void createCtorFunction(); + void calculateInitFunctions(); void assignIndexes(); void calculateImports(); void calculateOffsets(); @@ -78,7 +81,7 @@ void createHeader(); void createSections(); SyntheticSection *createSyntheticSection(uint32_t Type, - std::string Name = ""); + StringRef Name = ""); // Builtin sections void createTypeSection(); @@ -113,12 +116,15 @@ std::vector DefinedGlobals; std::vector DefinedFunctions; std::vector IndirectFunctions; + std::vector InitFunctions; // Elements that are used to construct the final output std::string Header; std::vector OutputSections; std::unique_ptr Buffer; + std::unique_ptr CtorFunction; + std::string CtorFunctionBody; std::vector Segments; llvm::SmallDenseMap SegmentMap; @@ -154,8 +160,7 @@ Import.Module = "env"; Import.Field = Sym->getName(); Import.Kind = WASM_EXTERNAL_FUNCTION; - assert(TypeIndices.count(Sym->getFunctionType()) > 0); - Import.SigIndex = TypeIndices.lookup(Sym->getFunctionType()); + Import.SigIndex = lookupType(Sym->getFunctionType()); writeImport(OS, Import); } @@ -196,8 +201,9 @@ raw_ostream &OS = Section->getStream(); writeUleb128(OS, DefinedFunctions.size(), "function count"); - for (const InputFunction *Func : DefinedFunctions) - writeUleb128(OS, TypeIndices.lookup(Func->Signature), "sig index"); + for (const InputFunction *Func : DefinedFunctions) { + writeUleb128(OS, lookupType(Func->Signature), "sig index"); + } } void Writer::createMemorySection() { @@ -410,15 +416,6 @@ SubSection.writeToStream(OS); } - std::vector InitFunctions; - for (ObjFile *File : Symtab->ObjectFiles) { - const WasmLinkingData &L = File->getWasmObj()->linkingData(); - InitFunctions.reserve(InitFunctions.size() + L.InitFunctions.size()); - for (const WasmInitFunc &F : L.InitFunctions) - InitFunctions.emplace_back(WasmInitFunc{ - F.Priority, File->relocateFunctionIndex(F.FunctionIndex)}); - } - if (!InitFunctions.empty()) { SubSection SubSection(WASM_INIT_FUNCS); writeUleb128(SubSection.getStream(), InitFunctions.size(), @@ -447,6 +444,13 @@ } } + for (Symbol *S : Symtab->getSymbols()) { + if (S->isFunction() && !S->getFile() && !S->WrittenToNameSec) { + S->WrittenToNameSec = true; + Names.emplace_back(S); + } + } + SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name"); std::sort(Names.begin(), Names.end(), [](const Symbol *A, const Symbol *B) { @@ -520,7 +524,7 @@ } SyntheticSection *Writer::createSyntheticSection(uint32_t Type, - std::string Name) { + StringRef Name) { auto Sec = make(Type, Name); log("createSection: " + toString(*Sec)); OutputSections.push_back(Sec); @@ -570,10 +574,19 @@ } } -uint32_t Writer::getTypeIndex(const WasmSignature &Sig) { +uint32_t Writer::lookupType(const WasmSignature &Sig) { + if (TypeIndices.count(Sig) == 0) + error("type not found: " + toString(Sig)); + assert(TypeIndices.count(Sig) > 0); + return TypeIndices.lookup(Sig); +} + +uint32_t Writer::registerType(const WasmSignature &Sig) { auto Pair = TypeIndices.insert(std::make_pair(Sig, Types.size())); - if (Pair.second) + if (Pair.second) { + DEBUG(dbgs() << "type " << toString(Sig) << "\n"); Types.push_back(&Sig); + } return Pair.first->second; } @@ -581,13 +594,17 @@ for (ObjFile *File : Symtab->ObjectFiles) { File->TypeMap.reserve(File->getWasmObj()->types().size()); for (const WasmSignature &Sig : File->getWasmObj()->types()) - File->TypeMap.push_back(getTypeIndex(Sig)); + File->TypeMap.push_back(registerType(Sig)); } + + for (Symbol *Sym : Symtab->getSymbols()) + if (Sym->isFunction()) + registerType(Sym->getFunctionType()); } void Writer::assignIndexes() { - uint32_t GlobalIndex = ImportedGlobals.size(); - uint32_t FunctionIndex = ImportedFunctions.size(); + uint32_t GlobalIndex = ImportedGlobals.size() + DefinedGlobals.size(); + uint32_t FunctionIndex = ImportedFunctions.size() + DefinedFunctions.size(); if (Config->StackPointerSymbol) { DefinedGlobals.emplace_back(Config->StackPointerSymbol); @@ -666,6 +683,38 @@ } } +static const int OPCODE_CALL = 0x10; +static const int OPCODE_END = 0xb; + +void Writer::createCtorFunction() { + uint32_t FunctionIndex = ImportedFunctions.size() + DefinedFunctions.size(); + Config->CtorSymbol->setOutputIndex(FunctionIndex); + + static WasmSignature Signature = {{}, WASM_TYPE_NORESULT}; + raw_string_ostream OS(CtorFunctionBody); + writeUleb128(OS, 2 + (2 * InitFunctions.size()), "function size"); + writeUleb128(OS, 0, "num locals"); + for (const WasmInitFunc &F : InitFunctions) { + writeUleb128(OS, OPCODE_CALL, "END"); + writeUleb128(OS, F.FunctionIndex, "function index"); + } + writeUleb128(OS, OPCODE_END, "END"); + OS.flush(); + CtorFunction = + llvm::make_unique(Signature, CtorFunctionBody); + DefinedFunctions.emplace_back(CtorFunction.get()); +} + +void Writer::calculateInitFunctions() { + for (ObjFile *File : Symtab->ObjectFiles) { + const WasmLinkingData &L = File->getWasmObj()->linkingData(); + InitFunctions.reserve(InitFunctions.size() + L.InitFunctions.size()); + for (const WasmInitFunc &F : L.InitFunctions) + InitFunctions.emplace_back(WasmInitFunc{ + F.Priority, File->relocateFunctionIndex(F.FunctionIndex)}); + } +} + void Writer::run() { if (!Config->Relocatable) InitialTableOffset = 1; @@ -676,6 +725,10 @@ calculateImports(); log("-- assignIndexes"); assignIndexes(); + log("-- calculateInitFunctions"); + calculateInitFunctions(); + if (!Config->Relocatable) + createCtorFunction(); if (errorHandler().Verbose) { log("Defined Functions: " + Twine(DefinedFunctions.size()));