feat: code generation for switch statements
This commit is contained in:
parent
e5e2b7c559
commit
fac5a968e3
3 changed files with 195 additions and 14 deletions
52
src/Ir.zig
52
src/Ir.zig
|
|
@ -72,6 +72,7 @@ pub const Inst = struct {
|
|||
block,
|
||||
condbr,
|
||||
@"break",
|
||||
switch_br,
|
||||
content_push,
|
||||
content_flush,
|
||||
};
|
||||
|
|
@ -126,6 +127,17 @@ pub const Inst = struct {
|
|||
then_body_len: u32,
|
||||
else_body_len: u32,
|
||||
};
|
||||
|
||||
pub const SwitchBr = struct {
|
||||
operand: Ref,
|
||||
cases_len: u32,
|
||||
else_body_len: u32,
|
||||
|
||||
pub const Case = struct {
|
||||
operand: Ref,
|
||||
body_len: u32,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pub const Global = struct {
|
||||
|
|
@ -277,6 +289,43 @@ const Render = struct {
|
|||
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 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);
|
||||
|
|
@ -340,6 +389,7 @@ const Render = struct {
|
|||
},
|
||||
.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),
|
||||
|
|
@ -366,7 +416,7 @@ const Render = struct {
|
|||
try io_w.print("{s}(\"{s}\")", .{ @tagName(inst.tag), str_bytes });
|
||||
},
|
||||
.content_push => try r.renderUnary(inst),
|
||||
.content_flush => try r.renderSimple(inst),
|
||||
.content_flush => try r.renderUnary(inst),
|
||||
}
|
||||
try io_w.writeAll("\n");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue