diff options
author | Alon Zakai <azakai@google.com> | 2019-09-30 17:15:20 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-30 17:15:20 -0700 |
commit | fc6d2df4eedfef53a0a29fed1ff3ce4707556700 (patch) | |
tree | fbfd641af0918ab06f5c0c9b7cf29b33ebc519e1 /src | |
parent | 3c27bc8267a52661ecfc2e1a369585ef420a6055 (diff) | |
download | binaryen-fc6d2df4eedfef53a0a29fed1ff3ce4707556700.tar.gz binaryen-fc6d2df4eedfef53a0a29fed1ff3ce4707556700.tar.bz2 binaryen-fc6d2df4eedfef53a0a29fed1ff3ce4707556700.zip |
Apply the sbrk/brk value at compile time (#2366)
We've had an option to set the location of the sbrk ptr, but not the value.
Applying the value as well is necessary for standalone wasm, as otherwise we set
it in JS.
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/memory-utils.h | 18 | ||||
-rw-r--r-- | src/passes/PostEmscripten.cpp | 22 |
2 files changed, 38 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 |