authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-14 22:44:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-20 12:19:16-07:00
log1294ebe1f5eaca1f11d68284d1b96419d53253be
tree8c01f0969b0c4a8be40a6bf3b89d2ec736bd46ae
parentc020a302960c499ffe811dd0601a2d386c191b91

Sema: AIR memory layout reworking for noreturn instructions


2 files changed, 41 insertions(+), 49 deletions(-)

src/Module.zig+1-1
...@@ -1255,7 +1255,7 @@ pub const Scope = struct {...@@ -1255,7 +1255,7 @@ pub const Scope = struct {
1255 pub fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref {1255 pub fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref {
1256 return block.addInst(.{1256 return block.addInst(.{
1257 .tag = tag,1257 .tag = tag,
1258 .data = .no_op,1258 .data = .{ .no_op = {} },
1259 });1259 });
1260 }1260 }
12611261
src/Sema.zig+40-48
...@@ -381,20 +381,20 @@ pub fn analyzeBody(...@@ -381,20 +381,20 @@ pub fn analyzeBody(
381 .sub => try sema.zirArithmetic(block, inst),381 .sub => try sema.zirArithmetic(block, inst),
382 .subwrap => try sema.zirArithmetic(block, inst),382 .subwrap => try sema.zirArithmetic(block, inst),
383383
384 //// Instructions that we know to *always* be noreturn based solely on their tag.384 // Instructions that we know to *always* be noreturn based solely on their tag.
385 //// These functions match the return type of analyzeBody so that we can385 // These functions match the return type of analyzeBody so that we can
386 //// tail call them here.386 // tail call them here.
387 //.break_inline => return inst,387 .break_inline => return inst,
388 //.condbr => return sema.zirCondbr(block, inst),388 .condbr => return sema.zirCondbr(block, inst),
389 //.@"break" => return sema.zirBreak(block, inst),389 .@"break" => return sema.zirBreak(block, inst),
390 //.compile_error => return sema.zirCompileError(block, inst),390 .compile_error => return sema.zirCompileError(block, inst),
391 //.ret_coerce => return sema.zirRetCoerce(block, inst, true),391 .ret_coerce => return sema.zirRetCoerce(block, inst, true),
392 //.ret_node => return sema.zirRetNode(block, inst),392 .ret_node => return sema.zirRetNode(block, inst),
393 //.ret_err_value => return sema.zirRetErrValue(block, inst),393 .ret_err_value => return sema.zirRetErrValue(block, inst),
394 //.@"unreachable" => return sema.zirUnreachable(block, inst),394 .@"unreachable" => return sema.zirUnreachable(block, inst),
395 //.repeat => return sema.zirRepeat(block, inst),395 .repeat => return sema.zirRepeat(block, inst),
396 //.panic => return sema.zirPanic(block, inst),396 .panic => return sema.zirPanic(block, inst),
397 //// zig fmt: on397 // zig fmt: on
398398
399 //// Instructions that we know can *never* be noreturn based solely on399 //// Instructions that we know can *never* be noreturn based solely on
400 //// their tag. We avoid needlessly checking if they are noreturn and400 //// their tag. We avoid needlessly checking if they are noreturn and
...@@ -534,7 +534,7 @@ pub fn analyzeBody(...@@ -534,7 +534,7 @@ pub fn analyzeBody(
534 return break_inst;534 return break_inst;
535 }535 }
536 },536 },
537 else => @panic("TODO finish updating Sema for AIR memory layout changes and then remove this else prong"),537 else => |t| @panic(@tagName(t)),
538 };538 };
539 if (sema.getTypeOf(air_inst).isNoReturn())539 if (sema.getTypeOf(air_inst).isNoReturn())
540 return always_noreturn;540 return always_noreturn;
...@@ -2128,7 +2128,6 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) Compil...@@ -2128,7 +2128,6 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) Compil
2128 defer tracy.end();2128 defer tracy.end();
21292129
2130 const inst_data = sema.code.instructions.items(.data)[inst].@"break";2130 const inst_data = sema.code.instructions.items(.data)[inst].@"break";
2131 const src = sema.src;
2132 const operand = sema.resolveInst(inst_data.operand);2131 const operand = sema.resolveInst(inst_data.operand);
2133 const zir_block = inst_data.block_inst;2132 const zir_block = inst_data.block_inst;
21342133
...@@ -2136,26 +2135,9 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) Compil...@@ -2136,26 +2135,9 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) Compil
2136 while (true) {2135 while (true) {
2137 if (block.label) |label| {2136 if (block.label) |label| {
2138 if (label.zir_block == zir_block) {2137 if (label.zir_block == zir_block) {
2139 // Here we add a br instruction, but we over-allocate a little bit2138 const br_ref = try start_block.addBr(label.merges.block_inst, operand);
2140 // (if necessary) to make it possible to convert the instruction into
2141 // a br_block_flat instruction later.
2142 const br = @ptrCast(*Inst.Br, try sema.arena.alignedAlloc(
2143 u8,
2144 Inst.convertable_br_align,
2145 Inst.convertable_br_size,
2146 ));
2147 br.* = .{
2148 .base = .{
2149 .tag = .br,
2150 .ty = Type.initTag(.noreturn),
2151 .src = src,
2152 },
2153 .operand = operand,
2154 .block = label.merges.block_inst,
2155 };
2156 try start_block.instructions.append(sema.gpa, &br.base);
2157 try label.merges.results.append(sema.gpa, operand);2139 try label.merges.results.append(sema.gpa, operand);
2158 try label.merges.br_list.append(sema.gpa, br);2140 try label.merges.br_list.append(sema.gpa, refToIndex(br_ref).?);
2159 return inst;2141 return inst;
2160 }2142 }
2161 }2143 }
...@@ -5391,25 +5373,35 @@ fn zirCondbr(...@@ -5391,25 +5373,35 @@ fn zirCondbr(
5391 return always_noreturn;5373 return always_noreturn;
5392 }5374 }
53935375
5376 const gpa = sema.gpa;
5377
5378 // We'll re-use the sub block to save on memory bandwidth, and yank out the
5379 // instructions array in between using it for the then block and else block.
5394 var sub_block = parent_block.makeSubBlock();5380 var sub_block = parent_block.makeSubBlock();
5395 sub_block.runtime_loop = null;5381 sub_block.runtime_loop = null;
5396 sub_block.runtime_cond = cond.src;5382 sub_block.runtime_cond = cond_src;
5397 sub_block.runtime_index += 1;5383 sub_block.runtime_index += 1;
5398 defer sub_block.instructions.deinit(sema.gpa);5384 defer sub_block.instructions.deinit(gpa);
53995385
5400 _ = try sema.analyzeBody(&sub_block, then_body);5386 _ = try sema.analyzeBody(&sub_block, then_body);
5401 const air_then_body: ir.Body = .{5387 const true_instructions = sub_block.instructions.toOwnedSlice(gpa);
5402 .instructions = try sema.arena.dupe(Air.Inst.Index, sub_block.instructions.items),5388 defer gpa.free(true_instructions);
5403 };
5404
5405 sub_block.instructions.shrinkRetainingCapacity(0);
54065389
5407 _ = try sema.analyzeBody(&sub_block, else_body);5390 _ = try sema.analyzeBody(&sub_block, else_body);
5408 const air_else_body: ir.Body = .{5391 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len +
5409 .instructions = try sema.arena.dupe(Air.Inst.Index, sub_block.instructions.items),5392 true_instructions.len + sub_block.instructions.items.len);
5410 };5393 _ = try parent_block.addInst(.{
54115394 .tag = .cond_br,
5412 _ = try parent_block.addCondBr(src, cond, air_then_body, air_else_body);5395 .data = .{ .pl_op = .{
5396 .operand = cond,
5397 .payload = sema.addExtraAssumeCapacity(Air.CondBr{
5398 .then_body_len = @intCast(u32, true_instructions.len),
5399 .else_body_len = @intCast(u32, sub_block.instructions.items.len),
5400 }),
5401 } },
5402 });
5403 sema.air_extra.appendSliceAssumeCapacity(true_instructions);
5404 sema.air_extra.appendSliceAssumeCapacity(sub_block.instructions.items);
5413 return always_noreturn;5405 return always_noreturn;
5414}5406}
54155407
...@@ -6443,7 +6435,7 @@ fn panicWithMsg(...@@ -6443,7 +6435,7 @@ fn panicWithMsg(
6443 try mod.optionalType(arena, ptr_stack_trace_ty),6435 try mod.optionalType(arena, ptr_stack_trace_ty),
6444 Value.initTag(.null_value),6436 Value.initTag(.null_value),
6445 );6437 );
6446 const args = try arena.create([2]Air.Inst.Index);6438 const args = try arena.create([2]Air.Inst.Ref);
6447 args.* = .{ msg_inst, null_stack_trace };6439 args.* = .{ msg_inst, null_stack_trace };
6448 _ = try sema.analyzeCall(block, panic_fn, src, src, .auto, false, args);6440 _ = try sema.analyzeCall(block, panic_fn, src, src, .auto, false, args);
6449 return always_noreturn;6441 return always_noreturn;