authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-20 11:16:50-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-20 11:16:50-07:00
logb4baa9eda2b4398d9fe0ea5847a8bb8dfdd16ba4
tree59ae577a349cb951e9548f1b3dd8f952ebcabf7b
parentee3c1c763c8201d31321643f72cd1506c369dd71

AstGen: `try` fixups

Primarily this required fixing `setCondBrPayloadElideBlockStorePtr` to not assume there would always be two `store_to_block_ptr` instructions in each of the condbr prongs.

1 files changed, 56 insertions(+), 57 deletions(-)

src/AstGen.zig+56-57
...@@ -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);
31693165
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);
31793175
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);
32033193
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);
32163206
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.
32243209
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);
32333218
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);
32853271
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 catch3272 // 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}
37603745
3761/// If `elide_block_store_ptr` is set, expects to find exactly 1 .store_to_block_ptr instruction.
3762fn setCondBrPayloadElideBlockStorePtr(3746fn 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;
37693754
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);
37733757
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 });
37803766 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}
37903789