aboutsummaryrefslogtreecommitdiff
path: root/src/compile.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/compile.zig')
-rw-r--r--src/compile.zig58
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;
}
}