diff options
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))) +) + |