| ... | @@ -2752,9 +2752,9 @@ fn switchExpr( | ... | @@ -2752,9 +2752,9 @@ fn switchExpr( |
| 2752 | }; | 2752 | }; |
| 2753 | break :blk &capture_val_scope.base; | 2753 | break :blk &capture_val_scope.base; |
| 2754 | }; | 2754 | }; |
| 2755 | block_scope.break_count += 1; | | |
| 2756 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); | 2755 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 2757 | if (!astgen.refIsNoReturn(case_result)) { | 2756 | if (!astgen.refIsNoReturn(case_result)) { |
| | 2757 | block_scope.break_count += 1; |
| 2758 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); | 2758 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| 2759 | } | 2759 | } |
| 2760 | // Documentation for this: `zir.Inst.SwitchBlock` and `zir.Inst.SwitchBlockMulti`. | 2760 | // Documentation for this: `zir.Inst.SwitchBlock` and `zir.Inst.SwitchBlockMulti`. |
| ... | @@ -2873,9 +2873,9 @@ fn switchExpr( | ... | @@ -2873,9 +2873,9 @@ fn switchExpr( |
| 2873 | }); | 2873 | }); |
| 2874 | } | 2874 | } |
| 2875 | | 2875 | |
| 2876 | block_scope.break_count += 1; | | |
| 2877 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); | 2876 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 2878 | if (!astgen.refIsNoReturn(case_result)) { | 2877 | if (!astgen.refIsNoReturn(case_result)) { |
| | 2878 | block_scope.break_count += 1; |
| 2879 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); | 2879 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| 2880 | } | 2880 | } |
| 2881 | | 2881 | |
| ... | @@ -2886,9 +2886,9 @@ fn switchExpr( | ... | @@ -2886,9 +2886,9 @@ fn switchExpr( |
| 2886 | } else { | 2886 | } else { |
| 2887 | const item_node = case.ast.values[0]; | 2887 | const item_node = case.ast.values[0]; |
| 2888 | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); | 2888 | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); |
| 2889 | block_scope.break_count += 1; | | |
| 2890 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); | 2889 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 2891 | if (!astgen.refIsNoReturn(case_result)) { | 2890 | if (!astgen.refIsNoReturn(case_result)) { |
| | 2891 | block_scope.break_count += 1; |
| 2892 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); | 2892 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| 2893 | } | 2893 | } |
| 2894 | try scalar_cases_payload.ensureCapacity(gpa, scalar_cases_payload.items.len + | 2894 | try scalar_cases_payload.ensureCapacity(gpa, scalar_cases_payload.items.len + |
| ... | @@ -2925,13 +2925,11 @@ fn switchExpr( | ... | @@ -2925,13 +2925,11 @@ fn switchExpr( |
| 2925 | 0b1_10_1 => .switch_block_ref_under_multi, | 2925 | 0b1_10_1 => .switch_block_ref_under_multi, |
| 2926 | else => unreachable, | 2926 | else => unreachable, |
| 2927 | }; | 2927 | }; |
| 2928 | const zir_datas = astgen.instructions.items(.data); | | |
| 2929 | const payload_index = astgen.extra.items.len; | 2928 | const payload_index = astgen.extra.items.len; |
| | 2929 | const zir_datas = astgen.instructions.items(.data); |
| 2930 | zir_datas[switch_block].pl_node.payload_index = @intCast(u32, payload_index); | 2930 | zir_datas[switch_block].pl_node.payload_index = @intCast(u32, payload_index); |
| 2931 | try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + | 2931 | try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + |
| 2932 | scalar_cases_payload.items.len + multi_cases_payload.items.len); | 2932 | scalar_cases_payload.items.len + multi_cases_payload.items.len); |
| 2933 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items); | | |
| 2934 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items); | | |
| 2935 | const strat = rl.strategy(&block_scope); | 2933 | const strat = rl.strategy(&block_scope); |
| 2936 | switch (strat.tag) { | 2934 | switch (strat.tag) { |
| 2937 | .break_operand => { | 2935 | .break_operand => { |
| ... | @@ -2939,51 +2937,90 @@ fn switchExpr( | ... | @@ -2939,51 +2937,90 @@ fn switchExpr( |
| 2939 | // this is always true. | 2937 | // this is always true. |
| 2940 | assert(strat.elide_store_to_block_ptr_instructions); | 2938 | assert(strat.elide_store_to_block_ptr_instructions); |
| 2941 | | 2939 | |
| | 2940 | // There will necessarily be a store_to_block_ptr for |
| | 2941 | // all prongs, except for prongs that ended with a noreturn instruction. |
| 2942 | // Elide all the `store_to_block_ptr` instructions. | 2942 | // Elide all the `store_to_block_ptr` instructions. |
| 2943 | var extra_index: usize = payload_index; | 2943 | |
| | 2944 | var extra_index: usize = 0; |
| 2944 | extra_index += 2; | 2945 | extra_index += 2; |
| 2945 | extra_index += @boolToInt(multi_cases_len != 0); | 2946 | extra_index += @boolToInt(multi_cases_len != 0); |
| 2946 | if (special_prong != .none) { | 2947 | if (special_prong != .none) { |
| 2947 | const body_len = astgen.extra.items[extra_index]; | 2948 | const body_len_index = extra_index; |
| | 2949 | const body_len = scalar_cases_payload.items[extra_index]; |
| 2948 | extra_index += 1; | 2950 | extra_index += 1; |
| 2949 | const body = astgen.extra.items[extra_index..][0..body_len]; | 2951 | extra_index += body_len - 2; |
| 2950 | extra_index += body_len; | 2952 | const store_inst = scalar_cases_payload.items[extra_index]; |
| 2951 | const store_inst = body[body.len - 2]; | 2953 | if (zir_tags[store_inst] == .store_to_block_ptr) { |
| 2952 | assert(zir_tags[store_inst] == .store_to_block_ptr); | 2954 | assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr); |
| 2953 | assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr); | 2955 | scalar_cases_payload.items[body_len_index] -= 1; |
| 2954 | zir_tags[store_inst] = .elided; | 2956 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]); |
| 2955 | zir_datas[store_inst] = undefined; | 2957 | extra_index += 1; |
| | 2958 | astgen.extra.appendAssumeCapacity(scalar_cases_payload.items[extra_index]); |
| | 2959 | extra_index += 1; |
| | 2960 | } else { |
| | 2961 | extra_index += 2; |
| | 2962 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]); |
| | 2963 | } |
| | 2964 | } else { |
| | 2965 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[0..extra_index]); |
| 2956 | } | 2966 | } |
| 2957 | var scalar_i: u32 = 0; | 2967 | var scalar_i: u32 = 0; |
| 2958 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 2968 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| | 2969 | const start_index = extra_index; |
| 2959 | extra_index += 1; | 2970 | extra_index += 1; |
| 2960 | const body_len = astgen.extra.items[extra_index]; | 2971 | const body_len_index = extra_index; |
| | 2972 | const body_len = scalar_cases_payload.items[extra_index]; |
| 2961 | extra_index += 1; | 2973 | extra_index += 1; |
| 2962 | const body = astgen.extra.items[extra_index..][0..body_len]; | 2974 | if (body_len < 2) { |
| 2963 | extra_index += body_len; | 2975 | extra_index += body_len; |
| 2964 | const store_inst = body[body.len - 2]; | 2976 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]); |
| 2965 | assert(zir_tags[store_inst] == .store_to_block_ptr); | 2977 | continue; |
| 2966 | assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr); | 2978 | } |
| 2967 | zir_tags[store_inst] = .elided; | 2979 | extra_index += body_len - 2; |
| 2968 | zir_datas[store_inst] = undefined; | 2980 | const store_inst = scalar_cases_payload.items[extra_index]; |
| | 2981 | if (zir_tags[store_inst] == .store_to_block_ptr) { |
| | 2982 | assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr); |
| | 2983 | scalar_cases_payload.items[body_len_index] -= 1; |
| | 2984 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]); |
| | 2985 | extra_index += 1; |
| | 2986 | astgen.extra.appendAssumeCapacity(scalar_cases_payload.items[extra_index]); |
| | 2987 | extra_index += 1; |
| | 2988 | } else { |
| | 2989 | extra_index += 2; |
| | 2990 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]); |
| | 2991 | } |
| 2969 | } | 2992 | } |
| | 2993 | extra_index = 0; |
| 2970 | var multi_i: u32 = 0; | 2994 | var multi_i: u32 = 0; |
| 2971 | while (multi_i < multi_cases_len) : (multi_i += 1) { | 2995 | while (multi_i < multi_cases_len) : (multi_i += 1) { |
| 2972 | const items_len = astgen.extra.items[extra_index]; | 2996 | const start_index = extra_index; |
| | 2997 | const items_len = multi_cases_payload.items[extra_index]; |
| 2973 | extra_index += 1; | 2998 | extra_index += 1; |
| 2974 | const ranges_len = astgen.extra.items[extra_index]; | 2999 | const ranges_len = multi_cases_payload.items[extra_index]; |
| 2975 | extra_index += 1; | 3000 | extra_index += 1; |
| 2976 | const body_len = astgen.extra.items[extra_index]; | 3001 | const body_len_index = extra_index; |
| | 3002 | const body_len = multi_cases_payload.items[extra_index]; |
| 2977 | extra_index += 1; | 3003 | extra_index += 1; |
| 2978 | extra_index += items_len; | 3004 | extra_index += items_len; |
| 2979 | extra_index += 2 * ranges_len; | 3005 | extra_index += 2 * ranges_len; |
| 2980 | const body = astgen.extra.items[extra_index..][0..body_len]; | 3006 | if (body_len < 2) { |
| 2981 | extra_index += body_len; | 3007 | extra_index += body_len; |
| 2982 | const store_inst = body[body.len - 2]; | 3008 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]); |
| 2983 | assert(zir_tags[store_inst] == .store_to_block_ptr); | 3009 | continue; |
| 2984 | assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr); | 3010 | } |
| 2985 | zir_tags[store_inst] = .elided; | 3011 | extra_index += body_len - 2; |
| 2986 | zir_datas[store_inst] = undefined; | 3012 | const store_inst = multi_cases_payload.items[extra_index]; |
| | 3013 | if (zir_tags[store_inst] == .store_to_block_ptr) { |
| | 3014 | assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr); |
| | 3015 | multi_cases_payload.items[body_len_index] -= 1; |
| | 3016 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]); |
| | 3017 | extra_index += 1; |
| | 3018 | astgen.extra.appendAssumeCapacity(multi_cases_payload.items[extra_index]); |
| | 3019 | extra_index += 1; |
| | 3020 | } else { |
| | 3021 | extra_index += 2; |
| | 3022 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]); |
| | 3023 | } |
| 2987 | } | 3024 | } |
| 2988 | | 3025 | |
| 2989 | const block_ref = astgen.indexToRef(switch_block); | 3026 | const block_ref = astgen.indexToRef(switch_block); |
| ... | @@ -2994,6 +3031,8 @@ fn switchExpr( | ... | @@ -2994,6 +3031,8 @@ fn switchExpr( |
| 2994 | }, | 3031 | }, |
| 2995 | .break_void => { | 3032 | .break_void => { |
| 2996 | assert(!strat.elide_store_to_block_ptr_instructions); | 3033 | assert(!strat.elide_store_to_block_ptr_instructions); |
| | 3034 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items); |
| | 3035 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items); |
| 2997 | // Modify all the terminating instruction tags to become `break` variants. | 3036 | // Modify all the terminating instruction tags to become `break` variants. |
| 2998 | var extra_index: usize = payload_index; | 3037 | var extra_index: usize = payload_index; |
| 2999 | extra_index += 2; | 3038 | extra_index += 2; |
| ... | @@ -3004,9 +3043,11 @@ fn switchExpr( | ... | @@ -3004,9 +3043,11 @@ fn switchExpr( |
| 3004 | const body = astgen.extra.items[extra_index..][0..body_len]; | 3043 | const body = astgen.extra.items[extra_index..][0..body_len]; |
| 3005 | extra_index += body_len; | 3044 | extra_index += body_len; |
| 3006 | const last = body[body.len - 1]; | 3045 | const last = body[body.len - 1]; |
| 3007 | assert(zir_tags[last] == .@"break"); | 3046 | if (zir_tags[last] == .@"break" and |
| 3008 | assert(zir_datas[last].@"break".block_inst == switch_block); | 3047 | zir_datas[last].@"break".block_inst == switch_block) |
| 3009 | zir_datas[last].@"break".operand = .void_value; | 3048 | { |
| | 3049 | zir_datas[last].@"break".operand = .void_value; |
| | 3050 | } |
| 3010 | } | 3051 | } |
| 3011 | var scalar_i: u32 = 0; | 3052 | var scalar_i: u32 = 0; |
| 3012 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 3053 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -3016,9 +3057,11 @@ fn switchExpr( | ... | @@ -3016,9 +3057,11 @@ fn switchExpr( |
| 3016 | const body = astgen.extra.items[extra_index..][0..body_len]; | 3057 | const body = astgen.extra.items[extra_index..][0..body_len]; |
| 3017 | extra_index += body_len; | 3058 | extra_index += body_len; |
| 3018 | const last = body[body.len - 1]; | 3059 | const last = body[body.len - 1]; |
| 3019 | assert(zir_tags[last] == .@"break"); | 3060 | if (zir_tags[last] == .@"break" and |
| 3020 | assert(zir_datas[last].@"break".block_inst == switch_block); | 3061 | zir_datas[last].@"break".block_inst == switch_block) |
| 3021 | zir_datas[last].@"break".operand = .void_value; | 3062 | { |
| | 3063 | zir_datas[last].@"break".operand = .void_value; |
| | 3064 | } |
| 3022 | } | 3065 | } |
| 3023 | var multi_i: u32 = 0; | 3066 | var multi_i: u32 = 0; |
| 3024 | while (multi_i < multi_cases_len) : (multi_i += 1) { | 3067 | while (multi_i < multi_cases_len) : (multi_i += 1) { |
| ... | @@ -3033,9 +3076,11 @@ fn switchExpr( | ... | @@ -3033,9 +3076,11 @@ fn switchExpr( |
| 3033 | const body = astgen.extra.items[extra_index..][0..body_len]; | 3076 | const body = astgen.extra.items[extra_index..][0..body_len]; |
| 3034 | extra_index += body_len; | 3077 | extra_index += body_len; |
| 3035 | const last = body[body.len - 1]; | 3078 | const last = body[body.len - 1]; |
| 3036 | assert(zir_tags[last] == .@"break"); | 3079 | if (zir_tags[last] == .@"break" and |
| 3037 | assert(zir_datas[last].@"break".block_inst == switch_block); | 3080 | zir_datas[last].@"break".block_inst == switch_block) |
| 3038 | zir_datas[last].@"break".operand = .void_value; | 3081 | { |
| | 3082 | zir_datas[last].@"break".operand = .void_value; |
| | 3083 | } |
| 3039 | } | 3084 | } |
| 3040 | | 3085 | |
| 3041 | return astgen.indexToRef(switch_block); | 3086 | return astgen.indexToRef(switch_block); |