From 582fd474ddc0318ca23ade8e22de20df85c492cc Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Fri, 7 Aug 2020 13:24:43 -0700 Subject: [PATCH] [WebAssembly] wasm64: fix memory.init operand types I had assumed they would all become in i64, but this is not necessary as long as data segments stay 32-bit, see: https://github.com/WebAssembly/memory64/blob/master/proposals/memory64/Overview.md Differential Revision: https://reviews.llvm.org/D85552 --- lld/wasm/InputChunks.cpp | 2 +- lld/wasm/OutputSections.cpp | 1 + lld/wasm/OutputSegment.h | 2 +- lld/wasm/SymbolTable.cpp | 2 +- lld/wasm/SymbolTable.h | 2 +- lld/wasm/Writer.cpp | 12 +++++++++--- llvm/lib/Target/WebAssembly/WebAssemblyInstrBulkMemory.td | 2 +- 7 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp index c7261cf..b85c8cc 100644 --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -350,7 +350,7 @@ void InputSegment::generateRelocationCode(raw_ostream &os) const { // TODO(sbc): Encode the relocations in the data section and write a loop // here to apply them. - uint32_t segmentVA = outputSeg->startVA + outputSegmentOffset; + uint64_t segmentVA = outputSeg->startVA + outputSegmentOffset; for (const WasmRelocation &rel : relocations) { uint64_t offset = rel.Offset - getInputSectionOffset(); uint64_t outputOffset = segmentVA + offset; diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp index 6b0ee98..a936562 100644 --- a/lld/wasm/OutputSections.cpp +++ b/lld/wasm/OutputSections.cpp @@ -152,6 +152,7 @@ void DataSection::finalizeContents() { initExpr.Opcode = WASM_OPCODE_GLOBAL_GET; initExpr.Value.Global = WasmSym::memoryBase->getGlobalIndex(); } else { + // FIXME(wvo): I64? initExpr.Opcode = WASM_OPCODE_I32_CONST; initExpr.Value.Int32 = segment->startVA; } diff --git a/lld/wasm/OutputSegment.h b/lld/wasm/OutputSegment.h index 06f675c..34c3c49 100644 --- a/lld/wasm/OutputSegment.h +++ b/lld/wasm/OutputSegment.h @@ -37,7 +37,7 @@ public: uint32_t initFlags = 0; uint32_t sectionOffset = 0; uint32_t alignment = 0; - uint32_t startVA = 0; + uint64_t startVA = 0; std::vector inputSegments; // Sum of the size of the all the input segments diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp index b3cb87c..cb152d5 100644 --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -211,7 +211,7 @@ DefinedFunction *SymbolTable::addSyntheticFunction(StringRef name, // exported via the --export flag. Otherwise we don't add the symbol and return // nullptr. DefinedData *SymbolTable::addOptionalDataSymbol(StringRef name, - uint32_t value) { + uint64_t value) { Symbol *s = find(name); if (!s && (config->exportAll || config->exportedSymbols.count(name) != 0)) s = insertName(name).first; diff --git a/lld/wasm/SymbolTable.h b/lld/wasm/SymbolTable.h index 8d0ad77..fe26f70 100644 --- a/lld/wasm/SymbolTable.h +++ b/lld/wasm/SymbolTable.h @@ -82,7 +82,7 @@ public: InputGlobal *global); DefinedFunction *addSyntheticFunction(StringRef name, uint32_t flags, InputFunction *function); - DefinedData *addOptionalDataSymbol(StringRef name, uint32_t value = 0); + DefinedData *addOptionalDataSymbol(StringRef name, uint64_t value = 0); void handleSymbolVariants(); void handleWeakUndefines(); diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 36b56a4..dddecad 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -354,8 +354,8 @@ static void addStartStopSymbols(const OutputSegment *seg) { if (!isValidCIdentifier(name)) return; LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << name << "\n"); - uint32_t start = seg->startVA; - uint32_t stop = start + seg->size; + uint64_t start = seg->startVA; + uint64_t stop = start + seg->size; symtab->addOptionalDataSymbol(saver.save("__start_" + name), start); symtab->addOptionalDataSymbol(saver.save("__stop_" + name), stop); } @@ -838,7 +838,12 @@ void Writer::createInitMemoryFunction() { for (const OutputSegment *s : segments) { if (needsPassiveInitialization(s)) { // destination address - writeI32Const(os, s->startVA, "destination address"); + if (config->is64) { + writeI64Const(os, s->startVA, "destination address"); + } else { + writeI32Const(os, static_cast(s->startVA), + "destination address"); + } // source segment offset writeI32Const(os, 0, "segment offset"); // memory region size @@ -960,6 +965,7 @@ void Writer::createInitTLSFunction() { writeU8(os, WASM_OPCODE_GLOBAL_SET, "global.set"); writeUleb128(os, WasmSym::tlsBase->getGlobalIndex(), "global index"); + // FIXME(wvo): this local needs to be I64 in wasm64, or we need an extend op. writeU8(os, WASM_OPCODE_LOCAL_GET, "local.get"); writeUleb128(os, 0, "local index"); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrBulkMemory.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrBulkMemory.td index 3e9ef6f..7aeae54 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrBulkMemory.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrBulkMemory.td @@ -39,7 +39,7 @@ let mayStore = 1, hasSideEffects = 1 in defm MEMORY_INIT_A#B : BULK_I<(outs), (ins i32imm_op:$seg, i32imm_op:$idx, rc:$dest, - rc:$offset, rc:$size), + I32:$offset, I32:$size), (outs), (ins i32imm_op:$seg, i32imm_op:$idx), [], "memory.init\t$seg, $idx, $dest, $offset, $size", -- 2.7.4