diff --git a/src/AstGen.zig b/src/AstGen.zig index 48e6a480f3..d71a2fd13d 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -5910,8 +5910,8 @@ fn whileExpr( defer loop_scope.unstack(); defer loop_scope.labeled_breaks.deinit(astgen.gpa); - var continue_scope = parent_gz.makeSubBlock(&loop_scope.base); - defer continue_scope.unstack(); + var cond_scope = parent_gz.makeSubBlock(&loop_scope.base); + defer cond_scope.unstack(); const payload_is_ref = if (while_full.payload_token) |payload_token| token_tags[payload_token] == .asterisk @@ -5925,22 +5925,22 @@ fn whileExpr( } = c: { if (while_full.error_token) |_| { const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; - const err_union = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr); + const err_union = try expr(&cond_scope, &cond_scope.base, cond_ri, while_full.ast.cond_expr); const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err; break :c .{ .inst = err_union, - .bool_bit = try continue_scope.addUnNode(tag, err_union, while_full.ast.then_expr), + .bool_bit = try cond_scope.addUnNode(tag, err_union, while_full.ast.then_expr), }; } else if (while_full.payload_token) |_| { const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; - const optional = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr); + const optional = try expr(&cond_scope, &cond_scope.base, cond_ri, while_full.ast.cond_expr); const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null; break :c .{ .inst = optional, - .bool_bit = try continue_scope.addUnNode(tag, optional, while_full.ast.then_expr), + .bool_bit = try cond_scope.addUnNode(tag, optional, while_full.ast.then_expr), }; } else { - const cond = try expr(&continue_scope, &continue_scope.base, bool_ri, while_full.ast.cond_expr); + const cond = try expr(&cond_scope, &cond_scope.base, bool_ri, while_full.ast.cond_expr); break :c .{ .inst = cond, .bool_bit = cond, @@ -5949,16 +5949,16 @@ fn whileExpr( }; const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; - const condbr = try continue_scope.addCondBr(condbr_tag, node); + const condbr = try cond_scope.addCondBr(condbr_tag, node); const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block; const cond_block = try loop_scope.makeBlockInst(block_tag, node); - try continue_scope.setBlockBody(cond_block); - // continue_scope unstacked now, can add new instructions to loop_scope + try cond_scope.setBlockBody(cond_block); + // cond_scope unstacked now, can add new instructions to loop_scope try loop_scope.instructions.append(astgen.gpa, cond_block); // make scope now but don't stack on parent_gz until loop_scope // gets unstacked after cont_expr is emitted and added below - var then_scope = parent_gz.makeSubBlock(&continue_scope.base); + var then_scope = parent_gz.makeSubBlock(&cond_scope.base); then_scope.instructions_top = GenZir.unstacked_top; defer then_scope.unstack(); @@ -6026,24 +6026,17 @@ fn whileExpr( } }; - // This code could be improved to avoid emitting the continue expr when there - // are no jumps to it. This happens when the last statement of a while body is noreturn - // and there are no `continue` statements. - // Tracking issue: https://github.com/ziglang/zig/issues/9185 - try then_scope.addDbgBlockBegin(); - if (dbg_var_name) |some| { - try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst); - } - if (while_full.ast.cont_expr != 0) { - _ = try unusedResultExpr(&loop_scope, then_sub_scope, while_full.ast.cont_expr); - } - try then_scope.addDbgBlockEnd(); + var continue_scope = parent_gz.makeSubBlock(then_sub_scope); + continue_scope.instructions_top = GenZir.unstacked_top; + defer continue_scope.unstack(); + const continue_block = try then_scope.makeBlockInst(block_tag, node); + const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat; _ = try loop_scope.addNode(repeat_tag, node); try loop_scope.setBlockBody(loop_block); loop_scope.break_block = loop_block; - loop_scope.continue_block = cond_block; + loop_scope.continue_block = continue_block; if (while_full.label_token) |label_token| { loop_scope.label = @as(?GenZir.Label, GenZir.Label{ .token = label_token, @@ -6054,18 +6047,30 @@ fn whileExpr( // done adding instructions to loop_scope, can now stack then_scope then_scope.instructions_top = then_scope.instructions.items.len; - if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst); try then_scope.addDbgBlockBegin(); - if (dbg_var_name) |some| { - try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst); + if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst); + if (dbg_var_name) |name| try then_scope.addDbgVar(.dbg_var_val, name, dbg_var_inst); + try then_scope.instructions.append(astgen.gpa, continue_block); + // This code could be improved to avoid emitting the continue expr when there + // are no jumps to it. This happens when the last statement of a while body is noreturn + // and there are no `continue` statements. + // Tracking issue: https://github.com/ziglang/zig/issues/9185 + if (while_full.ast.cont_expr != 0) { + _ = try unusedResultExpr(&then_scope, then_sub_scope, while_full.ast.cont_expr); } - const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, while_full.ast.then_expr); - _ = try addEnsureResult(&then_scope, then_result, while_full.ast.then_expr); - - try checkUsed(parent_gz, &then_scope.base, then_sub_scope); try then_scope.addDbgBlockEnd(); - var else_scope = parent_gz.makeSubBlock(&continue_scope.base); + continue_scope.instructions_top = continue_scope.instructions.items.len; + _ = try unusedResultExpr(&continue_scope, &continue_scope.base, while_full.ast.then_expr); + try checkUsed(parent_gz, &then_scope.base, then_sub_scope); + const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; + if (!continue_scope.endsWithNoReturn()) { + const break_inst = try continue_scope.makeBreak(break_tag, continue_block, .void_value); + try then_scope.instructions.append(astgen.gpa, break_inst); + } + try continue_scope.setBlockBody(continue_block); + + var else_scope = parent_gz.makeSubBlock(&cond_scope.base); defer else_scope.unstack(); const else_node = while_full.ast.else_expr; @@ -6128,7 +6133,6 @@ fn whileExpr( try astgen.appendErrorTok(some.token, "unused while loop label", .{}); } } - const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; const result = try finishThenElseBlock( parent_gz, ri, @@ -6138,7 +6142,7 @@ fn whileExpr( &else_scope, condbr, cond.bool_bit, - then_result, + .void_value, else_info.result, loop_block, cond_block, diff --git a/src/Sema.zig b/src/Sema.zig index a73c1eedcb..39f57ad1f2 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -71,8 +71,8 @@ preallocated_new_func: ?*Module.Fn = null, /// TODO: after upgrading to use InternPool change the key here to be an /// InternPool value index. types_to_resolve: std.ArrayListUnmanaged(Air.Inst.Ref) = .{}, -/// These are lazily created runtime blocks from inline_block instructions. -/// They are created when an inline_break passes through a runtime condition, because +/// These are lazily created runtime blocks from block_inline instructions. +/// They are created when an break_inline passes through a runtime condition, because /// Sema must convert comptime control flow to runtime control flow, which means /// breaking from a block. post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{}, @@ -147,7 +147,7 @@ pub const Block = struct { /// for the one that will be the same for all Block instances. src_decl: Decl.Index, /// Non zero if a non-inline loop or a runtime conditional have been encountered. - /// Stores to to comptime variables are only allowed when var.runtime_index <= runtime_index. + /// Stores to comptime variables are only allowed when var.runtime_index <= runtime_index. runtime_index: Value.RuntimeIndex = .zero, inline_block: Zir.Inst.Index = 0, @@ -1391,9 +1391,8 @@ fn analyzeBodyInner( // If this block contains a function prototype, we need to reset the // current list of parameters and restore it later. // Note: this probably needs to be resolved in a more general manner. - if (tags[inline_body[inline_body.len - 1]] == .repeat_inline) { - child_block.inline_block = inline_body[0]; - } else child_block.inline_block = block.inline_block; + child_block.inline_block = + if (tags[inline_body[inline_body.len - 1]] == .repeat_inline) inline_body[0] else inst; var label: Block.Label = .{ .zir_block = inst, diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index d47138010d..ddeac2a030 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -646,7 +646,6 @@ test "multiline string literal is null terminated" { } test "string escapes" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; diff --git a/test/behavior/bit_shifting.zig b/test/behavior/bit_shifting.zig index 1a01cbd732..a4a80f00a8 100644 --- a/test/behavior/bit_shifting.zig +++ b/test/behavior/bit_shifting.zig @@ -62,7 +62,6 @@ fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, compt test "sharded table" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // realistic 16-way sharding diff --git a/test/behavior/bugs/6456.zig b/test/behavior/bugs/6456.zig index a3b4720dbd..a47f0c0d6c 100644 --- a/test/behavior/bugs/6456.zig +++ b/test/behavior/bugs/6456.zig @@ -11,7 +11,6 @@ const text = ; test "issue 6456" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig index cf618259b1..d04e7fdb62 100644 --- a/test/behavior/optional.zig +++ b/test/behavior/optional.zig @@ -429,7 +429,6 @@ test "alignment of wrapping an optional payload" { test "Optional slice size is optimized" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig index 2e09aa2802..8ee7b5142a 100644 --- a/test/behavior/pointers.zig +++ b/test/behavior/pointers.zig @@ -483,7 +483,6 @@ test "pointer to constant decl preserves alignment" { test "ptrCast comptime known slice to C pointer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO const s: [:0]const u8 = "foo"; diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index 4fe61f521d..8d2c484b5f 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -702,7 +702,6 @@ test "slice field ptr var" { test "global slice field access" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO const S = struct { diff --git a/test/behavior/translate_c_macros.zig b/test/behavior/translate_c_macros.zig index 3328b657a1..51f7993cc2 100644 --- a/test/behavior/translate_c_macros.zig +++ b/test/behavior/translate_c_macros.zig @@ -123,7 +123,6 @@ test "large integer macro" { test "string literal macro with embedded tab character" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO @@ -133,7 +132,6 @@ test "string literal macro with embedded tab character" { test "string and char literals that are not UTF-8 encoded. Issue #12784" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO diff --git a/test/behavior/typename.zig b/test/behavior/typename.zig index 9b7a899653..e6e9390d6a 100644 --- a/test/behavior/typename.zig +++ b/test/behavior/typename.zig @@ -18,7 +18,6 @@ test "anon fn param" { return error.SkipZigTest; } - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -50,7 +49,6 @@ test "anon field init" { return error.SkipZigTest; } - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -76,7 +74,6 @@ test "anon field init" { } test "basic" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -92,7 +89,6 @@ test "top level decl" { return error.SkipZigTest; } - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -142,7 +138,6 @@ const B = struct { }; test "fn param" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -218,7 +213,6 @@ test "local variable" { return error.SkipZigTest; } - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -238,7 +232,6 @@ test "local variable" { test "comptime parameters not converted to anytype in function type" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -254,7 +247,6 @@ test "anon name strategy used in sub expression" { return error.SkipZigTest; } - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO