| ... | ... | @@ -3162,43 +3162,33 @@ fn tryExpr( |
| 3162 | 3162 | ) InnerError!Zir.Inst.Ref { |
| 3163 | 3163 | const astgen = parent_gz.astgen; |
| 3164 | 3164 | const tree = &astgen.file.tree; |
| 3165 | | const main_tokens = tree.nodes.items(.main_token); |
| 3166 | | const token_tags = tree.tokens.items(.tag); |
| 3167 | | const node_datas = tree.nodes.items(.data); |
| 3168 | | const node_tags = tree.nodes.items(.tag); |
| 3169 | 3165 | |
| 3170 | 3166 | var block_scope: GenZir = .{ |
| 3171 | 3167 | .parent = scope, |
| 3172 | 3168 | .decl_node_index = parent_gz.decl_node_index, |
| 3173 | | .astgen = parent_gz.astgen, |
| 3169 | .astgen = astgen, |
| 3174 | 3170 | .force_comptime = parent_gz.force_comptime, |
| 3175 | 3171 | .instructions = .{}, |
| 3176 | 3172 | }; |
| 3177 | 3173 | block_scope.setBreakResultLoc(rl); |
| 3178 | 3174 | defer block_scope.instructions.deinit(astgen.gpa); |
| 3179 | 3175 | |
| 3180 | | // This could be a pointer or value depending on the `operand_rl` parameter. |
| 3181 | | // We cannot use `block_scope.break_result_loc` because that has the bare |
| 3182 | | // type, whereas this expression has the optional type. Later we make |
| 3183 | | // up for this fact by calling rvalue on the else branch. |
| 3184 | | block_scope.break_count += 1; |
| 3185 | | |
| 3186 | 3176 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| 3187 | 3177 | .ref => .ref, |
| 3188 | | .discard, .none, .none_or_ref, .block_ptr, .inferred_ptr => .none, |
| 3189 | | .ty => |elem_ty| { |
| 3190 | | @panic("TODO"); |
| 3191 | | }, |
| 3192 | | .ptr => |ptr_ty| { |
| 3193 | | @panic("TODO"); |
| 3194 | | }, |
| 3178 | else => .none, |
| 3195 | 3179 | }; |
| 3196 | | const ops = switch (rl) { |
| 3180 | const err_ops = switch (rl) { |
| 3181 | // zig fmt: off |
| 3197 | 3182 | .ref => [3]Zir.Inst.Tag{ .is_err_ptr, .err_union_code_ptr, .err_union_payload_unsafe_ptr }, |
| 3198 | | else => [3]Zir.Inst.Tag{ .is_err, .err_union_code, .err_union_payload_unsafe }, |
| 3183 | else => [3]Zir.Inst.Tag{ .is_err, .err_union_code, .err_union_payload_unsafe }, |
| 3184 | // zig fmt: on |
| 3199 | 3185 | }; |
| 3186 | // This could be a pointer or value depending on the `operand_rl` parameter. |
| 3187 | // We cannot use `block_scope.break_result_loc` because that has the bare |
| 3188 | // type, whereas this expression has the optional type. Later we make |
| 3189 | // up for this fact by calling rvalue on the else branch. |
| 3200 | 3190 | const operand = try expr(&block_scope, &block_scope.base, operand_rl, node); |
| 3201 | | const cond = try block_scope.addUnNode(ops[0], operand, node); |
| 3191 | const cond = try block_scope.addUnNode(err_ops[0], operand, node); |
| 3202 | 3192 | const condbr = try block_scope.addCondBr(.condbr, node); |
| 3203 | 3193 | |
| 3204 | 3194 | const block = try parent_gz.addBlock(.block, node); |
| ... | ... | @@ -3208,31 +3198,27 @@ fn tryExpr( |
| 3208 | 3198 | var then_scope: GenZir = .{ |
| 3209 | 3199 | .parent = scope, |
| 3210 | 3200 | .decl_node_index = parent_gz.decl_node_index, |
| 3211 | | .astgen = parent_gz.astgen, |
| 3201 | .astgen = astgen, |
| 3212 | 3202 | .force_comptime = block_scope.force_comptime, |
| 3213 | 3203 | .instructions = .{}, |
| 3214 | 3204 | }; |
| 3215 | 3205 | defer then_scope.instructions.deinit(astgen.gpa); |
| 3216 | 3206 | |
| 3217 | | const then_result = try then_scope.addUnNode(ops[1], operand, node); |
| 3218 | | const to_return = try then_scope.addUnNode(.ret_node, then_result, node); |
| 3219 | | |
| 3220 | | block_scope.break_count += 1; |
| 3221 | | // We hold off on the break instructions as well as copying the then/else |
| 3222 | | // instructions into place until we know whether to keep store_to_block_ptr |
| 3223 | | // instructions or not. |
| 3207 | const err_code = try then_scope.addUnNode(err_ops[1], operand, node); |
| 3208 | const then_result = try then_scope.addUnNode(.ret_node, err_code, node); |
| 3224 | 3209 | |
| 3225 | 3210 | var else_scope: GenZir = .{ |
| 3226 | 3211 | .parent = scope, |
| 3227 | 3212 | .decl_node_index = parent_gz.decl_node_index, |
| 3228 | | .astgen = parent_gz.astgen, |
| 3213 | .astgen = astgen, |
| 3229 | 3214 | .force_comptime = block_scope.force_comptime, |
| 3230 | 3215 | .instructions = .{}, |
| 3231 | 3216 | }; |
| 3232 | 3217 | defer else_scope.instructions.deinit(astgen.gpa); |
| 3233 | 3218 | |
| 3234 | | // This could be a pointer or value depending on `unwrap_op`. |
| 3235 | | const unwrapped_payload = try else_scope.addUnNode(ops[2], operand, node); |
| 3219 | block_scope.break_count += 1; |
| 3220 | // This could be a pointer or value depending on `err_ops[2]`. |
| 3221 | const unwrapped_payload = try else_scope.addUnNode(err_ops[2], operand, node); |
| 3236 | 3222 | const else_result = switch (rl) { |
| 3237 | 3223 | .ref => unwrapped_payload, |
| 3238 | 3224 | else => try rvalue(&else_scope, &else_scope.base, block_scope.break_result_loc, unwrapped_payload, node), |
| ... | ... | @@ -3250,7 +3236,7 @@ fn tryExpr( |
| 3250 | 3236 | cond, |
| 3251 | 3237 | node, |
| 3252 | 3238 | node, |
| 3253 | | to_return, |
| 3239 | then_result, |
| 3254 | 3240 | else_result, |
| 3255 | 3241 | block, |
| 3256 | 3242 | block, |
| ... | ... | @@ -3276,19 +3262,13 @@ fn orelseCatchExpr( |
| 3276 | 3262 | var block_scope: GenZir = .{ |
| 3277 | 3263 | .parent = scope, |
| 3278 | 3264 | .decl_node_index = parent_gz.decl_node_index, |
| 3279 | | .astgen = parent_gz.astgen, |
| 3265 | .astgen = astgen, |
| 3280 | 3266 | .force_comptime = parent_gz.force_comptime, |
| 3281 | 3267 | .instructions = .{}, |
| 3282 | 3268 | }; |
| 3283 | 3269 | block_scope.setBreakResultLoc(rl); |
| 3284 | 3270 | defer block_scope.instructions.deinit(astgen.gpa); |
| 3285 | 3271 | |
| 3286 | | // This could be a pointer or value depending on the `operand_rl` parameter. |
| 3287 | | // We cannot use `block_scope.break_result_loc` because that has the bare |
| 3288 | | // type, whereas this expression has the optional type. Later we make |
| 3289 | | // up for this fact by calling rvalue on the else branch. |
| 3290 | | block_scope.break_count += 1; |
| 3291 | | |
| 3292 | 3272 | // TODO handle catch |
| 3293 | 3273 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| 3294 | 3274 | .ref => .ref, |
| ... | ... | @@ -3302,6 +3282,11 @@ fn orelseCatchExpr( |
| 3302 | 3282 | break :blk .{ .ty = wrapped_ty }; |
| 3303 | 3283 | }, |
| 3304 | 3284 | }; |
| 3285 | block_scope.break_count += 1; |
| 3286 | // This could be a pointer or value depending on the `operand_rl` parameter. |
| 3287 | // We cannot use `block_scope.break_result_loc` because that has the bare |
| 3288 | // type, whereas this expression has the optional type. Later we make |
| 3289 | // up for this fact by calling rvalue on the else branch. |
| 3305 | 3290 | const operand = try expr(&block_scope, &block_scope.base, operand_rl, lhs); |
| 3306 | 3291 | const cond = try block_scope.addUnNode(cond_op, operand, node); |
| 3307 | 3292 | const condbr = try block_scope.addCondBr(.condbr, node); |
| ... | ... | @@ -3313,7 +3298,7 @@ fn orelseCatchExpr( |
| 3313 | 3298 | var then_scope: GenZir = .{ |
| 3314 | 3299 | .parent = scope, |
| 3315 | 3300 | .decl_node_index = parent_gz.decl_node_index, |
| 3316 | | .astgen = parent_gz.astgen, |
| 3301 | .astgen = astgen, |
| 3317 | 3302 | .force_comptime = block_scope.force_comptime, |
| 3318 | 3303 | .instructions = .{}, |
| 3319 | 3304 | }; |
| ... | ... | @@ -3345,7 +3330,7 @@ fn orelseCatchExpr( |
| 3345 | 3330 | var else_scope: GenZir = .{ |
| 3346 | 3331 | .parent = scope, |
| 3347 | 3332 | .decl_node_index = parent_gz.decl_node_index, |
| 3348 | | .astgen = parent_gz.astgen, |
| 3333 | .astgen = astgen, |
| 3349 | 3334 | .force_comptime = block_scope.force_comptime, |
| 3350 | 3335 | .instructions = .{}, |
| 3351 | 3336 | }; |
| ... | ... | @@ -3424,12 +3409,12 @@ fn finishThenElseBlock( |
| 3424 | 3409 | } else { |
| 3425 | 3410 | _ = try else_scope.addBreak(break_tag, main_block, .void_value); |
| 3426 | 3411 | } |
| 3412 | const block_ref = parent_gz.indexToRef(main_block); |
| 3427 | 3413 | if (strat.elide_store_to_block_ptr_instructions) { |
| 3428 | | try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, else_scope); |
| 3414 | try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, else_scope, block_ref); |
| 3429 | 3415 | } else { |
| 3430 | 3416 | try setCondBrPayload(condbr, cond, then_scope, else_scope); |
| 3431 | 3417 | } |
| 3432 | | const block_ref = parent_gz.indexToRef(main_block); |
| 3433 | 3418 | switch (rl) { |
| 3434 | 3419 | .ref => return block_ref, |
| 3435 | 3420 | else => return rvalue(parent_gz, parent_scope, rl, block_ref, node), |
| ... | ... | @@ -3758,33 +3743,47 @@ fn setCondBrPayload( |
| 3758 | 3743 | astgen.extra.appendSliceAssumeCapacity(else_scope.instructions.items); |
| 3759 | 3744 | } |
| 3760 | 3745 | |
| 3761 | | /// If `elide_block_store_ptr` is set, expects to find exactly 1 .store_to_block_ptr instruction. |
| 3762 | 3746 | fn setCondBrPayloadElideBlockStorePtr( |
| 3763 | 3747 | condbr: Zir.Inst.Index, |
| 3764 | 3748 | cond: Zir.Inst.Ref, |
| 3765 | 3749 | then_scope: *GenZir, |
| 3766 | 3750 | else_scope: *GenZir, |
| 3751 | main_block: Zir.Inst.Ref, |
| 3767 | 3752 | ) !void { |
| 3768 | 3753 | const astgen = then_scope.astgen; |
| 3769 | 3754 | |
| 3770 | | try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len + |
| 3771 | | @typeInfo(Zir.Inst.CondBr).Struct.fields.len + |
| 3772 | | then_scope.instructions.items.len + else_scope.instructions.items.len - 2); |
| 3755 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + |
| 3756 | then_scope.instructions.items.len + else_scope.instructions.items.len); |
| 3773 | 3757 | |
| 3758 | const zir_tags = astgen.instructions.items(.tag); |
| 3774 | 3759 | const zir_datas = astgen.instructions.items(.data); |
| 3775 | | zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ |
| 3760 | |
| 3761 | const condbr_pl = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ |
| 3776 | 3762 | .condition = cond, |
| 3777 | | .then_body_len = @intCast(u32, then_scope.instructions.items.len - 1), |
| 3778 | | .else_body_len = @intCast(u32, else_scope.instructions.items.len - 1), |
| 3763 | .then_body_len = @intCast(u32, then_scope.instructions.items.len), |
| 3764 | .else_body_len = @intCast(u32, else_scope.instructions.items.len), |
| 3779 | 3765 | }); |
| 3780 | | |
| 3781 | | const zir_tags = astgen.instructions.items(.tag); |
| 3782 | | for ([_]*GenZir{ then_scope, else_scope }) |scope| { |
| 3783 | | for (scope.instructions.items) |src_inst| { |
| 3784 | | if (zir_tags[src_inst] != .store_to_block_ptr) { |
| 3785 | | astgen.extra.appendAssumeCapacity(src_inst); |
| 3766 | zir_datas[condbr].pl_node.payload_index = condbr_pl; |
| 3767 | const then_body_len_index = condbr_pl + 1; |
| 3768 | const else_body_len_index = condbr_pl + 2; |
| 3769 | |
| 3770 | for (then_scope.instructions.items) |src_inst| { |
| 3771 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 3772 | if (zir_datas[src_inst].bin.lhs == main_block) { |
| 3773 | astgen.extra.items[then_body_len_index] -= 1; |
| 3774 | continue; |
| 3775 | } |
| 3776 | } |
| 3777 | astgen.extra.appendAssumeCapacity(src_inst); |
| 3778 | } |
| 3779 | for (else_scope.instructions.items) |src_inst| { |
| 3780 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 3781 | if (zir_datas[src_inst].bin.lhs == main_block) { |
| 3782 | astgen.extra.items[else_body_len_index] -= 1; |
| 3783 | continue; |
| 3786 | 3784 | } |
| 3787 | 3785 | } |
| 3786 | astgen.extra.appendAssumeCapacity(src_inst); |
| 3788 | 3787 | } |
| 3789 | 3788 | } |
| 3790 | 3789 | |