sema: after block gets peer type resolved, insert type coercions
on the break instruction operands. This involves a new TZIR instruction, br_block_flat, which represents a break instruction where the operand is the result of a flat block. See the doc comments on the instructions for more details. How it works: when adding break instructions in semantic analysis, the underlying allocation is slightly padded so that it is the size of a br_block_flat instruction, which allows the break instruction to later be converted without removing instructions inside the parent body. The extra type coercion instructions go into the body of the br_block_flat, and backends are responsible for dispatching the instruction correctly (it should map to the same function calls for related instructions).
This commit is contained in:
@@ -671,14 +671,36 @@ pub const Scope = struct {
|
||||
};
|
||||
|
||||
pub const Merges = struct {
|
||||
results: ArrayListUnmanaged(*Inst),
|
||||
block_inst: *Inst.Block,
|
||||
/// Separate array list from break_inst_list so that it can be passed directly
|
||||
/// to resolvePeerTypes.
|
||||
results: ArrayListUnmanaged(*Inst),
|
||||
/// Keeps track of the break instructions so that the operand can be replaced
|
||||
/// if we need to add type coercion at the end of block analysis.
|
||||
/// Same indexes, capacity, length as `results`.
|
||||
br_list: ArrayListUnmanaged(*Inst.Br),
|
||||
};
|
||||
|
||||
/// For debugging purposes.
|
||||
pub fn dump(self: *Block, mod: Module) void {
|
||||
zir.dumpBlock(mod, self);
|
||||
}
|
||||
|
||||
pub fn makeSubBlock(parent: *Block) Block {
|
||||
return .{
|
||||
.parent = parent,
|
||||
.inst_table = parent.inst_table,
|
||||
.func = parent.func,
|
||||
.owner_decl = parent.owner_decl,
|
||||
.src_decl = parent.src_decl,
|
||||
.instructions = .{},
|
||||
.arena = parent.arena,
|
||||
.label = null,
|
||||
.inlining = parent.inlining,
|
||||
.is_comptime = parent.is_comptime,
|
||||
.branch_quota = parent.branch_quota,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// This is a temporary structure, references to it are valid only
|
||||
@@ -2107,7 +2129,7 @@ pub fn addBr(
|
||||
src: usize,
|
||||
target_block: *Inst.Block,
|
||||
operand: *Inst,
|
||||
) !*Inst {
|
||||
) !*Inst.Br {
|
||||
const inst = try scope_block.arena.create(Inst.Br);
|
||||
inst.* = .{
|
||||
.base = .{
|
||||
@@ -2119,7 +2141,7 @@ pub fn addBr(
|
||||
.block = target_block,
|
||||
};
|
||||
try scope_block.instructions.append(self.gpa, &inst.base);
|
||||
return &inst.base;
|
||||
return inst;
|
||||
}
|
||||
|
||||
pub fn addCondBr(
|
||||
|
||||
Reference in New Issue
Block a user