refactor: clean up ir print writer

This commit is contained in:
Brett Broadhurst 2026-03-18 01:37:42 -06:00
parent 20292bcc6a
commit 517eae1481
Failed to generate hash of commit
3 changed files with 319 additions and 384 deletions

View file

@ -1,5 +1,6 @@
const std = @import("std"); const std = @import("std");
const Ast = @import("Ast.zig"); const Ast = @import("Ast.zig");
const Writer = @import("print_ir.zig").Writer;
const assert = std.debug.assert; const assert = std.debug.assert;
const Ir = @This(); const Ir = @This();
@ -205,390 +206,10 @@ pub fn deinit(ir: *Ir, gpa: std.mem.Allocator) void {
ir.* = undefined; ir.* = undefined;
} }
const Render = struct { pub fn render(ir: Ir, writer: *std.Io.Writer) !void {
gpa: std.mem.Allocator,
prefix: Prefix,
code: Ir,
writer: *std.Io.Writer,
pub const Error = error{
OutOfMemory,
WriteFailed,
};
const Prefix = struct {
buf: std.ArrayListUnmanaged(u8) = .empty,
pub fn deinit(self: *Prefix, gpa: std.mem.Allocator) void {
self.buf.deinit(gpa);
}
pub fn writeIndent(self: *const Prefix, writer: *std.Io.Writer) !void {
try writer.writeAll(self.buf.items);
}
pub fn pushChildPrefix(self: *Prefix, gpa: std.mem.Allocator) !usize {
const old_len = self.buf.items.len;
const seg: []const u8 = " ";
try self.buf.appendSlice(gpa, seg);
return old_len;
}
pub fn restore(self: *Prefix, new_len: usize) void {
self.buf.shrinkRetainingCapacity(new_len);
}
};
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)});
}
fn renderUnary(r: *Render, inst: Inst) Error!void {
const io_w = r.writer;
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;
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 {
const io_w = r.writer;
try r.prefix.writeIndent(io_w);
try io_w.writeAll("{\n");
{
const old_len = try r.prefix.pushChildPrefix(r.gpa);
defer r.prefix.restore(old_len);
for (body_list) |inst| try r.renderInst(ir, inst);
}
try r.prefix.writeIndent(io_w);
try io_w.writeAll("}");
}
fn renderBlock(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const extra = ir.extraData(Inst.Block, inst.data.payload.payload_index);
const body_slice = ir.bodySlice(extra.end, extra.data.body_len);
try io_w.print("{s}(", .{@tagName(inst.tag)});
try renderBodyInner(r, ir, body_slice);
try io_w.writeAll(")");
}
fn renderBreak(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const extra = ir.extraData(Inst.Break, inst.data.payload.payload_index);
try io_w.print("{s}(%{d})", .{ @tagName(inst.tag), extra.data.block_inst });
}
fn renderCondbr(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const extra = ir.extraData(Inst.CondBr, inst.data.payload.payload_index);
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}(", .{@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);
try io_w.writeAll(")");
}
fn renderSwitchBr(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const switch_node = inst.data.payload;
const switch_extra = ir.extraData(Inst.SwitchBr, switch_node.payload_index);
const cases_slice = ir.bodySlice(switch_extra.end, switch_extra.data.cases_len);
try io_w.print("{s}(", .{@tagName(inst.tag)});
try renderInstRef(r, switch_extra.data.operand);
try io_w.print(", \n", .{});
for (cases_slice) |case_index| {
const case_extra = ir.extraData(Inst.SwitchBr.Case, @intFromEnum(case_index));
const body_slice = ir.bodySlice(case_extra.end, case_extra.data.body_len);
const old_len = try r.prefix.pushChildPrefix(r.gpa);
defer r.prefix.restore(old_len);
try r.prefix.writeIndent(io_w);
try renderInstRef(r, case_extra.data.operand);
try io_w.print(" = ", .{});
try renderBodyInner(r, ir, body_slice);
try io_w.writeAll(",\n");
}
const else_body = ir.bodySlice(
switch_extra.end + switch_extra.data.cases_len,
switch_extra.data.else_body_len,
);
{
const old_len = try r.prefix.pushChildPrefix(r.gpa);
defer r.prefix.restore(old_len);
try r.prefix.writeIndent(io_w);
try io_w.print("else = ", .{});
try renderBodyInner(r, ir, else_body);
}
try io_w.writeAll(")");
}
fn renderChoiceBr(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const data = inst.data.payload;
const choice_extra = ir.extraData(Inst.ChoiceBr, data.payload_index);
const options_slice = ir.bodySlice(choice_extra.end, choice_extra.data.cases_len);
try io_w.print("{s}(\n", .{@tagName(inst.tag)});
for (options_slice) |option_index| {
const case_extra = ir.extraData(Inst.ChoiceBr.Case, @intFromEnum(option_index));
const body_slice = ir.bodySlice(case_extra.end, case_extra.data.body_len);
const old_len = try r.prefix.pushChildPrefix(r.gpa);
defer r.prefix.restore(old_len);
try r.prefix.writeIndent(io_w);
try renderInstRef(r, case_extra.data.operand_1);
try io_w.writeAll(", ");
try renderInstRef(r, case_extra.data.operand_2);
try io_w.writeAll(", ");
try renderInstRef(r, case_extra.data.operand_3);
try io_w.print(" = ", .{});
try renderBodyInner(r, ir, body_slice);
try io_w.writeAll(",\n");
}
try r.prefix.writeIndent(io_w);
try io_w.writeAll(")");
}
fn renderKnotDecl(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const extra = ir.extraData(Inst.Knot, inst.data.payload.payload_index);
const body_slice = ir.bodySlice(extra.end, extra.data.body_len);
try io_w.print("{s}(body=", .{@tagName(inst.tag)});
try renderBodyInner(r, ir, body_slice);
try io_w.writeAll(")");
}
fn renderVarDecl(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const extra = ir.extraData(Inst.Knot, inst.data.payload.payload_index);
const body_slice = ir.bodySlice(extra.end, extra.data.body_len);
try io_w.print("{s}(body=", .{@tagName(inst.tag)});
try renderBodyInner(r, ir, body_slice);
try io_w.writeAll(")");
}
fn renderDeclaration(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const extra = ir.extraData(Inst.Declaration, inst.data.payload.payload_index);
const ident_str = ir.nullTerminatedString(extra.data.name);
try io_w.print("{s}(name=\"{s}\", value={{\n", .{ @tagName(inst.tag), ident_str });
{
const old_len = try r.prefix.pushChildPrefix(r.gpa);
defer r.prefix.restore(old_len);
try renderInst(r, ir, extra.data.value);
}
try r.prefix.writeIndent(io_w);
return io_w.writeAll(")");
}
fn renderFile(r: *Render, ir: Ir, inst: Inst) Error!void {
const io_w = r.writer;
const extra = ir.extraData(Inst.Block, inst.data.payload.payload_index);
const body_slice = ir.bodySlice(extra.end, extra.data.body_len);
try io_w.print("{s}(", .{@tagName(inst.tag)});
try renderBodyInner(r, ir, body_slice);
return io_w.writeAll(")");
}
fn writeTag(_: *Render, w: *std.Io.Writer, inst: Ir.Inst) Error!void {
return w.print("{s}", .{@tagName(inst.tag)});
}
fn writeIndent(self: *Render, w: *std.Io.Writer) Error!void {
return self.prefix.writeIndent(w);
}
fn writeString(self: *Render, w: *std.Io.Writer, str: Ir.NullTerminatedString) Error!void {
return w.print("\"{s}\"", .{self.code.nullTerminatedString(str)});
}
fn writeFieldPtr(self: *Render, w: *std.Io.Writer, inst: Ir.Inst) Error!void {
const data = inst.data.payload;
const extra = self.code.extraData(Inst.Field, data.payload_index).data;
try self.writeTag(w, inst);
try w.writeAll("(");
try self.renderInstRef(extra.lhs);
try w.writeAll(", ");
try self.writeString(w, extra.field_name_start);
return w.writeAll(")");
}
fn writeCall(
self: *Render,
w: *std.Io.Writer,
inst: Ir.Inst,
comptime kind: enum {
field,
direct,
},
) Error!void {
const ExtraType = switch (kind) {
.direct => Ir.Inst.Call,
.field => Ir.Inst.FieldCall,
};
const data = inst.data.payload;
const extra = self.code.extraData(ExtraType, data.payload_index);
const args_len = extra.data.args_len;
const body = self.code.extra[extra.end..];
try self.writeTag(w, inst);
try w.writeAll("(");
switch (kind) {
.direct => try self.renderInstRef(extra.data.callee),
.field => {
try self.renderInstRef(extra.data.obj_ptr);
try w.writeAll(", ");
try self.writeString(w, extra.data.field_name_start);
},
}
try w.writeAll(", ");
try w.writeAll("[\n");
var arg_start: u32 = args_len;
var i: u32 = 0;
while (i < args_len) : (i += 1) {
const old_len = try self.prefix.pushChildPrefix(self.gpa);
defer self.prefix.restore(old_len);
const arg_end = self.code.extra[extra.end + i];
defer arg_start = arg_end;
const arg_body = body[arg_start..arg_end];
try self.renderBodyInner(self.code, @ptrCast(arg_body));
try w.writeAll(",\n");
}
try self.writeIndent(w);
try w.writeAll("]");
return w.writeAll(")");
}
fn writeParam(self: *Render, w: *std.Io.Writer, inst: Ir.Inst) Error!void {
const data = inst.data.string.start;
try self.writeTag(w, inst);
try w.writeAll("(");
try self.writeString(w, data);
return w.writeAll(")");
}
fn renderInst(r: *Render, ir: Ir, index: Inst.Index) Error!void {
const io_w = r.writer;
const inst_index: u32 = @intFromEnum(index);
const inst = ir.instructions[inst_index];
try r.prefix.writeIndent(io_w);
try io_w.print("%{d} = ", .{inst_index});
switch (inst.tag) {
.file => try r.renderFile(ir, inst),
.declaration => try r.renderDeclaration(ir, inst),
.decl_knot => try r.renderKnotDecl(ir, inst),
.decl_var => try r.renderVarDecl(ir, inst),
.decl_ref => {
const str_bytes = inst.data.string.get(ir);
try io_w.print("{s}(\"{s}\")", .{ @tagName(inst.tag), str_bytes });
},
.condbr => try r.renderCondbr(ir, inst),
.@"break" => try r.renderBreak(ir, inst),
.switch_br => try r.renderSwitchBr(ir, 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),
.mul => try r.renderBinary(inst),
.div => try r.renderBinary(inst),
.mod => try r.renderBinary(inst),
.neg => try r.renderUnary(inst),
.not => try r.renderUnary(inst),
.cmp_eq => try r.renderBinary(inst),
.cmp_neq => try r.renderBinary(inst),
.cmp_gt => try r.renderBinary(inst),
.cmp_gte => try r.renderBinary(inst),
.cmp_lt => try r.renderBinary(inst),
.cmp_lte => try r.renderBinary(inst),
.integer => {
const value = inst.data.integer.value;
try io_w.print("{s}({d})", .{ @tagName(inst.tag), value });
},
.string => {
const str_bytes = inst.data.string.get(ir);
try io_w.print("{s}(\"{s}\")", .{ @tagName(inst.tag), str_bytes });
},
.content_push => try r.renderUnary(inst),
.content_flush => try r.renderUnary(inst),
.choice_br => try r.renderChoiceBr(ir, inst),
.implicit_ret => try r.renderUnary(inst),
.call => try r.writeCall(r.writer, inst, .direct),
.divert => try r.writeCall(r.writer, inst, .direct),
.field_call => try r.writeCall(r.writer, inst, .field),
.field_divert => try r.writeCall(r.writer, inst, .field),
.field_ptr => try r.writeFieldPtr(r.writer, inst),
.param => try r.writeParam(r.writer, inst),
}
try io_w.writeAll("\n");
}
};
pub fn render(ir: Ir, gpa: std.mem.Allocator, writer: *std.Io.Writer) !void {
assert(ir.instructions.len > 0); assert(ir.instructions.len > 0);
var r = Render{ var w: Writer = .{ .code = ir };
.gpa = gpa, try w.writeInst(writer, .file_inst);
.writer = writer,
.prefix = .{},
.code = ir,
};
defer r.prefix.deinit(gpa);
try r.renderInst(ir, @enumFromInt(0));
return writer.flush(); return writer.flush();
} }

View file

@ -572,7 +572,7 @@ pub fn loadFromString(
if (options.dump_writer) |w| { if (options.dump_writer) |w| {
try w.writeAll("=== Semantic IR ===\n"); try w.writeAll("=== Semantic IR ===\n");
try sem_ir.dumpInfo(w); try sem_ir.dumpInfo(w);
try sem_ir.render(gpa, w); try sem_ir.render(w);
} }
} }

314
src/print_ir.zig Normal file
View file

@ -0,0 +1,314 @@
const std = @import("std");
const Ir = @import("Ir.zig");
pub const Writer = struct {
code: Ir,
indent_level: usize = 0,
indent_size: usize = 2,
pub const Error = error{
OutOfMemory,
WriteFailed,
};
fn writeIndent(self: *Writer, w: *std.Io.Writer) Error!void {
try w.splatByteAll(' ', self.indent_level);
}
fn pushIndent(self: *Writer) void {
self.indent_level += self.indent_size;
}
fn popIndent(self: *Writer) void {
if (self.indent_level >= self.indent_size) {
self.indent_level -= self.indent_size;
}
}
fn writeTag(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)];
try w.print("{s}", .{@tagName(data.tag)});
}
fn writeStringRef(self: *Writer, w: *std.Io.Writer, str: Ir.NullTerminatedString) Error!void {
try w.print("\"{s}\"", .{self.code.nullTerminatedString(str)});
}
fn writeInstIndex(_: *Writer, w: *std.Io.Writer, index: Ir.Inst.Index) !void {
try w.print("%{d}", .{@intFromEnum(index)});
}
fn writeInstRef(self: *Writer, w: *std.Io.Writer, ref: Ir.Inst.Ref) !void {
if (ref == .none) {
return w.writeAll(".none");
} else if (ref.toIndex()) |index| {
return self.writeInstIndex(w, index);
} else {
return w.print("@{s}", .{@tagName(ref)});
}
}
fn writeIntegerInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.integer;
try w.print("{d}", .{data.value});
}
fn writeStringInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.string;
try self.writeStringRef(w, data.start);
}
fn writeUnaryInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.un;
try self.writeInstRef(w, data.lhs);
}
fn writeBinaryInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.bin;
try self.writeInstRef(w, data.lhs);
try w.writeAll(", ");
try self.writeInstRef(w, data.rhs);
}
fn writeFieldPtrInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
const extra = self.code.extraData(Ir.Inst.Field, data.payload_index).data;
try self.writeInstRef(w, extra.lhs);
try w.writeAll(", ");
try self.writeStringRef(w, extra.field_name_start);
}
fn writeCallInst(
self: *Writer,
w: *std.Io.Writer,
inst: Ir.Inst.Index,
comptime kind: enum {
field,
direct,
},
) Error!void {
const ExtraType = switch (kind) {
.direct => Ir.Inst.Call,
.field => Ir.Inst.FieldCall,
};
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
const extra = self.code.extraData(ExtraType, data.payload_index);
const args_len = extra.data.args_len;
const body = self.code.extra[extra.end..];
switch (kind) {
.direct => try self.writeInstRef(w, extra.data.callee),
.field => {
try self.writeInstRef(w, extra.data.obj_ptr);
try w.writeAll(", ");
try self.writeStringRef(w, extra.data.field_name_start);
},
}
try w.writeAll(", ");
try w.writeAll("[\n");
var arg_start: u32 = args_len;
var i: u32 = 0;
while (i < args_len) : (i += 1) {
self.pushIndent();
const arg_end = self.code.extra[extra.end + i];
defer arg_start = arg_end;
const arg_body = body[arg_start..arg_end];
try self.writeBodyInner(w, @ptrCast(arg_body));
try w.writeAll(",\n");
self.popIndent();
}
try self.writeIndent(w);
try w.writeAll("]");
}
fn writeParamInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.string;
try self.writeStringRef(w, data.start);
}
fn writeBreakInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
const extra = self.code.extraData(Ir.Inst.Break, data.payload_index);
try self.writeInstIndex(w, extra.data.block_inst);
}
fn writeCondbrInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
const extra = self.code.extraData(Ir.Inst.CondBr, data.payload_index);
const then_body = self.code.bodySlice(extra.end, extra.data.then_body_len);
const else_body = self.code.bodySlice(extra.end + then_body.len, extra.data.else_body_len);
try self.writeInstRef(w, extra.data.condition);
try w.writeAll(", ");
try self.writeBodyInner(w, then_body);
try w.writeAll(", ");
try self.writeBodyInner(w, else_body);
}
fn writeSwitchBrInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
const extra = self.code.extraData(Ir.Inst.SwitchBr, data.payload_index);
const cases_slice = self.code.bodySlice(extra.end, extra.data.cases_len);
try self.writeInstRef(w, extra.data.operand);
try w.writeAll(", \n");
for (cases_slice) |case_index| {
const case_extra = self.code.extraData(Ir.Inst.SwitchBr.Case, @intFromEnum(case_index));
const body_slice = self.code.bodySlice(case_extra.end, case_extra.data.body_len);
self.pushIndent();
try self.writeIndent(w);
try self.writeInstRef(w, case_extra.data.operand);
try w.writeAll(" = ");
try self.writeBodyInner(w, body_slice);
try w.writeAll(",\n");
self.popIndent();
}
const else_body = self.code.bodySlice(
extra.end + extra.data.cases_len,
extra.data.else_body_len,
);
self.pushIndent();
try self.writeIndent(w);
try w.writeAll("else = ");
try self.writeBodyInner(w, else_body);
try w.writeAll(")");
self.popIndent();
}
fn writeChoiceBrInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
const extra = self.code.extraData(Ir.Inst.ChoiceBr, data.payload_index);
const options_slice = self.code.bodySlice(extra.end, extra.data.cases_len);
for (options_slice) |option_index| {
const case_extra = self.code.extraData(Ir.Inst.ChoiceBr.Case, @intFromEnum(option_index));
const body_slice = self.code.bodySlice(case_extra.end, case_extra.data.body_len);
self.pushIndent();
try self.writeIndent(w);
try self.writeInstRef(w, case_extra.data.operand_1);
try w.writeAll(", ");
try self.writeInstRef(w, case_extra.data.operand_2);
try w.writeAll(", ");
try self.writeInstRef(w, case_extra.data.operand_3);
try w.writeAll(" = ");
try self.writeBodyInner(w, body_slice);
try w.writeAll(",\n");
self.popIndent();
}
try self.writeIndent(w);
}
fn writeKnotDeclInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
const extra = self.code.extraData(Ir.Inst.Knot, data.payload_index);
const body_slice = self.code.bodySlice(extra.end, extra.data.body_len);
try w.writeAll("body=");
try self.writeBodyInner(w, body_slice);
}
fn writeVarDeclInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
const extra = self.code.extraData(Ir.Inst.Knot, data.payload_index);
const body_slice = self.code.bodySlice(extra.end, extra.data.body_len);
try w.writeAll("body=");
try self.writeBodyInner(w, body_slice);
}
fn writeDeclarationInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
const extra = self.code.extraData(Ir.Inst.Declaration, data.payload_index);
try w.writeAll("name=");
try self.writeStringRef(w, extra.data.name);
try w.writeAll(", ");
try w.writeAll("value={\n");
self.pushIndent();
try self.writeInst(w, extra.data.value);
self.popIndent();
try self.writeIndent(w);
try w.writeAll("}");
}
fn writeBodyInner(
self: *Writer,
w: *std.Io.Writer,
body_list: []const Ir.Inst.Index,
) Error!void {
try w.writeAll("{\n");
self.pushIndent();
for (body_list) |inst| try self.writeInst(w, inst);
self.popIndent();
try self.writeIndent(w);
try w.writeAll("}");
}
fn writeBlockInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
const extra = self.code.extraData(Ir.Inst.Block, data.payload_index);
const body_slice = self.code.bodySlice(extra.end, extra.data.body_len);
try self.writeBodyInner(w, body_slice);
}
fn writeFileInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
const extra = self.code.extraData(Ir.Inst.Block, data.payload_index);
const body_slice = self.code.bodySlice(extra.end, extra.data.body_len);
try self.writeBodyInner(w, body_slice);
}
pub fn writeInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
const tmp = self.code.instructions[@intFromEnum(inst)];
try self.writeIndent(w);
try self.writeInstIndex(w, inst);
try w.writeAll(" = ");
try self.writeTag(w, inst);
try w.writeAll("(");
switch (tmp.tag) {
.file => try self.writeFileInst(w, inst),
.declaration => try self.writeDeclarationInst(w, inst),
.decl_knot => try self.writeKnotDeclInst(w, inst),
.decl_var => try self.writeVarDeclInst(w, inst),
.decl_ref => try self.writeStringInst(w, inst),
.condbr => try self.writeCondbrInst(w, inst),
.@"break" => try self.writeBreakInst(w, inst),
.switch_br => try self.writeSwitchBrInst(w, inst),
.alloc => {},
.load => try self.writeUnaryInst(w, inst),
.store => try self.writeBinaryInst(w, inst),
.block => try self.writeBlockInst(w, inst),
.add => try self.writeBinaryInst(w, inst),
.sub => try self.writeBinaryInst(w, inst),
.mul => try self.writeBinaryInst(w, inst),
.div => try self.writeBinaryInst(w, inst),
.mod => try self.writeBinaryInst(w, inst),
.neg => try self.writeUnaryInst(w, inst),
.not => try self.writeUnaryInst(w, inst),
.cmp_eq => try self.writeBinaryInst(w, inst),
.cmp_neq => try self.writeBinaryInst(w, inst),
.cmp_gt => try self.writeBinaryInst(w, inst),
.cmp_gte => try self.writeBinaryInst(w, inst),
.cmp_lt => try self.writeBinaryInst(w, inst),
.cmp_lte => try self.writeBinaryInst(w, inst),
.integer => try self.writeIntegerInst(w, inst),
.string => try self.writeStringInst(w, inst),
.content_push => try self.writeUnaryInst(w, inst),
.content_flush => try self.writeUnaryInst(w, inst),
.choice_br => try self.writeChoiceBrInst(w, inst),
.implicit_ret => try self.writeUnaryInst(w, inst),
.call => try self.writeCallInst(w, inst, .direct),
.divert => try self.writeCallInst(w, inst, .direct),
.field_call => try self.writeCallInst(w, inst, .field),
.field_divert => try self.writeCallInst(w, inst, .field),
.field_ptr => try self.writeFieldPtrInst(w, inst),
.param => try self.writeParamInst(w, inst),
}
try w.writeAll(")");
try w.writeAll("\n");
}
};