Add load8, store8, load64, store64 to the compiler. In c_factor(), where we handle function calls, check for builtins before emitting call $name.
For load8(addr): compile the address, emit i32.wrap_i64, i32.load8_u, i64.extend_i32_u.
For store8(addr, val): compile both, emit the store sequence with a $__tmp local to swap order.
For load64(addr): compile the address, emit i32.wrap_i64, i64.load.
For store64(addr, val): compile both, emit the 64-bit store sequence.
if (streq(name, "load8")) {
pos += 1; skip();
c_expression();
if (cur() == ')') { pos += 1; skip(); }
emit_op("i32.wrap_i64");
emit_op("i32.load8_u");
emit_op("i64.extend_i32_u");
return;
}
if (streq(name, "store8")) {
pos += 1; skip();
c_expression();
if (cur() == ',') { pos += 1; skip(); }
c_expression();
if (cur() == ')') { pos += 1; skip(); }
// stack: [addr, val]
// store8 needs: addr (i32), val (i32)
emit_str(" i32.wrap_i64\n"); // convert val to i32
emit_str(" local.set $__tmp\n");
emit_str(" i32.wrap_i64\n"); // convert addr to i32
emit_str(" local.get $__tmp\n");
emit_op("i32.store8");
emit_const(0); // store8 returns 0
return;
}
if (streq(name, "load64")) {
pos += 1; skip();
c_expression();
if (cur() == ')') { pos += 1; skip(); }
emit_op("i32.wrap_i64");
emit_op("i64.load");
return;
}
if (streq(name, "store64")) {
pos += 1; skip();
c_expression();
if (cur() == ',') { pos += 1; skip(); }
c_expression();
if (cur() == ')') { pos += 1; skip(); }
emit_str(" local.set $__tmp\n");
emit_str(" i32.wrap_i64\n");
emit_str(" local.get $__tmp\n");
emit_op("i64.store");
emit_const(0);
return;
}
We need a scratch local $__tmp for the store operations -- WAT's store instructions expect the address under the value on the stack, but our compiler pushes them in argument order (address first, value second). The temp local lets us swap them. Add (local $__tmp i64) to every function in c_program() -- it's one wasted local but saves us from tracking which functions use store.
This is a little ugly. Real compilers solve this more elegantly. But it works, and working is what matters right now.