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