Skip to content

Commit 159e9a4

Browse files
authored
Add a --standalone-wasm flag to wasm-emscripten-finalize (#2333)
The flag indicates that we want to run the wasm by itself, without JS support. In that case we don't emit JS dynCalls etc., and we also emit a wasi _start if there is a main, i.e., we try to use the current conventions in the wasm-only space.
1 parent 844998f commit 159e9a4

10 files changed

Lines changed: 367 additions & 1 deletion

scripts/test/lld.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ def args_for_finalize(filename):
2626
return ['--check-stack-overflow', '--global-base=568']
2727
elif 'shared' in filename:
2828
return ['--side-module']
29+
elif 'standalone-wasm' in filename:
30+
return ['--standalone-wasm', '--global-base=568']
2931
else:
3032
return ['--global-base=568']
3133

src/tools/wasm-emscripten-finalize.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ int main(int argc, const char* argv[]) {
5050
bool legalizeJavaScriptFFI = true;
5151
bool checkStackOverflow = false;
5252
uint64_t globalBase = INVALID_BASE;
53+
bool standaloneWasm = false;
54+
5355
ToolOptions options("wasm-emscripten-finalize",
5456
"Performs Emscripten-specific transforms on .wasm files");
5557
options
@@ -135,6 +137,14 @@ int main(int argc, const char* argv[]) {
135137
[&checkStackOverflow](Options* o, const std::string&) {
136138
checkStackOverflow = true;
137139
})
140+
.add("--standalone-wasm",
141+
"",
142+
"Emit a wasm file that does not depend on JS, as much as possible,"
143+
" using wasi and other standard conventions etc. where possible",
144+
Options::Arguments::Zero,
145+
[&standaloneWasm](Options* o, const std::string&) {
146+
standaloneWasm = true;
147+
})
138148
.add_positional("INFILE",
139149
Options::Arguments::One,
140150
[&infile](Options* o, const std::string& argument) {
@@ -233,7 +243,13 @@ int main(int argc, const char* argv[]) {
233243
}
234244
}
235245

236-
generator.generateDynCallThunks();
246+
if (standaloneWasm) {
247+
// Export a standard wasi "_start" method.
248+
generator.exportWasiStart();
249+
} else {
250+
// If not standalone wasm then JS is relevant and we need dynCalls.
251+
generator.generateDynCallThunks();
252+
}
237253

238254
// Legalize the wasm.
239255
{

src/wasm-emscripten.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class EmscriptenGlueGenerator {
5656

5757
void enforceStackLimit();
5858

59+
void exportWasiStart();
60+
5961
// Emits the data segments to a file. The file contains data from address base
6062
// onwards (we must pass in base, as we can't tell it from the wasm - the
6163
// first segment may start after a run of zeros, but we need those zeros in

src/wasm/wasm-emscripten.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "asmjs/shared-constants.h"
2323
#include "ir/function-type-utils.h"
2424
#include "ir/import-utils.h"
25+
#include "ir/literal-utils.h"
2526
#include "ir/module-utils.h"
2627
#include "shared-constants.h"
2728
#include "wasm-builder.h"
@@ -1210,4 +1211,22 @@ void EmscriptenGlueGenerator::separateDataSegments(Output* outfile,
12101211
wasm.memory.segments.clear();
12111212
}
12121213

1214+
void EmscriptenGlueGenerator::exportWasiStart() {
1215+
// If main exists, export a function to call it per the wasi standard.
1216+
Name main = "main";
1217+
if (!wasm.getFunctionOrNull(main)) {
1218+
return;
1219+
}
1220+
Name _start = "_start";
1221+
Builder builder(wasm);
1222+
auto* body = builder.makeDrop(builder.makeCall(
1223+
main,
1224+
{LiteralUtils::makeZero(i32, wasm), LiteralUtils::makeZero(i32, wasm)},
1225+
i32));
1226+
auto* func =
1227+
builder.makeFunction(_start, std::vector<wasm::Type>{}, none, {}, body);
1228+
wasm.addFunction(func);
1229+
wasm.addExport(builder.makeExport(_start, _start, ExternalKind::Function));
1230+
}
1231+
12131232
} // namespace wasm

test/lld/standalone-wasm.wast

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
(module
2+
(memory $0 2)
3+
(table $0 1 1 funcref)
4+
(elem (i32.const 0) $foo)
5+
(global $global$0 (mut i32) (i32.const 66112))
6+
(global $global$1 i32 (i32.const 66112))
7+
(global $global$2 i32 (i32.const 576))
8+
(export "memory" (memory $0))
9+
(export "main" (func $main))
10+
(export "__heap_base" (global $global$1))
11+
(export "__data_end" (global $global$2))
12+
(func $__original_main (result i32)
13+
(nop)
14+
)
15+
(func $main (param $0 i32) (param $1 i32) (result i32)
16+
(call $__original_main)
17+
)
18+
(func $foo (result i32))
19+
)
20+

test/lld/standalone-wasm.wast.out

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
(module
2+
(type $FUNCSIG$i (func (result i32)))
3+
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
4+
(memory $0 2)
5+
(table $0 1 1 funcref)
6+
(elem (i32.const 0) $foo)
7+
(global $global$0 (mut i32) (i32.const 66112))
8+
(global $global$1 i32 (i32.const 66112))
9+
(global $global$2 i32 (i32.const 576))
10+
(export "memory" (memory $0))
11+
(export "main" (func $main))
12+
(export "__heap_base" (global $global$1))
13+
(export "__data_end" (global $global$2))
14+
(export "stackSave" (func $stackSave))
15+
(export "stackAlloc" (func $stackAlloc))
16+
(export "stackRestore" (func $stackRestore))
17+
(export "__growWasmMemory" (func $__growWasmMemory))
18+
(export "_start" (func $_start))
19+
(func $__original_main (; 0 ;) (type $FUNCSIG$i) (result i32)
20+
(nop)
21+
)
22+
(func $main (; 1 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
23+
(call $__original_main)
24+
)
25+
(func $foo (; 2 ;) (type $FUNCSIG$i) (result i32)
26+
(nop)
27+
)
28+
(func $stackSave (; 3 ;) (result i32)
29+
(global.get $global$0)
30+
)
31+
(func $stackAlloc (; 4 ;) (param $0 i32) (result i32)
32+
(local $1 i32)
33+
(global.set $global$0
34+
(local.tee $1
35+
(i32.and
36+
(i32.sub
37+
(global.get $global$0)
38+
(local.get $0)
39+
)
40+
(i32.const -16)
41+
)
42+
)
43+
)
44+
(local.get $1)
45+
)
46+
(func $stackRestore (; 5 ;) (param $0 i32)
47+
(global.set $global$0
48+
(local.get $0)
49+
)
50+
)
51+
(func $__growWasmMemory (; 6 ;) (param $newSize i32) (result i32)
52+
(memory.grow
53+
(local.get $newSize)
54+
)
55+
)
56+
(func $_start (; 7 ;)
57+
(drop
58+
(call $main
59+
(i32.const 0)
60+
(i32.const 0)
61+
)
62+
)
63+
)
64+
)
65+
(;
66+
--BEGIN METADATA --
67+
{
68+
"staticBump": 8,
69+
"tableSize": 1,
70+
"declares": [
71+
],
72+
"externs": [
73+
],
74+
"implementedFunctions": [
75+
"_main",
76+
"_stackSave",
77+
"_stackAlloc",
78+
"_stackRestore",
79+
"___growWasmMemory",
80+
"__start"
81+
],
82+
"exports": [
83+
"main",
84+
"stackSave",
85+
"stackAlloc",
86+
"stackRestore",
87+
"__growWasmMemory",
88+
"_start"
89+
],
90+
"namedGlobals": {
91+
"__heap_base" : "66112",
92+
"__data_end" : "576"
93+
},
94+
"invokeFuncs": [
95+
],
96+
"features": [
97+
],
98+
"mainReadsParams": 0
99+
}
100+
-- END METADATA --
101+
;)

test/lld/standalone-wasm2.wast

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
(module
2+
(memory $0 2)
3+
(global $global$0 (mut i32) (i32.const 66112))
4+
(global $global$1 i32 (i32.const 66112))
5+
(global $global$2 i32 (i32.const 576))
6+
(export "memory" (memory $0))
7+
(export "main" (func $main))
8+
(export "__heap_base" (global $global$1))
9+
(export "__data_end" (global $global$2))
10+
(func $__original_main (param $0 i32) (param $1 i32) (result i32)
11+
(nop)
12+
)
13+
(func $main (param $0 i32) (param $1 i32) (result i32)
14+
(call $__original_main (local.get $0) (local.get $1))
15+
)
16+
)
17+

test/lld/standalone-wasm2.wast.out

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
(module
2+
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
3+
(memory $0 2)
4+
(global $global$0 (mut i32) (i32.const 66112))
5+
(global $global$1 i32 (i32.const 66112))
6+
(global $global$2 i32 (i32.const 576))
7+
(export "memory" (memory $0))
8+
(export "main" (func $main))
9+
(export "__heap_base" (global $global$1))
10+
(export "__data_end" (global $global$2))
11+
(export "stackSave" (func $stackSave))
12+
(export "stackAlloc" (func $stackAlloc))
13+
(export "stackRestore" (func $stackRestore))
14+
(export "__growWasmMemory" (func $__growWasmMemory))
15+
(export "_start" (func $_start))
16+
(func $__original_main (; 0 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
17+
(nop)
18+
)
19+
(func $main (; 1 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
20+
(call $__original_main
21+
(local.get $0)
22+
(local.get $1)
23+
)
24+
)
25+
(func $stackSave (; 2 ;) (result i32)
26+
(global.get $global$0)
27+
)
28+
(func $stackAlloc (; 3 ;) (param $0 i32) (result i32)
29+
(local $1 i32)
30+
(global.set $global$0
31+
(local.tee $1
32+
(i32.and
33+
(i32.sub
34+
(global.get $global$0)
35+
(local.get $0)
36+
)
37+
(i32.const -16)
38+
)
39+
)
40+
)
41+
(local.get $1)
42+
)
43+
(func $stackRestore (; 4 ;) (param $0 i32)
44+
(global.set $global$0
45+
(local.get $0)
46+
)
47+
)
48+
(func $__growWasmMemory (; 5 ;) (param $newSize i32) (result i32)
49+
(memory.grow
50+
(local.get $newSize)
51+
)
52+
)
53+
(func $_start (; 6 ;)
54+
(drop
55+
(call $main
56+
(i32.const 0)
57+
(i32.const 0)
58+
)
59+
)
60+
)
61+
)
62+
(;
63+
--BEGIN METADATA --
64+
{
65+
"staticBump": 8,
66+
"tableSize": 0,
67+
"declares": [
68+
],
69+
"externs": [
70+
],
71+
"implementedFunctions": [
72+
"_main",
73+
"_stackSave",
74+
"_stackAlloc",
75+
"_stackRestore",
76+
"___growWasmMemory",
77+
"__start"
78+
],
79+
"exports": [
80+
"main",
81+
"stackSave",
82+
"stackAlloc",
83+
"stackRestore",
84+
"__growWasmMemory",
85+
"_start"
86+
],
87+
"namedGlobals": {
88+
"__heap_base" : "66112",
89+
"__data_end" : "576"
90+
},
91+
"invokeFuncs": [
92+
],
93+
"features": [
94+
],
95+
"mainReadsParams": 1
96+
}
97+
-- END METADATA --
98+
;)

test/lld/standalone-wasm3.wast

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
(module
2+
(memory $0 2)
3+
(global $global$0 (mut i32) (i32.const 66112))
4+
(global $global$1 i32 (i32.const 66112))
5+
(global $global$2 i32 (i32.const 576))
6+
(export "memory" (memory $0))
7+
(export "__heap_base" (global $global$1))
8+
(export "__data_end" (global $global$2))
9+
(func $__original_main (param $0 i32) (param $1 i32) (result i32)
10+
(nop)
11+
)
12+
)
13+

0 commit comments

Comments
 (0)