Skip to content

Commit fc6d2df

Browse files
authored
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.
1 parent 3c27bc8 commit fc6d2df

File tree

4 files changed

+133
-2
lines changed

4 files changed

+133
-2
lines changed

src/ir/memory-utils.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,31 @@
2222

2323
#include "literal.h"
2424
#include "wasm-binary.h"
25+
#include "wasm-builder.h"
2526
#include "wasm.h"
2627

2728
namespace wasm {
2829

2930
namespace MemoryUtils {
30-
// flattens memory into a single data segment. returns true if successful
31-
inline bool flatten(Memory& memory) {
31+
// Flattens memory into a single data segment, or no segment. If there is
32+
// a segment, it starts at 0.
33+
// If ensuredSegmentSize is provided, then a segment is always emitted,
34+
// and of at least that size.
35+
// Returns true if successful (e.g. relocatable segments cannot be flattened).
36+
inline bool flatten(Memory& memory,
37+
Index ensuredSegmentSize = 0,
38+
Module* module = nullptr) {
3239
if (memory.segments.size() == 0) {
40+
if (ensuredSegmentSize > 0) {
41+
assert(module); // must provide a module if ensuring a size.
42+
Builder builder(*module);
43+
memory.segments.emplace_back(builder.makeConst(Literal(int32_t(0))));
44+
memory.segments[0].data.resize(ensuredSegmentSize);
45+
}
3346
return true;
3447
}
3548
std::vector<char> data;
49+
data.resize(ensuredSegmentSize);
3650
for (auto& segment : memory.segments) {
3751
if (segment.isPassive) {
3852
return false;

src/passes/PostEmscripten.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <asmjs/shared-constants.h>
2323
#include <ir/import-utils.h>
2424
#include <ir/localize.h>
25+
#include <ir/memory-utils.h>
2526
#include <pass.h>
2627
#include <shared-constants.h>
2728
#include <wasm-builder.h>
@@ -80,6 +81,27 @@ struct PostEmscripten : public Pass {
8081
func->body = builder.makeConst(Literal(int32_t(sbrkPtr)));
8182
func->module = func->base = Name();
8283
}
84+
// Apply the sbrk ptr value, if it was provided. This lets emscripten set
85+
// up sbrk entirely in wasm, without depending on the JS side to init
86+
// anything; this is necessary for standalone wasm mode, in which we do
87+
// not have any JS. Otherwise, the JS would set this value during
88+
// startup.
89+
auto sbrkValStr =
90+
runner->options.getArgumentOrDefault("emscripten-sbrk-val", "");
91+
if (sbrkValStr != "") {
92+
uint32_t sbrkVal = std::stoi(sbrkValStr);
93+
auto end = sbrkPtr + sizeof(sbrkVal);
94+
// Flatten memory to make it simple to write to. Later passes can
95+
// re-optimize it.
96+
MemoryUtils::ensureExists(module->memory);
97+
if (!MemoryUtils::flatten(module->memory, end, module)) {
98+
Fatal() << "cannot apply sbrk-val since memory is not flattenable\n";
99+
}
100+
auto& segment = module->memory.segments[0];
101+
assert(segment.offset->cast<Const>()->value.geti32() == 0);
102+
assert(end <= segment.data.size());
103+
memcpy(segment.data.data() + sbrkPtr, &sbrkVal, sizeof(sbrkVal));
104+
}
83105
}
84106

85107
// Optimize calls
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
(module
2+
(type $FUNCSIG$i (func (result i32)))
3+
(memory $0 1 1)
4+
(data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00*\00\00\00")
5+
(func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
6+
(i32.const 16)
7+
)
8+
)
9+
(module
10+
(memory $0 1 1)
11+
(data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00*\00\00\00")
12+
)
13+
(module
14+
(type $FUNCSIG$i (func (result i32)))
15+
(memory $0 10 10)
16+
(data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00*\00\00\00")
17+
(func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
18+
(i32.const 16)
19+
)
20+
)
21+
(module
22+
(type $FUNCSIG$i (func (result i32)))
23+
(memory $0 10 10)
24+
(data (i32.const 0) "1234567890123456*\00\00\00")
25+
(func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
26+
(i32.const 16)
27+
)
28+
)
29+
(module
30+
(type $FUNCSIG$i (func (result i32)))
31+
(memory $0 10 10)
32+
(data (i32.const 0) "1234567890\00\00\00\00\00\00*\00\00\00")
33+
(func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
34+
(i32.const 16)
35+
)
36+
)
37+
(module
38+
(type $FUNCSIG$i (func (result i32)))
39+
(memory $0 10 10)
40+
(data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00123456*\00\00\001234567890")
41+
(func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
42+
(i32.const 16)
43+
)
44+
)
45+
(module
46+
(type $FUNCSIG$i (func (result i32)))
47+
(memory $0 10 10)
48+
(data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00123456*\00\00\00")
49+
(func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
50+
(i32.const 16)
51+
)
52+
)
53+
(module
54+
(type $FUNCSIG$i (func (result i32)))
55+
(memory $0 10 10)
56+
(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")
57+
(func $internal (; 0 ;) (type $FUNCSIG$i) (result i32)
58+
(i32.const 16)
59+
)
60+
)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
(module
2+
(import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
3+
)
4+
(module
5+
)
6+
(module
7+
(memory $0 10 10)
8+
(import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
9+
)
10+
(module
11+
(memory $0 10 10)
12+
(data (i32.const 0) "12345678901234567890")
13+
(import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
14+
)
15+
(module
16+
(memory $0 10 10)
17+
(data (i32.const 0) "1234567890")
18+
(import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
19+
)
20+
(module
21+
(memory $0 10 10)
22+
(data (i32.const 10) "12345678901234567890")
23+
(import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
24+
)
25+
(module
26+
(memory $0 10 10)
27+
(data (i32.const 10) "1234567890")
28+
(import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
29+
)
30+
(module
31+
(memory $0 10 10)
32+
(data (i32.const 24) "1234567890")
33+
(import "env" "emscripten_get_sbrk_ptr" (func $internal(result i32)))
34+
)
35+

0 commit comments

Comments
 (0)