aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-01-22 16:45:09 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-01-31 21:09:22 -0700
commit588171c30b34426fbb07645aa2625e989f369eec (patch)
tree254ff4567279c496dd61a4a790c64c64a8d7e763 /src/codegen.zig
parent06bb360dd296288db33844d682188e33116d7ab6 (diff)
downloadzig-588171c30b34426fbb07645aa2625e989f369eec.tar.gz
zig-588171c30b34426fbb07645aa2625e989f369eec.zip
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).
Diffstat (limited to 'src/codegen.zig')
-rw-r--r--src/codegen.zig31
1 files changed, 21 insertions, 10 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index a7b067f7e1..1f5aad8ab8 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -844,6 +844,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.bit_or => return self.genBitOr(inst.castTag(.bit_or).?),
.block => return self.genBlock(inst.castTag(.block).?),
.br => return self.genBr(inst.castTag(.br).?),
+ .br_block_flat => return self.genBrBlockFlat(inst.castTag(.br_block_flat).?),
.breakpoint => return self.genBreakpoint(inst.src),
.brvoid => return self.genBrVoid(inst.castTag(.brvoid).?),
.bool_and => return self.genBoolOp(inst.castTag(.bool_and).?),
@@ -2441,17 +2442,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
}
}
+ fn genBrBlockFlat(self: *Self, parent_inst: *ir.Inst.BrBlockFlat) !MCValue {
+ try self.genBody(parent_inst.body);
+ const last = parent_inst.body.instructions[parent_inst.body.instructions.len - 1];
+ return self.br(parent_inst.base.src, parent_inst.block, last);
+ }
+
fn genBr(self: *Self, inst: *ir.Inst.Br) !MCValue {
- if (inst.operand.ty.hasCodeGenBits()) {
- const operand = try self.resolveInst(inst.operand);
- const block_mcv = @bitCast(MCValue, inst.block.codegen.mcv);
- if (block_mcv == .none) {
- inst.block.codegen.mcv = @bitCast(AnyMCValue, operand);
- } else {
- try self.setRegOrMem(inst.base.src, inst.block.base.ty, block_mcv, operand);
- }
- }
- return self.brVoid(inst.base.src, inst.block);
+ return self.br(inst.base.src, inst.block, inst.operand);
}
fn genBrVoid(self: *Self, inst: *ir.Inst.BrVoid) !MCValue {
@@ -2478,6 +2476,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
}
}
+ fn br(self: *Self, src: usize, block: *ir.Inst.Block, operand: *ir.Inst) !MCValue {
+ if (operand.ty.hasCodeGenBits()) {
+ const operand_mcv = try self.resolveInst(operand);
+ const block_mcv = @bitCast(MCValue, block.codegen.mcv);
+ if (block_mcv == .none) {
+ block.codegen.mcv = @bitCast(AnyMCValue, operand_mcv);
+ } else {
+ try self.setRegOrMem(src, block.base.ty, block_mcv, operand_mcv);
+ }
+ }
+ return self.brVoid(src, block);
+ }
+
fn brVoid(self: *Self, src: usize, block: *ir.Inst.Block) !MCValue {
// Emit a jump with a relocation. It will be patched up after the block ends.
try block.codegen.relocs.ensureCapacity(self.gpa, block.codegen.relocs.items.len + 1);