| ... | @@ -3162,43 +3162,33 @@ fn tryExpr( | ... | @@ -3162,43 +3162,33 @@ fn tryExpr( |
| 3162 | ) InnerError!Zir.Inst.Ref { | 3162 | ) InnerError!Zir.Inst.Ref { |
| 3163 | const astgen = parent_gz.astgen; | 3163 | const astgen = parent_gz.astgen; |
| 3164 | const tree = &astgen.file.tree; | 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 | var block_scope: GenZir = .{ | 3166 | var block_scope: GenZir = .{ |
| 3171 | .parent = scope, | 3167 | .parent = scope, |
| 3172 | .decl_node_index = parent_gz.decl_node_index, | 3168 | .decl_node_index = parent_gz.decl_node_index, |
| 3173 | .astgen = parent_gz.astgen, | 3169 | .astgen = astgen, |
| 3174 | .force_comptime = parent_gz.force_comptime, | 3170 | .force_comptime = parent_gz.force_comptime, |
| 3175 | .instructions = .{}, | 3171 | .instructions = .{}, |
| 3176 | }; | 3172 | }; |
| 3177 | block_scope.setBreakResultLoc(rl); | 3173 | block_scope.setBreakResultLoc(rl); |
| 3178 | defer block_scope.instructions.deinit(astgen.gpa); | 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 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { | 3176 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| 3187 | .ref => .ref, | 3177 | .ref => .ref, |
| 3188 | .discard, .none, .none_or_ref, .block_ptr, .inferred_ptr => .none, | 3178 | else => .none, |
| 3189 | .ty => |elem_ty| { | | |
| 3190 | @panic("TODO"); | | |
| 3191 | }, | | |
| 3192 | .ptr => |ptr_ty| { | | |
| 3193 | @panic("TODO"); | | |
| 3194 | }, | | |
| 3195 | }; | 3179 | }; |
| 3196 | const ops = switch (rl) { | 3180 | const err_ops = switch (rl) { |
| | 3181 | // zig fmt: off |
| 3197 | .ref => [3]Zir.Inst.Tag{ .is_err_ptr, .err_union_code_ptr, .err_union_payload_unsafe_ptr }, | 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 | const operand = try expr(&block_scope, &block_scope.base, operand_rl, node); | 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 | const condbr = try block_scope.addCondBr(.condbr, node); | 3192 | const condbr = try block_scope.addCondBr(.condbr, node); |
| 3203 | | 3193 | |
| 3204 | const block = try parent_gz.addBlock(.block, node); | 3194 | const block = try parent_gz.addBlock(.block, node); |
| ... | @@ -3208,31 +3198,27 @@ fn tryExpr( | ... | @@ -3208,31 +3198,27 @@ fn tryExpr( |
| 3208 | var then_scope: GenZir = .{ | 3198 | var then_scope: GenZir = .{ |
| 3209 | .parent = scope, | 3199 | .parent = scope, |
| 3210 | .decl_node_index = parent_gz.decl_node_index, | 3200 | .decl_node_index = parent_gz.decl_node_index, |
| 3211 | .astgen = parent_gz.astgen, | 3201 | .astgen = astgen, |
| 3212 | .force_comptime = block_scope.force_comptime, | 3202 | .force_comptime = block_scope.force_comptime, |
| 3213 | .instructions = .{}, | 3203 | .instructions = .{}, |
| 3214 | }; | 3204 | }; |
| 3215 | defer then_scope.instructions.deinit(astgen.gpa); | 3205 | defer then_scope.instructions.deinit(astgen.gpa); |
| 3216 | | 3206 | |
| 3217 | const then_result = try then_scope.addUnNode(ops[1], operand, node); | 3207 | const err_code = try then_scope.addUnNode(err_ops[1], operand, node); |
| 3218 | const to_return = try then_scope.addUnNode(.ret_node, then_result, node); | 3208 | const then_result = try then_scope.addUnNode(.ret_node, err_code, 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. | | |
| 3224 | | 3209 | |
| 3225 | var else_scope: GenZir = .{ | 3210 | var else_scope: GenZir = .{ |
| 3226 | .parent = scope, | 3211 | .parent = scope, |
| 3227 | .decl_node_index = parent_gz.decl_node_index, | 3212 | .decl_node_index = parent_gz.decl_node_index, |
| 3228 | .astgen = parent_gz.astgen, | 3213 | .astgen = astgen, |
| 3229 | .force_comptime = block_scope.force_comptime, | 3214 | .force_comptime = block_scope.force_comptime, |
| 3230 | .instructions = .{}, | 3215 | .instructions = .{}, |
| 3231 | }; | 3216 | }; |
| 3232 | defer else_scope.instructions.deinit(astgen.gpa); | 3217 | defer else_scope.instructions.deinit(astgen.gpa); |
| 3233 | | 3218 | |
| 3234 | // This could be a pointer or value depending on `unwrap_op`. | 3219 | block_scope.break_count += 1; |
| 3235 | const unwrapped_payload = try else_scope.addUnNode(ops[2], operand, node); | 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 | const else_result = switch (rl) { | 3222 | const else_result = switch (rl) { |
| 3237 | .ref => unwrapped_payload, | 3223 | .ref => unwrapped_payload, |
| 3238 | else => try rvalue(&else_scope, &else_scope.base, block_scope.break_result_loc, unwrapped_payload, node), | 3224 | else => try rvalue(&else_scope, &else_scope.base, block_scope.break_result_loc, unwrapped_payload, node), |
| ... | @@ -3250,7 +3236,7 @@ fn tryExpr( | ... | @@ -3250,7 +3236,7 @@ fn tryExpr( |
| 3250 | cond, | 3236 | cond, |
| 3251 | node, | 3237 | node, |
| 3252 | node, | 3238 | node, |
| 3253 | to_return, | 3239 | then_result, |
| 3254 | else_result, | 3240 | else_result, |
| 3255 | block, | 3241 | block, |
| 3256 | block, | 3242 | block, |
| ... | @@ -3276,19 +3262,13 @@ fn orelseCatchExpr( | ... | @@ -3276,19 +3262,13 @@ fn orelseCatchExpr( |
| 3276 | var block_scope: GenZir = .{ | 3262 | var block_scope: GenZir = .{ |
| 3277 | .parent = scope, | 3263 | .parent = scope, |
| 3278 | .decl_node_index = parent_gz.decl_node_index, | 3264 | .decl_node_index = parent_gz.decl_node_index, |
| 3279 | .astgen = parent_gz.astgen, | 3265 | .astgen = astgen, |
| 3280 | .force_comptime = parent_gz.force_comptime, | 3266 | .force_comptime = parent_gz.force_comptime, |
| 3281 | .instructions = .{}, | 3267 | .instructions = .{}, |
| 3282 | }; | 3268 | }; |
| 3283 | block_scope.setBreakResultLoc(rl); | 3269 | block_scope.setBreakResultLoc(rl); |
| 3284 | defer block_scope.instructions.deinit(astgen.gpa); | 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 | // TODO handle catch | 3272 | // TODO handle catch |
| 3293 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { | 3273 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| 3294 | .ref => .ref, | 3274 | .ref => .ref, |
| ... | @@ -3302,6 +3282,11 @@ fn orelseCatchExpr( | ... | @@ -3302,6 +3282,11 @@ fn orelseCatchExpr( |
| 3302 | break :blk .{ .ty = wrapped_ty }; | 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 | const operand = try expr(&block_scope, &block_scope.base, operand_rl, lhs); | 3290 | const operand = try expr(&block_scope, &block_scope.base, operand_rl, lhs); |
| 3306 | const cond = try block_scope.addUnNode(cond_op, operand, node); | 3291 | const cond = try block_scope.addUnNode(cond_op, operand, node); |
| 3307 | const condbr = try block_scope.addCondBr(.condbr, node); | 3292 | const condbr = try block_scope.addCondBr(.condbr, node); |
| ... | @@ -3313,7 +3298,7 @@ fn orelseCatchExpr( | ... | @@ -3313,7 +3298,7 @@ fn orelseCatchExpr( |
| 3313 | var then_scope: GenZir = .{ | 3298 | var then_scope: GenZir = .{ |
| 3314 | .parent = scope, | 3299 | .parent = scope, |
| 3315 | .decl_node_index = parent_gz.decl_node_index, | 3300 | .decl_node_index = parent_gz.decl_node_index, |
| 3316 | .astgen = parent_gz.astgen, | 3301 | .astgen = astgen, |
| 3317 | .force_comptime = block_scope.force_comptime, | 3302 | .force_comptime = block_scope.force_comptime, |
| 3318 | .instructions = .{}, | 3303 | .instructions = .{}, |
| 3319 | }; | 3304 | }; |
| ... | @@ -3345,7 +3330,7 @@ fn orelseCatchExpr( | ... | @@ -3345,7 +3330,7 @@ fn orelseCatchExpr( |
| 3345 | var else_scope: GenZir = .{ | 3330 | var else_scope: GenZir = .{ |
| 3346 | .parent = scope, | 3331 | .parent = scope, |
| 3347 | .decl_node_index = parent_gz.decl_node_index, | 3332 | .decl_node_index = parent_gz.decl_node_index, |
| 3348 | .astgen = parent_gz.astgen, | 3333 | .astgen = astgen, |
| 3349 | .force_comptime = block_scope.force_comptime, | 3334 | .force_comptime = block_scope.force_comptime, |
| 3350 | .instructions = .{}, | 3335 | .instructions = .{}, |
| 3351 | }; | 3336 | }; |
| ... | @@ -3424,12 +3409,12 @@ fn finishThenElseBlock( | ... | @@ -3424,12 +3409,12 @@ fn finishThenElseBlock( |
| 3424 | } else { | 3409 | } else { |
| 3425 | _ = try else_scope.addBreak(break_tag, main_block, .void_value); | 3410 | _ = try else_scope.addBreak(break_tag, main_block, .void_value); |
| 3426 | } | 3411 | } |
| | 3412 | const block_ref = parent_gz.indexToRef(main_block); |
| 3427 | if (strat.elide_store_to_block_ptr_instructions) { | 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 | } else { | 3415 | } else { |
| 3430 | try setCondBrPayload(condbr, cond, then_scope, else_scope); | 3416 | try setCondBrPayload(condbr, cond, then_scope, else_scope); |
| 3431 | } | 3417 | } |
| 3432 | const block_ref = parent_gz.indexToRef(main_block); | | |
| 3433 | switch (rl) { | 3418 | switch (rl) { |
| 3434 | .ref => return block_ref, | 3419 | .ref => return block_ref, |
| 3435 | else => return rvalue(parent_gz, parent_scope, rl, block_ref, node), | 3420 | else => return rvalue(parent_gz, parent_scope, rl, block_ref, node), |
| ... | @@ -3758,33 +3743,47 @@ fn setCondBrPayload( | ... | @@ -3758,33 +3743,47 @@ fn setCondBrPayload( |
| 3758 | astgen.extra.appendSliceAssumeCapacity(else_scope.instructions.items); | 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 | fn setCondBrPayloadElideBlockStorePtr( | 3746 | fn setCondBrPayloadElideBlockStorePtr( |
| 3763 | condbr: Zir.Inst.Index, | 3747 | condbr: Zir.Inst.Index, |
| 3764 | cond: Zir.Inst.Ref, | 3748 | cond: Zir.Inst.Ref, |
| 3765 | then_scope: *GenZir, | 3749 | then_scope: *GenZir, |
| 3766 | else_scope: *GenZir, | 3750 | else_scope: *GenZir, |
| | 3751 | main_block: Zir.Inst.Ref, |
| 3767 | ) !void { | 3752 | ) !void { |
| 3768 | const astgen = then_scope.astgen; | 3753 | const astgen = then_scope.astgen; |
| 3769 | | 3754 | |
| 3770 | try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len + | 3755 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + |
| 3771 | @typeInfo(Zir.Inst.CondBr).Struct.fields.len + | 3756 | then_scope.instructions.items.len + else_scope.instructions.items.len); |
| 3772 | then_scope.instructions.items.len + else_scope.instructions.items.len - 2); | | |
| 3773 | | 3757 | |
| | 3758 | const zir_tags = astgen.instructions.items(.tag); |
| 3774 | const zir_datas = astgen.instructions.items(.data); | 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 | .condition = cond, | 3762 | .condition = cond, |
| 3777 | .then_body_len = @intCast(u32, then_scope.instructions.items.len - 1), | 3763 | .then_body_len = @intCast(u32, then_scope.instructions.items.len), |
| 3778 | .else_body_len = @intCast(u32, else_scope.instructions.items.len - 1), | 3764 | .else_body_len = @intCast(u32, else_scope.instructions.items.len), |
| 3779 | }); | 3765 | }); |
| 3780 | | 3766 | zir_datas[condbr].pl_node.payload_index = condbr_pl; |
| 3781 | const zir_tags = astgen.instructions.items(.tag); | 3767 | const then_body_len_index = condbr_pl + 1; |
| 3782 | for ([_]*GenZir{ then_scope, else_scope }) |scope| { | 3768 | const else_body_len_index = condbr_pl + 2; |
| 3783 | for (scope.instructions.items) |src_inst| { | 3769 | |
| 3784 | if (zir_tags[src_inst] != .store_to_block_ptr) { | 3770 | for (then_scope.instructions.items) |src_inst| { |
| 3785 | astgen.extra.appendAssumeCapacity(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 | |