diff options
Diffstat (limited to 'src/compile.zig')
-rw-r--r-- | src/compile.zig | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/src/compile.zig b/src/compile.zig index c84b2cc..80a9a17 100644 --- a/src/compile.zig +++ b/src/compile.zig @@ -41,24 +41,36 @@ pub const Module = struct { for (self.procedures) |proc| { try writer.print("{}", .{proc}); } + for ([_]struct { []const u8, BlockRef }{ + .{ "print", self.print_block }, + .{ "read_int", self.read_int_block }, + .{ "exit", self.exit_block }, + }) |builtin| { + const name, const block = builtin; + try writer.print("{s}:\n ${}: @builtin\n\n", .{ name, @intFromEnum(block) }); + } } }; pub const Procedure = struct { name: []const u8, blocks: []BasicBlock, + param_reg: ?VReg, - fn init(allocator: Allocator, name: []const u8, blocks: []BasicBlock) !Procedure { + fn init(allocator: Allocator, name: []const u8, blocks: []BasicBlock, param_reg: ?VReg) !Procedure { for (blocks) |*block| { try block.finalize(allocator); + if (param_reg) |p| _ = block.vreg_last_use.remove(p); } - return .{ .name = name, .blocks = blocks }; + return .{ .name = name, .blocks = blocks, .param_reg = param_reg }; } pub fn format(self: Procedure, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { _ = .{ fmt, options }; - try writer.print("{s}:\n", .{self.name}); + try writer.print("{s}(", .{self.name}); + if (self.param_reg) |reg| try writer.print("%{}", .{@intFromEnum(reg)}); + try writer.print("):\n", .{}); for (self.blocks) |block| { try writer.print("{}", .{block}); } @@ -111,7 +123,7 @@ pub const Instr = struct { pub const Type = union(enum) { constant: Constant, bin_op: BinOp, - proc_call: ProcCall, + call: Call, branch: Branch, jump: Jump, assign_local: AssignLocal, @@ -148,12 +160,12 @@ pub const Instr = struct { } }; - pub const ProcCall = struct { + pub const Call = struct { dest: VReg, arg: VReg, proc: BlockRef, - pub fn sources(self: ProcCall) Sources { + pub fn sources(self: Call) Sources { return Sources.fromSlice(&.{self.arg}) catch unreachable; } }; @@ -216,7 +228,7 @@ pub const Instr = struct { pub fn dest(self: *const Instr) ?VReg { return switch (self.type) { - inline .constant, .bin_op, .proc_call, .get_local => |s| s.dest, + inline .constant, .bin_op, .call, .get_local => |s| s.dest, .branch, .jump, .ret, .assign_local => null, }; } @@ -240,12 +252,12 @@ pub const Instr = struct { @intFromEnum(bin_op.rhs), }, ), - .proc_call => |proc_call| try writer.print( + .call => |call| try writer.print( "%{} = call ${}(%{})", .{ - @intFromEnum(proc_call.dest), - @intFromEnum(proc_call.proc), - @intFromEnum(proc_call.arg), + @intFromEnum(call.dest), + @intFromEnum(call.proc), + @intFromEnum(call.arg), }, ), .branch => |branch| { @@ -264,7 +276,6 @@ pub const Instr = struct { .get_local => |get_local| { try writer.print("%{} = @{}", .{ @intFromEnum(get_local.dest), @intFromEnum(get_local.local) }); }, - .ret => |ret| try writer.print("return %{}", .{@intFromEnum(ret.val)}), } } @@ -341,9 +352,16 @@ fn compileProcedure( .vreg_ctr = .init, .lvar_ctr = .init, .scope = .{ .locals = .empty, .parent = null }, + .param = .{ .name = "", .reg = undefined }, .blocks = try .init(ctx.allocator, &.{first_block}, &.{.{ .ref = first_block }}), .current_block = first_block, }; + const param_reg = if (proc.param) |param| blk: { + const reg = pctx.vreg_ctr.get(); + const param_name = param.getIdent(ctx.source); + pctx.param = .{ .name = param_name, .reg = reg }; + break :blk reg; + } else null; try pctx.compileBlock(proc.body); const proc_res = pctx.vreg_ctr.get(); try pctx.addInstr(.{ @@ -361,7 +379,7 @@ fn compileProcedure( std.debug.assert(kv.key_ptr.* == kv.value_ptr.ref); blocks[i] = kv.value_ptr.*; } - return try .init(ctx.allocator, name.getIdent(ctx.source), blocks); + return try .init(ctx.allocator, name.getIdent(ctx.source), blocks, param_reg); } const ProcedureContext = struct { @@ -371,6 +389,7 @@ const ProcedureContext = struct { lvar_ctr: IdCounter(LVar), scope: Scope, + param: struct { name: []const u8, reg: VReg }, blocks: std.AutoArrayHashMapUnmanaged(BlockRef, BasicBlock), current_block: BlockRef, @@ -407,7 +426,10 @@ const ProcedureContext = struct { while (scope) |s| : (scope = s.parent) { if (s.locals.get(assign_var.ident.getIdent(self.ctx.source))) |local| break :blk local; - } else return error.UnknownVariable; + } else { + std.log.debug("{s}", .{assign_var.ident.getIdent(self.ctx.source)}); + return error.UnknownVariable; + } }; const val = try self.compileExpr(assign_var.value); @@ -488,7 +510,7 @@ const ProcedureContext = struct { const arg = try self.compileExpr(call.arg); try self.addInstr(.{ .loc = expr.loc, - .type = .{ .proc_call = .{ + .type = .{ .call = .{ .dest = dest, .arg = arg, .proc = proc, @@ -496,10 +518,14 @@ const ProcedureContext = struct { }); }, .identifier => { + const ident = expr.loc.getIdent(self.ctx.source); + if (std.mem.eql(u8, ident, self.param.name)) { + return self.param.reg; + } var scope: ?*Scope = &self.scope; const local: LVar = blk: { while (scope) |s| : (scope = s.parent) { - if (s.locals.get(expr.loc.getIdent(self.ctx.source))) |local| { + if (s.locals.get(ident)) |local| { break :blk local; } } |