Sikau

WebAssembly · Day 4 · about 45 min

Project: Build a module from scratch

Emit the sections yourself and run functions you assembled by hand.

Become the compiler's back end

Compilers end by writing bytes. Write buildModule: given a list of functions (all i32) and their instruction bytes, emit the type, function, export and code sections — then the browser compiles your binary.

The builder

const nameBytes = (s) => [...encodeULEB128(s.length), ...[...s].map((c) => c.charCodeAt(0))];
const section = (id, content) => [id, ...encodeULEB128(content.length), ...content];

// funcs: [{ name, params, locals = 0, body }] — every param, local and result is i32.
function buildModule(funcs) {
  const types = funcs.map((f) => [0x60, ...encodeULEB128(f.params), ...Array(f.params).fill(0x7f), 1, 0x7f]);
  const typeSec = section(1, [...encodeULEB128(funcs.length), ...types.flat()]);
  const funcSec = section(3, [...encodeULEB128(funcs.length), ...funcs.flatMap((_, i) => encodeULEB128(i))]);
  const exportSec = section(7, [...encodeULEB128(funcs.length), ...funcs.flatMap((f, i) => [...nameBytes(f.name), 0x00, ...encodeULEB128(i)])]);
  const bodies = funcs.flatMap((f) => {
    const locals = f.locals ? [1, ...encodeULEB128(f.locals), 0x7f] : [0];
    const body = [...locals, ...f.body, 0x0b]; // every body ends with "end"
    return [...encodeULEB128(body.length), ...body];
  });
  const codeSec = section(10, [...encodeULEB128(funcs.length), ...bodies]);
  return new Uint8Array([0x00, 0x61, 0x73, 0x6d, 1, 0, 0, 0, ...typeSec, ...funcSec, ...exportSec, ...codeSec]);
}
  • 0x20 n local.get, 0x21 n local.set
  • 0x41 n i32.const (signed LEB128)
  • 0x6a i32.add, 0x6b i32.sub, 0x6c i32.mul
  • 0x02 0x40 … 0x0b block, 0x03 0x40 … 0x0b loop, 0x0d n br_if, 0x0c n br, 0x4c i32.le_s

The rest of this lesson

  • One function's bodyexplain
  • Assembling the moduleexplain
  • Module layoutorder
  • Opcode to instructionmatch
  • buildModulechallenge
  • Badge quizquiz
  • Unit 1 completerecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 8 lessons of WebAssembly