summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2019-09-30 17:15:20 -0700
committerGitHub <noreply@github.com>2019-09-30 17:15:20 -0700
commitfc6d2df4eedfef53a0a29fed1ff3ce4707556700 (patch)
treefbfd641af0918ab06f5c0c9b7cf29b33ebc519e1 /src
parent3c27bc8267a52661ecfc2e1a369585ef420a6055 (diff)
downloadbinaryen-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.h18
-rw-r--r--src/passes/PostEmscripten.cpp22
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