feat: code generation for simple choice statements, testing machinery
This commit is contained in:
parent
fac5a968e3
commit
ee26be6254
13 changed files with 304 additions and 70 deletions
84
src/Sema.zig
84
src/Sema.zig
|
|
@ -238,6 +238,76 @@ fn irContentFlush(_: *Sema, chunk: *Chunk, _: Ir.Inst.Index) InnerError!Ref {
|
|||
return chunk.addByteOp(.stream_flush);
|
||||
}
|
||||
|
||||
fn irChoiceBr(sema: *Sema, chunk: *Chunk, inst: Ir.Inst.Index) InnerError!void {
|
||||
const data = sema.ir.instructions[@intFromEnum(inst)].data.payload;
|
||||
const choice_extra = sema.ir.extraData(Ir.Inst.ChoiceBr, data.payload_index);
|
||||
const options_slice = sema.ir.bodySlice(choice_extra.end, choice_extra.data.cases_len);
|
||||
|
||||
var branch_labels: std.ArrayListUnmanaged(usize) = .empty;
|
||||
try branch_labels.ensureUnusedCapacity(sema.gpa, options_slice.len + 1);
|
||||
defer branch_labels.deinit(sema.gpa);
|
||||
|
||||
for (options_slice) |option_index| {
|
||||
const case_extra = sema.ir.extraData(Ir.Inst.ChoiceBr.Case, @intFromEnum(option_index));
|
||||
const case_label = try chunk.addLabel();
|
||||
branch_labels.appendAssumeCapacity(case_label);
|
||||
|
||||
switch (case_extra.data.operand_1) {
|
||||
.none => {},
|
||||
else => |content| {
|
||||
const content_inst = chunk.resolveInst(content);
|
||||
_ = try chunk.doLoad(content_inst);
|
||||
_ = try chunk.addByteOp(.stream_push);
|
||||
},
|
||||
}
|
||||
switch (case_extra.data.operand_2) {
|
||||
.none => {},
|
||||
else => |content| {
|
||||
const content_inst = chunk.resolveInst(content);
|
||||
_ = try chunk.doLoad(content_inst);
|
||||
_ = try chunk.addByteOp(.stream_push);
|
||||
},
|
||||
}
|
||||
|
||||
try chunk.addFixupAbsolute(.br_push, case_label);
|
||||
}
|
||||
|
||||
_ = try chunk.addByteOp(.br_table);
|
||||
_ = try chunk.addByteOp(.br_select_index);
|
||||
_ = try chunk.addByteOp(.br_dispatch);
|
||||
|
||||
for (options_slice, branch_labels.items) |option_index, label| {
|
||||
const case_extra = sema.ir.extraData(Ir.Inst.ChoiceBr.Case, @intFromEnum(option_index));
|
||||
const body_slice = sema.ir.bodySlice(case_extra.end, case_extra.data.body_len);
|
||||
|
||||
chunk.setLabel(label);
|
||||
|
||||
switch (case_extra.data.operand_1) {
|
||||
.none => {},
|
||||
else => |content| {
|
||||
const content_inst = chunk.resolveInst(content);
|
||||
_ = try chunk.doLoad(content_inst);
|
||||
_ = try chunk.addByteOp(.stream_push);
|
||||
},
|
||||
}
|
||||
switch (case_extra.data.operand_3) {
|
||||
.none => {},
|
||||
else => |content| {
|
||||
const content_inst = chunk.resolveInst(content);
|
||||
_ = try chunk.doLoad(content_inst);
|
||||
_ = try chunk.addByteOp(.stream_push);
|
||||
},
|
||||
}
|
||||
_ = try chunk.addByteOp(.stream_flush);
|
||||
|
||||
try blockBodyInner(sema, chunk, body_slice);
|
||||
}
|
||||
}
|
||||
|
||||
fn irImplicitRet(_: *Sema, chunk: *Chunk, _: Ir.Inst.Index) InnerError!Ref {
|
||||
return chunk.addByteOp(.exit);
|
||||
}
|
||||
|
||||
fn irDeclRef(sema: *Sema, _: *Chunk, inst: Ir.Inst.Index) InnerError!Ref {
|
||||
const data = sema.ir.instructions[@intFromEnum(inst)].data.string;
|
||||
return sema.getGlobal(data.start);
|
||||
|
|
@ -358,6 +428,11 @@ fn blockBodyInner(sema: *Sema, chunk: *Chunk, body: []const Ir.Inst.Index) Inner
|
|||
},
|
||||
.content_push => try irContentPush(sema, chunk, inst),
|
||||
.content_flush => try irContentFlush(sema, chunk, inst),
|
||||
.choice_br => {
|
||||
try irChoiceBr(sema, chunk, inst);
|
||||
continue;
|
||||
},
|
||||
.implicit_ret => try irImplicitRet(sema, chunk, inst),
|
||||
};
|
||||
try chunk.inst_map.put(gpa, inst, ref);
|
||||
}
|
||||
|
|
@ -446,6 +521,15 @@ const Chunk = struct {
|
|||
});
|
||||
}
|
||||
|
||||
fn addFixupAbsolute(chunk: *Chunk, op: Story.Opcode, label: usize) !void {
|
||||
const code_ref = try chunk.addJumpOp(op);
|
||||
return chunk.fixups.append(chunk.sema.gpa, .{
|
||||
.mode = .absolute,
|
||||
.label_index = @intCast(label),
|
||||
.code_offset = code_ref.index,
|
||||
});
|
||||
}
|
||||
|
||||
fn addLabel(chunk: *Chunk) error{OutOfMemory}!usize {
|
||||
const label_index = chunk.labels.items.len;
|
||||
try chunk.labels.append(chunk.sema.gpa, .{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue