| ... | @@ -520,14 +520,14 @@ fn resolveBody( | ... | @@ -520,14 +520,14 @@ fn resolveBody( |
| 520 | /// use to return from the body. | 520 | /// use to return from the body. |
| 521 | body_inst: Zir.Inst.Index, | 521 | body_inst: Zir.Inst.Index, |
| 522 | ) CompileError!Air.Inst.Ref { | 522 | ) CompileError!Air.Inst.Ref { |
| 523 | const break_inst = try sema.analyzeBody(block, body); | 523 | const break_data = (try sema.analyzeBodyBreak(block, body)) orelse |
| 524 | const break_data = sema.code.instructions.items(.data)[break_inst].@"break"; | 524 | return Air.Inst.Ref.unreachable_value; |
| 525 | // For comptime control flow, we need to detect when `analyzeBody` reports | 525 | // For comptime control flow, we need to detect when `analyzeBody` reports |
| 526 | // that we need to break from an outer block. In such case we | 526 | // that we need to break from an outer block. In such case we |
| 527 | // use Zig's error mechanism to send control flow up the stack until | 527 | // use Zig's error mechanism to send control flow up the stack until |
| 528 | // we find the corresponding block to this break. | 528 | // we find the corresponding block to this break. |
| 529 | if (block.is_comptime and break_data.block_inst != body_inst) { | 529 | if (block.is_comptime and break_data.block_inst != body_inst) { |
| 530 | sema.comptime_break_inst = break_inst; | 530 | sema.comptime_break_inst = break_data.inst; |
| 531 | return error.ComptimeBreak; | 531 | return error.ComptimeBreak; |
| 532 | } | 532 | } |
| 533 | return sema.resolveInst(break_data.operand); | 533 | return sema.resolveInst(break_data.operand); |
| ... | @@ -537,11 +537,37 @@ pub fn analyzeBody( | ... | @@ -537,11 +537,37 @@ pub fn analyzeBody( |
| 537 | sema: *Sema, | 537 | sema: *Sema, |
| 538 | block: *Block, | 538 | block: *Block, |
| 539 | body: []const Zir.Inst.Index, | 539 | body: []const Zir.Inst.Index, |
| 540 | ) CompileError!Zir.Inst.Index { | 540 | ) !void { |
| 541 | return sema.analyzeBodyInner(block, body) catch |err| switch (err) { | 541 | _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) { |
| | 542 | error.ComptimeBreak => unreachable, // unexpected comptime control flow |
| | 543 | else => |e| return e, |
| | 544 | }; |
| | 545 | } |
| | 546 | |
| | 547 | const BreakData = struct { |
| | 548 | block_inst: Zir.Inst.Index, |
| | 549 | operand: Air.Inst.Ref, |
| | 550 | inst: Air.Inst.Index, |
| | 551 | }; |
| | 552 | |
| | 553 | pub fn analyzeBodyBreak( |
| | 554 | sema: *Sema, |
| | 555 | block: *Block, |
| | 556 | body: []const Zir.Inst.Index, |
| | 557 | ) CompileError!?BreakData { |
| | 558 | const break_inst = sema.analyzeBodyInner(block, body) catch |err| switch (err) { |
| 542 | error.ComptimeBreak => sema.comptime_break_inst, | 559 | error.ComptimeBreak => sema.comptime_break_inst, |
| 543 | else => |e| return e, | 560 | else => |e| return e, |
| 544 | }; | 561 | }; |
| | 562 | if (block.instructions.items.len != 0 and |
| | 563 | sema.typeOf(Air.indexToRef(block.instructions.items[block.instructions.items.len - 1])).isNoReturn()) |
| | 564 | return null; |
| | 565 | const break_data = sema.code.instructions.items(.data)[break_inst].@"break"; |
| | 566 | return BreakData{ |
| | 567 | .block_inst = break_data.block_inst, |
| | 568 | .operand = break_data.operand, |
| | 569 | .inst = break_inst, |
| | 570 | }; |
| 545 | } | 571 | } |
| 546 | | 572 | |
| 547 | /// ZIR instructions which are always `noreturn` return this. This matches the | 573 | /// ZIR instructions which are always `noreturn` return this. This matches the |
| ... | @@ -1045,12 +1071,12 @@ fn analyzeBodyInner( | ... | @@ -1045,12 +1071,12 @@ fn analyzeBodyInner( |
| 1045 | const inst_data = datas[inst].pl_node; | 1071 | const inst_data = datas[inst].pl_node; |
| 1046 | const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index); | 1072 | const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index); |
| 1047 | const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len]; | 1073 | const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len]; |
| 1048 | const break_inst = try sema.analyzeBody(block, inline_body); | 1074 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse |
| 1049 | const break_data = datas[break_inst].@"break"; | 1075 | break always_noreturn; |
| 1050 | if (inst == break_data.block_inst) { | 1076 | if (inst == break_data.block_inst) { |
| 1051 | break :blk sema.resolveInst(break_data.operand); | 1077 | break :blk sema.resolveInst(break_data.operand); |
| 1052 | } else { | 1078 | } else { |
| 1053 | break break_inst; | 1079 | break break_data.inst; |
| 1054 | } | 1080 | } |
| 1055 | }, | 1081 | }, |
| 1056 | .block => blk: { | 1082 | .block => blk: { |
| ... | @@ -1068,12 +1094,12 @@ fn analyzeBodyInner( | ... | @@ -1068,12 +1094,12 @@ fn analyzeBodyInner( |
| 1068 | block.params.deinit(sema.gpa); | 1094 | block.params.deinit(sema.gpa); |
| 1069 | block.params = prev_params; | 1095 | block.params = prev_params; |
| 1070 | } | 1096 | } |
| 1071 | const break_inst = try sema.analyzeBody(block, inline_body); | 1097 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse |
| 1072 | const break_data = datas[break_inst].@"break"; | 1098 | break always_noreturn; |
| 1073 | if (inst == break_data.block_inst) { | 1099 | if (inst == break_data.block_inst) { |
| 1074 | break :blk sema.resolveInst(break_data.operand); | 1100 | break :blk sema.resolveInst(break_data.operand); |
| 1075 | } else { | 1101 | } else { |
| 1076 | break break_inst; | 1102 | break break_data.inst; |
| 1077 | } | 1103 | } |
| 1078 | }, | 1104 | }, |
| 1079 | .block_inline => blk: { | 1105 | .block_inline => blk: { |
| ... | @@ -1090,12 +1116,12 @@ fn analyzeBodyInner( | ... | @@ -1090,12 +1116,12 @@ fn analyzeBodyInner( |
| 1090 | block.params.deinit(sema.gpa); | 1116 | block.params.deinit(sema.gpa); |
| 1091 | block.params = prev_params; | 1117 | block.params = prev_params; |
| 1092 | } | 1118 | } |
| 1093 | const break_inst = try sema.analyzeBody(block, inline_body); | 1119 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse |
| 1094 | const break_data = datas[break_inst].@"break"; | 1120 | break always_noreturn; |
| 1095 | if (inst == break_data.block_inst) { | 1121 | if (inst == break_data.block_inst) { |
| 1096 | break :blk sema.resolveInst(break_data.operand); | 1122 | break :blk sema.resolveInst(break_data.operand); |
| 1097 | } else { | 1123 | } else { |
| 1098 | break break_inst; | 1124 | break break_data.inst; |
| 1099 | } | 1125 | } |
| 1100 | }, | 1126 | }, |
| 1101 | .condbr => blk: { | 1127 | .condbr => blk: { |
| ... | @@ -1108,12 +1134,12 @@ fn analyzeBodyInner( | ... | @@ -1108,12 +1134,12 @@ fn analyzeBodyInner( |
| 1108 | const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; | 1134 | const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; |
| 1109 | const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition); | 1135 | const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition); |
| 1110 | const inline_body = if (cond.val.toBool()) then_body else else_body; | 1136 | const inline_body = if (cond.val.toBool()) then_body else else_body; |
| 1111 | const break_inst = try sema.analyzeBody(block, inline_body); | 1137 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse |
| 1112 | const break_data = datas[break_inst].@"break"; | 1138 | break always_noreturn; |
| 1113 | if (inst == break_data.block_inst) { | 1139 | if (inst == break_data.block_inst) { |
| 1114 | break :blk sema.resolveInst(break_data.operand); | 1140 | break :blk sema.resolveInst(break_data.operand); |
| 1115 | } else { | 1141 | } else { |
| 1116 | break break_inst; | 1142 | break break_data.inst; |
| 1117 | } | 1143 | } |
| 1118 | }, | 1144 | }, |
| 1119 | .condbr_inline => blk: { | 1145 | .condbr_inline => blk: { |
| ... | @@ -1124,12 +1150,12 @@ fn analyzeBodyInner( | ... | @@ -1124,12 +1150,12 @@ fn analyzeBodyInner( |
| 1124 | const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; | 1150 | const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; |
| 1125 | const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition); | 1151 | const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition); |
| 1126 | const inline_body = if (cond.val.toBool()) then_body else else_body; | 1152 | const inline_body = if (cond.val.toBool()) then_body else else_body; |
| 1127 | const break_inst = try sema.analyzeBody(block, inline_body); | 1153 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse |
| 1128 | const break_data = datas[break_inst].@"break"; | 1154 | break always_noreturn; |
| 1129 | if (inst == break_data.block_inst) { | 1155 | if (inst == break_data.block_inst) { |
| 1130 | break :blk sema.resolveInst(break_data.operand); | 1156 | break :blk sema.resolveInst(break_data.operand); |
| 1131 | } else { | 1157 | } else { |
| 1132 | break break_inst; | 1158 | break break_data.inst; |
| 1133 | } | 1159 | } |
| 1134 | }, | 1160 | }, |
| 1135 | }; | 1161 | }; |
| ... | @@ -1915,7 +1941,7 @@ fn zirEnumDecl( | ... | @@ -1915,7 +1941,7 @@ fn zirEnumDecl( |
| 1915 | defer assert(enum_block.instructions.items.len == 0); // should all be comptime instructions | 1941 | defer assert(enum_block.instructions.items.len == 0); // should all be comptime instructions |
| 1916 | | 1942 | |
| 1917 | if (body.len != 0) { | 1943 | if (body.len != 0) { |
| 1918 | _ = try sema.analyzeBody(&enum_block, body); | 1944 | try sema.analyzeBody(&enum_block, body); |
| 1919 | } | 1945 | } |
| 1920 | | 1946 | |
| 1921 | try wip_captures.finalize(); | 1947 | try wip_captures.finalize(); |
| ... | @@ -3639,7 +3665,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -3639,7 +3665,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError |
| 3639 | var loop_block = child_block.makeSubBlock(); | 3665 | var loop_block = child_block.makeSubBlock(); |
| 3640 | defer loop_block.instructions.deinit(gpa); | 3666 | defer loop_block.instructions.deinit(gpa); |
| 3641 | | 3667 | |
| 3642 | _ = try sema.analyzeBody(&loop_block, body); | 3668 | try sema.analyzeBody(&loop_block, body); |
| 3643 | | 3669 | |
| 3644 | try child_block.instructions.append(gpa, loop_inst); | 3670 | try child_block.instructions.append(gpa, loop_inst); |
| 3645 | | 3671 | |
| ... | @@ -3681,7 +3707,8 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -3681,7 +3707,8 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 3681 | }; | 3707 | }; |
| 3682 | defer child_block.instructions.deinit(sema.gpa); | 3708 | defer child_block.instructions.deinit(sema.gpa); |
| 3683 | | 3709 | |
| 3684 | _ = try sema.analyzeBody(&child_block, body); | 3710 | // Ignore the result, all the relevant operations have written to c_import_buf already. |
| | 3711 | _ = try sema.analyzeBodyBreak(&child_block, body); |
| 3685 | | 3712 | |
| 3686 | const c_import_res = sema.mod.comp.cImport(c_import_buf.items) catch |err| | 3713 | const c_import_res = sema.mod.comp.cImport(c_import_buf.items) catch |err| |
| 3687 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); | 3714 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); |
| ... | @@ -4658,9 +4685,8 @@ fn analyzeCall( | ... | @@ -4658,9 +4685,8 @@ fn analyzeCall( |
| 4658 | } | 4685 | } |
| 4659 | | 4686 | |
| 4660 | const result = result: { | 4687 | const result = result: { |
| 4661 | _ = sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) { | 4688 | sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) { |
| 4662 | error.ComptimeReturn => break :result inlining.comptime_result, | 4689 | error.ComptimeReturn => break :result inlining.comptime_result, |
| 4663 | error.ComptimeBreak => unreachable, // Can't break through a fn call. | | |
| 4664 | error.AnalysisFail => { | 4690 | error.AnalysisFail => { |
| 4665 | const err_msg = inlining.err orelse return err; | 4691 | const err_msg = inlining.err orelse return err; |
| 4666 | try sema.errNote(block, call_src, err_msg, "called from here", .{}); | 4692 | try sema.errNote(block, call_src, err_msg, "called from here", .{}); |
| ... | @@ -7313,7 +7339,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -7313,7 +7339,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 7313 | const item = sema.resolveInst(item_ref); | 7339 | const item = sema.resolveInst(item_ref); |
| 7314 | // `item` is already guaranteed to be constant known. | 7340 | // `item` is already guaranteed to be constant known. |
| 7315 | | 7341 | |
| 7316 | _ = try sema.analyzeBody(&case_block, body); | 7342 | try sema.analyzeBody(&case_block, body); |
| 7317 | | 7343 | |
| 7318 | try wip_captures.finalize(); | 7344 | try wip_captures.finalize(); |
| 7319 | | 7345 | |
| ... | @@ -7356,7 +7382,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -7356,7 +7382,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 7356 | | 7382 | |
| 7357 | const body = sema.code.extra[extra_index..][0..body_len]; | 7383 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 7358 | extra_index += body_len; | 7384 | extra_index += body_len; |
| 7359 | _ = try sema.analyzeBody(&case_block, body); | 7385 | try sema.analyzeBody(&case_block, body); |
| 7360 | | 7386 | |
| 7361 | try cases_extra.ensureUnusedCapacity(gpa, 2 + items.len + | 7387 | try cases_extra.ensureUnusedCapacity(gpa, 2 + items.len + |
| 7362 | case_block.instructions.items.len); | 7388 | case_block.instructions.items.len); |
| ... | @@ -7431,7 +7457,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -7431,7 +7457,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 7431 | | 7457 | |
| 7432 | const body = sema.code.extra[extra_index..][0..body_len]; | 7458 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 7433 | extra_index += body_len; | 7459 | extra_index += body_len; |
| 7434 | _ = try sema.analyzeBody(&case_block, body); | 7460 | try sema.analyzeBody(&case_block, body); |
| 7435 | | 7461 | |
| 7436 | try wip_captures.finalize(); | 7462 | try wip_captures.finalize(); |
| 7437 | | 7463 | |
| ... | @@ -7468,7 +7494,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -7468,7 +7494,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 7468 | case_block.wip_capture_scope = wip_captures.scope; | 7494 | case_block.wip_capture_scope = wip_captures.scope; |
| 7469 | | 7495 | |
| 7470 | if (special.body.len != 0) { | 7496 | if (special.body.len != 0) { |
| 7471 | _ = try sema.analyzeBody(&case_block, special.body); | 7497 | try sema.analyzeBody(&case_block, special.body); |
| 7472 | } else { | 7498 | } else { |
| 7473 | // We still need a terminator in this block, but we have proven | 7499 | // We still need a terminator in this block, but we have proven |
| 7474 | // that it is unreachable. | 7500 | // that it is unreachable. |
| ... | @@ -10990,7 +11016,8 @@ fn zirTypeofPeer( | ... | @@ -10990,7 +11016,8 @@ fn zirTypeofPeer( |
| 10990 | .is_typeof = true, | 11016 | .is_typeof = true, |
| 10991 | }; | 11017 | }; |
| 10992 | defer child_block.instructions.deinit(sema.gpa); | 11018 | defer child_block.instructions.deinit(sema.gpa); |
| 10993 | _ = try sema.analyzeBody(&child_block, body); | 11019 | // Ignore the result, we only care about the instructions in `args`. |
| | 11020 | _ = try sema.analyzeBodyBreak(&child_block, body); |
| 10994 | | 11021 | |
| 10995 | const args = sema.code.refSlice(extra.end, extended.small); | 11022 | const args = sema.code.refSlice(extra.end, extended.small); |
| 10996 | | 11023 | |
| ... | @@ -11186,6 +11213,8 @@ fn zirCondbr( | ... | @@ -11186,6 +11213,8 @@ fn zirCondbr( |
| 11186 | | 11213 | |
| 11187 | if (try sema.resolveDefinedValue(parent_block, src, cond)) |cond_val| { | 11214 | if (try sema.resolveDefinedValue(parent_block, src, cond)) |cond_val| { |
| 11188 | const body = if (cond_val.toBool()) then_body else else_body; | 11215 | const body = if (cond_val.toBool()) then_body else else_body; |
| | 11216 | // We use `analyzeBodyInner` since we want to propagate any possible |
| | 11217 | // `error.ComptimeBreak` to the caller. |
| 11189 | return sema.analyzeBodyInner(parent_block, body); | 11218 | return sema.analyzeBodyInner(parent_block, body); |
| 11190 | } | 11219 | } |
| 11191 | | 11220 | |
| ... | @@ -11199,11 +11228,11 @@ fn zirCondbr( | ... | @@ -11199,11 +11228,11 @@ fn zirCondbr( |
| 11199 | sub_block.runtime_index += 1; | 11228 | sub_block.runtime_index += 1; |
| 11200 | defer sub_block.instructions.deinit(gpa); | 11229 | defer sub_block.instructions.deinit(gpa); |
| 11201 | | 11230 | |
| 11202 | _ = try sema.analyzeBody(&sub_block, then_body); | 11231 | try sema.analyzeBody(&sub_block, then_body); |
| 11203 | const true_instructions = sub_block.instructions.toOwnedSlice(gpa); | 11232 | const true_instructions = sub_block.instructions.toOwnedSlice(gpa); |
| 11204 | defer gpa.free(true_instructions); | 11233 | defer gpa.free(true_instructions); |
| 11205 | | 11234 | |
| 11206 | _ = try sema.analyzeBody(&sub_block, else_body); | 11235 | try sema.analyzeBody(&sub_block, else_body); |
| 11207 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len + | 11236 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len + |
| 11208 | true_instructions.len + sub_block.instructions.items.len); | 11237 | true_instructions.len + sub_block.instructions.items.len); |
| 11209 | _ = try parent_block.addInst(.{ | 11238 | _ = try parent_block.addInst(.{ |
| ... | @@ -19186,7 +19215,7 @@ fn semaStructFields( | ... | @@ -19186,7 +19215,7 @@ fn semaStructFields( |
| 19186 | } | 19215 | } |
| 19187 | | 19216 | |
| 19188 | if (body.len != 0) { | 19217 | if (body.len != 0) { |
| 19189 | _ = try sema.analyzeBody(&block_scope, body); | 19218 | try sema.analyzeBody(&block_scope, body); |
| 19190 | } | 19219 | } |
| 19191 | | 19220 | |
| 19192 | try wip_captures.finalize(); | 19221 | try wip_captures.finalize(); |
| ... | @@ -19360,7 +19389,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -19360,7 +19389,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 19360 | } | 19389 | } |
| 19361 | | 19390 | |
| 19362 | if (body.len != 0) { | 19391 | if (body.len != 0) { |
| 19363 | _ = try sema.analyzeBody(&block_scope, body); | 19392 | try sema.analyzeBody(&block_scope, body); |
| 19364 | } | 19393 | } |
| 19365 | | 19394 | |
| 19366 | try wip_captures.finalize(); | 19395 | try wip_captures.finalize(); |