summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/memory-utils.h18
-rw-r--r--src/passes/PostEmscripten.cpp22
-rw-r--r--test/passes/post-emscripten_pass-arg=emscripten-sbrk-ptr@16_pass-arg=emscripten-sbrk-val@42.txt60
-rw-r--r--test/passes/post-emscripten_pass-arg=emscripten-sbrk-ptr@16_pass-arg=emscripten-sbrk-val@42.wast35
4 files changed, 133 insertions, 2 deletions
diff --git a/src/ir/memory-utils.h b/src/ir/memory-utils.h
index fd4b865f4..39914a95a 100644
--- a/src/ir/memory-utils.h
+++ b/src/ir/memory-utils.h
@@ -22,17 +22,31 @@
#include "literal.h"
#include "wasm-binary.h"
+#include "wasm-builder.h"
#include "wasm.h"
namespace wasm {
namespace MemoryUtils {
-// flattens memory into a single data segment. returns true if successful
-inline bool flatten(Memory& memory) {
+// Flattens memory into a single data segment, or no segment. If there is
+// a segment, it starts at 0.
+// If ensuredSegmentSize is provided, then a segment is always emitted,
+// and of at least that size.
+// Returns true if successful (e.g. relocatable segments cannot be flattened).
+inline bool flatten(Memory& memory,
+ Index ensuredSegmentSize = 0,
+ Module* module = nullptr) {
if (memory.segments.size() == 0) {
+ if (ensuredSegmentSize > 0) {
+ assert(module); // must provide a module if ensuring a size.
+ Builder builder(*module);
+ memory.segments.emplace_back(builder.makeConst(Literal(int32_t(0))));
+ memory.segments[0].data.resize(ensuredSegmentSize);
+ }
return true;
}
std::vector<char> data;
+ data.resize(ensuredSegmentSize);
for (auto& segment : memory.segments) {
if (segment.isPassive) {
return false;
diff --git a/src/passes/PostEmscripten.cpp b/src/passes/PostEmscripten.cpp
index 62fd9d845..55ffd6e0c 100644
--- a/src/passes/PostEmscripten.cpp
+++ b/src/passes/PostEmscripten.cpp
@@ -22,6 +22,7 @@
#include <asmjs/shared-constants.h>
#include <ir/import-utils.h>
#include <ir/localize.h>
+#include <ir/memory-utils.h>
#include <pass.h>
#include <shared-constants.h>
#include <wasm-builder.h>
@@ -80,6 +81,27 @@ struct PostEmscripten : public Pass {
func->body = builder.makeConst(Literal(int32_t(sbrkPtr)));
func->module = func->base = Name();
}
+ // Apply the sbrk ptr value, if it was provided. This lets emscripten set
+ // up sbrk entirely in wasm, without depending on the JS side to init
+ // anything; this is necessary for standalone wasm mode, in which we do
+ // not have any JS. Otherwise, the JS would set this value during
+ // startup.
+ auto sbrkValStr =
+ runner->options.getArgumentOrDefault("emscripten-sbrk-val", "");
+ if (sbrkValStr != "") {
+ uint32_t sbrkVal = std::stoi(sbrkValStr);
+ auto end = sbrkPtr + sizeof(sbrkVal);
+ // Flatten memory to make it simple to write to. Later passes can
+ // re-optimize it.
+ MemoryUtils::ensureExists(module->memory);
+ if (!MemoryUtils::flatten(module->memory, end, module)) {
+ Fatal() << "cannot apply sbrk-val since memory is not flattenable\n";
+ }
+ auto& segment = module->memory.segments[0];
+ assert(segment.offset->cast<Const>()->value.geti32() == 0);
+ assert(end <= segment.data.size());
+ memcpy(segment.data.data() + sbrkPtr, &sbrkVal, sizeof(sbrkVal));
+ }
}
// Optimize calls
diff --git a/test/passes/post-emscripten_pass-arg=emscripten-sbrk-ptr@16_pass-arg=emscripten-sbrk-val@42.txt b/test/passes/post-emscripten_pass-arg=emscripten-sbrk-ptr@16_pass-arg=emscripten-sbrk-val@42.txt
new file mode 100644
index 000000000..119366efd
--- /dev/null
+++ b/test/passes/post-emscripten_pass-arg=emscripten-sbrk-ptr@16_pass-arg=emscripten-sbrk-val@42.txt
@@ -0,0 +1,60 @@
+(module
+ (type $FUNCSIG$i (func (result i32)))
+ (memory $0 1 1)
+ (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00*\00\00\00")
+ (func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
+ (i32.const 16)
+ )
+)
+(module
+ (memory $0 1 1)
+ (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00*\00\00\00")
+)
+(module
+ (type $FUNCSIG$i (func (result i32)))
+ (memory $0 10 10)
+ (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00*\00\00\00")
+ (func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
+ (i32.const 16)
+ )
+)
+(module
+ (type $FUNCSIG$i (func (result i32)))
+ (memory $0 10 10)
+ (data (i32.const 0) "1234567890123456*\00\00\00")
+ (func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
+ (i32.const 16)
+ )
+)
+(module
+ (type $FUNCSIG$i (func (result i32)))
+ (memory $0 10 10)
+ (data (i32.const 0) "1234567890\00\00\00\00\00\00*\00\00\00")
+ (func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
+ (i32.const 16)
+ )
+)
+(module
+ (type $FUNCSIG$i (func (result i32)))
+ (memory $0 10 10)
+ (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00123456*\00\00\001234567890")
+ (func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
+ (i32.const 16)
+ )
+)
+(module
+ (type $FUNCSIG$i (func (result i32)))
+ (memory $0 10 10)
+ (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00123456*\00\00\00")
+ (func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
+ (i32.const 16)
+ )
+)
+(module
+ (type $FUNCSIG$i (func (result i32)))
+ (memory $0 10 10)
+ (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00*\00\00\00\00\00\00\001234567890")
+ (func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
+ (i32.const 16)
+ )
+)
diff --git a/test/passes/post-emscripten_pass-arg=emscripten-sbrk-ptr@16_pass-arg=emscripten-sbrk-val@42.wast b/test/passes/post-emscripten_pass-arg=emscripten-sbrk-ptr@16_pass-arg=emscripten-sbrk-val@42.wast
new file mode 100644
index 000000000..377afbc84
--- /dev/null
+++ b/test/passes/post-emscripten_pass-arg=emscripten-sbrk-ptr@16_pass-arg=emscripten-sbrk-val@42.wast
@@ -0,0 +1,35 @@
+(module
+ (import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
+)
+(module
+)
+(module
+ (memory $0 10 10)
+ (import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
+)
+(module
+ (memory $0 10 10)
+ (data (i32.const 0) "12345678901234567890")
+ (import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
+)
+(module
+ (memory $0 10 10)
+ (data (i32.const 0) "1234567890")
+ (import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
+)
+(module
+ (memory $0 10 10)
+ (data (i32.const 10) "12345678901234567890")
+ (import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
+)
+(module
+ (memory $0 10 10)
+ (data (i32.const 10) "1234567890")
+ (import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
+)
+(module
+ (memory $0 10 10)
+ (data (i32.const 24) "1234567890")
+ (import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
+)
+