diff --git a/lld/wasm/SyntheticSections.h b/lld/wasm/SyntheticSections.h --- a/lld/wasm/SyntheticSections.h +++ b/lld/wasm/SyntheticSections.h @@ -167,8 +167,8 @@ bool isNeeded() const override { return !config->importMemory; } void writeBody() override; - uint32_t numMemoryPages = 0; - uint32_t maxMemoryPages = 0; + uint64_t numMemoryPages = 0; + uint64_t maxMemoryPages = 0; }; // The event section contains a list of declared wasm events associated with the diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -139,6 +139,8 @@ } if (config->sharedMemory) import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED; + if (config->is64) + import.Memory.Flags |= WASM_LIMITS_FLAG_IS_64; writeImport(os, import); } @@ -234,6 +236,8 @@ flags |= WASM_LIMITS_FLAG_HAS_MAX; if (config->sharedMemory) flags |= WASM_LIMITS_FLAG_IS_SHARED; + if (config->is64) + flags |= WASM_LIMITS_FLAG_IS_64; writeUleb128(os, flags, "memory limits flags"); writeUleb128(os, numMemoryPages, "initial pages"); if (hasMax) diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -296,13 +296,16 @@ if (WasmSym::heapBase) WasmSym::heapBase->setVirtualAddress(memoryPtr); + uint64_t maxMemorySetting = 1ULL << (config->is64 ? 48 : 32); + if (config->initialMemory != 0) { if (config->initialMemory != alignTo(config->initialMemory, WasmPageSize)) error("initial memory must be " + Twine(WasmPageSize) + "-byte aligned"); if (memoryPtr > config->initialMemory) error("initial memory too small, " + Twine(memoryPtr) + " bytes needed"); - if (config->initialMemory > (1ULL << 32)) - error("initial memory too large, cannot be greater than 4294967296"); + if (config->initialMemory > maxMemorySetting) + error("initial memory too large, cannot be greater than " + + Twine(maxMemorySetting)); memoryPtr = config->initialMemory; } out.dylinkSec->memSize = memoryPtr; @@ -316,8 +319,9 @@ error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned"); if (memoryPtr > config->maxMemory) error("maximum memory too small, " + Twine(memoryPtr) + " bytes needed"); - if (config->maxMemory > (1ULL << 32)) - error("maximum memory too large, cannot be greater than 4294967296"); + if (config->maxMemory > maxMemorySetting) + error("maximum memory too large, cannot be greater than " + + Twine(maxMemorySetting)); out.memorySec->maxMemoryPages = config->maxMemory / WasmPageSize; log("mem: max pages = " + Twine(out.memorySec->maxMemoryPages)); } diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h --- a/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/llvm/include/llvm/BinaryFormat/Wasm.h @@ -63,8 +63,8 @@ struct WasmLimits { uint8_t Flags; - uint32_t Initial; - uint32_t Maximum; + uint64_t Initial; + uint64_t Maximum; }; struct WasmTable { @@ -282,6 +282,7 @@ enum : unsigned { WASM_LIMITS_FLAG_HAS_MAX = 0x1, WASM_LIMITS_FLAG_IS_SHARED = 0x2, + WASM_LIMITS_FLAG_IS_64 = 0x4, }; enum : unsigned { diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -108,7 +108,7 @@ MCSectionWasm *Section; StringRef Name; uint32_t InitFlags; - uint32_t Offset; + uint64_t Offset; uint32_t Alignment; uint32_t LinkerFlags; SmallVector Data; @@ -326,7 +326,7 @@ void writeValueType(wasm::ValType Ty) { W.OS << static_cast(Ty); } void writeTypeSection(ArrayRef Signatures); - void writeImportSection(ArrayRef Imports, uint32_t DataSize, + void writeImportSection(ArrayRef Imports, uint64_t DataSize, uint32_t NumElements); void writeFunctionSection(ArrayRef Functions); void writeExportSection(ArrayRef Exports); @@ -730,12 +730,12 @@ } void WasmObjectWriter::writeImportSection(ArrayRef Imports, - uint32_t DataSize, + uint64_t DataSize, uint32_t NumElements) { if (Imports.empty()) return; - uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize; + uint64_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize; SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_IMPORT); @@ -755,8 +755,8 @@ W.OS << char(Import.Global.Mutable ? 1 : 0); break; case wasm::WASM_EXTERNAL_MEMORY: - encodeULEB128(0, W.OS); // flags - encodeULEB128(NumPages, W.OS); // initial + encodeULEB128(Import.Memory.Flags, W.OS); + encodeULEB128(NumPages, W.OS); // initial break; case wasm::WASM_EXTERNAL_TABLE: W.OS << char(Import.Table.ElemType); @@ -935,7 +935,9 @@ if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX) encodeULEB128(0, W.OS); // memory index if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0) { - W.OS << char(wasm::WASM_OPCODE_I32_CONST); + W.OS << char(Segment.Offset > std::numeric_limits().max() + ? wasm::WASM_OPCODE_I64_CONST + : wasm::WASM_OPCODE_I32_CONST); encodeSLEB128(Segment.Offset, W.OS); // offset W.OS << char(wasm::WASM_OPCODE_END); } @@ -1187,7 +1189,7 @@ SmallVector SymbolInfos; SmallVector, 2> InitFuncs; std::map> Comdats; - uint32_t DataSize = 0; + uint64_t DataSize = 0; // 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 @@ -1196,6 +1198,7 @@ MemImport.Module = "env"; MemImport.Field = "__linear_memory"; MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY; + MemImport.Memory.Flags = is64Bit() ? wasm::WASM_LIMITS_FLAG_IS_64 : 0; Imports.push_back(MemImport); // For now, always emit the table section, since indirect calls are not diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -208,9 +208,9 @@ static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) { wasm::WasmLimits Result; Result.Flags = readVaruint32(Ctx); - Result.Initial = readVaruint32(Ctx); + Result.Initial = readVaruint64(Ctx); if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) - Result.Maximum = readVaruint32(Ctx); + Result.Maximum = readVaruint64(Ctx); return Result; } diff --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp --- a/llvm/lib/ObjectYAML/WasmYAML.cpp +++ b/llvm/lib/ObjectYAML/WasmYAML.cpp @@ -522,6 +522,7 @@ #define BCase(X) IO.bitSetCase(Value, #X, wasm::WASM_LIMITS_FLAG_##X) BCase(HAS_MAX); BCase(IS_SHARED); + BCase(IS_64); #undef BCase } diff --git a/llvm/test/MC/WebAssembly/wasm64.s b/llvm/test/MC/WebAssembly/wasm64.s --- a/llvm/test/MC/WebAssembly/wasm64.s +++ b/llvm/test/MC/WebAssembly/wasm64.s @@ -147,6 +147,7 @@ # BIN-NEXT: Field: __linear_memory # BIN-NEXT: Kind: MEMORY # BIN-NEXT: Memory: +# BIN-NEXT: Flags: [ IS_64 ] # BIN-NEXT: Initial: 0x00000001 # BIN-NEXT: - Module: env # BIN-NEXT: Field: __indirect_function_table