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