aboutsummaryrefslogtreecommitdiff
path: root/src/compile.zig
diff options
context:
space:
mode:
authorMathias Magnusson <mathias@magnusson.space>2025-05-31 02:12:02 +0200
committerMathias Magnusson <mathias@magnusson.space>2025-05-31 02:12:02 +0200
commitee78756a504dc61f50422298cc1123c5ac6b3b69 (patch)
treefe99400865ef7fe652cee6678f27d7e8093b3e23 /src/compile.zig
parent1ba97916933d858434294b3fde9631873bbf16c8 (diff)
downloadhuginn-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.zig79
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;
}