diff options
Diffstat (limited to 'src/compile.zig')
-rw-r--r-- | src/compile.zig | 79 |
1 files changed, 58 insertions, 21 deletions
diff --git a/src/compile.zig b/src/compile.zig index b9e1a86..822153f 100644 --- a/src/compile.zig +++ b/src/compile.zig @@ -5,47 +5,80 @@ const Token = root.Lexer.Token; const Expr = root.Expr; const Location = root.Lexer.Location; -pub const Reg = enum(u32) { _ }; +pub const VReg = enum(u32) { _ }; -pub const Instr = union(enum) { - constant: Constant, - bin_op: BinOp, +pub const Instr = struct { + loc: Location, + type: Type, + + const Type = union(enum) { + constant: Constant, + bin_op: BinOp, + }; const Constant = struct { - dest: Reg, - value: Location, + dest: VReg, + value: u64, }; const BinOp = struct { - dest: Reg, - lhs: Reg, - rhs: Reg, + dest: VReg, + lhs: VReg, + rhs: VReg, op: Op, const Op = enum { add, }; }; + + pub fn sources(self: Instr) std.BoundedArray(VReg, 2) { + return switch (self.type) { + .bin_op => |bin_op| std.BoundedArray(VReg, 2).fromSlice(&.{ bin_op.lhs, bin_op.rhs }) catch unreachable, + .constant => std.BoundedArray(VReg, 2).init(0) catch unreachable, + }; + } + + pub fn dest(self: *const Instr) VReg { + return switch (self.type) { + inline .constant, .bin_op => |s| s.dest, + }; + } }; pub const Block = struct { // arguments: []Reg, instrs: []Instr, + vreg_last_use: std.AutoHashMap(VReg, usize), + + fn init(allocator: Allocator, instrs: []Instr) !Block { + var vreg_last_use: std.AutoHashMap(VReg, usize) = .init(allocator); + for (0.., instrs) |i, instr| { + for (instr.sources().slice()) |src| + try vreg_last_use.put(src, i); + } + return .{ + .instrs = instrs, + .vreg_last_use = vreg_last_use, + }; + } }; -pub fn compile(allocator: Allocator, expr: *const Expr) !Block { +pub fn compile(allocator: Allocator, source: []const u8, expr: *const Expr) !Block { const instrs: std.ArrayListUnmanaged(Instr) = try .initCapacity(allocator, 0); var ctx: CompileContext = .{ .allocator = allocator, + .source = source, .register_counter = 0, .instrs = instrs, }; _ = try ctx.compileExpr(expr); - return .{ .instrs = ctx.instrs.items }; + return .init(allocator, ctx.instrs.items); } const CompileContext = struct { allocator: Allocator, + source: []const u8, register_counter: u32, instrs: std.ArrayListUnmanaged(Instr), @@ -55,22 +88,26 @@ const CompileContext = struct { try self.instrs.append(self.allocator, instr); } - fn compileExpr(self: *Self, expr: *const Expr) !Reg { + fn compileExpr(self: *Self, expr: *const Expr) !VReg { const dest = self.register(); switch (expr.type) { .integer_literal => try addInstr(self, .{ - .constant = .{ .dest = dest, .value = expr.loc }, + .loc = expr.loc, + .type = .{ .constant = .{ .dest = dest, .value = expr.getInt(self.source) } }, }), .bin_op => |binop| { const lhs = try self.compileExpr(binop.lhs); const rhs = try self.compileExpr(binop.rhs); try addInstr(self, .{ - .bin_op = .{ - .dest = dest, - .lhs = lhs, - .rhs = rhs, - .op = switch (binop.op) { - .plus => .add, + .loc = expr.loc, + .type = .{ + .bin_op = .{ + .dest = dest, + .lhs = lhs, + .rhs = rhs, + .op = switch (binop.op) { + .plus => .add, + }, }, }, }); @@ -80,8 +117,8 @@ const CompileContext = struct { return dest; } - fn register(self: *Self) Reg { - const reg: Reg = @enumFromInt(self.register_counter); + fn register(self: *Self) VReg { + const reg: VReg = @enumFromInt(self.register_counter); self.register_counter += 1; return reg; } |