diff options
author | Mathias Magnusson <mathias@magnusson.space> | 2025-05-31 02:12:02 +0200 |
---|---|---|
committer | Mathias Magnusson <mathias@magnusson.space> | 2025-05-31 02:12:02 +0200 |
commit | ee78756a504dc61f50422298cc1123c5ac6b3b69 (patch) | |
tree | fe99400865ef7fe652cee6678f27d7e8093b3e23 /src/compile.zig | |
parent | 1ba97916933d858434294b3fde9631873bbf16c8 (diff) | |
download | huginn-ee78756a504dc61f50422298cc1123c5ac6b3b69.tar.gz |
actually codegen the provided code
... well, since all we can do is to add integer literals, we produce
code for the calculations and then perform the exit syscall with the
result
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; } |