[lld][WebAssembly] Handle 4gb max memories
authorThomas Lively <tlively@google.com>
Fri, 3 Apr 2020 23:18:29 +0000 (16:18 -0700)
committerThomas Lively <tlively@google.com>
Thu, 9 Apr 2020 20:06:41 +0000 (13:06 -0700)
Summary:
A previous change (53211a) had updated the argument parsing to handle
large max memories, but 4294967296 would still wrap to zero after the
options were parsed. This change updates the configuration to use a
64-bit integer to store the max memory to avoid that overflow.

Reviewers: sbc100

Subscribers: dschuff, jgravelle-google, aheejin, sunfish, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D77437

lld/test/wasm/large-memory.test
lld/wasm/Config.h
lld/wasm/Writer.cpp

index 8d403b5..0713a8b 100644 (file)
@@ -2,4 +2,23 @@ RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.o
 
 ; Verify we can parse large integers such as when we ask for 2G of total
 ; memory.
-RUN: wasm-ld %t.o -o %t.wasm --max-memory=2147483648
+RUN: wasm-ld %t.o -o %t1.wasm --max-memory=2147483648
+RUN: obj2yaml %t1.wasm | FileCheck %s --check-prefixes=CHECK,CHECK-2G
+
+; And also 4G of total memory
+RUN: wasm-ld %t.o -o %t2.wasm --max-memory=4294967296
+RUN: obj2yaml %t2.wasm | FileCheck %s --check-prefixes=CHECK,CHECK-4G
+
+CHECK:      - Type:            MEMORY
+CHECK-NEXT:   Memories:
+CHECK-NEXT:     - Flags:           [ HAS_MAX ]
+CHECK-NEXT:       Initial:         0x00000002
+CHECK-2G-NEXT:    Maximum:         0x00008000
+CHECK-4G-NEXT:    Maximum:         0x00010000
+
+; Test error for more than 4G of memory
+RUN: not wasm-ld %t.o -o %t3.wasm --initial-memory=4295032832 2>&1 | FileCheck %s --check-prefix INIT-ERROR
+RUN: not wasm-ld %t.o -o %t4.wasm --max-memory=4295032832 2>&1 | FileCheck %s --check-prefix MAX-ERROR
+
+INIT-ERROR: initial memory too large, cannot be greater than 4294967296
+MAX-ERROR: maximum memory too large, cannot be greater than 4294967296
index b396bda..1ba2889 100644 (file)
@@ -46,10 +46,10 @@ struct Configuration {
   bool stripDebug;
   bool stackFirst;
   bool trace;
-  uint32_t globalBase;
-  uint32_t initialMemory;
-  uint32_t maxMemory;
-  uint32_t zStackSize;
+  uint64_t globalBase;
+  uint64_t initialMemory;
+  uint64_t maxMemory;
+  uint64_t zStackSize;
   unsigned ltoPartitions;
   unsigned ltoo;
   unsigned optimize;
index 9f4b6ad..d1ada22 100644 (file)
@@ -201,7 +201,7 @@ void Writer::writeSections() {
 // rather than overwriting global data, but also increases code size since all
 // static data loads and stores requires larger offsets.
 void Writer::layoutMemory() {
-  uint32_t memoryPtr = 0;
+  uint64_t memoryPtr = 0;
 
   auto placeStack = [&]() {
     if (config->relocatable || config->isPic)
@@ -227,7 +227,7 @@ void Writer::layoutMemory() {
   if (WasmSym::globalBase)
     WasmSym::globalBase->setVirtualAddress(memoryPtr);
 
-  uint32_t dataStart = memoryPtr;
+  uint64_t dataStart = memoryPtr;
 
   // Arbitrarily set __dso_handle handle to point to the start of the data
   // segments.
@@ -286,8 +286,9 @@ void Writer::layoutMemory() {
       error("initial memory must be " + Twine(WasmPageSize) + "-byte aligned");
     if (memoryPtr > config->initialMemory)
       error("initial memory too small, " + Twine(memoryPtr) + " bytes needed");
-    else
-      memoryPtr = config->initialMemory;
+    if (config->initialMemory > (1ULL << 32))
+      error("initial memory too large, cannot be greater than 4294967296");
+    memoryPtr = config->initialMemory;
   }
   out.dylinkSec->memSize = memoryPtr;
   out.memorySec->numMemoryPages =
@@ -300,6 +301,8 @@ 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");
     out.memorySec->maxMemoryPages = config->maxMemory / WasmPageSize;
     log("mem: max pages   = " + Twine(out.memorySec->maxMemoryPages));
   }