Skip to content

Commit

Permalink
Apply the sbrk/brk value at compile time (#2366)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
kripken committed Oct 1, 2019
1 parent 3c27bc8 commit fc6d2df
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 2 deletions.
18 changes: 16 additions & 2 deletions src/ir/memory-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
22 changes: 22 additions & 0 deletions src/passes/PostEmscripten.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
)
)
Original file line number Diff line number Diff line change
@@ -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)))
)

0 comments on commit fc6d2df

Please sign in to comment.