authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2020-08-16 01:10:08+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2020-08-18 01:01:04+02:00
log97300896ed137f411c1eef04f8cde86abf4d32df
treef3efbc465b86bb0c75e540ac884b99eb29bc9f32
parent3370b5f1097d0610048e29b322b4cbf81ff0a431
signature Commit is signed but in an unrecognized format.

stage2/wasm: implement trivial codegen

We now generate code for returning constants of any of the basic types.

1 files changed, 53 insertions(+), 4 deletions(-)

src-self-hosted/codegen/wasm.zig+53-4
......@@ -3,9 +3,12 @@ const Allocator = std.mem.Allocator;
33const ArrayList = std.ArrayList;
44const assert = std.debug.assert;
55const leb = std.debug.leb;
6const mem = std.mem;
67
78const Decl = @import("../Module.zig").Decl;
9const Inst = @import("../ir.zig").Inst;
810const Type = @import("../type.zig").Type;
11const Value = @import("../value.zig").Value;
912
1013fn genValtype(ty: Type) u8 {
1114 return switch (ty.tag()) {
......@@ -56,10 +59,10 @@ pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void {
5659 try leb.writeULEB128(writer, @as(u32, 0));
5760
5861 // Write instructions
59
60 // TODO: actually implement codegen
61 try writer.writeByte(0x41); // i32.const
62 try leb.writeILEB128(writer, @as(i32, 42));
62 // TODO: check for and handle death of instructions
63 const tv = decl.typed_value.most_recent.typed_value;
64 const mod_fn = tv.val.cast(Value.Payload.Function).?.func;
65 for (mod_fn.analysis.success.instructions) |inst| try genInst(writer, inst);
6366
6467 // Write 'end' opcode
6568 try writer.writeByte(0x0B);
......@@ -68,3 +71,49 @@ pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void {
6871 // beginning of the buffer.
6972 leb.writeUnsignedFixed(5, buf.items[0..5], @intCast(u32, buf.items.len - 5));
7073}
74
75fn genInst(writer: ArrayList(u8).Writer, inst: *Inst) !void {
76 return switch (inst.tag) {
77 .dbg_stmt => {},
78 .ret => genRet(writer, inst.castTag(.ret).?),
79 else => error.TODOImplementMoreWasmCodegen,
80 };
81}
82
83fn genRet(writer: ArrayList(u8).Writer, inst: *Inst.UnOp) !void {
84 switch (inst.operand.tag) {
85 .constant => {
86 const constant = inst.operand.castTag(.constant).?;
87 switch (inst.operand.ty.tag()) {
88 .u32 => {
89 try writer.writeByte(0x41); // i32.const
90 try leb.writeILEB128(writer, constant.val.toUnsignedInt());
91 },
92 .i32 => {
93 try writer.writeByte(0x41); // i32.const
94 try leb.writeILEB128(writer, constant.val.toSignedInt());
95 },
96 .u64 => {
97 try writer.writeByte(0x42); // i64.const
98 try leb.writeILEB128(writer, constant.val.toUnsignedInt());
99 },
100 .i64 => {
101 try writer.writeByte(0x42); // i64.const
102 try leb.writeILEB128(writer, constant.val.toSignedInt());
103 },
104 .f32 => {
105 try writer.writeByte(0x43); // f32.const
106 // TODO: enforce LE byte order
107 try writer.writeAll(mem.asBytes(&constant.val.toFloat(f32)));
108 },
109 .f64 => {
110 try writer.writeByte(0x44); // f64.const
111 // TODO: enforce LE byte order
112 try writer.writeAll(mem.asBytes(&constant.val.toFloat(f64)));
113 },
114 else => return error.TODOImplementMoreWasmCodegen,
115 }
116 },
117 else => return error.TODOImplementMoreWasmCodegen,
118 }
119}