aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-07-14 22:44:57 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-07-20 12:19:16 -0700
commit1294ebe1f5eaca1f11d68284d1b96419d53253be (patch)
tree8c01f0969b0c4a8be40a6bf3b89d2ec736bd46ae
parentc020a302960c499ffe811dd0601a2d386c191b91 (diff)
downloadzig-1294ebe1f5eaca1f11d68284d1b96419d53253be.tar.gz
zig-1294ebe1f5eaca1f11d68284d1b96419d53253be.zip
Sema: AIR memory layout reworking for noreturn instructions
-rw-r--r--src/Module.zig2
-rw-r--r--src/Sema.zig88
2 files changed, 41 insertions, 49 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 94d8b63744..fb514ccbd2 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -1255,7 +1255,7 @@ pub const Scope = struct {
pub fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref {
return block.addInst(.{
.tag = tag,
- .data = .no_op,
+ .data = .{ .no_op = {} },
});
}
diff --git a/src/Sema.zig b/src/Sema.zig
index b4e8cd5af5..d33d5bd49b 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -381,20 +381,20 @@ pub fn analyzeBody(
.sub => try sema.zirArithmetic(block, inst),
.subwrap => try sema.zirArithmetic(block, inst),
- //// Instructions that we know to *always* be noreturn based solely on their tag.
- //// These functions match the return type of analyzeBody so that we can
- //// tail call them here.
- //.break_inline => return inst,
- //.condbr => return sema.zirCondbr(block, inst),
- //.@"break" => return sema.zirBreak(block, inst),
- //.compile_error => return sema.zirCompileError(block, inst),
- //.ret_coerce => return sema.zirRetCoerce(block, inst, true),
- //.ret_node => return sema.zirRetNode(block, inst),
- //.ret_err_value => return sema.zirRetErrValue(block, inst),
- //.@"unreachable" => return sema.zirUnreachable(block, inst),
- //.repeat => return sema.zirRepeat(block, inst),
- //.panic => return sema.zirPanic(block, inst),
- //// zig fmt: on
+ // Instructions that we know to *always* be noreturn based solely on their tag.
+ // These functions match the return type of analyzeBody so that we can
+ // tail call them here.
+ .break_inline => return inst,
+ .condbr => return sema.zirCondbr(block, inst),
+ .@"break" => return sema.zirBreak(block, inst),
+ .compile_error => return sema.zirCompileError(block, inst),
+ .ret_coerce => return sema.zirRetCoerce(block, inst, true),
+ .ret_node => return sema.zirRetNode(block, inst),
+ .ret_err_value => return sema.zirRetErrValue(block, inst),
+ .@"unreachable" => return sema.zirUnreachable(block, inst),
+ .repeat => return sema.zirRepeat(block, inst),
+ .panic => return sema.zirPanic(block, inst),
+ // zig fmt: on
//// Instructions that we know can *never* be noreturn based solely on
//// their tag. We avoid needlessly checking if they are noreturn and
@@ -534,7 +534,7 @@ pub fn analyzeBody(
return break_inst;
}
},
- else => @panic("TODO finish updating Sema for AIR memory layout changes and then remove this else prong"),
+ else => |t| @panic(@tagName(t)),
};
if (sema.getTypeOf(air_inst).isNoReturn())
return always_noreturn;
@@ -2128,7 +2128,6 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) Compil
defer tracy.end();
const inst_data = sema.code.instructions.items(.data)[inst].@"break";
- const src = sema.src;
const operand = sema.resolveInst(inst_data.operand);
const zir_block = inst_data.block_inst;
@@ -2136,26 +2135,9 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) Compil
while (true) {
if (block.label) |label| {
if (label.zir_block == zir_block) {
- // Here we add a br instruction, but we over-allocate a little bit
- // (if necessary) to make it possible to convert the instruction into
- // a br_block_flat instruction later.
- const br = @ptrCast(*Inst.Br, try sema.arena.alignedAlloc(
- u8,
- Inst.convertable_br_align,
- Inst.convertable_br_size,
- ));
- br.* = .{
- .base = .{
- .tag = .br,
- .ty = Type.initTag(.noreturn),
- .src = src,
- },
- .operand = operand,
- .block = label.merges.block_inst,
- };
- try start_block.instructions.append(sema.gpa, &br.base);
+ const br_ref = try start_block.addBr(label.merges.block_inst, operand);
try label.merges.results.append(sema.gpa, operand);
- try label.merges.br_list.append(sema.gpa, br);
+ try label.merges.br_list.append(sema.gpa, refToIndex(br_ref).?);
return inst;
}
}
@@ -5391,25 +5373,35 @@ fn zirCondbr(
return always_noreturn;
}
+ const gpa = sema.gpa;
+
+ // We'll re-use the sub block to save on memory bandwidth, and yank out the
+ // instructions array in between using it for the then block and else block.
var sub_block = parent_block.makeSubBlock();
sub_block.runtime_loop = null;
- sub_block.runtime_cond = cond.src;
+ sub_block.runtime_cond = cond_src;
sub_block.runtime_index += 1;
- defer sub_block.instructions.deinit(sema.gpa);
+ defer sub_block.instructions.deinit(gpa);
_ = try sema.analyzeBody(&sub_block, then_body);
- const air_then_body: ir.Body = .{
- .instructions = try sema.arena.dupe(Air.Inst.Index, sub_block.instructions.items),
- };
-
- sub_block.instructions.shrinkRetainingCapacity(0);
+ const true_instructions = sub_block.instructions.toOwnedSlice(gpa);
+ defer gpa.free(true_instructions);
_ = try sema.analyzeBody(&sub_block, else_body);
- const air_else_body: ir.Body = .{
- .instructions = try sema.arena.dupe(Air.Inst.Index, sub_block.instructions.items),
- };
-
- _ = try parent_block.addCondBr(src, cond, air_then_body, air_else_body);
+ try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len +
+ true_instructions.len + sub_block.instructions.items.len);
+ _ = try parent_block.addInst(.{
+ .tag = .cond_br,
+ .data = .{ .pl_op = .{
+ .operand = cond,
+ .payload = sema.addExtraAssumeCapacity(Air.CondBr{
+ .then_body_len = @intCast(u32, true_instructions.len),
+ .else_body_len = @intCast(u32, sub_block.instructions.items.len),
+ }),
+ } },
+ });
+ sema.air_extra.appendSliceAssumeCapacity(true_instructions);
+ sema.air_extra.appendSliceAssumeCapacity(sub_block.instructions.items);
return always_noreturn;
}
@@ -6443,7 +6435,7 @@ fn panicWithMsg(
try mod.optionalType(arena, ptr_stack_trace_ty),
Value.initTag(.null_value),
);
- const args = try arena.create([2]Air.Inst.Index);
+ const args = try arena.create([2]Air.Inst.Ref);
args.* = .{ msg_inst, null_stack_trace };
_ = try sema.analyzeCall(block, panic_fn, src, src, .auto, false, args);
return always_noreturn;