Index: llvm/trunk/lib/MC/WasmObjectWriter.cpp =================================================================== --- llvm/trunk/lib/MC/WasmObjectWriter.cpp +++ llvm/trunk/lib/MC/WasmObjectWriter.cpp @@ -270,10 +270,9 @@ } void writeTypeSection(ArrayRef FunctionTypes); - void writeImportSection(ArrayRef Imports); + void writeImportSection(ArrayRef Imports, uint32_t DataSize, + uint32_t NumElements); void writeFunctionSection(ArrayRef Functions); - void writeTableSection(uint32_t NumElements); - void writeMemorySection(uint32_t DataSize); void writeGlobalSection(); void writeExportSection(ArrayRef Exports); void writeElemSection(ArrayRef TableElems); @@ -661,10 +660,14 @@ endSection(Section); } -void WasmObjectWriter::writeImportSection(ArrayRef Imports) { +void WasmObjectWriter::writeImportSection(ArrayRef Imports, + uint32_t DataSize, + uint32_t NumElements) { if (Imports.empty()) return; + uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize; + SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_IMPORT); @@ -683,6 +686,15 @@ encodeSLEB128(int32_t(Import.Type), getStream()); encodeULEB128(int32_t(Import.IsMutable), getStream()); break; + case wasm::WASM_EXTERNAL_MEMORY: + encodeULEB128(0, getStream()); // flags + encodeULEB128(NumPages, getStream()); // initial + break; + case wasm::WASM_EXTERNAL_TABLE: + encodeSLEB128(int32_t(Import.Type), getStream()); + encodeULEB128(0, getStream()); // flags + encodeULEB128(NumElements, getStream()); // initial + break; default: llvm_unreachable("unsupported import kind"); } @@ -705,39 +717,6 @@ endSection(Section); } -void WasmObjectWriter::writeTableSection(uint32_t NumElements) { - // For now, always emit the table section, since indirect calls are not - // valid without it. In the future, we could perhaps be more clever and omit - // it if there are no indirect calls. - - SectionBookkeeping Section; - startSection(Section, wasm::WASM_SEC_TABLE); - - encodeULEB128(1, getStream()); // The number of tables. - // Fixed to 1 for now. - encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); // Type of table - encodeULEB128(0, getStream()); // flags - encodeULEB128(NumElements, getStream()); // initial - - endSection(Section); -} - -void WasmObjectWriter::writeMemorySection(uint32_t DataSize) { - // For now, always emit the memory section, since loads and stores are not - // valid without it. In the future, we could perhaps be more clever and omit - // it if there are no loads or stores. - SectionBookkeeping Section; - uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize; - - startSection(Section, wasm::WASM_SEC_MEMORY); - encodeULEB128(1, getStream()); // number of memory spaces - - encodeULEB128(0, getStream()); // flags - encodeULEB128(NumPages, getStream()); // initial - - endSection(Section); -} - void WasmObjectWriter::writeGlobalSection() { if (Globals.empty()) return; @@ -1085,6 +1064,29 @@ } } + // For now, always emit the memory import, since loads and stores are not + // valid without it. In the future, we could perhaps be more clever and omit + // it if there are no loads or stores. + MCSymbolWasm *MemorySym = + cast(Ctx.getOrCreateSymbol("__linear_memory")); + WasmImport MemImport; + MemImport.ModuleName = MemorySym->getModuleName(); + MemImport.FieldName = MemorySym->getName(); + MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY; + Imports.push_back(MemImport); + + // For now, always emit the table section, since indirect calls are not + // valid without it. In the future, we could perhaps be more clever and omit + // it if there are no indirect calls. + MCSymbolWasm *TableSym = + cast(Ctx.getOrCreateSymbol("__indirect_function_table")); + WasmImport TableImport; + TableImport.ModuleName = TableSym->getModuleName(); + TableImport.FieldName = TableSym->getName(); + TableImport.Kind = wasm::WASM_EXTERNAL_TABLE; + TableImport.Type = wasm::WASM_TYPE_ANYFUNC; + Imports.push_back(TableImport); + // Populate FunctionTypeIndices and Imports. for (const MCSymbol &S : Asm.symbols()) { const auto &WS = static_cast(S); @@ -1295,10 +1297,10 @@ writeHeader(Asm); writeTypeSection(FunctionTypes); - writeImportSection(Imports); + writeImportSection(Imports, DataSize, TableElems.size()); writeFunctionSection(Functions); - writeTableSection(TableElems.size()); - writeMemorySection(DataSize); + // Skip the "table" section; we import the table instead. + // Skip the "memory" section; we import the memory instead. writeGlobalSection(); writeExportSection(Exports); // TODO: Start Section Index: llvm/trunk/test/MC/WebAssembly/external-func-address.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/external-func-address.ll +++ llvm/trunk/test/MC/WebAssembly/external-func-address.ll @@ -17,7 +17,11 @@ ; CHECK-NEXT: - I32 ; CHECK: - Type: IMPORT ; CHECK-NEXT: Imports: -; CHECK-NEXT: - Module: env +; CHECK: - Module: env +; CHECK-NEXT: Field: __linear_memory +; CHECK: - Module: env +; CHECK-NEXT: Field: __indirect_function_table +; CHECK: - Module: env ; CHECK-NEXT: Field: f1 ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 0 Index: llvm/trunk/test/MC/WebAssembly/func-address.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/func-address.ll +++ llvm/trunk/test/MC/WebAssembly/func-address.ll @@ -28,7 +28,7 @@ ; CHECK: } ; CHECK: Relocations [ -; CHECK: Section (8) CODE { +; CHECK: Section (6) CODE { ; CHECK: Relocation { ; CHECK: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0) ; CHECK: Offset: 0x4 Index: llvm/trunk/test/MC/WebAssembly/init-fini-array.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/init-fini-array.ll +++ llvm/trunk/test/MC/WebAssembly/init-fini-array.ll @@ -14,6 +14,18 @@ ; CHECK: - Type: IMPORT ; CHECK-NEXT: Imports: ; CHECK-NEXT: - Module: env +; CHECK-NEXT: Field: __linear_memory +; CHECK-NEXT: Kind: MEMORY +; CHECK-NEXT: Memory: +; CHECK-NEXT: Initial: 0x00000001 +; CHECK-NEXT: - Module: env +; CHECK-NEXT: Field: __indirect_function_table +; CHECK-NEXT: Kind: TABLE +; CHECK-NEXT: Table: +; CHECK-NEXT: ElemType: ANYFUNC +; CHECK-NEXT: Limits: +; CHECK-NEXT: Initial: 0x00000002 +; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: func1 ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 0 @@ -21,14 +33,6 @@ ; CHECK-NEXT: Field: func2 ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 0 -; CHECK-NEXT: - Type: TABLE -; CHECK-NEXT: Tables: -; CHECK-NEXT: - ElemType: ANYFUNC -; CHECK-NEXT: Limits: -; CHECK-NEXT: Initial: 0x00000002 -; CHECK-NEXT: - Type: MEMORY -; CHECK-NEXT: Memories: -; CHECK-NEXT: - Initial: 0x00000001 ; CHECK-NEXT: - Type: GLOBAL ; CHECK-NEXT: Globals: ; CHECK-NEXT: - Type: I32 Index: llvm/trunk/test/MC/WebAssembly/reloc-code.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/reloc-code.ll +++ llvm/trunk/test/MC/WebAssembly/reloc-code.ll @@ -22,7 +22,7 @@ ; CHECK: Format: WASM ; CHECK: Relocations [ -; CHECK-NEXT: Section (8) CODE { +; CHECK-NEXT: Section (6) CODE { ; CHECK-NEXT: Relocation { ; CHECK-NEXT: Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB (3) ; CHECK-NEXT: Offset: 0x9 Index: llvm/trunk/test/MC/WebAssembly/reloc-data.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/reloc-data.ll +++ llvm/trunk/test/MC/WebAssembly/reloc-data.ll @@ -10,7 +10,7 @@ ; CHECK: Format: WASM ; CHECK: Relocations [ -; CHECK-NEXT: Section (6) DATA { +; CHECK-NEXT: Section (4) DATA { ; CHECK-NEXT: Relocation { ; CHECK-NEXT: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) ; CHECK-NEXT: Offset: 0x13 Index: llvm/trunk/test/MC/WebAssembly/sections.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/sections.ll +++ llvm/trunk/test/MC/WebAssembly/sections.ll @@ -28,17 +28,6 @@ ; CHECK: Type: FUNCTION (0x3) ; CHECK: } ; CHECK: Section { -; CHECK: Type: TABLE (0x4) -; CHECK: } -; CHECK: Section { -; CHECK: Type: MEMORY (0x5) -; CHECK: Memories [ -; CHECK: Memory { -; CHECK: InitialPages: 1 -; CHECK: } -; CHECK: ] -; CHECK: } -; CHECK: Section { ; CHECK: Type: GLOBAL (0x6) ; CHECK: } ; CHECK: Section { Index: llvm/trunk/test/MC/WebAssembly/weak-alias.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/weak-alias.ll +++ llvm/trunk/test/MC/WebAssembly/weak-alias.ll @@ -29,16 +29,22 @@ ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: ReturnType: I32 ; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Type: IMPORT +; CHECK-NEXT: Imports: +; CHECK-NEXT: - Module: env +; CHECK-NEXT: Field: __linear_memory +; CHECK-NEXT: Kind: MEMORY +; CHECK-NEXT: Memory: +; CHECK-NEXT: Initial: 0x00000001 +; CHECK-NEXT: - Module: env +; CHECK-NEXT: Field: __indirect_function_table +; CHECK-NEXT: Kind: TABLE +; CHECK-NEXT: Table: +; CHECK-NEXT: ElemType: ANYFUNC +; CHECK-NEXT: Limits: +; CHECK-NEXT: Initial: 0x00000000 ; CHECK-NEXT: - Type: FUNCTION ; CHECK-NEXT: FunctionTypes: [ 0, 0 ] -; CHECK-NEXT: - Type: TABLE -; CHECK-NEXT: Tables: -; CHECK-NEXT: - ElemType: ANYFUNC -; CHECK-NEXT: Limits: -; CHECK-NEXT: Initial: 0x00000000 -; CHECK-NEXT: - Type: MEMORY -; CHECK-NEXT: Memories: -; CHECK-NEXT: - Initial: 0x00000001 ; CHECK-NEXT: - Type: GLOBAL ; CHECK-NEXT: Globals: ; CHECK-NEXT: - Type: I32 Index: llvm/trunk/test/MC/WebAssembly/weak.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/weak.ll +++ llvm/trunk/test/MC/WebAssembly/weak.ll @@ -12,7 +12,11 @@ ; CHECK: - Type: IMPORT ; CHECK-NEXT: Imports: -; CHECK-NEXT: - Module: env +; CHECK: - Module: env +; CHECK-NEXT: Field: __linear_memory +; CHECK: - Module: env +; CHECK-NEXT: Field: __indirect_function_table +; CHECK: - Module: env ; CHECK-NEXT: Field: weak_external_data ; CHECK-NEXT: Kind: GLOBAL ; CHECK-NEXT: GlobalType: I32