Created
June 11, 2020 17:35
-
-
Save xaviervia/ae4c81a87813be48c72340f8b949ca28 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// --- WASM COMMANDS | |
const WASM_BINARY_MAGIC = [0x00, 0x61, 0x73, 0x6d] | |
const WASM_BINARY_VERSION = [0x01, 0x00, 0x00, 0x00] | |
const HEADER = WASM_BINARY_MAGIC.concat(WASM_BINARY_VERSION) | |
const I32 = 0x7F | |
const I32_ADD = 0x6a | |
const SECTION_CODE_TYPE = 0x01 | |
const SECTION_CODE_FUNCTION = 0x03 | |
const SECTION_CODE_EXPORT = 0x07 | |
const SECTION_CODE_CODE = 0x0a | |
const KEYWORD_FUNC = 0x60 | |
const KEYWORD_END = 0x0b | |
const KEYWORD_LOCAL_GET = 0x20 | |
// --- HELPERS | |
const getSectionSize = (items) => ( | |
items.map((i) => i.length).reduce((a, b) => a + b, 1) | |
) | |
const flatten = (items) => items.reduce((a, b) => a.concat(b), []) | |
// --- PROGRAM | |
const functionTypes = [ | |
[ | |
KEYWORD_FUNC, | |
0x02, // Two parameters | |
I32, | |
I32, | |
0x01, // One result (only option for now) | |
I32, | |
] | |
] | |
const typeSection = [ | |
SECTION_CODE_TYPE, | |
getSectionSize(functionTypes), | |
functionTypes.length, | |
...flatten(functionTypes), | |
] | |
const functions = [ | |
[ | |
0x00, // function type index, TODO link dynamically | |
] | |
] | |
const functionSection = [ | |
SECTION_CODE_FUNCTION, | |
getSectionSize(functions), | |
functions.length, | |
...flatten(functions), | |
] | |
const moduleExports = [ | |
[ | |
'addTwo'.length, | |
...'addTwo'.split('').map((char) => char.codePointAt(0)), | |
0x00, // "export kind" -- always zero from the examples I saw | |
0x00, // export fucntion index, TODO link dynamically | |
] | |
] | |
const exportSection = [ | |
SECTION_CODE_EXPORT, | |
getSectionSize(moduleExports), | |
moduleExports.length, | |
...flatten(moduleExports), | |
] | |
const functionBodies = [ | |
[ | |
0x00, // "local decl count" -- always zero from the examples I saw | |
KEYWORD_LOCAL_GET, | |
0x00, // first parameter | |
KEYWORD_LOCAL_GET, | |
0x01, // second parameter | |
I32_ADD, | |
KEYWORD_END | |
] | |
] | |
const functionBodiesWithSize = functionBodies.map( | |
(functionBody) => [functionBody.length, ...functionBody] | |
) | |
const codeSection = [ | |
SECTION_CODE_CODE, | |
getSectionSize(functionBodiesWithSize), | |
functionBodiesWithSize.length, | |
...flatten(functionBodiesWithSize) | |
] | |
const fullModule = [ | |
...HEADER, | |
...typeSection, | |
...functionSection, | |
...exportSection, | |
...codeSection, | |
] | |
console.log({ | |
HEADER, | |
typeSection, | |
functionSection, | |
exportSection, | |
codeSection, | |
fullModule, | |
length: fullModule.length, | |
}) | |
const buf = Buffer.from(fullModule) | |
console.log(buf) | |
const compiled = new WebAssembly.Module(buf) | |
const instance = new WebAssembly.Instance(compiled, {}) | |
const { addTwo } = instance.exports | |
console.log(addTwo(2, 3)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment