| ... | ... | @@ -3893,15 +3893,16 @@ pub const FuncGen = struct { |
| 3893 | 3893 | /// This data structure is used to implement breaking to blocks. |
| 3894 | 3894 | blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, struct { |
| 3895 | 3895 | parent_bb: *const llvm.BasicBlock, |
| 3896 | | break_bbs: *BreakBasicBlocks, |
| 3897 | | break_vals: *BreakValues, |
| 3896 | breaks: *BreakList, |
| 3898 | 3897 | }), |
| 3899 | 3898 | |
| 3900 | 3899 | single_threaded: bool, |
| 3901 | 3900 | |
| 3902 | 3901 | const DbgState = struct { loc: *llvm.DILocation, scope: *llvm.DIScope, base_line: u32 }; |
| 3903 | | const BreakBasicBlocks = std.ArrayListUnmanaged(*const llvm.BasicBlock); |
| 3904 | | const BreakValues = std.ArrayListUnmanaged(*const llvm.Value); |
| 3902 | const BreakList = std.MultiArrayList(struct { |
| 3903 | bb: *const llvm.BasicBlock, |
| 3904 | val: *const llvm.Value, |
| 3905 | }); |
| 3905 | 3906 | |
| 3906 | 3907 | fn deinit(self: *FuncGen) void { |
| 3907 | 3908 | self.builder.dispose(); |
| ... | ... | @@ -4649,16 +4650,12 @@ pub const FuncGen = struct { |
| 4649 | 4650 | return null; |
| 4650 | 4651 | } |
| 4651 | 4652 | |
| 4652 | | var break_bbs: BreakBasicBlocks = .{}; |
| 4653 | | defer break_bbs.deinit(self.gpa); |
| 4654 | | |
| 4655 | | var break_vals: BreakValues = .{}; |
| 4656 | | defer break_vals.deinit(self.gpa); |
| 4653 | var breaks: BreakList = .{}; |
| 4654 | defer breaks.deinit(self.gpa); |
| 4657 | 4655 | |
| 4658 | 4656 | try self.blocks.putNoClobber(self.gpa, inst, .{ |
| 4659 | 4657 | .parent_bb = parent_bb, |
| 4660 | | .break_bbs = &break_bbs, |
| 4661 | | .break_vals = &break_vals, |
| 4658 | .breaks = &breaks, |
| 4662 | 4659 | }); |
| 4663 | 4660 | defer assert(self.blocks.remove(inst)); |
| 4664 | 4661 | |
| ... | ... | @@ -4667,7 +4664,7 @@ pub const FuncGen = struct { |
| 4667 | 4664 | self.llvm_func.appendExistingBasicBlock(parent_bb); |
| 4668 | 4665 | self.builder.positionBuilderAtEnd(parent_bb); |
| 4669 | 4666 | |
| 4670 | | // If the block does not return a value, we dont have to create a phi node. |
| 4667 | // Create a phi node only if the block returns a value. |
| 4671 | 4668 | const is_body = inst_ty.zigTypeTag() == .Fn; |
| 4672 | 4669 | if (!is_body and !inst_ty.hasRuntimeBitsIgnoreComptime()) return null; |
| 4673 | 4670 | |
| ... | ... | @@ -4686,9 +4683,9 @@ pub const FuncGen = struct { |
| 4686 | 4683 | |
| 4687 | 4684 | const phi_node = self.builder.buildPhi(llvm_ty, ""); |
| 4688 | 4685 | phi_node.addIncoming( |
| 4689 | | break_vals.items.ptr, |
| 4690 | | break_bbs.items.ptr, |
| 4691 | | @intCast(c_uint, break_vals.items.len), |
| 4686 | breaks.items(.val).ptr, |
| 4687 | breaks.items(.bb).ptr, |
| 4688 | @intCast(c_uint, breaks.len), |
| 4692 | 4689 | ); |
| 4693 | 4690 | return phi_node; |
| 4694 | 4691 | } |
| ... | ... | @@ -4697,16 +4694,17 @@ pub const FuncGen = struct { |
| 4697 | 4694 | const branch = self.air.instructions.items(.data)[inst].br; |
| 4698 | 4695 | const block = self.blocks.get(branch.block_inst).?; |
| 4699 | 4696 | |
| 4700 | | // If the break doesn't break a value, then we don't have to add |
| 4701 | | // the values to the lists. |
| 4697 | // Add the values to the lists only if the break provides a value. |
| 4702 | 4698 | const operand_ty = self.air.typeOf(branch.operand); |
| 4703 | 4699 | if (operand_ty.hasRuntimeBitsIgnoreComptime() or operand_ty.zigTypeTag() == .Fn) { |
| 4704 | 4700 | const val = try self.resolveInst(branch.operand); |
| 4705 | 4701 | |
| 4706 | 4702 | // For the phi node, we need the basic blocks and the values of the |
| 4707 | 4703 | // break instructions. |
| 4708 | | try block.break_bbs.append(self.gpa, self.builder.getInsertBlock()); |
| 4709 | | try block.break_vals.append(self.gpa, val); |
| 4704 | try block.breaks.append(self.gpa, .{ |
| 4705 | .bb = self.builder.getInsertBlock(), |
| 4706 | .val = val, |
| 4707 | }); |
| 4710 | 4708 | } |
| 4711 | 4709 | _ = self.builder.buildBr(block.parent_bb); |
| 4712 | 4710 | return null; |