summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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