Skip to content

Instantly share code, notes, and snippets.

@xaviervia
Created June 11, 2020 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xaviervia/ae4c81a87813be48c72340f8b949ca28 to your computer and use it in GitHub Desktop.
Save xaviervia/ae4c81a87813be48c72340f8b949ca28 to your computer and use it in GitHub Desktop.
// --- 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