authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-24 11:40:15-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-24 21:47:53-07:00
log8bb679bc6e25d1f7c08bb4e5e5272ae5f27aed47
tree8c43d6c8bc7d0358a89c3af236dc75d57244c7a5
parent65576ea2ea8f0d1bcbd1b60dce115c25fc4647ad

Sema: resolveBody takes a parameter for break blocks

Previously, break instructions which wanted to break out of multiple nesting layers did not work correctly at comptime.

2 files changed, 45 insertions(+), 36 deletions(-)

src/Sema.zig+43-36
...@@ -487,20 +487,23 @@ pub fn deinit(sema: *Sema) void {...@@ -487,20 +487,23 @@ pub fn deinit(sema: *Sema) void {
487/// Returns only the result from the body that is specified.487/// Returns only the result from the body that is specified.
488/// Only appropriate to call when it is determined at comptime that this body488/// Only appropriate to call when it is determined at comptime that this body
489/// has no peers.489/// has no peers.
490fn resolveBody(sema: *Sema, block: *Block, body: []const Zir.Inst.Index) CompileError!Air.Inst.Ref {490fn resolveBody(
491 sema: *Sema,
492 block: *Block,
493 body: []const Zir.Inst.Index,
494 /// This is the instruction that a break instruction within `body` can
495 /// use to return from the body.
496 body_inst: Zir.Inst.Index,
497) CompileError!Air.Inst.Ref {
491 const break_inst = try sema.analyzeBody(block, body);498 const break_inst = try sema.analyzeBody(block, body);
492 const break_data = sema.code.instructions.items(.data)[break_inst].@"break";499 const break_data = sema.code.instructions.items(.data)[break_inst].@"break";
493 // For comptime control flow, we need to detect when `analyzeBody` reports500 // For comptime control flow, we need to detect when `analyzeBody` reports
494 // that we need to break from an outer block. In such case we501 // that we need to break from an outer block. In such case we
495 // use Zig's error mechanism to send control flow up the stack until502 // use Zig's error mechanism to send control flow up the stack until
496 // we find the corresponding block to this break.503 // we find the corresponding block to this break.
497 if (block.is_comptime) {504 if (block.is_comptime and break_data.block_inst != body_inst) {
498 if (block.label) |label| {505 sema.comptime_break_inst = break_inst;
499 if (label.zir_block != break_data.block_inst) {506 return error.ComptimeBreak;
500 sema.comptime_break_inst = break_inst;
501 return error.ComptimeBreak;
502 }
503 }
504 }507 }
505 return sema.resolveInst(break_data.operand);508 return sema.resolveInst(break_data.operand);
506}509}
...@@ -3508,10 +3511,13 @@ fn resolveBlockBody(...@@ -3508,10 +3511,13 @@ fn resolveBlockBody(
3508 src: LazySrcLoc,3511 src: LazySrcLoc,
3509 child_block: *Block,3512 child_block: *Block,
3510 body: []const Zir.Inst.Index,3513 body: []const Zir.Inst.Index,
3514 /// This is the instruction that a break instruction within `body` can
3515 /// use to return from the body.
3516 body_inst: Zir.Inst.Index,
3511 merges: *Block.Merges,3517 merges: *Block.Merges,
3512) CompileError!Air.Inst.Ref {3518) CompileError!Air.Inst.Ref {
3513 if (child_block.is_comptime) {3519 if (child_block.is_comptime) {
3514 return sema.resolveBody(child_block, body);3520 return sema.resolveBody(child_block, body, body_inst);
3515 } else {3521 } else {
3516 _ = try sema.analyzeBody(child_block, body);3522 _ = try sema.analyzeBody(child_block, body);
3517 return sema.analyzeBlockBody(parent_block, src, child_block, merges);3523 return sema.analyzeBlockBody(parent_block, src, child_block, merges);
...@@ -4251,7 +4257,7 @@ fn analyzeCall(...@@ -4251,7 +4257,7 @@ fn analyzeCall(
4251 const param_src = pl_tok.src();4257 const param_src = pl_tok.src();
4252 const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index);4258 const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index);
4253 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];4259 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];
4254 const param_ty_inst = try sema.resolveBody(&child_block, param_body);4260 const param_ty_inst = try sema.resolveBody(&child_block, param_body, inst);
4255 const param_ty = try sema.analyzeAsType(&child_block, param_src, param_ty_inst);4261 const param_ty = try sema.analyzeAsType(&child_block, param_src, param_ty_inst);
4256 const arg_src = call_src; // TODO: better source location4262 const arg_src = call_src; // TODO: better source location
4257 const casted_arg = try sema.coerce(&child_block, param_ty, uncasted_args[arg_i], arg_src);4263 const casted_arg = try sema.coerce(&child_block, param_ty, uncasted_args[arg_i], arg_src);
...@@ -4308,7 +4314,7 @@ fn analyzeCall(...@@ -4308,7 +4314,7 @@ fn analyzeCall(
4308 // on parameters, we must now do the same for the return type as we just did with4314 // on parameters, we must now do the same for the return type as we just did with
4309 // each of the parameters, resolving the return type and providing it to the child4315 // each of the parameters, resolving the return type and providing it to the child
4310 // `Sema` so that it can be used for the `ret_ptr` instruction.4316 // `Sema` so that it can be used for the `ret_ptr` instruction.
4311 const ret_ty_inst = try sema.resolveBody(&child_block, fn_info.ret_ty_body);4317 const ret_ty_inst = try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst);
4312 const ret_ty_src = func_src; // TODO better source location4318 const ret_ty_src = func_src; // TODO better source location
4313 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);4319 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);
4314 // Create a fresh inferred error set type for inline/comptime calls.4320 // Create a fresh inferred error set type for inline/comptime calls.
...@@ -4589,7 +4595,7 @@ fn analyzeCall(...@@ -4589,7 +4595,7 @@ fn analyzeCall(
4589 }4595 }
4590 arg_i += 1;4596 arg_i += 1;
4591 }4597 }
4592 const new_func_inst = child_sema.resolveBody(&child_block, fn_info.param_body) catch |err| {4598 const new_func_inst = child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst) catch |err| {
4593 // TODO look up the compile error that happened here and attach a note to it4599 // TODO look up the compile error that happened here and attach a note to it
4594 // pointing here, at the generic instantiation callsite.4600 // pointing here, at the generic instantiation callsite.
4595 if (sema.owner_func) |owner_func| {4601 if (sema.owner_func) |owner_func| {
...@@ -5388,10 +5394,9 @@ fn zirFunc(...@@ -5388,10 +5394,9 @@ fn zirFunc(
5388 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];5394 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
5389 extra_index += ret_ty_body.len;5395 extra_index += ret_ty_body.len;
53905396
5391 var body_inst: Zir.Inst.Index = 0;
5392 var src_locs: Zir.Inst.Func.SrcLocs = undefined;5397 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
5393 if (extra.data.body_len != 0) {5398 const has_body = extra.data.body_len != 0;
5394 body_inst = inst;5399 if (has_body) {
5395 extra_index += extra.data.body_len;5400 extra_index += extra.data.body_len;
5396 src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;5401 src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
5397 }5402 }
...@@ -5404,13 +5409,14 @@ fn zirFunc(...@@ -5404,13 +5409,14 @@ fn zirFunc(
5404 return sema.funcCommon(5409 return sema.funcCommon(
5405 block,5410 block,
5406 inst_data.src_node,5411 inst_data.src_node,
5407 body_inst,5412 inst,
5408 ret_ty_body,5413 ret_ty_body,
5409 cc,5414 cc,
5410 Value.@"null",5415 Value.@"null",
5411 false,5416 false,
5412 inferred_error_set,5417 inferred_error_set,
5413 false,5418 false,
5419 has_body,
5414 src_locs,5420 src_locs,
5415 null,5421 null,
5416 );5422 );
...@@ -5420,13 +5426,14 @@ fn funcCommon(...@@ -5420,13 +5426,14 @@ fn funcCommon(
5420 sema: *Sema,5426 sema: *Sema,
5421 block: *Block,5427 block: *Block,
5422 src_node_offset: i32,5428 src_node_offset: i32,
5423 body_inst: Zir.Inst.Index,5429 func_inst: Zir.Inst.Index,
5424 ret_ty_body: []const Zir.Inst.Index,5430 ret_ty_body: []const Zir.Inst.Index,
5425 cc: std.builtin.CallingConvention,5431 cc: std.builtin.CallingConvention,
5426 align_val: Value,5432 align_val: Value,
5427 var_args: bool,5433 var_args: bool,
5428 inferred_error_set: bool,5434 inferred_error_set: bool,
5429 is_extern: bool,5435 is_extern: bool,
5436 has_body: bool,
5430 src_locs: Zir.Inst.Func.SrcLocs,5437 src_locs: Zir.Inst.Func.SrcLocs,
5431 opt_lib_name: ?[]const u8,5438 opt_lib_name: ?[]const u8,
5432) CompileError!Air.Inst.Ref {5439) CompileError!Air.Inst.Ref {
...@@ -5447,7 +5454,7 @@ fn funcCommon(...@@ -5447,7 +5454,7 @@ fn funcCommon(
5447 block.params.deinit(sema.gpa);5454 block.params.deinit(sema.gpa);
5448 block.params = prev_params;5455 block.params = prev_params;
5449 }5456 }
5450 if (sema.resolveBody(block, ret_ty_body)) |ret_ty_inst| {5457 if (sema.resolveBody(block, ret_ty_body, func_inst)) |ret_ty_inst| {
5451 if (sema.analyzeAsType(block, ret_ty_src, ret_ty_inst)) |ret_ty| {5458 if (sema.analyzeAsType(block, ret_ty_src, ret_ty_inst)) |ret_ty| {
5452 break :ret_ty ret_ty;5459 break :ret_ty ret_ty;
5453 } else |err| break :err err;5460 } else |err| break :err err;
...@@ -5466,15 +5473,15 @@ fn funcCommon(...@@ -5466,15 +5473,15 @@ fn funcCommon(
5466 const mod = sema.mod;5473 const mod = sema.mod;
54675474
5468 const new_func: *Module.Fn = new_func: {5475 const new_func: *Module.Fn = new_func: {
5469 if (body_inst == 0) break :new_func undefined;5476 if (!has_body) break :new_func undefined;
5470 if (sema.comptime_args_fn_inst == body_inst) {5477 if (sema.comptime_args_fn_inst == func_inst) {
5471 const new_func = sema.preallocated_new_func.?;5478 const new_func = sema.preallocated_new_func.?;
5472 sema.preallocated_new_func = null; // take ownership5479 sema.preallocated_new_func = null; // take ownership
5473 break :new_func new_func;5480 break :new_func new_func;
5474 }5481 }
5475 break :new_func try sema.gpa.create(Module.Fn);5482 break :new_func try sema.gpa.create(Module.Fn);
5476 };5483 };
5477 errdefer if (body_inst != 0) sema.gpa.destroy(new_func);5484 errdefer if (has_body) sema.gpa.destroy(new_func);
54785485
5479 var maybe_inferred_error_set_node: ?*Module.Fn.InferredErrorSetListNode = null;5486 var maybe_inferred_error_set_node: ?*Module.Fn.InferredErrorSetListNode = null;
5480 errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node);5487 errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node);
...@@ -5599,21 +5606,21 @@ fn funcCommon(...@@ -5599,21 +5606,21 @@ fn funcCommon(
5599 );5606 );
5600 }5607 }
56015608
5602 if (body_inst == 0) {5609 if (!has_body) {
5603 return sema.addType(fn_ty);5610 return sema.addType(fn_ty);
5604 }5611 }
56055612
5606 const is_inline = fn_ty.fnCallingConvention() == .Inline;5613 const is_inline = fn_ty.fnCallingConvention() == .Inline;
5607 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .queued;5614 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .queued;
56085615
5609 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == body_inst) blk: {5616 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {
5610 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;5617 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;
5611 } else null;5618 } else null;
56125619
5613 const fn_payload = try sema.arena.create(Value.Payload.Function);5620 const fn_payload = try sema.arena.create(Value.Payload.Function);
5614 new_func.* = .{5621 new_func.* = .{
5615 .state = anal_state,5622 .state = anal_state,
5616 .zir_body_inst = body_inst,5623 .zir_body_inst = func_inst,
5617 .owner_decl = sema.owner_decl,5624 .owner_decl = sema.owner_decl,
5618 .comptime_args = comptime_args,5625 .comptime_args = comptime_args,
5619 .lbrace_line = src_locs.lbrace_line,5626 .lbrace_line = src_locs.lbrace_line,
...@@ -5660,7 +5667,7 @@ fn zirParam(...@@ -5660,7 +5667,7 @@ fn zirParam(
5660 block.params = prev_params;5667 block.params = prev_params;
5661 }5668 }
56625669
5663 if (sema.resolveBody(block, body)) |param_ty_inst| {5670 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {
5664 if (sema.analyzeAsType(block, src, param_ty_inst)) |param_ty| {5671 if (sema.analyzeAsType(block, src, param_ty_inst)) |param_ty| {
5665 break :param_ty param_ty;5672 break :param_ty param_ty;
5666 } else |err| break :err err;5673 } else |err| break :err err;
...@@ -6809,7 +6816,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -6809,7 +6816,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
6809 // Validation above ensured these will succeed.6816 // Validation above ensured these will succeed.
6810 const item_val = sema.resolveConstValue(&child_block, .unneeded, item) catch unreachable;6817 const item_val = sema.resolveConstValue(&child_block, .unneeded, item) catch unreachable;
6811 if (operand_val.eql(item_val, operand_ty)) {6818 if (operand_val.eql(item_val, operand_ty)) {
6812 return sema.resolveBlockBody(block, src, &child_block, body, merges);6819 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
6813 }6820 }
6814 }6821 }
6815 }6822 }
...@@ -6831,7 +6838,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -6831,7 +6838,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
6831 // Validation above ensured these will succeed.6838 // Validation above ensured these will succeed.
6832 const item_val = sema.resolveConstValue(&child_block, .unneeded, item) catch unreachable;6839 const item_val = sema.resolveConstValue(&child_block, .unneeded, item) catch unreachable;
6833 if (operand_val.eql(item_val, operand_ty)) {6840 if (operand_val.eql(item_val, operand_ty)) {
6834 return sema.resolveBlockBody(block, src, &child_block, body, merges);6841 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
6835 }6842 }
6836 }6843 }
68376844
...@@ -6848,18 +6855,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -6848,18 +6855,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
6848 if (Value.compare(operand_val, .gte, first_tv.val, operand_ty) and6855 if (Value.compare(operand_val, .gte, first_tv.val, operand_ty) and
6849 Value.compare(operand_val, .lte, last_tv.val, operand_ty))6856 Value.compare(operand_val, .lte, last_tv.val, operand_ty))
6850 {6857 {
6851 return sema.resolveBlockBody(block, src, &child_block, body, merges);6858 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
6852 }6859 }
6853 }6860 }
68546861
6855 extra_index += body_len;6862 extra_index += body_len;
6856 }6863 }
6857 }6864 }
6858 return sema.resolveBlockBody(block, src, &child_block, special.body, merges);6865 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
6859 }6866 }
68606867
6861 if (scalar_cases_len + multi_cases_len == 0) {6868 if (scalar_cases_len + multi_cases_len == 0) {
6862 return sema.resolveBlockBody(block, src, &child_block, special.body, merges);6869 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
6863 }6870 }
68646871
6865 try sema.requireRuntimeBlock(block, src);6872 try sema.requireRuntimeBlock(block, src);
...@@ -10038,7 +10045,7 @@ fn zirBoolBr(...@@ -10038,7 +10045,7 @@ fn zirBoolBr(
10038 // comptime-known left-hand side. No need for a block here; the result10045 // comptime-known left-hand side. No need for a block here; the result
10039 // is simply the rhs expression. Here we rely on there only being 110046 // is simply the rhs expression. Here we rely on there only being 1
10040 // break instruction (`break_inline`).10047 // break instruction (`break_inline`).
10041 return sema.resolveBody(parent_block, body);10048 return sema.resolveBody(parent_block, body, inst);
10042 }10049 }
1004310050
10044 const block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);10051 const block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);
...@@ -10068,7 +10075,7 @@ fn zirBoolBr(...@@ -10068,7 +10075,7 @@ fn zirBoolBr(
10068 const lhs_result: Air.Inst.Ref = if (is_bool_or) .bool_true else .bool_false;10075 const lhs_result: Air.Inst.Ref = if (is_bool_or) .bool_true else .bool_false;
10069 _ = try lhs_block.addBr(block_inst, lhs_result);10076 _ = try lhs_block.addBr(block_inst, lhs_result);
1007010077
10071 const rhs_result = try sema.resolveBody(rhs_block, body);10078 const rhs_result = try sema.resolveBody(rhs_block, body, inst);
10072 _ = try rhs_block.addBr(block_inst, rhs_result);10079 _ = try rhs_block.addBr(block_inst, rhs_result);
1007310080
10074 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len +10081 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len +
...@@ -12419,10 +12426,9 @@ fn zirFuncExtended(...@@ -12419,10 +12426,9 @@ fn zirFuncExtended(
12419 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];12426 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
12420 extra_index += ret_ty_body.len;12427 extra_index += ret_ty_body.len;
1242112428
12422 var body_inst: Zir.Inst.Index = 0;
12423 var src_locs: Zir.Inst.Func.SrcLocs = undefined;12429 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
12424 if (extra.data.body_len != 0) {12430 const has_body = extra.data.body_len != 0;
12425 body_inst = inst;12431 if (has_body) {
12426 extra_index += extra.data.body_len;12432 extra_index += extra.data.body_len;
12427 src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;12433 src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
12428 }12434 }
...@@ -12434,13 +12440,14 @@ fn zirFuncExtended(...@@ -12434,13 +12440,14 @@ fn zirFuncExtended(
12434 return sema.funcCommon(12440 return sema.funcCommon(
12435 block,12441 block,
12436 extra.data.src_node,12442 extra.data.src_node,
12437 body_inst,12443 inst,
12438 ret_ty_body,12444 ret_ty_body,
12439 cc,12445 cc,
12440 align_val,12446 align_val,
12441 is_var_args,12447 is_var_args,
12442 is_inferred_error,12448 is_inferred_error,
12443 is_extern,12449 is_extern,
12450 has_body,
12444 src_locs,12451 src_locs,
12445 lib_name,12452 lib_name,
12446 );12453 );
src/Zir.zig+2
...@@ -3273,6 +3273,7 @@ fn findDeclsBody(...@@ -3273,6 +3273,7 @@ fn findDeclsBody(
32733273
3274pub const FnInfo = struct {3274pub const FnInfo = struct {
3275 param_body: []const Inst.Index,3275 param_body: []const Inst.Index,
3276 param_body_inst: Inst.Index,
3276 ret_ty_body: []const Inst.Index,3277 ret_ty_body: []const Inst.Index,
3277 body: []const Inst.Index,3278 body: []const Inst.Index,
3278 total_params_len: u32,3279 total_params_len: u32,
...@@ -3338,6 +3339,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -3338,6 +3339,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
3338 }3339 }
3339 return .{3340 return .{
3340 .param_body = param_body,3341 .param_body = param_body,
3342 .param_body_inst = info.param_block,
3341 .ret_ty_body = info.ret_ty_body,3343 .ret_ty_body = info.ret_ty_body,
3342 .body = info.body,3344 .body = info.body,
3343 .total_params_len = total_params_len,3345 .total_params_len = total_params_len,