diff --git a/src-self-hosted/codegen/wasm.zig b/src-self-hosted/codegen/wasm.zig index 78d8d22ded..8e794ff934 100644 --- a/src-self-hosted/codegen/wasm.zig +++ b/src-self-hosted/codegen/wasm.zig @@ -3,9 +3,12 @@ const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; const assert = std.debug.assert; const leb = std.debug.leb; +const mem = std.mem; const Decl = @import("../Module.zig").Decl; +const Inst = @import("../ir.zig").Inst; const Type = @import("../type.zig").Type; +const Value = @import("../value.zig").Value; fn genValtype(ty: Type) u8 { return switch (ty.tag()) { @@ -56,10 +59,10 @@ pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void { try leb.writeULEB128(writer, @as(u32, 0)); // Write instructions - - // TODO: actually implement codegen - try writer.writeByte(0x41); // i32.const - try leb.writeILEB128(writer, @as(i32, 42)); + // TODO: check for and handle death of instructions + const tv = decl.typed_value.most_recent.typed_value; + const mod_fn = tv.val.cast(Value.Payload.Function).?.func; + for (mod_fn.analysis.success.instructions) |inst| try genInst(writer, inst); // Write 'end' opcode try writer.writeByte(0x0B); @@ -68,3 +71,49 @@ pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void { // beginning of the buffer. leb.writeUnsignedFixed(5, buf.items[0..5], @intCast(u32, buf.items.len - 5)); } + +fn genInst(writer: ArrayList(u8).Writer, inst: *Inst) !void { + return switch (inst.tag) { + .dbg_stmt => {}, + .ret => genRet(writer, inst.castTag(.ret).?), + else => error.TODOImplementMoreWasmCodegen, + }; +} + +fn genRet(writer: ArrayList(u8).Writer, inst: *Inst.UnOp) !void { + switch (inst.operand.tag) { + .constant => { + const constant = inst.operand.castTag(.constant).?; + switch (inst.operand.ty.tag()) { + .u32 => { + try writer.writeByte(0x41); // i32.const + try leb.writeILEB128(writer, constant.val.toUnsignedInt()); + }, + .i32 => { + try writer.writeByte(0x41); // i32.const + try leb.writeILEB128(writer, constant.val.toSignedInt()); + }, + .u64 => { + try writer.writeByte(0x42); // i64.const + try leb.writeILEB128(writer, constant.val.toUnsignedInt()); + }, + .i64 => { + try writer.writeByte(0x42); // i64.const + try leb.writeILEB128(writer, constant.val.toSignedInt()); + }, + .f32 => { + try writer.writeByte(0x43); // f32.const + // TODO: enforce LE byte order + try writer.writeAll(mem.asBytes(&constant.val.toFloat(f32))); + }, + .f64 => { + try writer.writeByte(0x44); // f64.const + // TODO: enforce LE byte order + try writer.writeAll(mem.asBytes(&constant.val.toFloat(f64))); + }, + else => return error.TODOImplementMoreWasmCodegen, + } + }, + else => return error.TODOImplementMoreWasmCodegen, + } +}