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 {
487487/// Returns only the result from the body that is specified.
488488/// Only appropriate to call when it is determined at comptime that this body
489489/// 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 {
491498 const break_inst = try sema.analyzeBody(block, body);
492499 const break_data = sema.code.instructions.items(.data)[break_inst].@"break";
493500 // For comptime control flow, we need to detect when `analyzeBody` reports
494501 // that we need to break from an outer block. In such case we
495502 // use Zig's error mechanism to send control flow up the stack until
496503 // we find the corresponding block to this break.
497 if (block.is_comptime) {
498 if (block.label) |label| {
499 if (label.zir_block != break_data.block_inst) {
500 sema.comptime_break_inst = break_inst;
501 return error.ComptimeBreak;
502 }
503 }
504 if (block.is_comptime and break_data.block_inst != body_inst) {
505 sema.comptime_break_inst = break_inst;
506 return error.ComptimeBreak;
504507 }
505508 return sema.resolveInst(break_data.operand);
506509}
......@@ -3508,10 +3511,13 @@ fn resolveBlockBody(
35083511 src: LazySrcLoc,
35093512 child_block: *Block,
35103513 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,
35113517 merges: *Block.Merges,
35123518) CompileError!Air.Inst.Ref {
35133519 if (child_block.is_comptime) {
3514 return sema.resolveBody(child_block, body);
3520 return sema.resolveBody(child_block, body, body_inst);
35153521 } else {
35163522 _ = try sema.analyzeBody(child_block, body);
35173523 return sema.analyzeBlockBody(parent_block, src, child_block, merges);
......@@ -4251,7 +4257,7 @@ fn analyzeCall(
42514257 const param_src = pl_tok.src();
42524258 const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index);
42534259 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);
42554261 const param_ty = try sema.analyzeAsType(&child_block, param_src, param_ty_inst);
42564262 const arg_src = call_src; // TODO: better source location
42574263 const casted_arg = try sema.coerce(&child_block, param_ty, uncasted_args[arg_i], arg_src);
......@@ -4308,7 +4314,7 @@ fn analyzeCall(
43084314 // on parameters, we must now do the same for the return type as we just did with
43094315 // each of the parameters, resolving the return type and providing it to the child
43104316 // `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);
43124318 const ret_ty_src = func_src; // TODO better source location
43134319 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);
43144320 // Create a fresh inferred error set type for inline/comptime calls.
......@@ -4589,7 +4595,7 @@ fn analyzeCall(
45894595 }
45904596 arg_i += 1;
45914597 }
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| {
45934599 // TODO look up the compile error that happened here and attach a note to it
45944600 // pointing here, at the generic instantiation callsite.
45954601 if (sema.owner_func) |owner_func| {
......@@ -5388,10 +5394,9 @@ fn zirFunc(
53885394 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
53895395 extra_index += ret_ty_body.len;
53905396
5391 var body_inst: Zir.Inst.Index = 0;
53925397 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
5393 if (extra.data.body_len != 0) {
5394 body_inst = inst;
5398 const has_body = extra.data.body_len != 0;
5399 if (has_body) {
53955400 extra_index += extra.data.body_len;
53965401 src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
53975402 }
......@@ -5404,13 +5409,14 @@ fn zirFunc(
54045409 return sema.funcCommon(
54055410 block,
54065411 inst_data.src_node,
5407 body_inst,
5412 inst,
54085413 ret_ty_body,
54095414 cc,
54105415 Value.@"null",
54115416 false,
54125417 inferred_error_set,
54135418 false,
5419 has_body,
54145420 src_locs,
54155421 null,
54165422 );
......@@ -5420,13 +5426,14 @@ fn funcCommon(
54205426 sema: *Sema,
54215427 block: *Block,
54225428 src_node_offset: i32,
5423 body_inst: Zir.Inst.Index,
5429 func_inst: Zir.Inst.Index,
54245430 ret_ty_body: []const Zir.Inst.Index,
54255431 cc: std.builtin.CallingConvention,
54265432 align_val: Value,
54275433 var_args: bool,
54285434 inferred_error_set: bool,
54295435 is_extern: bool,
5436 has_body: bool,
54305437 src_locs: Zir.Inst.Func.SrcLocs,
54315438 opt_lib_name: ?[]const u8,
54325439) CompileError!Air.Inst.Ref {
......@@ -5447,7 +5454,7 @@ fn funcCommon(
54475454 block.params.deinit(sema.gpa);
54485455 block.params = prev_params;
54495456 }
5450 if (sema.resolveBody(block, ret_ty_body)) |ret_ty_inst| {
5457 if (sema.resolveBody(block, ret_ty_body, func_inst)) |ret_ty_inst| {
54515458 if (sema.analyzeAsType(block, ret_ty_src, ret_ty_inst)) |ret_ty| {
54525459 break :ret_ty ret_ty;
54535460 } else |err| break :err err;
......@@ -5466,15 +5473,15 @@ fn funcCommon(
54665473 const mod = sema.mod;
54675474
54685475 const new_func: *Module.Fn = new_func: {
5469 if (body_inst == 0) break :new_func undefined;
5470 if (sema.comptime_args_fn_inst == body_inst) {
5476 if (!has_body) break :new_func undefined;
5477 if (sema.comptime_args_fn_inst == func_inst) {
54715478 const new_func = sema.preallocated_new_func.?;
54725479 sema.preallocated_new_func = null; // take ownership
54735480 break :new_func new_func;
54745481 }
54755482 break :new_func try sema.gpa.create(Module.Fn);
54765483 };
5477 errdefer if (body_inst != 0) sema.gpa.destroy(new_func);
5484 errdefer if (has_body) sema.gpa.destroy(new_func);
54785485
54795486 var maybe_inferred_error_set_node: ?*Module.Fn.InferredErrorSetListNode = null;
54805487 errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node);
......@@ -5599,21 +5606,21 @@ fn funcCommon(
55995606 );
56005607 }
56015608
5602 if (body_inst == 0) {
5609 if (!has_body) {
56035610 return sema.addType(fn_ty);
56045611 }
56055612
56065613 const is_inline = fn_ty.fnCallingConvention() == .Inline;
56075614 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: {
56105617 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;
56115618 } else null;
56125619
56135620 const fn_payload = try sema.arena.create(Value.Payload.Function);
56145621 new_func.* = .{
56155622 .state = anal_state,
5616 .zir_body_inst = body_inst,
5623 .zir_body_inst = func_inst,
56175624 .owner_decl = sema.owner_decl,
56185625 .comptime_args = comptime_args,
56195626 .lbrace_line = src_locs.lbrace_line,
......@@ -5660,7 +5667,7 @@ fn zirParam(
56605667 block.params = prev_params;
56615668 }
56625669
5663 if (sema.resolveBody(block, body)) |param_ty_inst| {
5670 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {
56645671 if (sema.analyzeAsType(block, src, param_ty_inst)) |param_ty| {
56655672 break :param_ty param_ty;
56665673 } else |err| break :err err;
......@@ -6809,7 +6816,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
68096816 // Validation above ensured these will succeed.
68106817 const item_val = sema.resolveConstValue(&child_block, .unneeded, item) catch unreachable;
68116818 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);
68136820 }
68146821 }
68156822 }
......@@ -6831,7 +6838,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
68316838 // Validation above ensured these will succeed.
68326839 const item_val = sema.resolveConstValue(&child_block, .unneeded, item) catch unreachable;
68336840 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);
68356842 }
68366843 }
68376844
......@@ -6848,18 +6855,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
68486855 if (Value.compare(operand_val, .gte, first_tv.val, operand_ty) and
68496856 Value.compare(operand_val, .lte, last_tv.val, operand_ty))
68506857 {
6851 return sema.resolveBlockBody(block, src, &child_block, body, merges);
6858 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
68526859 }
68536860 }
68546861
68556862 extra_index += body_len;
68566863 }
68576864 }
6858 return sema.resolveBlockBody(block, src, &child_block, special.body, merges);
6865 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
68596866 }
68606867
68616868 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);
68636870 }
68646871
68656872 try sema.requireRuntimeBlock(block, src);
......@@ -10038,7 +10045,7 @@ fn zirBoolBr(
1003810045 // comptime-known left-hand side. No need for a block here; the result
1003910046 // is simply the rhs expression. Here we rely on there only being 1
1004010047 // break instruction (`break_inline`).
10041 return sema.resolveBody(parent_block, body);
10048 return sema.resolveBody(parent_block, body, inst);
1004210049 }
1004310050
1004410051 const block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);
......@@ -10068,7 +10075,7 @@ fn zirBoolBr(
1006810075 const lhs_result: Air.Inst.Ref = if (is_bool_or) .bool_true else .bool_false;
1006910076 _ = 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);
1007210079 _ = try rhs_block.addBr(block_inst, rhs_result);
1007310080
1007410081 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len +
......@@ -12419,10 +12426,9 @@ fn zirFuncExtended(
1241912426 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
1242012427 extra_index += ret_ty_body.len;
1242112428
12422 var body_inst: Zir.Inst.Index = 0;
1242312429 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
12424 if (extra.data.body_len != 0) {
12425 body_inst = inst;
12430 const has_body = extra.data.body_len != 0;
12431 if (has_body) {
1242612432 extra_index += extra.data.body_len;
1242712433 src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
1242812434 }
......@@ -12434,13 +12440,14 @@ fn zirFuncExtended(
1243412440 return sema.funcCommon(
1243512441 block,
1243612442 extra.data.src_node,
12437 body_inst,
12443 inst,
1243812444 ret_ty_body,
1243912445 cc,
1244012446 align_val,
1244112447 is_var_args,
1244212448 is_inferred_error,
1244312449 is_extern,
12450 has_body,
1244412451 src_locs,
1244512452 lib_name,
1244612453 );
src/Zir.zig+2
......@@ -3273,6 +3273,7 @@ fn findDeclsBody(
32733273
32743274pub const FnInfo = struct {
32753275 param_body: []const Inst.Index,
3276 param_body_inst: Inst.Index,
32763277 ret_ty_body: []const Inst.Index,
32773278 body: []const Inst.Index,
32783279 total_params_len: u32,
......@@ -3338,6 +3339,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
33383339 }
33393340 return .{
33403341 .param_body = param_body,
3342 .param_body_inst = info.param_block,
33413343 .ret_ty_body = info.ret_ty_body,
33423344 .body = info.body,
33433345 .total_params_len = total_params_len,