Index: include/llvm/BinaryFormat/Wasm.h =================================================================== --- include/llvm/BinaryFormat/Wasm.h +++ include/llvm/BinaryFormat/Wasm.h @@ -187,6 +187,8 @@ WASM_DATA_SIZE = 0x3, WASM_DATA_ALIGNMENT = 0x4, WASM_SEGMENT_INFO = 0x5, + WASM_DEFAULT_LINEAR_MEMORY = 0x6, + WASM_DEFAULT_FUNCTION_TABLE = 0x7, }; const unsigned WASM_SYMBOL_BINDING_MASK = 0x3; Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ 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); @@ -286,7 +285,7 @@ void writeCodeRelocSection(); void writeDataRelocSection(); void writeLinkingMetaDataSection( - ArrayRef Segments, uint32_t DataSize, + ArrayRef Segments, SmallVector, 4> SymbolFlags, Optional StackPointerGlobal); @@ -662,10 +661,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); @@ -684,6 +687,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"); } @@ -706,39 +718,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; @@ -928,7 +907,7 @@ } void WasmObjectWriter::writeLinkingMetaDataSection( - ArrayRef Segments, uint32_t DataSize, + ArrayRef Segments, SmallVector, 4> SymbolFlags, Optional StackPointerGlobal) { SectionBookkeeping Section; @@ -941,6 +920,15 @@ endSection(SubSection); } + // Declare the default linear memory and default function table. Since we + // only have one of each right now, the index is always zero. + startSection(SubSection, wasm::WASM_DEFAULT_LINEAR_MEMORY); + encodeULEB128(0, getStream()); // id + endSection(SubSection); + startSection(SubSection, wasm::WASM_DEFAULT_FUNCTION_TABLE); + encodeULEB128(0, getStream()); // id + endSection(SubSection); + if (SymbolFlags.size() != 0) { startSection(SubSection, wasm::WASM_SYMBOL_INFO); encodeULEB128(SymbolFlags.size(), getStream()); @@ -951,12 +939,6 @@ endSection(SubSection); } - if (DataSize > 0) { - startSection(SubSection, wasm::WASM_DATA_SIZE); - encodeULEB128(DataSize, getStream()); - endSection(SubSection); - } - if (Segments.size()) { startSection(SubSection, wasm::WASM_SEGMENT_INFO); encodeULEB128(Segments.size(), getStream()); @@ -1112,6 +1094,29 @@ StackPointerGlobalName = StringRef(Contents.data(), Contents.size()); } + // 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); @@ -1325,10 +1330,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 @@ -1338,8 +1343,7 @@ writeNameSection(Functions, Imports, NumFuncImports); writeCodeRelocSection(); writeDataRelocSection(); - writeLinkingMetaDataSection(DataSegments, DataSize, SymbolFlags, - StackPointerGlobal); + writeLinkingMetaDataSection(DataSegments, SymbolFlags, StackPointerGlobal); // TODO: Translate the .comment section to the output. // TODO: Translate debug sections to the output.