1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
//
// wasm intepreter for asm2wasm output, in a js environment. receives asm.js,
// generates a runnable module suitable as a polyfill.
//
// this polyfills an emscripten --separate-asm *.asm.js file, as a drop-in
// replacement. it writes the wasm module to Module.asm, and sets Module.buffer.
//
#include <emscripten.h>
#include "asm2wasm.h"
#include "wasm-interpreter.h"
using namespace cashew;
using namespace wasm;
// receives asm.js code, parses into wasm and returns an instance handle.
// this creates a module, an external interface, and a module instance,
// all of which are then the responsibility of the caller to free.
// note: this modifies the input.
extern "C" ModuleInstance* EMSCRIPTEN_KEEPALIVE load_asm(char *input) {
// emcc --separate-asm modules look like
//
// Module["asm"] = (function(global, env, buffer) {
// ..
// });
//
// we need to clean that up.
size_t num = strlen(input);
assert(*input == 'M');
while (*input != 'f') {
input++;
num--;
}
char *end = input + num - 1;
while (*end != '}') {
*end = 0;
end--;
}
if (debug) std::cerr << "parsing...\n";
cashew::Parser<Ref, DotZeroValueBuilder> builder;
Ref asmjs = builder.parseToplevel(input);
Module* wasm = new Module();
if (debug) std::cerr << "wasming...\n";
Asm2WasmBuilder asm2wasm(*wasm);
asm2wasm.processAsm(asmjs);
if (debug) std::cerr << "optimizing...\n";
asm2wasm.optimize();
if (debug) std::cerr << "returning instance.\n";
struct JSExternalInterface : ModuleInstance::ExternalInterface {
Literal callImport(Import *import, ModuleInstance::LiteralList& arguments) override {
}
Literal load(Load* load, Literal ptr) override {
}
Literal store(Store* store, Literal ptr, Literal value) override {
}
};
return new ModuleInstance(*wasm, new JSExternalInterface());
}
|