feat: code generation for diverts, wip
This commit is contained in:
parent
ee26be6254
commit
20292bcc6a
5 changed files with 699 additions and 149 deletions
121
src/Ir.zig
121
src/Ir.zig
|
|
@ -77,6 +77,12 @@ pub const Inst = struct {
|
|||
content_flush,
|
||||
choice_br,
|
||||
implicit_ret,
|
||||
call,
|
||||
divert,
|
||||
field_ptr,
|
||||
field_call,
|
||||
field_divert,
|
||||
param,
|
||||
};
|
||||
|
||||
pub const Data = union {
|
||||
|
|
@ -116,6 +122,11 @@ pub const Inst = struct {
|
|||
body_len: u32,
|
||||
};
|
||||
|
||||
pub const Field = struct {
|
||||
lhs: Ref,
|
||||
field_name_start: NullTerminatedString,
|
||||
};
|
||||
|
||||
pub const Block = struct {
|
||||
body_len: u32,
|
||||
};
|
||||
|
|
@ -151,6 +162,17 @@ pub const Inst = struct {
|
|||
body_len: u32,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Call = struct {
|
||||
args_len: u32,
|
||||
callee: Ref,
|
||||
};
|
||||
|
||||
pub const FieldCall = struct {
|
||||
args_len: u32,
|
||||
obj_ptr: Ref,
|
||||
field_name_start: NullTerminatedString,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Global = struct {
|
||||
|
|
@ -186,6 +208,7 @@ pub fn deinit(ir: *Ir, gpa: std.mem.Allocator) void {
|
|||
const Render = struct {
|
||||
gpa: std.mem.Allocator,
|
||||
prefix: Prefix,
|
||||
code: Ir,
|
||||
writer: *std.Io.Writer,
|
||||
|
||||
pub const Error = error{
|
||||
|
|
@ -259,6 +282,7 @@ const Render = struct {
|
|||
|
||||
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);
|
||||
|
|
@ -413,6 +437,88 @@ const Render = struct {
|
|||
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);
|
||||
|
|
@ -461,14 +567,25 @@ const Render = struct {
|
|||
.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 {
|
||||
std.debug.assert(ir.instructions.len > 0);
|
||||
var r = Render{ .gpa = gpa, .writer = writer, .prefix = .{} };
|
||||
assert(ir.instructions.len > 0);
|
||||
var r = Render{
|
||||
.gpa = gpa,
|
||||
.writer = writer,
|
||||
.prefix = .{},
|
||||
.code = ir,
|
||||
};
|
||||
defer r.prefix.deinit(gpa);
|
||||
|
||||
try r.renderInst(ir, @enumFromInt(0));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue