feat: added Ir.Inst.Ref, global constant pool, lazy lowering in Sema
This commit is contained in:
parent
ce5385ebac
commit
e5e2b7c559
6 changed files with 615 additions and 534 deletions
105
src/Ir.zig
105
src/Ir.zig
|
|
@ -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"),
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue