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