| ... | ... | @@ -11353,9 +11353,14 @@ const SwitchProngAnalysis = struct { |
| 11353 | 11353 | const coerced = try sema.coerce(&coerce_block, capture_ty, uncoerced, case_src); |
| 11354 | 11354 | _ = try coerce_block.addBr(capture_block_inst, coerced); |
| 11355 | 11355 | |
| 11356 | | try cases_extra.ensureUnusedCapacity(3 + coerce_block.instructions.items.len); |
| 11357 | | cases_extra.appendAssumeCapacity(1); // items_len |
| 11358 | | cases_extra.appendAssumeCapacity(@intCast(coerce_block.instructions.items.len)); // body_len |
| 11356 | try cases_extra.ensureUnusedCapacity(@typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 11357 | 1 + // `item`, no ranges |
| 11358 | coerce_block.instructions.items.len); |
| 11359 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 11360 | .items_len = 1, |
| 11361 | .ranges_len = 0, |
| 11362 | .body_len = @intCast(coerce_block.instructions.items.len), |
| 11363 | })); |
| 11359 | 11364 | cases_extra.appendAssumeCapacity(@intFromEnum(case_vals[idx])); // item |
| 11360 | 11365 | cases_extra.appendSliceAssumeCapacity(@ptrCast(coerce_block.instructions.items)); // body |
| 11361 | 11366 | } |
| ... | ... | @@ -12578,21 +12583,18 @@ fn analyzeSwitchRuntimeBlock( |
| 12578 | 12583 | }; |
| 12579 | 12584 | |
| 12580 | 12585 | try branch_hints.append(gpa, prong_hint); |
| 12581 | | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); |
| 12582 | | cases_extra.appendAssumeCapacity(1); // items_len |
| 12583 | | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); |
| 12586 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12587 | 1 + // `item`, no ranges |
| 12588 | case_block.instructions.items.len); |
| 12589 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 12590 | .items_len = 1, |
| 12591 | .ranges_len = 0, |
| 12592 | .body_len = @intCast(case_block.instructions.items.len), |
| 12593 | })); |
| 12584 | 12594 | cases_extra.appendAssumeCapacity(@intFromEnum(item)); |
| 12585 | 12595 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12586 | 12596 | } |
| 12587 | 12597 | |
| 12588 | | var is_first = true; |
| 12589 | | var prev_cond_br: Air.Inst.Index = undefined; |
| 12590 | | var prev_hint: std.builtin.BranchHint = undefined; |
| 12591 | | var first_else_body: []const Air.Inst.Index = &.{}; |
| 12592 | | defer gpa.free(first_else_body); |
| 12593 | | var prev_then_body: []const Air.Inst.Index = &.{}; |
| 12594 | | defer gpa.free(prev_then_body); |
| 12595 | | |
| 12596 | 12598 | var cases_len = scalar_cases_len; |
| 12597 | 12599 | var case_val_idx: usize = scalar_cases_len; |
| 12598 | 12600 | var multi_i: u32 = 0; |
| ... | ... | @@ -12602,31 +12604,27 @@ fn analyzeSwitchRuntimeBlock( |
| 12602 | 12604 | const ranges_len = sema.code.extra[extra_index]; |
| 12603 | 12605 | extra_index += 1; |
| 12604 | 12606 | const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(sema.code.extra[extra_index]); |
| 12605 | | extra_index += 1 + items_len; |
| 12607 | extra_index += 1 + items_len + 2 * ranges_len; |
| 12606 | 12608 | |
| 12607 | 12609 | const items = case_vals.items[case_val_idx..][0..items_len]; |
| 12608 | 12610 | case_val_idx += items_len; |
| 12611 | // TODO: @ptrCast slice once Sema supports it |
| 12612 | const ranges: []const [2]Air.Inst.Ref = @as([*]const [2]Air.Inst.Ref, @ptrCast(case_vals.items[case_val_idx..]))[0..ranges_len]; |
| 12613 | case_val_idx += ranges_len * 2; |
| 12614 | |
| 12615 | const body = sema.code.bodySlice(extra_index, info.body_len); |
| 12616 | extra_index += info.body_len; |
| 12609 | 12617 | |
| 12610 | 12618 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12611 | 12619 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12612 | 12620 | |
| 12613 | 12621 | // Generate all possible cases as scalar prongs. |
| 12614 | 12622 | if (info.is_inline) { |
| 12615 | | const body_start = extra_index + 2 * ranges_len; |
| 12616 | | const body = sema.code.bodySlice(body_start, info.body_len); |
| 12617 | 12623 | var emit_bb = false; |
| 12618 | 12624 | |
| 12619 | | var range_i: u32 = 0; |
| 12620 | | while (range_i < ranges_len) : (range_i += 1) { |
| 12621 | | const range_items = case_vals.items[case_val_idx..][0..2]; |
| 12622 | | extra_index += 2; |
| 12623 | | case_val_idx += 2; |
| 12624 | | |
| 12625 | | const item_first_ref = range_items[0]; |
| 12626 | | const item_last_ref = range_items[1]; |
| 12627 | | |
| 12628 | | var item = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, item_first_ref, undefined) catch unreachable; |
| 12629 | | const item_last = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, item_last_ref, undefined) catch unreachable; |
| 12625 | for (ranges, 0..) |range_items, range_i| { |
| 12626 | var item = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, range_items[0], undefined) catch unreachable; |
| 12627 | const item_last = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, range_items[1], undefined) catch unreachable; |
| 12630 | 12628 | |
| 12631 | 12629 | while (item.compareScalar(.lte, item_last, operand_ty, zcu)) : ({ |
| 12632 | 12630 | // Previous validation has resolved any possible lazy values. |
| ... | ... | @@ -12664,9 +12662,14 @@ fn analyzeSwitchRuntimeBlock( |
| 12664 | 12662 | ); |
| 12665 | 12663 | try branch_hints.append(gpa, prong_hint); |
| 12666 | 12664 | |
| 12667 | | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); |
| 12668 | | cases_extra.appendAssumeCapacity(1); // items_len |
| 12669 | | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); |
| 12665 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12666 | 1 + // `item`, no ranges |
| 12667 | case_block.instructions.items.len); |
| 12668 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 12669 | .items_len = 1, |
| 12670 | .ranges_len = 0, |
| 12671 | .body_len = @intCast(case_block.instructions.items.len), |
| 12672 | })); |
| 12670 | 12673 | cases_extra.appendAssumeCapacity(@intFromEnum(item_ref)); |
| 12671 | 12674 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12672 | 12675 | |
| ... | ... | @@ -12713,134 +12716,39 @@ fn analyzeSwitchRuntimeBlock( |
| 12713 | 12716 | }; |
| 12714 | 12717 | try branch_hints.append(gpa, prong_hint); |
| 12715 | 12718 | |
| 12716 | | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); |
| 12717 | | cases_extra.appendAssumeCapacity(1); // items_len |
| 12718 | | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); |
| 12719 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12720 | 1 + // `item`, no ranges |
| 12721 | case_block.instructions.items.len); |
| 12722 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 12723 | .items_len = 1, |
| 12724 | .ranges_len = 0, |
| 12725 | .body_len = @intCast(case_block.instructions.items.len), |
| 12726 | })); |
| 12719 | 12727 | cases_extra.appendAssumeCapacity(@intFromEnum(item)); |
| 12720 | 12728 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12721 | 12729 | } |
| 12722 | 12730 | |
| 12723 | | extra_index += info.body_len; |
| 12724 | 12731 | continue; |
| 12725 | 12732 | } |
| 12726 | 12733 | |
| 12727 | | var any_ok: Air.Inst.Ref = .none; |
| 12728 | | |
| 12729 | | // If there are any ranges, we have to put all the items into the |
| 12730 | | // else prong. Otherwise, we can take advantage of multiple items |
| 12731 | | // mapping to the same body. |
| 12732 | | if (ranges_len == 0) { |
| 12733 | | cases_len += 1; |
| 12734 | | |
| 12735 | | const analyze_body = if (union_originally) |
| 12736 | | for (items) |item| { |
| 12737 | | const item_val = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, item, undefined) catch unreachable; |
| 12738 | | const field_ty = maybe_union_ty.unionFieldType(item_val, zcu).?; |
| 12739 | | if (field_ty.zigTypeTag(zcu) != .noreturn) break true; |
| 12740 | | } else false |
| 12741 | | else |
| 12742 | | true; |
| 12734 | cases_len += 1; |
| 12743 | 12735 | |
| 12744 | | const body = sema.code.bodySlice(extra_index, info.body_len); |
| 12745 | | extra_index += info.body_len; |
| 12746 | | const prong_hint: std.builtin.BranchHint = if (err_set and |
| 12747 | | try sema.maybeErrorUnwrap(&case_block, body, operand, operand_src, allow_err_code_unwrap)) |
| 12748 | | h: { |
| 12749 | | // nothing to do here. weight against error branch |
| 12750 | | break :h .unlikely; |
| 12751 | | } else if (analyze_body) h: { |
| 12752 | | break :h try spa.analyzeProngRuntime( |
| 12753 | | &case_block, |
| 12754 | | .normal, |
| 12755 | | body, |
| 12756 | | info.capture, |
| 12757 | | child_block.src(.{ .switch_capture = .{ |
| 12758 | | .switch_node_offset = switch_node_offset, |
| 12759 | | .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, |
| 12760 | | } }), |
| 12761 | | items, |
| 12762 | | .none, |
| 12763 | | false, |
| 12764 | | ); |
| 12765 | | } else h: { |
| 12766 | | _ = try case_block.addNoOp(.unreach); |
| 12767 | | break :h .none; |
| 12768 | | }; |
| 12769 | | |
| 12770 | | try branch_hints.append(gpa, prong_hint); |
| 12771 | | try cases_extra.ensureUnusedCapacity(gpa, 2 + items.len + |
| 12772 | | case_block.instructions.items.len); |
| 12773 | | |
| 12774 | | cases_extra.appendAssumeCapacity(@intCast(items.len)); |
| 12775 | | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); |
| 12776 | | |
| 12777 | | for (items) |item| { |
| 12778 | | cases_extra.appendAssumeCapacity(@intFromEnum(item)); |
| 12779 | | } |
| 12780 | | |
| 12781 | | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12782 | | } else { |
| 12736 | const analyze_body = if (union_originally) |
| 12783 | 12737 | for (items) |item| { |
| 12784 | | const cmp_ok = try case_block.addBinOp(if (case_block.float_mode == .optimized) .cmp_eq_optimized else .cmp_eq, operand, item); |
| 12785 | | if (any_ok != .none) { |
| 12786 | | any_ok = try case_block.addBinOp(.bool_or, any_ok, cmp_ok); |
| 12787 | | } else { |
| 12788 | | any_ok = cmp_ok; |
| 12789 | | } |
| 12790 | | } |
| 12791 | | |
| 12792 | | var range_i: usize = 0; |
| 12793 | | while (range_i < ranges_len) : (range_i += 1) { |
| 12794 | | const range_items = case_vals.items[case_val_idx..][0..2]; |
| 12795 | | extra_index += 2; |
| 12796 | | case_val_idx += 2; |
| 12797 | | |
| 12798 | | const item_first = range_items[0]; |
| 12799 | | const item_last = range_items[1]; |
| 12800 | | |
| 12801 | | // operand >= first and operand <= last |
| 12802 | | const range_first_ok = try case_block.addBinOp( |
| 12803 | | if (case_block.float_mode == .optimized) .cmp_gte_optimized else .cmp_gte, |
| 12804 | | operand, |
| 12805 | | item_first, |
| 12806 | | ); |
| 12807 | | const range_last_ok = try case_block.addBinOp( |
| 12808 | | if (case_block.float_mode == .optimized) .cmp_lte_optimized else .cmp_lte, |
| 12809 | | operand, |
| 12810 | | item_last, |
| 12811 | | ); |
| 12812 | | const range_ok = try case_block.addBinOp( |
| 12813 | | .bool_and, |
| 12814 | | range_first_ok, |
| 12815 | | range_last_ok, |
| 12816 | | ); |
| 12817 | | if (any_ok != .none) { |
| 12818 | | any_ok = try case_block.addBinOp(.bool_or, any_ok, range_ok); |
| 12819 | | } else { |
| 12820 | | any_ok = range_ok; |
| 12821 | | } |
| 12822 | | } |
| 12823 | | |
| 12824 | | const new_cond_br = try case_block.addInstAsIndex(.{ .tag = .cond_br, .data = .{ |
| 12825 | | .pl_op = .{ |
| 12826 | | .operand = any_ok, |
| 12827 | | .payload = undefined, |
| 12828 | | }, |
| 12829 | | } }); |
| 12830 | | var cond_body = try case_block.instructions.toOwnedSlice(gpa); |
| 12831 | | defer gpa.free(cond_body); |
| 12832 | | |
| 12833 | | case_block.instructions.shrinkRetainingCapacity(0); |
| 12834 | | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12738 | const item_val = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, item, undefined) catch unreachable; |
| 12739 | const field_ty = maybe_union_ty.unionFieldType(item_val, zcu).?; |
| 12740 | if (field_ty.zigTypeTag(zcu) != .noreturn) break true; |
| 12741 | } else false |
| 12742 | else |
| 12743 | true; |
| 12835 | 12744 | |
| 12836 | | const body = sema.code.bodySlice(extra_index, info.body_len); |
| 12837 | | extra_index += info.body_len; |
| 12838 | | const prong_hint: std.builtin.BranchHint = if (err_set and |
| 12839 | | try sema.maybeErrorUnwrap(&case_block, body, operand, operand_src, allow_err_code_unwrap)) |
| 12840 | | h: { |
| 12841 | | // nothing to do here. weight against error branch |
| 12842 | | break :h .unlikely; |
| 12843 | | } else try spa.analyzeProngRuntime( |
| 12745 | const prong_hint: std.builtin.BranchHint = if (err_set and |
| 12746 | try sema.maybeErrorUnwrap(&case_block, body, operand, operand_src, allow_err_code_unwrap)) |
| 12747 | h: { |
| 12748 | // nothing to do here. weight against error branch |
| 12749 | break :h .unlikely; |
| 12750 | } else if (analyze_body) h: { |
| 12751 | break :h try spa.analyzeProngRuntime( |
| 12844 | 12752 | &case_block, |
| 12845 | 12753 | .normal, |
| 12846 | 12754 | body, |
| ... | ... | @@ -12853,40 +12761,36 @@ fn analyzeSwitchRuntimeBlock( |
| 12853 | 12761 | .none, |
| 12854 | 12762 | false, |
| 12855 | 12763 | ); |
| 12764 | } else h: { |
| 12765 | _ = try case_block.addNoOp(.unreach); |
| 12766 | break :h .none; |
| 12767 | }; |
| 12856 | 12768 | |
| 12857 | | if (is_first) { |
| 12858 | | is_first = false; |
| 12859 | | first_else_body = cond_body; |
| 12860 | | cond_body = &.{}; |
| 12861 | | } else { |
| 12862 | | try sema.air_extra.ensureUnusedCapacity( |
| 12863 | | gpa, |
| 12864 | | @typeInfo(Air.CondBr).@"struct".fields.len + prev_then_body.len + cond_body.len, |
| 12865 | | ); |
| 12769 | try branch_hints.append(gpa, prong_hint); |
| 12866 | 12770 | |
| 12867 | | sema.air_instructions.items(.data)[@intFromEnum(prev_cond_br)].pl_op.payload = sema.addExtraAssumeCapacity(Air.CondBr{ |
| 12868 | | .then_body_len = @intCast(prev_then_body.len), |
| 12869 | | .else_body_len = @intCast(cond_body.len), |
| 12870 | | .branch_hints = .{ |
| 12871 | | .true = prev_hint, |
| 12872 | | .false = .none, |
| 12873 | | // Code coverage is desired for error handling. |
| 12874 | | .then_cov = .poi, |
| 12875 | | .else_cov = .poi, |
| 12876 | | }, |
| 12877 | | }); |
| 12878 | | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(prev_then_body)); |
| 12879 | | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(cond_body)); |
| 12880 | | } |
| 12881 | | gpa.free(prev_then_body); |
| 12882 | | prev_then_body = try case_block.instructions.toOwnedSlice(gpa); |
| 12883 | | prev_cond_br = new_cond_br; |
| 12884 | | prev_hint = prong_hint; |
| 12771 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12772 | items.len + 2 * ranges_len + |
| 12773 | case_block.instructions.items.len); |
| 12774 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 12775 | .items_len = @intCast(items.len), |
| 12776 | .ranges_len = @intCast(ranges_len), |
| 12777 | .body_len = @intCast(case_block.instructions.items.len), |
| 12778 | })); |
| 12779 | |
| 12780 | for (items) |item| { |
| 12781 | cases_extra.appendAssumeCapacity(@intFromEnum(item)); |
| 12885 | 12782 | } |
| 12783 | for (ranges) |range| { |
| 12784 | cases_extra.appendSliceAssumeCapacity(&.{ |
| 12785 | @intFromEnum(range[0]), |
| 12786 | @intFromEnum(range[1]), |
| 12787 | }); |
| 12788 | } |
| 12789 | |
| 12790 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12886 | 12791 | } |
| 12887 | 12792 | |
| 12888 | | var final_else_body: []const Air.Inst.Index = &.{}; |
| 12889 | | if (special.body.len != 0 or !is_first or case_block.wantSafety()) { |
| 12793 | const else_body: []const Air.Inst.Index = if (special.body.len != 0 or case_block.wantSafety()) else_body: { |
| 12890 | 12794 | var emit_bb = false; |
| 12891 | 12795 | if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) { |
| 12892 | 12796 | .@"enum" => { |
| ... | ... | @@ -12933,9 +12837,14 @@ fn analyzeSwitchRuntimeBlock( |
| 12933 | 12837 | }; |
| 12934 | 12838 | try branch_hints.append(gpa, prong_hint); |
| 12935 | 12839 | |
| 12936 | | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); |
| 12937 | | cases_extra.appendAssumeCapacity(1); // items_len |
| 12938 | | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); |
| 12840 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12841 | 1 + // `item`, no ranges |
| 12842 | case_block.instructions.items.len); |
| 12843 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 12844 | .items_len = 1, |
| 12845 | .ranges_len = 0, |
| 12846 | .body_len = @intCast(case_block.instructions.items.len), |
| 12847 | })); |
| 12939 | 12848 | cases_extra.appendAssumeCapacity(@intFromEnum(item_ref)); |
| 12940 | 12849 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12941 | 12850 | } |
| ... | ... | @@ -12979,9 +12888,14 @@ fn analyzeSwitchRuntimeBlock( |
| 12979 | 12888 | ); |
| 12980 | 12889 | try branch_hints.append(gpa, prong_hint); |
| 12981 | 12890 | |
| 12982 | | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); |
| 12983 | | cases_extra.appendAssumeCapacity(1); // items_len |
| 12984 | | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); |
| 12891 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12892 | 1 + // `item`, no ranges |
| 12893 | case_block.instructions.items.len); |
| 12894 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 12895 | .items_len = 1, |
| 12896 | .ranges_len = 0, |
| 12897 | .body_len = @intCast(case_block.instructions.items.len), |
| 12898 | })); |
| 12985 | 12899 | cases_extra.appendAssumeCapacity(@intFromEnum(item_ref)); |
| 12986 | 12900 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12987 | 12901 | } |
| ... | ... | @@ -13014,9 +12928,14 @@ fn analyzeSwitchRuntimeBlock( |
| 13014 | 12928 | ); |
| 13015 | 12929 | try branch_hints.append(gpa, prong_hint); |
| 13016 | 12930 | |
| 13017 | | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); |
| 13018 | | cases_extra.appendAssumeCapacity(1); // items_len |
| 13019 | | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); |
| 12931 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12932 | 1 + // `item`, no ranges |
| 12933 | case_block.instructions.items.len); |
| 12934 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 12935 | .items_len = 1, |
| 12936 | .ranges_len = 0, |
| 12937 | .body_len = @intCast(case_block.instructions.items.len), |
| 12938 | })); |
| 13020 | 12939 | cases_extra.appendAssumeCapacity(@intFromEnum(item_ref)); |
| 13021 | 12940 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 13022 | 12941 | } |
| ... | ... | @@ -13046,9 +12965,14 @@ fn analyzeSwitchRuntimeBlock( |
| 13046 | 12965 | ); |
| 13047 | 12966 | try branch_hints.append(gpa, prong_hint); |
| 13048 | 12967 | |
| 13049 | | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); |
| 13050 | | cases_extra.appendAssumeCapacity(1); // items_len |
| 13051 | | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); |
| 12968 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12969 | 1 + // `item`, no ranges |
| 12970 | case_block.instructions.items.len); |
| 12971 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 12972 | .items_len = 1, |
| 12973 | .ranges_len = 0, |
| 12974 | .body_len = @intCast(case_block.instructions.items.len), |
| 12975 | })); |
| 13052 | 12976 | cases_extra.appendAssumeCapacity(@intFromEnum(Air.Inst.Ref.bool_true)); |
| 13053 | 12977 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 13054 | 12978 | } |
| ... | ... | @@ -13076,9 +13000,14 @@ fn analyzeSwitchRuntimeBlock( |
| 13076 | 13000 | ); |
| 13077 | 13001 | try branch_hints.append(gpa, prong_hint); |
| 13078 | 13002 | |
| 13079 | | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); |
| 13080 | | cases_extra.appendAssumeCapacity(1); // items_len |
| 13081 | | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); |
| 13003 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 13004 | 1 + // `item`, no ranges |
| 13005 | case_block.instructions.items.len); |
| 13006 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 13007 | .items_len = 1, |
| 13008 | .ranges_len = 0, |
| 13009 | .body_len = @intCast(case_block.instructions.items.len), |
| 13010 | })); |
| 13082 | 13011 | cases_extra.appendAssumeCapacity(@intFromEnum(Air.Inst.Ref.bool_false)); |
| 13083 | 13012 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 13084 | 13013 | } |
| ... | ... | @@ -13142,41 +13071,22 @@ fn analyzeSwitchRuntimeBlock( |
| 13142 | 13071 | break :h .cold; |
| 13143 | 13072 | }; |
| 13144 | 13073 | |
| 13145 | | if (is_first) { |
| 13146 | | try branch_hints.append(gpa, else_hint); |
| 13147 | | final_else_body = case_block.instructions.items; |
| 13148 | | } else { |
| 13149 | | try branch_hints.append(gpa, .none); // we have the range conditionals first |
| 13150 | | try sema.air_extra.ensureUnusedCapacity(gpa, prev_then_body.len + |
| 13151 | | @typeInfo(Air.CondBr).@"struct".fields.len + case_block.instructions.items.len); |
| 13152 | | |
| 13153 | | sema.air_instructions.items(.data)[@intFromEnum(prev_cond_br)].pl_op.payload = sema.addExtraAssumeCapacity(Air.CondBr{ |
| 13154 | | .then_body_len = @intCast(prev_then_body.len), |
| 13155 | | .else_body_len = @intCast(case_block.instructions.items.len), |
| 13156 | | .branch_hints = .{ |
| 13157 | | .true = prev_hint, |
| 13158 | | .false = else_hint, |
| 13159 | | .then_cov = .poi, |
| 13160 | | .else_cov = .poi, |
| 13161 | | }, |
| 13162 | | }); |
| 13163 | | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(prev_then_body)); |
| 13164 | | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 13165 | | final_else_body = first_else_body; |
| 13166 | | } |
| 13167 | | } else { |
| 13074 | try branch_hints.append(gpa, else_hint); |
| 13075 | break :else_body case_block.instructions.items; |
| 13076 | } else else_body: { |
| 13168 | 13077 | try branch_hints.append(gpa, .none); |
| 13169 | | } |
| 13078 | break :else_body &.{}; |
| 13079 | }; |
| 13170 | 13080 | |
| 13171 | 13081 | assert(branch_hints.items.len == cases_len + 1); |
| 13172 | 13082 | |
| 13173 | 13083 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr).@"struct".fields.len + |
| 13174 | | cases_extra.items.len + final_else_body.len + |
| 13084 | cases_extra.items.len + else_body.len + |
| 13175 | 13085 | (std.math.divCeil(usize, branch_hints.items.len, 10) catch unreachable)); // branch hints |
| 13176 | 13086 | |
| 13177 | 13087 | const payload_index = sema.addExtraAssumeCapacity(Air.SwitchBr{ |
| 13178 | 13088 | .cases_len = @intCast(cases_len), |
| 13179 | | .else_body_len = @intCast(final_else_body.len), |
| 13089 | .else_body_len = @intCast(else_body.len), |
| 13180 | 13090 | }); |
| 13181 | 13091 | |
| 13182 | 13092 | { |
| ... | ... | @@ -13195,7 +13105,7 @@ fn analyzeSwitchRuntimeBlock( |
| 13195 | 13105 | } |
| 13196 | 13106 | } |
| 13197 | 13107 | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(cases_extra.items)); |
| 13198 | | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(final_else_body)); |
| 13108 | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(else_body)); |
| 13199 | 13109 | |
| 13200 | 13110 | return try child_block.addInst(.{ |
| 13201 | 13111 | .tag = .switch_br, |
| ... | ... | @@ -37386,15 +37296,21 @@ pub fn addExtra(sema: *Sema, extra: anytype) Allocator.Error!u32 { |
| 37386 | 37296 | } |
| 37387 | 37297 | |
| 37388 | 37298 | pub fn addExtraAssumeCapacity(sema: *Sema, extra: anytype) u32 { |
| 37389 | | const fields = std.meta.fields(@TypeOf(extra)); |
| 37390 | 37299 | const result: u32 = @intCast(sema.air_extra.items.len); |
| 37391 | | inline for (fields) |field| { |
| 37392 | | sema.air_extra.appendAssumeCapacity(switch (field.type) { |
| 37393 | | u32 => @field(extra, field.name), |
| 37394 | | i32, Air.CondBr.BranchHints => @bitCast(@field(extra, field.name)), |
| 37395 | | Air.Inst.Ref, InternPool.Index => @intFromEnum(@field(extra, field.name)), |
| 37300 | sema.air_extra.appendSliceAssumeCapacity(&payloadToExtraItems(extra)); |
| 37301 | return result; |
| 37302 | } |
| 37303 | |
| 37304 | fn payloadToExtraItems(data: anytype) [@typeInfo(@TypeOf(data)).@"struct".fields.len]u32 { |
| 37305 | const fields = @typeInfo(@TypeOf(data)).@"struct".fields; |
| 37306 | var result: [fields.len]u32 = undefined; |
| 37307 | inline for (&result, fields) |*val, field| { |
| 37308 | val.* = switch (field.type) { |
| 37309 | u32 => @field(data, field.name), |
| 37310 | i32, Air.CondBr.BranchHints => @bitCast(@field(data, field.name)), |
| 37311 | Air.Inst.Ref, InternPool.Index => @intFromEnum(@field(data, field.name)), |
| 37396 | 37312 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 37397 | | }); |
| 37313 | }; |
| 37398 | 37314 | } |
| 37399 | 37315 | return result; |
| 37400 | 37316 | } |