[llvm] 4d135b0 - [WebAssembly] 64-bit memory limits
Wouter van Oortmerssen via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 6 12:41:23 PDT 2020
Author: Wouter van Oortmerssen
Date: 2020-07-06T12:40:45-07:00
New Revision: 4d135b0446dc34885811bf103ba2c8b69fe6793b
URL: https://github.com/llvm/llvm-project/commit/4d135b0446dc34885811bf103ba2c8b69fe6793b
DIFF: https://github.com/llvm/llvm-project/commit/4d135b0446dc34885811bf103ba2c8b69fe6793b.diff
LOG: [WebAssembly] 64-bit memory limits
Added:
Modified:
lld/test/wasm/data-layout.ll
lld/wasm/SyntheticSections.cpp
lld/wasm/SyntheticSections.h
lld/wasm/Writer.cpp
llvm/include/llvm/BinaryFormat/Wasm.h
llvm/lib/MC/WasmObjectWriter.cpp
llvm/lib/Object/WasmObjectFile.cpp
llvm/lib/ObjectYAML/WasmYAML.cpp
llvm/test/MC/WebAssembly/wasm64.s
Removed:
################################################################################
diff --git a/lld/test/wasm/data-layout.ll b/lld/test/wasm/data-layout.ll
index 759c5440fe99..863447cfd26b 100644
--- a/lld/test/wasm/data-layout.ll
+++ b/lld/test/wasm/data-layout.ll
@@ -1,7 +1,12 @@
-; RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/hello.s -o %t.hello.o
-; RUN: llc -filetype=obj %s -o %t.o
+; RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/hello.s -o %t.hello32.o
+; RUN: llc -mtriple=wasm32-unknown-unknown -filetype=obj %s -o %t32.o
+; RUN: wasm-ld -m wasm32 -no-gc-sections --export=__data_end --export=__heap_base --allow-undefined --no-entry -o %t32.wasm %t32.o %t.hello32.o
+; RUN: obj2yaml %t32.wasm | FileCheck --check-prefixes CHECK,CHK32 %s
-target triple = "wasm32-unknown-unknown"
+; RUN: llvm-mc -filetype=obj -triple=wasm64-unknown-unknown %p/Inputs/hello.s -o %t.hello64.o
+; RUN: llc -mtriple=wasm64-unknown-unknown -filetype=obj %s -o %t64.o
+; RUN: wasm-ld -m wasm64 -no-gc-sections --export=__data_end --export=__heap_base --allow-undefined --no-entry -o %t64.wasm %t64.o %t.hello64.o
+; RUN: obj2yaml %t64.wasm | FileCheck --check-prefixes CHECK,CHK64 %s
@foo = hidden global i32 1, align 4
@aligned_bar = hidden global i32 3, align 16
@@ -13,26 +18,28 @@ target triple = "wasm32-unknown-unknown"
@local_struct = hidden global %struct.s zeroinitializer, align 4
@local_struct_internal_ptr = hidden local_unnamed_addr global i32* getelementptr inbounds (%struct.s, %struct.s* @local_struct, i32 0, i32 1), align 4
-; RUN: wasm-ld -no-gc-sections --export=__data_end --export=__heap_base --allow-undefined --no-entry -o %t.wasm %t.o %t.hello.o
-; RUN: obj2yaml %t.wasm | FileCheck %s
-
; CHECK: - Type: MEMORY
; CHECK-NEXT: Memories:
-; CHECK-NEXT: - Initial: 0x00000002
+; CHK32-NEXT: - Initial: 0x00000002
+; CHK64-NEXT: - Flags: [ IS_64 ]
+; CHK64-NEXT: Initial: 0x00000002
; CHECK-NEXT: - Type: GLOBAL
; CHECK-NEXT: Globals:
; CHECK-NEXT: - Index: 0
-; CHECK-NEXT: Type: I32
+; CHK32-NEXT: Type: I32
+; CHK64-NEXT: Type: I64
; CHECK-NEXT: Mutable: true
; CHECK-NEXT: InitExpr:
-; CHECK-NEXT: Opcode: I32_CONST
+; CHK32-NEXT: Opcode: I32_CONST
+; CHK64-NEXT: Opcode: I64_CONST
; CHECK-NEXT: Value: 66624
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1080
+; CHK32-NEXT: Value: 1080
+; CHK64-NEXT: Value: 1088
; CHECK-NEXT: - Index: 2
; CHECK-NEXT: Type: I32
; CHECK-NEXT: Mutable: false
@@ -53,13 +60,11 @@ target triple = "wasm32-unknown-unknown"
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 1040
-; CHECK-NEXT: Content: '0100000000000000000000000000000003000000000000000004000034040000'
-; CHECK-NEXT: - Type: CUSTOM
; RUN: wasm-ld -no-gc-sections --allow-undefined --no-entry \
-; RUN: --initial-memory=131072 --max-memory=131072 -o %t_max.wasm %t.o \
-; RUN: %t.hello.o
+; RUN: --initial-memory=131072 --max-memory=131072 -o %t_max.wasm %t32.o \
+; RUN: %t.hello32.o
; RUN: obj2yaml %t_max.wasm | FileCheck %s -check-prefix=CHECK-MAX
; CHECK-MAX: - Type: MEMORY
@@ -70,7 +75,7 @@ target triple = "wasm32-unknown-unknown"
; RUN: wasm-ld -no-gc-sections --allow-undefined --no-entry --shared-memory \
; RUN: --features=atomics,bulk-memory --initial-memory=131072 \
-; RUN: --max-memory=131072 -o %t_max.wasm %t.o %t.hello.o
+; RUN: --max-memory=131072 -o %t_max.wasm %t32.o %t.hello32.o
; RUN: obj2yaml %t_max.wasm | FileCheck %s -check-prefix=CHECK-SHARED
; CHECK-SHARED: - Type: MEMORY
@@ -79,7 +84,7 @@ target triple = "wasm32-unknown-unknown"
; CHECK-SHARED-NEXT: Initial: 0x00000002
; CHECK-SHARED-NEXT: Maximum: 0x00000002
-; RUN: wasm-ld --relocatable -o %t_reloc.wasm %t.o %t.hello.o
+; RUN: wasm-ld --relocatable -o %t_reloc.wasm %t32.o %t.hello32.o
; RUN: obj2yaml %t_reloc.wasm | FileCheck %s -check-prefix=RELOC
; RELOC: - Type: DATA
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index 0ed3ea273d70..70d6a10200c6 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -139,6 +139,8 @@ void ImportSection::writeBody() {
}
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 @@ void MemorySection::writeBody() {
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/SyntheticSections.h b/lld/wasm/SyntheticSections.h
index 6cf593cf016c..3e125ca84e40 100644
--- a/lld/wasm/SyntheticSections.h
+++ b/lld/wasm/SyntheticSections.h
@@ -167,8 +167,8 @@ class MemorySection : public SyntheticSection {
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/Writer.cpp b/lld/wasm/Writer.cpp
index 0434a4cf0293..1401dc50931b 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -224,8 +224,16 @@ void Writer::layoutMemory() {
log("mem: stack base = " + Twine(memoryPtr));
memoryPtr += config->zStackSize;
auto *sp = cast<DefinedGlobal>(WasmSym::stackPointer);
- assert(sp->global->global.InitExpr.Opcode == WASM_OPCODE_I32_CONST);
- sp->global->global.InitExpr.Value.Int32 = memoryPtr;
+ switch (sp->global->global.InitExpr.Opcode) {
+ case WASM_OPCODE_I32_CONST:
+ sp->global->global.InitExpr.Value.Int32 = memoryPtr;
+ break;
+ case WASM_OPCODE_I64_CONST:
+ sp->global->global.InitExpr.Value.Int64 = memoryPtr;
+ break;
+ default:
+ llvm_unreachable("init expr must be i32/i64.const");
+ }
log("mem: stack top = " + Twine(memoryPtr));
};
@@ -296,13 +304,16 @@ void Writer::layoutMemory() {
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 +327,9 @@ void Writer::layoutMemory() {
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
index b8d3b3f4d66f..d8d72cacf226 100644
--- a/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -63,8 +63,8 @@ struct WasmExport {
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 {
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
index c6029b66a388..d1290b050ef2 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -108,7 +108,7 @@ struct WasmDataSegment {
MCSectionWasm *Section;
StringRef Name;
uint32_t InitFlags;
- uint32_t Offset;
+ uint64_t Offset;
uint32_t Alignment;
uint32_t LinkerFlags;
SmallVector<char, 4> Data;
@@ -326,7 +326,7 @@ class WasmObjectWriter : public MCObjectWriter {
void writeValueType(wasm::ValType Ty) { W.OS << static_cast<char>(Ty); }
void writeTypeSection(ArrayRef<WasmSignature> Signatures);
- void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint32_t DataSize,
+ void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint64_t DataSize,
uint32_t NumElements);
void writeFunctionSection(ArrayRef<WasmFunction> Functions);
void writeExportSection(ArrayRef<wasm::WasmExport> Exports);
@@ -730,12 +730,12 @@ void WasmObjectWriter::writeTypeSection(ArrayRef<WasmSignature> Signatures) {
}
void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> 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 @@ void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
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 @@ uint32_t WasmObjectWriter::writeDataSection(const MCAsmLayout &Layout) {
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<int32_t>().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 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
std::map<StringRef, std::vector<WasmComdatEntry>> 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 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
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
index 25990b012118..bb2e81d64047 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -208,9 +208,9 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
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
index b12fd448de5a..d1aa1181a344 100644
--- a/llvm/lib/ObjectYAML/WasmYAML.cpp
+++ b/llvm/lib/ObjectYAML/WasmYAML.cpp
@@ -522,6 +522,7 @@ void ScalarBitSetTraits<WasmYAML::LimitFlags>::bitset(
#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
index 2ec331f751d6..b89718816a9f 100644
--- a/llvm/test/MC/WebAssembly/wasm64.s
+++ b/llvm/test/MC/WebAssembly/wasm64.s
@@ -147,6 +147,7 @@ test:
# 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
More information about the llvm-commits
mailing list