| ... | @@ -11353,9 +11353,14 @@ const SwitchProngAnalysis = struct { | ... | @@ -11353,9 +11353,14 @@ const SwitchProngAnalysis = struct { |
| 11353 | const coerced = try sema.coerce(&coerce_block, capture_ty, uncoerced, case_src); | 11353 | const coerced = try sema.coerce(&coerce_block, capture_ty, uncoerced, case_src); |
| 11354 | _ = try coerce_block.addBr(capture_block_inst, coerced); | 11354 | _ = try coerce_block.addBr(capture_block_inst, coerced); |
| 11355 | | 11355 | |
| 11356 | try cases_extra.ensureUnusedCapacity(3 + coerce_block.instructions.items.len); | 11356 | try cases_extra.ensureUnusedCapacity(@typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 11357 | cases_extra.appendAssumeCapacity(1); // items_len | 11357 | 1 + // `item`, no ranges |
| 11358 | cases_extra.appendAssumeCapacity(@intCast(coerce_block.instructions.items.len)); // body_len | 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 | cases_extra.appendAssumeCapacity(@intFromEnum(case_vals[idx])); // item | 11364 | cases_extra.appendAssumeCapacity(@intFromEnum(case_vals[idx])); // item |
| 11360 | cases_extra.appendSliceAssumeCapacity(@ptrCast(coerce_block.instructions.items)); // body | 11365 | cases_extra.appendSliceAssumeCapacity(@ptrCast(coerce_block.instructions.items)); // body |
| 11361 | } | 11366 | } |
| ... | @@ -12578,21 +12583,18 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12578,21 +12583,18 @@ fn analyzeSwitchRuntimeBlock( |
| 12578 | }; | 12583 | }; |
| 12579 | | 12584 | |
| 12580 | try branch_hints.append(gpa, prong_hint); | 12585 | try branch_hints.append(gpa, prong_hint); |
| 12581 | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); | 12586 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12582 | cases_extra.appendAssumeCapacity(1); // items_len | 12587 | 1 + // `item`, no ranges |
| 12583 | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); | 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 | cases_extra.appendAssumeCapacity(@intFromEnum(item)); | 12594 | cases_extra.appendAssumeCapacity(@intFromEnum(item)); |
| 12585 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); | 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 | var cases_len = scalar_cases_len; | 12598 | var cases_len = scalar_cases_len; |
| 12597 | var case_val_idx: usize = scalar_cases_len; | 12599 | var case_val_idx: usize = scalar_cases_len; |
| 12598 | var multi_i: u32 = 0; | 12600 | var multi_i: u32 = 0; |
| ... | @@ -12602,31 +12604,27 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12602,31 +12604,27 @@ fn analyzeSwitchRuntimeBlock( |
| 12602 | const ranges_len = sema.code.extra[extra_index]; | 12604 | const ranges_len = sema.code.extra[extra_index]; |
| 12603 | extra_index += 1; | 12605 | extra_index += 1; |
| 12604 | const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(sema.code.extra[extra_index]); | 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 | const items = case_vals.items[case_val_idx..][0..items_len]; | 12609 | const items = case_vals.items[case_val_idx..][0..items_len]; |
| 12608 | case_val_idx += items_len; | 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 | case_block.instructions.shrinkRetainingCapacity(0); | 12618 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12611 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12619 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12612 | | 12620 | |
| 12613 | // Generate all possible cases as scalar prongs. | 12621 | // Generate all possible cases as scalar prongs. |
| 12614 | if (info.is_inline) { | 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 | var emit_bb = false; | 12623 | var emit_bb = false; |
| 12618 | | 12624 | |
| 12619 | var range_i: u32 = 0; | 12625 | for (ranges, 0..) |range_items, range_i| { |
| 12620 | while (range_i < ranges_len) : (range_i += 1) { | 12626 | var item = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, range_items[0], undefined) catch unreachable; |
| 12621 | const range_items = case_vals.items[case_val_idx..][0..2]; | 12627 | const item_last = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, range_items[1], undefined) catch unreachable; |
| 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; | | |
| 12630 | | 12628 | |
| 12631 | while (item.compareScalar(.lte, item_last, operand_ty, zcu)) : ({ | 12629 | while (item.compareScalar(.lte, item_last, operand_ty, zcu)) : ({ |
| 12632 | // Previous validation has resolved any possible lazy values. | 12630 | // Previous validation has resolved any possible lazy values. |
| ... | @@ -12664,9 +12662,14 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12664,9 +12662,14 @@ fn analyzeSwitchRuntimeBlock( |
| 12664 | ); | 12662 | ); |
| 12665 | try branch_hints.append(gpa, prong_hint); | 12663 | try branch_hints.append(gpa, prong_hint); |
| 12666 | | 12664 | |
| 12667 | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); | 12665 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12668 | cases_extra.appendAssumeCapacity(1); // items_len | 12666 | 1 + // `item`, no ranges |
| 12669 | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); | 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 | cases_extra.appendAssumeCapacity(@intFromEnum(item_ref)); | 12673 | cases_extra.appendAssumeCapacity(@intFromEnum(item_ref)); |
| 12671 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); | 12674 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12672 | | 12675 | |
| ... | @@ -12713,134 +12716,39 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12713,134 +12716,39 @@ fn analyzeSwitchRuntimeBlock( |
| 12713 | }; | 12716 | }; |
| 12714 | try branch_hints.append(gpa, prong_hint); | 12717 | try branch_hints.append(gpa, prong_hint); |
| 12715 | | 12718 | |
| 12716 | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); | 12719 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12717 | cases_extra.appendAssumeCapacity(1); // items_len | 12720 | 1 + // `item`, no ranges |
| 12718 | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); | 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 | cases_extra.appendAssumeCapacity(@intFromEnum(item)); | 12727 | cases_extra.appendAssumeCapacity(@intFromEnum(item)); |
| 12720 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); | 12728 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12721 | } | 12729 | } |
| 12722 | | 12730 | |
| 12723 | extra_index += info.body_len; | | |
| 12724 | continue; | 12731 | continue; |
| 12725 | } | 12732 | } |
| 12726 | | 12733 | |
| 12727 | var any_ok: Air.Inst.Ref = .none; | 12734 | cases_len += 1; |
| 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; | | |
| 12743 | | 12735 | |
| 12744 | const body = sema.code.bodySlice(extra_index, info.body_len); | 12736 | const analyze_body = if (union_originally) |
| 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 { | | |
| 12783 | for (items) |item| { | 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); | 12738 | const item_val = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, item, undefined) catch unreachable; |
| 12785 | if (any_ok != .none) { | 12739 | const field_ty = maybe_union_ty.unionFieldType(item_val, zcu).?; |
| 12786 | any_ok = try case_block.addBinOp(.bool_or, any_ok, cmp_ok); | 12740 | if (field_ty.zigTypeTag(zcu) != .noreturn) break true; |
| 12787 | } else { | 12741 | } else false |
| 12788 | any_ok = cmp_ok; | 12742 | else |
| 12789 | } | 12743 | true; |
| 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; | | |
| 12835 | | 12744 | |
| 12836 | const body = sema.code.bodySlice(extra_index, info.body_len); | 12745 | const prong_hint: std.builtin.BranchHint = if (err_set and |
| 12837 | extra_index += info.body_len; | 12746 | try sema.maybeErrorUnwrap(&case_block, body, operand, operand_src, allow_err_code_unwrap)) |
| 12838 | const prong_hint: std.builtin.BranchHint = if (err_set and | 12747 | h: { |
| 12839 | try sema.maybeErrorUnwrap(&case_block, body, operand, operand_src, allow_err_code_unwrap)) | 12748 | // nothing to do here. weight against error branch |
| 12840 | h: { | 12749 | break :h .unlikely; |
| 12841 | // nothing to do here. weight against error branch | 12750 | } else if (analyze_body) h: { |
| 12842 | break :h .unlikely; | 12751 | break :h try spa.analyzeProngRuntime( |
| 12843 | } else try spa.analyzeProngRuntime( | | |
| 12844 | &case_block, | 12752 | &case_block, |
| 12845 | .normal, | 12753 | .normal, |
| 12846 | body, | 12754 | body, |
| ... | @@ -12853,40 +12761,36 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12853,40 +12761,36 @@ fn analyzeSwitchRuntimeBlock( |
| 12853 | .none, | 12761 | .none, |
| 12854 | false, | 12762 | false, |
| 12855 | ); | 12763 | ); |
| | 12764 | } else h: { |
| | 12765 | _ = try case_block.addNoOp(.unreach); |
| | 12766 | break :h .none; |
| | 12767 | }; |
| 12856 | | 12768 | |
| 12857 | if (is_first) { | 12769 | try branch_hints.append(gpa, prong_hint); |
| 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 | ); | | |
| 12866 | | 12770 | |
| 12867 | sema.air_instructions.items(.data)[@intFromEnum(prev_cond_br)].pl_op.payload = sema.addExtraAssumeCapacity(Air.CondBr{ | 12771 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12868 | .then_body_len = @intCast(prev_then_body.len), | 12772 | items.len + 2 * ranges_len + |
| 12869 | .else_body_len = @intCast(cond_body.len), | 12773 | case_block.instructions.items.len); |
| 12870 | .branch_hints = .{ | 12774 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 12871 | .true = prev_hint, | 12775 | .items_len = @intCast(items.len), |
| 12872 | .false = .none, | 12776 | .ranges_len = @intCast(ranges_len), |
| 12873 | // Code coverage is desired for error handling. | 12777 | .body_len = @intCast(case_block.instructions.items.len), |
| 12874 | .then_cov = .poi, | 12778 | })); |
| 12875 | .else_cov = .poi, | 12779 | |
| 12876 | }, | 12780 | for (items) |item| { |
| 12877 | }); | 12781 | cases_extra.appendAssumeCapacity(@intFromEnum(item)); |
| 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; | | |
| 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 = &.{}; | 12793 | const else_body: []const Air.Inst.Index = if (special.body.len != 0 or case_block.wantSafety()) else_body: { |
| 12889 | if (special.body.len != 0 or !is_first or case_block.wantSafety()) { | | |
| 12890 | var emit_bb = false; | 12794 | var emit_bb = false; |
| 12891 | if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) { | 12795 | if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) { |
| 12892 | .@"enum" => { | 12796 | .@"enum" => { |
| ... | @@ -12933,9 +12837,14 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12933,9 +12837,14 @@ fn analyzeSwitchRuntimeBlock( |
| 12933 | }; | 12837 | }; |
| 12934 | try branch_hints.append(gpa, prong_hint); | 12838 | try branch_hints.append(gpa, prong_hint); |
| 12935 | | 12839 | |
| 12936 | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); | 12840 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12937 | cases_extra.appendAssumeCapacity(1); // items_len | 12841 | 1 + // `item`, no ranges |
| 12938 | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); | 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 | cases_extra.appendAssumeCapacity(@intFromEnum(item_ref)); | 12848 | cases_extra.appendAssumeCapacity(@intFromEnum(item_ref)); |
| 12940 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); | 12849 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12941 | } | 12850 | } |
| ... | @@ -12979,9 +12888,14 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12979,9 +12888,14 @@ fn analyzeSwitchRuntimeBlock( |
| 12979 | ); | 12888 | ); |
| 12980 | try branch_hints.append(gpa, prong_hint); | 12889 | try branch_hints.append(gpa, prong_hint); |
| 12981 | | 12890 | |
| 12982 | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); | 12891 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12983 | cases_extra.appendAssumeCapacity(1); // items_len | 12892 | 1 + // `item`, no ranges |
| 12984 | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); | 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 | cases_extra.appendAssumeCapacity(@intFromEnum(item_ref)); | 12899 | cases_extra.appendAssumeCapacity(@intFromEnum(item_ref)); |
| 12986 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); | 12900 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12987 | } | 12901 | } |
| ... | @@ -13014,9 +12928,14 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -13014,9 +12928,14 @@ fn analyzeSwitchRuntimeBlock( |
| 13014 | ); | 12928 | ); |
| 13015 | try branch_hints.append(gpa, prong_hint); | 12929 | try branch_hints.append(gpa, prong_hint); |
| 13016 | | 12930 | |
| 13017 | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); | 12931 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 13018 | cases_extra.appendAssumeCapacity(1); // items_len | 12932 | 1 + // `item`, no ranges |
| 13019 | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); | 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 | cases_extra.appendAssumeCapacity(@intFromEnum(item_ref)); | 12939 | cases_extra.appendAssumeCapacity(@intFromEnum(item_ref)); |
| 13021 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); | 12940 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 13022 | } | 12941 | } |
| ... | @@ -13046,9 +12965,14 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -13046,9 +12965,14 @@ fn analyzeSwitchRuntimeBlock( |
| 13046 | ); | 12965 | ); |
| 13047 | try branch_hints.append(gpa, prong_hint); | 12966 | try branch_hints.append(gpa, prong_hint); |
| 13048 | | 12967 | |
| 13049 | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); | 12968 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 13050 | cases_extra.appendAssumeCapacity(1); // items_len | 12969 | 1 + // `item`, no ranges |
| 13051 | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); | 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 | cases_extra.appendAssumeCapacity(@intFromEnum(Air.Inst.Ref.bool_true)); | 12976 | cases_extra.appendAssumeCapacity(@intFromEnum(Air.Inst.Ref.bool_true)); |
| 13053 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); | 12977 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 13054 | } | 12978 | } |
| ... | @@ -13076,9 +13000,14 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -13076,9 +13000,14 @@ fn analyzeSwitchRuntimeBlock( |
| 13076 | ); | 13000 | ); |
| 13077 | try branch_hints.append(gpa, prong_hint); | 13001 | try branch_hints.append(gpa, prong_hint); |
| 13078 | | 13002 | |
| 13079 | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); | 13003 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 13080 | cases_extra.appendAssumeCapacity(1); // items_len | 13004 | 1 + // `item`, no ranges |
| 13081 | cases_extra.appendAssumeCapacity(@intCast(case_block.instructions.items.len)); | 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 | cases_extra.appendAssumeCapacity(@intFromEnum(Air.Inst.Ref.bool_false)); | 13011 | cases_extra.appendAssumeCapacity(@intFromEnum(Air.Inst.Ref.bool_false)); |
| 13083 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); | 13012 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 13084 | } | 13013 | } |
| ... | @@ -13142,41 +13071,22 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -13142,41 +13071,22 @@ fn analyzeSwitchRuntimeBlock( |
| 13142 | break :h .cold; | 13071 | break :h .cold; |
| 13143 | }; | 13072 | }; |
| 13144 | | 13073 | |
| 13145 | if (is_first) { | 13074 | try branch_hints.append(gpa, else_hint); |
| 13146 | try branch_hints.append(gpa, else_hint); | 13075 | break :else_body case_block.instructions.items; |
| 13147 | final_else_body = case_block.instructions.items; | 13076 | } else else_body: { |
| 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 { | | |
| 13168 | try branch_hints.append(gpa, .none); | 13077 | try branch_hints.append(gpa, .none); |
| 13169 | } | 13078 | break :else_body &.{}; |
| | 13079 | }; |
| 13170 | | 13080 | |
| 13171 | assert(branch_hints.items.len == cases_len + 1); | 13081 | assert(branch_hints.items.len == cases_len + 1); |
| 13172 | | 13082 | |
| 13173 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr).@"struct".fields.len + | 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 | (std.math.divCeil(usize, branch_hints.items.len, 10) catch unreachable)); // branch hints | 13085 | (std.math.divCeil(usize, branch_hints.items.len, 10) catch unreachable)); // branch hints |
| 13176 | | 13086 | |
| 13177 | const payload_index = sema.addExtraAssumeCapacity(Air.SwitchBr{ | 13087 | const payload_index = sema.addExtraAssumeCapacity(Air.SwitchBr{ |
| 13178 | .cases_len = @intCast(cases_len), | 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,7 +13105,7 @@ fn analyzeSwitchRuntimeBlock( |
| 13195 | } | 13105 | } |
| 13196 | } | 13106 | } |
| 13197 | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(cases_extra.items)); | 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 | return try child_block.addInst(.{ | 13110 | return try child_block.addInst(.{ |
| 13201 | .tag = .switch_br, | 13111 | .tag = .switch_br, |
| ... | @@ -37386,15 +37296,21 @@ pub fn addExtra(sema: *Sema, extra: anytype) Allocator.Error!u32 { | ... | @@ -37386,15 +37296,21 @@ pub fn addExtra(sema: *Sema, extra: anytype) Allocator.Error!u32 { |
| 37386 | } | 37296 | } |
| 37387 | | 37297 | |
| 37388 | pub fn addExtraAssumeCapacity(sema: *Sema, extra: anytype) u32 { | 37298 | pub fn addExtraAssumeCapacity(sema: *Sema, extra: anytype) u32 { |
| 37389 | const fields = std.meta.fields(@TypeOf(extra)); | | |
| 37390 | const result: u32 = @intCast(sema.air_extra.items.len); | 37299 | const result: u32 = @intCast(sema.air_extra.items.len); |
| 37391 | inline for (fields) |field| { | 37300 | sema.air_extra.appendSliceAssumeCapacity(&payloadToExtraItems(extra)); |
| 37392 | sema.air_extra.appendAssumeCapacity(switch (field.type) { | 37301 | return result; |
| 37393 | u32 => @field(extra, field.name), | 37302 | } |
| 37394 | i32, Air.CondBr.BranchHints => @bitCast(@field(extra, field.name)), | 37303 | |
| 37395 | Air.Inst.Ref, InternPool.Index => @intFromEnum(@field(extra, field.name)), | 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 | else => @compileError("bad field type: " ++ @typeName(field.type)), | 37312 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 37397 | }); | 37313 | }; |
| 37398 | } | 37314 | } |
| 37399 | return result; | 37315 | return result; |
| 37400 | } | 37316 | } |