| ... | ... | @@ -345,7 +345,10 @@ fn finishAir(cg: *CodeGen, inst: Air.Inst.Index, result: WValue, operands: []con |
| 345 | 345 | if (!dies) continue; |
| 346 | 346 | processDeath(cg, operand); |
| 347 | 347 | } |
| 348 | try cg.finishAirResult(inst, result); |
| 349 | } |
| 348 | 350 | |
| 351 | fn finishAirResult(cg: *CodeGen, inst: Air.Inst.Index, result: WValue) InnerError!void { |
| 349 | 352 | // results of `none` can never be referenced. |
| 350 | 353 | if (result != .none) { |
| 351 | 354 | const trackable_result = if (result != .stack) |
| ... | ... | @@ -374,37 +377,10 @@ inline fn currentBranch(cg: *CodeGen) *Branch { |
| 374 | 377 | return &cg.branches.items[cg.branches.items.len - 1]; |
| 375 | 378 | } |
| 376 | 379 | |
| 377 | | const BigTomb = struct { |
| 378 | | gen: *CodeGen, |
| 379 | | inst: Air.Inst.Index, |
| 380 | | lbt: Air.Liveness.BigTomb, |
| 381 | | |
| 382 | | fn feed(bt: *BigTomb, op_ref: Air.Inst.Ref) void { |
| 383 | | const dies = bt.lbt.feed(); |
| 384 | | if (!dies) return; |
| 385 | | // This will be a nop for interned constants. |
| 386 | | processDeath(bt.gen, op_ref); |
| 380 | fn feed(cg: *CodeGen, bt: *Air.Liveness.BigTomb, operand: Air.Inst.Ref) void { |
| 381 | if (bt.feed()) { |
| 382 | cg.processDeath(operand); |
| 387 | 383 | } |
| 388 | | |
| 389 | | fn finishAir(bt: *BigTomb, result: WValue) void { |
| 390 | | assert(result != .stack); |
| 391 | | if (result != .none) { |
| 392 | | bt.gen.currentBranch().values.putAssumeCapacityNoClobber(bt.inst.toRef(), result); |
| 393 | | } |
| 394 | | |
| 395 | | if (std.debug.runtime_safety) { |
| 396 | | bt.gen.air_bookkeeping += 1; |
| 397 | | } |
| 398 | | } |
| 399 | | }; |
| 400 | | |
| 401 | | fn iterateBigTomb(cg: *CodeGen, inst: Air.Inst.Index, operand_count: usize) !BigTomb { |
| 402 | | try cg.currentBranch().values.ensureUnusedCapacity(cg.gpa, operand_count + 1); |
| 403 | | return BigTomb{ |
| 404 | | .gen = cg, |
| 405 | | .inst = inst, |
| 406 | | .lbt = cg.liveness.iterateBigTomb(inst), |
| 407 | | }; |
| 408 | 384 | } |
| 409 | 385 | |
| 410 | 386 | fn processDeath(cg: *CodeGen, ref: Air.Inst.Ref) void { |
| ... | ... | @@ -766,11 +742,15 @@ pub fn generate( |
| 766 | 742 | |
| 767 | 743 | fn generateInner(cg: *CodeGen, any_returns: bool) InnerError!Mir { |
| 768 | 744 | const zcu = cg.pt.zcu; |
| 745 | // branch used for const values |
| 746 | try cg.branches.append(cg.gpa, .{}); |
| 747 | // func scope branch |
| 769 | 748 | try cg.branches.append(cg.gpa, .{}); |
| 770 | | // clean up outer branch |
| 771 | 749 | defer { |
| 772 | | var outer_branch = cg.branches.pop().?; |
| 773 | | outer_branch.deinit(cg.gpa); |
| 750 | var func_branch = cg.branches.pop().?; |
| 751 | func_branch.deinit(cg.gpa); |
| 752 | var const_branch = cg.branches.pop().?; |
| 753 | const_branch.deinit(cg.gpa); |
| 774 | 754 | assert(cg.branches.items.len == 0); // missing branch merge |
| 775 | 755 | } |
| 776 | 756 | // Generate MIR for function body |
| ... | ... | @@ -1920,7 +1900,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 1920 | 1900 | continue; |
| 1921 | 1901 | } |
| 1922 | 1902 | const old_bookkeeping_value = cg.air_bookkeeping; |
| 1923 | | try cg.currentBranch().values.ensureUnusedCapacity(cg.gpa, Air.Liveness.bpi); |
| 1903 | try cg.currentBranch().values.ensureUnusedCapacity(cg.gpa, 1); |
| 1924 | 1904 | try cg.genInst(inst); |
| 1925 | 1905 | |
| 1926 | 1906 | if (std.debug.runtime_safety and cg.air_bookkeeping < old_bookkeeping_value + 1) { |
| ... | ... | @@ -2102,10 +2082,10 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie |
| 2102 | 2082 | } |
| 2103 | 2083 | }; |
| 2104 | 2084 | |
| 2105 | | var bt = try cg.iterateBigTomb(inst, 1 + args.len); |
| 2106 | | bt.feed(call.callee); |
| 2107 | | for (args) |arg| bt.feed(arg); |
| 2108 | | return bt.finishAir(result_value); |
| 2085 | var bt = cg.liveness.iterateBigTomb(inst); |
| 2086 | cg.feed(&bt, call.callee); |
| 2087 | for (args) |arg| cg.feed(&bt, arg); |
| 2088 | return cg.finishAirResult(inst, result_value); |
| 2109 | 2089 | } |
| 2110 | 2090 | |
| 2111 | 2091 | fn airAlloc(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| ... | ... | @@ -4608,11 +4588,15 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []const |
| 4608 | 4588 | .value = block_result, |
| 4609 | 4589 | }); |
| 4610 | 4590 | |
| 4611 | | try cg.genBody(body); |
| 4612 | | try cg.endBlock(); |
| 4613 | | |
| 4614 | | const liveness = cg.liveness.getBlock(inst); |
| 4615 | | try cg.currentBranch().values.ensureUnusedCapacity(cg.gpa, liveness.deaths.len); |
| 4591 | { |
| 4592 | try cg.branches.append(cg.gpa, .{}); |
| 4593 | defer { |
| 4594 | var branch = cg.branches.pop().?; |
| 4595 | branch.deinit(cg.gpa); |
| 4596 | } |
| 4597 | try cg.genBody(body); |
| 4598 | try cg.endBlock(); |
| 4599 | } |
| 4616 | 4600 | |
| 4617 | 4601 | return cg.finishAir(inst, block_result, &.{}); |
| 4618 | 4602 | } |
| ... | ... | @@ -4653,7 +4637,6 @@ fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4653 | 4637 | const condition = try cg.resolveInst(cond_br.condition); |
| 4654 | 4638 | const then_body = cond_br.then_body; |
| 4655 | 4639 | const else_body = cond_br.else_body; |
| 4656 | | const liveness_condbr = cg.liveness.getCondBr(inst); |
| 4657 | 4640 | |
| 4658 | 4641 | // result type is always noreturn, so use `block_empty` as type. |
| 4659 | 4642 | try cg.startBlock(.block, .empty); |
| ... | ... | @@ -4668,7 +4651,6 @@ fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4668 | 4651 | try cg.branches.ensureUnusedCapacity(cg.gpa, 2); |
| 4669 | 4652 | { |
| 4670 | 4653 | cg.branches.appendAssumeCapacity(.{}); |
| 4671 | | try cg.currentBranch().values.ensureUnusedCapacity(cg.gpa, @as(u32, @intCast(liveness_condbr.else_deaths.len))); |
| 4672 | 4654 | defer { |
| 4673 | 4655 | var else_stack = cg.branches.pop().?; |
| 4674 | 4656 | else_stack.deinit(cg.gpa); |
| ... | ... | @@ -4680,7 +4662,6 @@ fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4680 | 4662 | // Outer block that matches the condition |
| 4681 | 4663 | { |
| 4682 | 4664 | cg.branches.appendAssumeCapacity(.{}); |
| 4683 | | try cg.currentBranch().values.ensureUnusedCapacity(cg.gpa, @as(u32, @intCast(liveness_condbr.then_deaths.len))); |
| 4684 | 4665 | defer { |
| 4685 | 4666 | var then_stack = cg.branches.pop().?; |
| 4686 | 4667 | then_stack.deinit(cg.gpa); |
| ... | ... | @@ -5172,9 +5153,6 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Inner |
| 5172 | 5153 | break :target target; |
| 5173 | 5154 | } else try cg.resolveInst(switch_br.operand); |
| 5174 | 5155 | |
| 5175 | | const liveness = try cg.liveness.getSwitchBr(cg.gpa, inst, switch_br.cases_len + 1); |
| 5176 | | defer cg.gpa.free(liveness.deaths); |
| 5177 | | |
| 5178 | 5156 | const has_else_body = switch_br.else_body_len != 0; |
| 5179 | 5157 | const branch_count = switch_br.cases_len + 1; // if else branch is missing, we trap when failing all conditions |
| 5180 | 5158 | try cg.branches.ensureUnusedCapacity(cg.gpa, switch_br.cases_len + @intFromBool(has_else_body)); |
| ... | ... | @@ -5186,8 +5164,6 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Inner |
| 5186 | 5164 | const else_body = it.elseBody(); |
| 5187 | 5165 | |
| 5188 | 5166 | cg.branches.appendAssumeCapacity(.{}); |
| 5189 | | const else_deaths = liveness.deaths.len - 1; |
| 5190 | | try cg.currentBranch().values.ensureUnusedCapacity(cg.gpa, liveness.deaths[else_deaths].len); |
| 5191 | 5167 | defer { |
| 5192 | 5168 | var else_branch = cg.branches.pop().?; |
| 5193 | 5169 | else_branch.deinit(cg.gpa); |
| ... | ... | @@ -5321,7 +5297,6 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Inner |
| 5321 | 5297 | try cg.endBlock(); |
| 5322 | 5298 | |
| 5323 | 5299 | cg.branches.appendAssumeCapacity(.{}); |
| 5324 | | try cg.currentBranch().values.ensureUnusedCapacity(cg.gpa, liveness.deaths[case.idx].len); |
| 5325 | 5300 | defer { |
| 5326 | 5301 | var case_branch = cg.branches.pop().?; |
| 5327 | 5302 | case_branch.deinit(cg.gpa); |
| ... | ... | @@ -5336,8 +5311,6 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Inner |
| 5336 | 5311 | const else_body = cases_it.elseBody(); |
| 5337 | 5312 | |
| 5338 | 5313 | cg.branches.appendAssumeCapacity(.{}); |
| 5339 | | const else_deaths = liveness.deaths.len - 1; |
| 5340 | | try cg.currentBranch().values.ensureUnusedCapacity(cg.gpa, liveness.deaths[else_deaths].len); |
| 5341 | 5314 | defer { |
| 5342 | 5315 | var else_branch = cg.branches.pop().?; |
| 5343 | 5316 | else_branch.deinit(cg.gpa); |
| ... | ... | @@ -6329,14 +6302,9 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6329 | 6302 | } |
| 6330 | 6303 | }; |
| 6331 | 6304 | |
| 6332 | | if (elements.len <= Air.Liveness.bpi - 1) { |
| 6333 | | var buf = [1]Air.Inst.Ref{.none} ** (Air.Liveness.bpi - 1); |
| 6334 | | @memcpy(buf[0..elements.len], elements); |
| 6335 | | return cg.finishAir(inst, result, &buf); |
| 6336 | | } |
| 6337 | | var bt = try cg.iterateBigTomb(inst, elements.len); |
| 6338 | | for (elements) |arg| bt.feed(arg); |
| 6339 | | return bt.finishAir(result); |
| 6305 | var bt = cg.liveness.iterateBigTomb(inst); |
| 6306 | for (elements) |arg| cg.feed(&bt, arg); |
| 6307 | return cg.finishAirResult(inst, result); |
| 6340 | 6308 | } |
| 6341 | 6309 | |
| 6342 | 6310 | fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| ... | ... | @@ -6671,6 +6639,7 @@ fn lowerTry( |
| 6671 | 6639 | err_union_ty: Type, |
| 6672 | 6640 | operand_is_ptr: bool, |
| 6673 | 6641 | ) InnerError!WValue { |
| 6642 | _ = inst; |
| 6674 | 6643 | const zcu = cg.pt.zcu; |
| 6675 | 6644 | |
| 6676 | 6645 | const pl_ty = err_union_ty.errorUnionPayload(zcu); |
| ... | ... | @@ -6692,9 +6661,7 @@ fn lowerTry( |
| 6692 | 6661 | try cg.addTag(.i32_eqz); |
| 6693 | 6662 | try cg.addLabel(.br_if, 0); // jump out of block when error is '0' |
| 6694 | 6663 | |
| 6695 | | const liveness = cg.liveness.getCondBr(inst); |
| 6696 | 6664 | try cg.branches.append(cg.gpa, .{}); |
| 6697 | | try cg.currentBranch().values.ensureUnusedCapacity(cg.gpa, liveness.else_deaths.len + liveness.then_deaths.len); |
| 6698 | 6665 | defer { |
| 6699 | 6666 | var branch = cg.branches.pop().?; |
| 6700 | 6667 | branch.deinit(cg.gpa); |