aboutsummaryrefslogtreecommitdiff
path: root/src/compile.zig
diff options
context:
space:
mode:
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;
}