feat: added Ir.Inst.Ref, global constant pool, lazy lowering in Sema

This commit is contained in:
Brett Broadhurst 2026-03-11 20:15:52 -06:00
parent ce5385ebac
commit e5e2b7c559
Failed to generate hash of commit
6 changed files with 615 additions and 534 deletions

View file

@ -1,5 +1,6 @@
const std = @import("std");
const Ast = @import("Ast.zig");
const assert = std.debug.assert;
const Ir = @This();
string_bytes: []u8,
@ -13,8 +14,35 @@ pub const Inst = struct {
data: Data,
pub const Index = enum(u32) {
file_inst = 0,
file_inst,
ref_start_index = 32,
_,
pub fn toRef(i: Index) Inst.Ref {
return @enumFromInt(@intFromEnum(Index.ref_start_index) + @intFromEnum(i));
}
};
pub const Ref = enum(u32) {
bool_true,
bool_false,
none = std.math.maxInt(u32),
_,
pub fn toIndex(inst: Ref) ?Index {
assert(inst != .none);
const ref_int = @intFromEnum(inst);
if (ref_int >= @intFromEnum(Index.ref_start_index)) {
return @enumFromInt(ref_int - @intFromEnum(Index.ref_start_index));
} else {
return null;
}
}
pub fn toIndexAllowNone(inst: Ref) ?Index {
if (inst == .none) return null;
return toIndex(inst);
}
};
pub const Tag = enum {
@ -23,12 +51,9 @@ pub const Inst = struct {
decl_knot,
decl_var,
decl_ref,
block,
condbr,
@"break",
alloc_local,
load_local,
store_local,
alloc,
load,
store,
add,
sub,
mul,
@ -42,10 +67,11 @@ pub const Inst = struct {
cmp_gte,
cmp_lt,
cmp_lte,
true_literal,
false_literal,
integer,
string,
block,
condbr,
@"break",
content_push,
content_flush,
};
@ -55,11 +81,11 @@ pub const Inst = struct {
payload_index: u32,
},
un: struct {
lhs: Index,
lhs: Ref,
},
bin: struct {
lhs: Index,
rhs: Index,
lhs: Ref,
rhs: Ref,
},
integer: struct {
value: u64,
@ -96,7 +122,7 @@ pub const Inst = struct {
};
pub const CondBr = struct {
condition: Index,
condition: Ref,
then_body_len: u32,
else_body_len: u32,
};
@ -165,6 +191,22 @@ const Render = struct {
}
};
fn renderInstIndex(r: *Render, index: Inst.Index) !void {
const io_w = r.writer;
return io_w.print("%{d}", .{@intFromEnum(index)});
}
fn renderInstRef(r: *Render, ref: Inst.Ref) !void {
const io_w = r.writer;
if (ref == .none) {
return io_w.writeAll(".none");
} else if (ref.toIndex()) |i| {
return r.renderInstIndex(i);
} else {
return io_w.print("@{s}", .{@tagName(ref)});
}
}
fn renderSimple(r: *Render, inst: Inst) Error!void {
const io_w = r.writer;
return io_w.print("{s}(?)", .{@tagName(inst.tag)});
@ -172,12 +214,22 @@ const Render = struct {
fn renderUnary(r: *Render, inst: Inst) Error!void {
const io_w = r.writer;
return io_w.print("{s}(%{d})", .{ @tagName(inst.tag), inst.data.un.lhs });
const data = inst.data.un;
try io_w.print("{s}(", .{@tagName(inst.tag)});
const lhs = data.lhs;
try renderInstRef(r, lhs);
return io_w.writeAll(")");
}
fn renderBinary(r: *Render, inst: Inst) Error!void {
const io_w = r.writer;
return io_w.print("{s}(%{d}, %{d})", .{ @tagName(inst.tag), inst.data.bin.lhs, inst.data.bin.rhs });
const data = inst.data.bin;
try io_w.print("{s}(", .{@tagName(inst.tag)});
try renderInstRef(r, data.lhs);
try io_w.writeAll(", ");
try renderInstRef(r, data.rhs);
return io_w.writeAll(")");
}
fn renderBodyInner(r: *Render, ir: Ir, body_list: []const Inst.Index) Error!void {
@ -216,7 +268,9 @@ const Render = struct {
const then_body = ir.bodySlice(extra.end, extra.data.then_body_len);
const else_body = ir.bodySlice(extra.end + then_body.len, extra.data.else_body_len);
try io_w.print("{s}(%{d}, ", .{ @tagName(inst.tag), extra.data.condition });
try io_w.print("{s}(", .{@tagName(inst.tag)});
try renderInstRef(r, extra.data.condition);
try io_w.writeAll(", ");
try renderBodyInner(r, ir, then_body);
try io_w.writeAll(", ");
try renderBodyInner(r, ir, else_body);
@ -286,9 +340,9 @@ const Render = struct {
},
.condbr => try r.renderCondbr(ir, inst),
.@"break" => try r.renderBreak(ir, inst),
.alloc_local => try r.renderSimple(inst),
.load_local => try r.renderUnary(inst),
.store_local => try r.renderBinary(inst),
.alloc => try r.renderSimple(inst),
.load => try r.renderUnary(inst),
.store => try r.renderBinary(inst),
.block => try r.renderBlock(ir, inst),
.add => try r.renderBinary(inst),
.sub => try r.renderBinary(inst),
@ -303,12 +357,6 @@ const Render = struct {
.cmp_gte => try r.renderBinary(inst),
.cmp_lt => try r.renderBinary(inst),
.cmp_lte => try r.renderBinary(inst),
.true_literal => {
try io_w.print("{s}", .{@tagName(inst.tag)});
},
.false_literal => {
try io_w.print("{s}", .{@tagName(inst.tag)});
},
.integer => {
const value = inst.data.integer.value;
try io_w.print("{s}({d})", .{ @tagName(inst.tag), value });
@ -317,8 +365,8 @@ const Render = struct {
const str_bytes = inst.data.string.get(ir);
try io_w.print("{s}(\"{s}\")", .{ @tagName(inst.tag), str_bytes });
},
.content_push => try r.renderSimple(inst),
.content_flush => try r.renderUnary(inst),
.content_push => try r.renderUnary(inst),
.content_flush => try r.renderSimple(inst),
}
try io_w.writeAll("\n");
}
@ -329,7 +377,7 @@ pub fn render(ir: Ir, gpa: std.mem.Allocator, writer: *std.Io.Writer) !void {
var r = Render{ .gpa = gpa, .writer = writer, .prefix = .{} };
defer r.prefix.deinit(gpa);
try r.renderInst(ir, .file_inst);
try r.renderInst(ir, @enumFromInt(0));
return writer.flush();
}
@ -367,6 +415,7 @@ pub fn extraData(ir: Ir, comptime T: type, index: usize) ExtraData(T) {
@field(result, field.name) = switch (field.type) {
u32 => ir.extra[i],
Inst.Index => @enumFromInt(ir.extra[i]),
Inst.Ref => @enumFromInt(ir.extra[i]),
NullTerminatedString => @enumFromInt(ir.extra[i]),
else => @compileError("bad field type"),
};