diff options
Diffstat (limited to 'src-self-hosted/codegen/wasm.zig')
| -rw-r--r-- | src-self-hosted/codegen/wasm.zig | 142 |
1 files changed, 0 insertions, 142 deletions
diff --git a/src-self-hosted/codegen/wasm.zig b/src-self-hosted/codegen/wasm.zig deleted file mode 100644 index 4ea8838409..0000000000 --- a/src-self-hosted/codegen/wasm.zig +++ /dev/null @@ -1,142 +0,0 @@ -const std = @import("std"); -const Allocator = std.mem.Allocator; -const ArrayList = std.ArrayList; -const assert = std.debug.assert; -const leb = std.debug.leb; -const mem = std.mem; - -const Module = @import("../Module.zig"); -const Decl = Module.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()) { - .u32, .i32 => 0x7F, - .u64, .i64 => 0x7E, - .f32 => 0x7D, - .f64 => 0x7C, - else => @panic("TODO: Implement more types for wasm."), - }; -} - -pub fn genFunctype(buf: *ArrayList(u8), decl: *Decl) !void { - const ty = decl.typed_value.most_recent.typed_value.ty; - const writer = buf.writer(); - - // functype magic - try writer.writeByte(0x60); - - // param types - try leb.writeULEB128(writer, @intCast(u32, ty.fnParamLen())); - if (ty.fnParamLen() != 0) { - const params = try buf.allocator.alloc(Type, ty.fnParamLen()); - defer buf.allocator.free(params); - ty.fnParamTypes(params); - for (params) |param_type| try writer.writeByte(genValtype(param_type)); - } - - // return type - const return_type = ty.fnReturnType(); - switch (return_type.tag()) { - .void, .noreturn => try leb.writeULEB128(writer, @as(u32, 0)), - else => { - try leb.writeULEB128(writer, @as(u32, 1)); - try writer.writeByte(genValtype(return_type)); - }, - } -} - -pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void { - assert(buf.items.len == 0); - const writer = buf.writer(); - - // Reserve space to write the size after generating the code - try buf.resize(5); - - // Write the size of the locals vec - // TODO: implement locals - try leb.writeULEB128(writer, @as(u32, 0)); - - // Write instructions - // 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(buf, decl, inst); - - // Write 'end' opcode - try writer.writeByte(0x0B); - - // Fill in the size of the generated code to the reserved space at the - // beginning of the buffer. - const size = buf.items.len - 5 + decl.fn_link.wasm.?.idx_refs.items.len * 5; - leb.writeUnsignedFixed(5, buf.items[0..5], @intCast(u32, size)); -} - -fn genInst(buf: *ArrayList(u8), decl: *Decl, inst: *Inst) !void { - return switch (inst.tag) { - .call => genCall(buf, decl, inst.castTag(.call).?), - .constant => genConstant(buf, decl, inst.castTag(.constant).?), - .dbg_stmt => {}, - .ret => genRet(buf, decl, inst.castTag(.ret).?), - .retvoid => {}, - else => error.TODOImplementMoreWasmCodegen, - }; -} - -fn genConstant(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.Constant) !void { - const writer = buf.writer(); - switch (inst.base.ty.tag()) { - .u32 => { - try writer.writeByte(0x41); // i32.const - try leb.writeILEB128(writer, inst.val.toUnsignedInt()); - }, - .i32 => { - try writer.writeByte(0x41); // i32.const - try leb.writeILEB128(writer, inst.val.toSignedInt()); - }, - .u64 => { - try writer.writeByte(0x42); // i64.const - try leb.writeILEB128(writer, inst.val.toUnsignedInt()); - }, - .i64 => { - try writer.writeByte(0x42); // i64.const - try leb.writeILEB128(writer, inst.val.toSignedInt()); - }, - .f32 => { - try writer.writeByte(0x43); // f32.const - // TODO: enforce LE byte order - try writer.writeAll(mem.asBytes(&inst.val.toFloat(f32))); - }, - .f64 => { - try writer.writeByte(0x44); // f64.const - // TODO: enforce LE byte order - try writer.writeAll(mem.asBytes(&inst.val.toFloat(f64))); - }, - .void => {}, - else => return error.TODOImplementMoreWasmCodegen, - } -} - -fn genRet(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.UnOp) !void { - try genInst(buf, decl, inst.operand); -} - -fn genCall(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.Call) !void { - const func_inst = inst.func.castTag(.constant).?; - const func_val = func_inst.val.cast(Value.Payload.Function).?; - const target = func_val.func.owner_decl; - const target_ty = target.typed_value.most_recent.typed_value.ty; - - if (inst.args.len != 0) return error.TODOImplementMoreWasmCodegen; - - try buf.append(0x10); // call - - // The function index immediate argument will be filled in using this data - // in link.Wasm.flush(). - try decl.fn_link.wasm.?.idx_refs.append(buf.allocator, .{ - .offset = @intCast(u32, buf.items.len), - .decl = target, - }); -} |
