| author | |
| committer | |
| log | 8775d8bbcef347640c6ae7e73da02ca6eff1d669 |
| tree | 3f04f80b042d7baf10074b6f88fabb5693b2b71e |
| parent | f803761e13a65ccbc6a5508f2dc2d7723b010dab |
| parent | 59447e53056d8fb6682b79accccffa176d0b44d1 |
| signature |
compiler: decide dbg_var scoping based on AIR blocks18 files changed, 187 insertions(+), 287 deletions(-)
src/Air.zig-8| ... | ... | @@ -443,10 +443,6 @@ pub const Inst = struct { |
| 443 | 443 | /// Result type is always void. |
| 444 | 444 | /// Uses the `dbg_stmt` field. |
| 445 | 445 | dbg_stmt, |
| 446 | /// Marks the beginning of a semantic scope for debug info variables. | |
| 447 | dbg_block_begin, | |
| 448 | /// Marks the end of a semantic scope for debug info variables. | |
| 449 | dbg_block_end, | |
| 450 | 446 | /// Marks the start of an inline call. |
| 451 | 447 | /// Uses the `ty_fn` field. |
| 452 | 448 | dbg_inline_begin, |
| ... | ... | @@ -1454,8 +1450,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1454 | 1450 | .dbg_stmt, |
| 1455 | 1451 | .dbg_inline_begin, |
| 1456 | 1452 | .dbg_inline_end, |
| 1457 | .dbg_block_begin, | |
| 1458 | .dbg_block_end, | |
| 1459 | 1453 | .dbg_var_ptr, |
| 1460 | 1454 | .dbg_var_val, |
| 1461 | 1455 | .store, |
| ... | ... | @@ -1612,8 +1606,6 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { |
| 1612 | 1606 | .@"try", |
| 1613 | 1607 | .try_ptr, |
| 1614 | 1608 | .dbg_stmt, |
| 1615 | .dbg_block_begin, | |
| 1616 | .dbg_block_end, | |
| 1617 | 1609 | .dbg_inline_begin, |
| 1618 | 1610 | .dbg_inline_end, |
| 1619 | 1611 | .dbg_var_ptr, |
src/AstGen.zig-51| ... | ... | @@ -2445,8 +2445,6 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2445 | 2445 | |
| 2446 | 2446 | if (statements.len == 0) return; |
| 2447 | 2447 | |
| 2448 | try gz.addDbgBlockBegin(); | |
| 2449 | ||
| 2450 | 2448 | var block_arena = std.heap.ArenaAllocator.init(gz.astgen.gpa); |
| 2451 | 2449 | defer block_arena.deinit(); |
| 2452 | 2450 | const block_arena_allocator = block_arena.allocator(); |
| ... | ... | @@ -2518,8 +2516,6 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2518 | 2516 | } |
| 2519 | 2517 | } |
| 2520 | 2518 | |
| 2521 | try gz.addDbgBlockEnd(); | |
| 2522 | ||
| 2523 | 2519 | try genDefers(gz, parent_scope, scope, .normal_only); |
| 2524 | 2520 | try checkUsed(gz, parent_scope, scope); |
| 2525 | 2521 | } |
| ... | ... | @@ -2804,8 +2800,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2804 | 2800 | .dbg_stmt, |
| 2805 | 2801 | .dbg_var_ptr, |
| 2806 | 2802 | .dbg_var_val, |
| 2807 | .dbg_block_begin, | |
| 2808 | .dbg_block_end, | |
| 2809 | 2803 | .ensure_result_used, |
| 2810 | 2804 | .ensure_result_non_error, |
| 2811 | 2805 | .ensure_err_union_payload_void, |
| ... | ... | @@ -3026,7 +3020,6 @@ fn deferStmt( |
| 3026 | 3020 | var opt_remapped_err_code: Zir.Inst.OptionalIndex = .none; |
| 3027 | 3021 | const have_err_code = scope_tag == .defer_error and payload_token != 0; |
| 3028 | 3022 | const sub_scope = if (!have_err_code) &defer_gen.base else blk: { |
| 3029 | try gz.addDbgBlockBegin(); | |
| 3030 | 3023 | const ident_name = try gz.astgen.identAsString(payload_token); |
| 3031 | 3024 | const remapped_err_code: Zir.Inst.Index = @enumFromInt(gz.astgen.instructions.len); |
| 3032 | 3025 | opt_remapped_err_code = remapped_err_code.toOptional(); |
| ... | ... | @@ -3052,7 +3045,6 @@ fn deferStmt( |
| 3052 | 3045 | }; |
| 3053 | 3046 | _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node); |
| 3054 | 3047 | try checkUsed(gz, scope, sub_scope); |
| 3055 | if (have_err_code) try gz.addDbgBlockEnd(); | |
| 3056 | 3048 | _ = try defer_gen.addBreak(.break_inline, @enumFromInt(0), .void_value); |
| 3057 | 3049 | |
| 3058 | 3050 | // We must handle ref_table for remapped_err_code manually. |
| ... | ... | @@ -6245,7 +6237,6 @@ fn ifExpr( |
| 6245 | 6237 | |
| 6246 | 6238 | var payload_val_scope: Scope.LocalVal = undefined; |
| 6247 | 6239 | |
| 6248 | try then_scope.addDbgBlockBegin(); | |
| 6249 | 6240 | const then_node = if_full.ast.then_expr; |
| 6250 | 6241 | const then_sub_scope = s: { |
| 6251 | 6242 | if (if_full.error_token != null) { |
| ... | ... | @@ -6305,7 +6296,6 @@ fn ifExpr( |
| 6305 | 6296 | const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_info, then_node); |
| 6306 | 6297 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 6307 | 6298 | if (!then_scope.endsWithNoReturn()) { |
| 6308 | try then_scope.addDbgBlockEnd(); | |
| 6309 | 6299 | _ = try then_scope.addBreakWithSrcNode(.@"break", block, then_result, then_node); |
| 6310 | 6300 | } |
| 6311 | 6301 | |
| ... | ... | @@ -6319,7 +6309,6 @@ fn ifExpr( |
| 6319 | 6309 | |
| 6320 | 6310 | const else_node = if_full.ast.else_expr; |
| 6321 | 6311 | if (else_node != 0) { |
| 6322 | try else_scope.addDbgBlockBegin(); | |
| 6323 | 6312 | const sub_scope = s: { |
| 6324 | 6313 | if (if_full.error_token) |error_token| { |
| 6325 | 6314 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| ... | ... | @@ -6347,7 +6336,6 @@ fn ifExpr( |
| 6347 | 6336 | } |
| 6348 | 6337 | }; |
| 6349 | 6338 | const else_result = try expr(&else_scope, sub_scope, block_scope.break_result_info, else_node); |
| 6350 | try else_scope.addDbgBlockEnd(); | |
| 6351 | 6339 | if (!else_scope.endsWithNoReturn()) { |
| 6352 | 6340 | // As our last action before the break, "pop" the error trace if needed |
| 6353 | 6341 | if (do_err_trace) |
| ... | ... | @@ -6579,7 +6567,6 @@ fn whileExpr( |
| 6579 | 6567 | // done adding instructions to loop_scope, can now stack then_scope |
| 6580 | 6568 | then_scope.instructions_top = then_scope.instructions.items.len; |
| 6581 | 6569 | |
| 6582 | try then_scope.addDbgBlockBegin(); | |
| 6583 | 6570 | const then_node = while_full.ast.then_expr; |
| 6584 | 6571 | if (opt_payload_inst.unwrap()) |payload_inst| { |
| 6585 | 6572 | try then_scope.instructions.append(astgen.gpa, payload_inst); |
| ... | ... | @@ -6593,7 +6580,6 @@ fn whileExpr( |
| 6593 | 6580 | if (while_full.ast.cont_expr != 0) { |
| 6594 | 6581 | _ = try unusedResultExpr(&then_scope, then_sub_scope, while_full.ast.cont_expr); |
| 6595 | 6582 | } |
| 6596 | try then_scope.addDbgBlockEnd(); | |
| 6597 | 6583 | |
| 6598 | 6584 | continue_scope.instructions_top = continue_scope.instructions.items.len; |
| 6599 | 6585 | _ = try unusedResultExpr(&continue_scope, &continue_scope.base, then_node); |
| ... | ... | @@ -6610,7 +6596,6 @@ fn whileExpr( |
| 6610 | 6596 | |
| 6611 | 6597 | const else_node = while_full.ast.else_expr; |
| 6612 | 6598 | if (else_node != 0) { |
| 6613 | try else_scope.addDbgBlockBegin(); | |
| 6614 | 6599 | const sub_scope = s: { |
| 6615 | 6600 | if (while_full.error_token) |error_token| { |
| 6616 | 6601 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| ... | ... | @@ -6647,7 +6632,6 @@ fn whileExpr( |
| 6647 | 6632 | } |
| 6648 | 6633 | |
| 6649 | 6634 | try checkUsed(parent_gz, &else_scope.base, sub_scope); |
| 6650 | try else_scope.addDbgBlockEnd(); | |
| 6651 | 6635 | if (!else_scope.endsWithNoReturn()) { |
| 6652 | 6636 | _ = try else_scope.addBreakWithSrcNode(break_tag, loop_block, else_result, else_node); |
| 6653 | 6637 | } |
| ... | ... | @@ -6849,8 +6833,6 @@ fn forExpr( |
| 6849 | 6833 | var then_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 6850 | 6834 | defer then_scope.unstack(); |
| 6851 | 6835 | |
| 6852 | try then_scope.addDbgBlockBegin(); | |
| 6853 | ||
| 6854 | 6836 | const capture_scopes = try gpa.alloc(Scope.LocalVal, for_full.ast.inputs.len); |
| 6855 | 6837 | defer gpa.free(capture_scopes); |
| 6856 | 6838 | |
| ... | ... | @@ -6916,7 +6898,6 @@ fn forExpr( |
| 6916 | 6898 | _ = try addEnsureResult(&then_scope, then_result, then_node); |
| 6917 | 6899 | |
| 6918 | 6900 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 6919 | try then_scope.addDbgBlockEnd(); | |
| 6920 | 6901 | |
| 6921 | 6902 | const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; |
| 6922 | 6903 | |
| ... | ... | @@ -7149,8 +7130,6 @@ fn switchExprErrUnion( |
| 7149 | 7130 | case_scope.instructions_top = parent_gz.instructions.items.len; |
| 7150 | 7131 | defer case_scope.unstack(); |
| 7151 | 7132 | |
| 7152 | try case_scope.addDbgBlockBegin(); | |
| 7153 | ||
| 7154 | 7133 | const unwrap_payload_tag: Zir.Inst.Tag = if (payload_is_ref) |
| 7155 | 7134 | .err_union_payload_unsafe_ptr |
| 7156 | 7135 | else |
| ... | ... | @@ -7173,7 +7152,6 @@ fn switchExprErrUnion( |
| 7173 | 7152 | catch_or_if_node, |
| 7174 | 7153 | ), |
| 7175 | 7154 | }; |
| 7176 | try case_scope.addDbgBlockEnd(); | |
| 7177 | 7155 | _ = try case_scope.addBreakWithSrcNode( |
| 7178 | 7156 | .@"break", |
| 7179 | 7157 | switch_block, |
| ... | ... | @@ -7184,7 +7162,6 @@ fn switchExprErrUnion( |
| 7184 | 7162 | .@"if" => { |
| 7185 | 7163 | var payload_val_scope: Scope.LocalVal = undefined; |
| 7186 | 7164 | |
| 7187 | try case_scope.addDbgBlockBegin(); | |
| 7188 | 7165 | const then_node = if_full.ast.then_expr; |
| 7189 | 7166 | const then_sub_scope = s: { |
| 7190 | 7167 | assert(if_full.error_token != null); |
| ... | ... | @@ -7228,7 +7205,6 @@ fn switchExprErrUnion( |
| 7228 | 7205 | ); |
| 7229 | 7206 | try checkUsed(parent_gz, &case_scope.base, then_sub_scope); |
| 7230 | 7207 | if (!case_scope.endsWithNoReturn()) { |
| 7231 | try case_scope.addDbgBlockEnd(); | |
| 7232 | 7208 | _ = try case_scope.addBreakWithSrcNode( |
| 7233 | 7209 | .@"break", |
| 7234 | 7210 | switch_block, |
| ... | ... | @@ -7407,7 +7383,6 @@ fn switchExprErrUnion( |
| 7407 | 7383 | if (do_err_trace and nodeMayAppendToErrorTrace(tree, operand_node)) |
| 7408 | 7384 | _ = try case_scope.addSaveErrRetIndex(.always); |
| 7409 | 7385 | |
| 7410 | try case_scope.addDbgBlockBegin(); | |
| 7411 | 7386 | if (dbg_var_name != .empty) { |
| 7412 | 7387 | try case_scope.addDbgVar(.dbg_var_val, dbg_var_name, dbg_var_inst); |
| 7413 | 7388 | } |
| ... | ... | @@ -7421,7 +7396,6 @@ fn switchExprErrUnion( |
| 7421 | 7396 | try case_scope.addDbgVar(.dbg_var_val, err_name, err_inst.toRef()); |
| 7422 | 7397 | any_uses_err_capture = true; |
| 7423 | 7398 | } |
| 7424 | try case_scope.addDbgBlockEnd(); | |
| 7425 | 7399 | |
| 7426 | 7400 | if (!parent_gz.refIsNoReturn(case_result)) { |
| 7427 | 7401 | if (do_err_trace) |
| ... | ... | @@ -7868,7 +7842,6 @@ fn switchExpr( |
| 7868 | 7842 | case_scope.instructions_top = parent_gz.instructions.items.len; |
| 7869 | 7843 | defer case_scope.unstack(); |
| 7870 | 7844 | |
| 7871 | try case_scope.addDbgBlockBegin(); | |
| 7872 | 7845 | if (dbg_var_name != .empty) { |
| 7873 | 7846 | try case_scope.addDbgVar(.dbg_var_val, dbg_var_name, dbg_var_inst); |
| 7874 | 7847 | } |
| ... | ... | @@ -7878,7 +7851,6 @@ fn switchExpr( |
| 7878 | 7851 | const target_expr_node = case.ast.target_expr; |
| 7879 | 7852 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node); |
| 7880 | 7853 | try checkUsed(parent_gz, &case_scope.base, sub_scope); |
| 7881 | try case_scope.addDbgBlockEnd(); | |
| 7882 | 7854 | if (!parent_gz.refIsNoReturn(case_result)) { |
| 7883 | 7855 | _ = try case_scope.addBreakWithSrcNode(.@"break", switch_block, case_result, target_expr_node); |
| 7884 | 7856 | } |
| ... | ... | @@ -13165,29 +13137,6 @@ const GenZir = struct { |
| 13165 | 13137 | }, |
| 13166 | 13138 | } }); |
| 13167 | 13139 | } |
| 13168 | ||
| 13169 | fn addDbgBlockBegin(gz: *GenZir) !void { | |
| 13170 | if (gz.is_comptime) return; | |
| 13171 | ||
| 13172 | _ = try gz.add(.{ .tag = .dbg_block_begin, .data = undefined }); | |
| 13173 | } | |
| 13174 | ||
| 13175 | fn addDbgBlockEnd(gz: *GenZir) !void { | |
| 13176 | if (gz.is_comptime) return; | |
| 13177 | const gpa = gz.astgen.gpa; | |
| 13178 | ||
| 13179 | const tags = gz.astgen.instructions.items(.tag); | |
| 13180 | const last_inst = gz.instructions.items[gz.instructions.items.len - 1]; | |
| 13181 | // remove dbg_block_begin immediately followed by dbg_block_end | |
| 13182 | if (tags[@intFromEnum(last_inst)] == .dbg_block_begin) { | |
| 13183 | _ = gz.instructions.pop(); | |
| 13184 | return; | |
| 13185 | } | |
| 13186 | ||
| 13187 | const new_index: Zir.Inst.Index = @enumFromInt(gz.astgen.instructions.len); | |
| 13188 | try gz.astgen.instructions.append(gpa, .{ .tag = .dbg_block_end, .data = undefined }); | |
| 13189 | try gz.instructions.append(gpa, new_index); | |
| 13190 | } | |
| 13191 | 13140 | }; |
| 13192 | 13141 | |
| 13193 | 13142 | /// This can only be for short-lived references; the memory becomes invalidated |
src/Liveness.zig-4| ... | ... | @@ -329,8 +329,6 @@ pub fn categorizeOperand( |
| 329 | 329 | .dbg_stmt, |
| 330 | 330 | .dbg_inline_begin, |
| 331 | 331 | .dbg_inline_end, |
| 332 | .dbg_block_begin, | |
| 333 | .dbg_block_end, | |
| 334 | 332 | .unreach, |
| 335 | 333 | .ret_addr, |
| 336 | 334 | .frame_addr, |
| ... | ... | @@ -967,8 +965,6 @@ fn analyzeInst( |
| 967 | 965 | .dbg_stmt, |
| 968 | 966 | .dbg_inline_begin, |
| 969 | 967 | .dbg_inline_end, |
| 970 | .dbg_block_begin, | |
| 971 | .dbg_block_end, | |
| 972 | 968 | .fence, |
| 973 | 969 | .ret_addr, |
| 974 | 970 | .frame_addr, |
src/Liveness/Verify.zig-2| ... | ... | @@ -48,8 +48,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 48 | 48 | .dbg_stmt, |
| 49 | 49 | .dbg_inline_begin, |
| 50 | 50 | .dbg_inline_end, |
| 51 | .dbg_block_begin, | |
| 52 | .dbg_block_end, | |
| 53 | 51 | .fence, |
| 54 | 52 | .ret_addr, |
| 55 | 53 | .frame_addr, |
src/Sema.zig+148-124| ... | ... | @@ -364,6 +364,12 @@ pub const Block = struct { |
| 364 | 364 | |
| 365 | 365 | c_import_buf: ?*std.ArrayList(u8) = null, |
| 366 | 366 | |
| 367 | /// If not `null`, this boolean is set when a `dbg_var_ptr` or `dbg_var_val` | |
| 368 | /// instruction is emitted. It signals that the innermost lexically | |
| 369 | /// enclosing `block`/`block_inline` should be translated into a real AIR | |
| 370 | /// `block` in order for codegen to match lexical scoping for debug vars. | |
| 371 | need_debug_scope: ?*bool = null, | |
| 372 | ||
| 367 | 373 | const ComptimeReason = union(enum) { |
| 368 | 374 | c_import: struct { |
| 369 | 375 | block: *Block, |
| ... | ... | @@ -482,6 +488,7 @@ pub const Block = struct { |
| 482 | 488 | .float_mode = parent.float_mode, |
| 483 | 489 | .c_import_buf = parent.c_import_buf, |
| 484 | 490 | .error_return_trace_index = parent.error_return_trace_index, |
| 491 | .need_debug_scope = parent.need_debug_scope, | |
| 485 | 492 | }; |
| 486 | 493 | } |
| 487 | 494 | |
| ... | ... | @@ -986,8 +993,6 @@ fn analyzeBodyInner( |
| 986 | 993 | crash_info.push(); |
| 987 | 994 | defer crash_info.pop(); |
| 988 | 995 | |
| 989 | var dbg_block_begins: u32 = 0; | |
| 990 | ||
| 991 | 996 | // We use a while (true) loop here to avoid a redundant way of breaking out of |
| 992 | 997 | // the loop. The only way to break out of the loop is with a `noreturn` |
| 993 | 998 | // instruction. |
| ... | ... | @@ -1332,18 +1337,6 @@ fn analyzeBodyInner( |
| 1332 | 1337 | i += 1; |
| 1333 | 1338 | continue; |
| 1334 | 1339 | }, |
| 1335 | .dbg_block_begin => { | |
| 1336 | dbg_block_begins += 1; | |
| 1337 | try zirDbgBlockBegin(block); | |
| 1338 | i += 1; | |
| 1339 | continue; | |
| 1340 | }, | |
| 1341 | .dbg_block_end => { | |
| 1342 | dbg_block_begins -= 1; | |
| 1343 | try zirDbgBlockEnd(block); | |
| 1344 | i += 1; | |
| 1345 | continue; | |
| 1346 | }, | |
| 1347 | 1340 | .ensure_err_union_payload_void => { |
| 1348 | 1341 | try sema.zirEnsureErrUnionPayloadVoid(block, inst); |
| 1349 | 1342 | i += 1; |
| ... | ... | @@ -1641,10 +1634,12 @@ fn analyzeBodyInner( |
| 1641 | 1634 | const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 1642 | 1635 | const gpa = sema.gpa; |
| 1643 | 1636 | |
| 1644 | const opt_break_data = b: { | |
| 1637 | const opt_break_data, const need_debug_scope = b: { | |
| 1645 | 1638 | // Create a temporary child block so that this inline block is properly |
| 1646 | 1639 | // labeled for any .restore_err_ret_index instructions |
| 1647 | 1640 | var child_block = block.makeSubBlock(); |
| 1641 | var need_debug_scope = false; | |
| 1642 | child_block.need_debug_scope = &need_debug_scope; | |
| 1648 | 1643 | |
| 1649 | 1644 | // If this block contains a function prototype, we need to reset the |
| 1650 | 1645 | // current list of parameters and restore it later. |
| ... | ... | @@ -1665,7 +1660,11 @@ fn analyzeBodyInner( |
| 1665 | 1660 | child_block.instructions = block.instructions; |
| 1666 | 1661 | defer block.instructions = child_block.instructions; |
| 1667 | 1662 | |
| 1668 | break :b try sema.analyzeBodyBreak(&child_block, inline_body); | |
| 1663 | const result = try sema.analyzeBodyBreak(&child_block, inline_body); | |
| 1664 | if (need_debug_scope) { | |
| 1665 | _ = try sema.ensurePostHoc(block, inst); | |
| 1666 | } | |
| 1667 | break :b .{ result, need_debug_scope }; | |
| 1669 | 1668 | }; |
| 1670 | 1669 | |
| 1671 | 1670 | // A runtime conditional branch that needs a post-hoc block to be |
| ... | ... | @@ -1686,28 +1685,22 @@ fn analyzeBodyInner( |
| 1686 | 1685 | // since it crosses a runtime branch. |
| 1687 | 1686 | // It may pass through our currently being analyzed block_inline or it |
| 1688 | 1687 | // may point directly to it. In the latter case, this modifies the |
| 1689 | // block that we are about to look up in the post_hoc_blocks map below. | |
| 1688 | // block that we looked up in the post_hoc_blocks map above. | |
| 1690 | 1689 | try sema.addRuntimeBreak(block, break_data); |
| 1691 | } else { | |
| 1692 | // Here the comptime control flow ends with noreturn; however | |
| 1693 | // we have runtime control flow continuing after this block. | |
| 1694 | // This branch is therefore handled by the `i += 1; continue;` | |
| 1695 | // logic below. | |
| 1696 | 1690 | } |
| 1697 | 1691 | |
| 1698 | 1692 | try labeled_block.block.instructions.appendSlice(gpa, block.instructions.items[block_index..]); |
| 1699 | 1693 | block.instructions.items.len = block_index; |
| 1700 | 1694 | |
| 1701 | const block_result = try sema.analyzeBlockBody(block, inst_data.src(), &labeled_block.block, &labeled_block.label.merges); | |
| 1695 | const block_result = try sema.analyzeBlockBody(block, inst_data.src(), &labeled_block.block, &labeled_block.label.merges, need_debug_scope); | |
| 1702 | 1696 | { |
| 1703 | 1697 | // Destroy the ad-hoc block entry so that it does not interfere with |
| 1704 | 1698 | // the next iteration of comptime control flow, if any. |
| 1705 | 1699 | labeled_block.destroy(gpa); |
| 1706 | 1700 | assert(sema.post_hoc_blocks.remove(new_block_inst)); |
| 1707 | 1701 | } |
| 1708 | map.putAssumeCapacity(inst, block_result); | |
| 1709 | i += 1; | |
| 1710 | continue; | |
| 1702 | ||
| 1703 | break :blk block_result; | |
| 1711 | 1704 | } |
| 1712 | 1705 | |
| 1713 | 1706 | const break_data = opt_break_data orelse break always_noreturn; |
| ... | ... | @@ -1860,19 +1853,6 @@ fn analyzeBodyInner( |
| 1860 | 1853 | i += 1; |
| 1861 | 1854 | }; |
| 1862 | 1855 | |
| 1863 | // balance out dbg_block_begins in case of early noreturn | |
| 1864 | if (!block.is_comptime and !block.ownerModule().strip) { | |
| 1865 | const noreturn_inst = block.instructions.popOrNull(); | |
| 1866 | while (dbg_block_begins > 0) { | |
| 1867 | dbg_block_begins -= 1; | |
| 1868 | _ = try block.addInst(.{ | |
| 1869 | .tag = .dbg_block_end, | |
| 1870 | .data = undefined, | |
| 1871 | }); | |
| 1872 | } | |
| 1873 | if (noreturn_inst) |some| try block.instructions.append(sema.gpa, some); | |
| 1874 | } | |
| 1875 | ||
| 1876 | 1856 | // We may have overwritten the capture scope due to a `repeat` instruction where |
| 1877 | 1857 | // the body had a capture; restore it now. |
| 1878 | 1858 | block.wip_capture_scope = parent_capture_scope; |
| ... | ... | @@ -5762,7 +5742,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError |
| 5762 | 5742 | ); |
| 5763 | 5743 | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(loop_block.instructions.items)); |
| 5764 | 5744 | } |
| 5765 | return sema.analyzeBlockBody(parent_block, src, &child_block, merges); | |
| 5745 | return sema.analyzeBlockBody(parent_block, src, &child_block, merges, false); | |
| 5766 | 5746 | } |
| 5767 | 5747 | |
| 5768 | 5748 | fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -5950,13 +5930,31 @@ fn resolveBlockBody( |
| 5950 | 5930 | if (child_block.is_comptime) { |
| 5951 | 5931 | return sema.resolveBody(child_block, body, body_inst); |
| 5952 | 5932 | } else { |
| 5933 | var need_debug_scope = false; | |
| 5934 | child_block.need_debug_scope = &need_debug_scope; | |
| 5953 | 5935 | if (sema.analyzeBodyInner(child_block, body)) |_| { |
| 5954 | return sema.analyzeBlockBody(parent_block, src, child_block, merges); | |
| 5936 | return sema.analyzeBlockBody(parent_block, src, child_block, merges, need_debug_scope); | |
| 5955 | 5937 | } else |err| switch (err) { |
| 5956 | 5938 | error.ComptimeBreak => { |
| 5957 | 5939 | // Comptime control flow is happening, however child_block may still contain |
| 5958 | 5940 | // runtime instructions which need to be copied to the parent block. |
| 5959 | try parent_block.instructions.appendSlice(sema.gpa, child_block.instructions.items); | |
| 5941 | if (need_debug_scope and child_block.instructions.items.len > 0) { | |
| 5942 | // We need a runtime block for scoping reasons. | |
| 5943 | _ = try child_block.addBr(merges.block_inst, .void_value); | |
| 5944 | try parent_block.instructions.append(sema.gpa, merges.block_inst); | |
| 5945 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Block).Struct.fields.len + | |
| 5946 | child_block.instructions.items.len); | |
| 5947 | sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{ | |
| 5948 | .ty = .void_type, | |
| 5949 | .payload = sema.addExtraAssumeCapacity(Air.Block{ | |
| 5950 | .body_len = @intCast(child_block.instructions.items.len), | |
| 5951 | }), | |
| 5952 | } }; | |
| 5953 | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items)); | |
| 5954 | } else { | |
| 5955 | // We can copy instructions directly to the parent block. | |
| 5956 | try parent_block.instructions.appendSlice(sema.gpa, child_block.instructions.items); | |
| 5957 | } | |
| 5960 | 5958 | |
| 5961 | 5959 | const break_inst = sema.comptime_break_inst; |
| 5962 | 5960 | const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break"; |
| ... | ... | @@ -5978,6 +5976,7 @@ fn analyzeBlockBody( |
| 5978 | 5976 | src: LazySrcLoc, |
| 5979 | 5977 | child_block: *Block, |
| 5980 | 5978 | merges: *Block.Merges, |
| 5979 | need_debug_scope: bool, | |
| 5981 | 5980 | ) CompileError!Air.Inst.Ref { |
| 5982 | 5981 | const tracy = trace(@src()); |
| 5983 | 5982 | defer tracy.end(); |
| ... | ... | @@ -5992,25 +5991,57 @@ fn analyzeBlockBody( |
| 5992 | 5991 | if (merges.results.items.len == 0) { |
| 5993 | 5992 | // No need for a block instruction. We can put the new instructions |
| 5994 | 5993 | // directly into the parent block. |
| 5994 | if (need_debug_scope) { | |
| 5995 | // The code following this block is unreachable, as the block has no | |
| 5996 | // merges, so we don't necessarily need to emit this as an AIR block. | |
| 5997 | // However, we need a block *somewhere* to make the scoping correct, | |
| 5998 | // so forward this request to the parent block. | |
| 5999 | if (parent_block.need_debug_scope) |ptr| ptr.* = true; | |
| 6000 | } | |
| 5995 | 6001 | try parent_block.instructions.appendSlice(gpa, child_block.instructions.items); |
| 5996 | 6002 | return child_block.instructions.items[child_block.instructions.items.len - 1].toRef(); |
| 5997 | 6003 | } |
| 5998 | 6004 | if (merges.results.items.len == 1) { |
| 5999 | const last_inst_index = child_block.instructions.items.len - 1; | |
| 6000 | const last_inst = child_block.instructions.items[last_inst_index]; | |
| 6001 | if (sema.getBreakBlock(last_inst)) |br_block| { | |
| 6002 | if (br_block == merges.block_inst) { | |
| 6003 | // No need for a block instruction. We can put the new instructions directly | |
| 6004 | // into the parent block. Here we omit the break instruction. | |
| 6005 | const without_break = child_block.instructions.items[0..last_inst_index]; | |
| 6006 | try parent_block.instructions.appendSlice(gpa, without_break); | |
| 6007 | return merges.results.items[0]; | |
| 6008 | } | |
| 6005 | // If the `break` is trailing, we may be able to elide the AIR block here | |
| 6006 | // by appending the new instructions directly to the parent block. | |
| 6007 | if (!need_debug_scope) { | |
| 6008 | const last_inst_index = child_block.instructions.items.len - 1; | |
| 6009 | const last_inst = child_block.instructions.items[last_inst_index]; | |
| 6010 | if (sema.getBreakBlock(last_inst)) |br_block| { | |
| 6011 | if (br_block == merges.block_inst) { | |
| 6012 | // Great, the last instruction is the break! Put the instructions | |
| 6013 | // directly into the parent block. | |
| 6014 | try parent_block.instructions.appendSlice(gpa, child_block.instructions.items[0..last_inst_index]); | |
| 6015 | return merges.results.items[0]; | |
| 6016 | } | |
| 6017 | } | |
| 6018 | } | |
| 6019 | // Okay, we need a runtime block. If the value is comptime-known, the | |
| 6020 | // block should just return void, and we return the merge result | |
| 6021 | // directly. Otherwise, we can defer to the logic below. | |
| 6022 | if (try sema.resolveValue(merges.results.items[0])) |result_val| { | |
| 6023 | // Create a block containing all instruction from the body. | |
| 6024 | try parent_block.instructions.append(gpa, merges.block_inst); | |
| 6025 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + | |
| 6026 | child_block.instructions.items.len); | |
| 6027 | sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{ | |
| 6028 | .ty = .void_type, | |
| 6029 | .payload = sema.addExtraAssumeCapacity(Air.Block{ | |
| 6030 | .body_len = @intCast(child_block.instructions.items.len), | |
| 6031 | }), | |
| 6032 | } }; | |
| 6033 | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items)); | |
| 6034 | // Rewrite the break to just give value {}; the value is | |
| 6035 | // comptime-known and will be returned directly. | |
| 6036 | sema.air_instructions.items(.data)[@intFromEnum(merges.br_list.items[0])].br.operand = .void_value; | |
| 6037 | return Air.internedToRef(result_val.toIntern()); | |
| 6009 | 6038 | } |
| 6010 | 6039 | } |
| 6011 | 6040 | // It is impossible to have the number of results be > 1 in a comptime scope. |
| 6012 | 6041 | assert(!child_block.is_comptime); // Should already got a compile error in the condbr condition. |
| 6013 | 6042 | |
| 6043 | // Note that we'll always create an AIR block here, so `need_debug_scope` is irrelevant. | |
| 6044 | ||
| 6014 | 6045 | // Need to set the type and emit the Block instruction. This allows machine code generation |
| 6015 | 6046 | // to emit a jump instruction to after the block when it encounters the break. |
| 6016 | 6047 | try parent_block.instructions.append(gpa, merges.block_inst); |
| ... | ... | @@ -6388,24 +6419,6 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi |
| 6388 | 6419 | }); |
| 6389 | 6420 | } |
| 6390 | 6421 | |
| 6391 | fn zirDbgBlockBegin(block: *Block) CompileError!void { | |
| 6392 | if (block.is_comptime or block.ownerModule().strip) return; | |
| 6393 | ||
| 6394 | _ = try block.addInst(.{ | |
| 6395 | .tag = .dbg_block_begin, | |
| 6396 | .data = undefined, | |
| 6397 | }); | |
| 6398 | } | |
| 6399 | ||
| 6400 | fn zirDbgBlockEnd(block: *Block) CompileError!void { | |
| 6401 | if (block.is_comptime or block.ownerModule().strip) return; | |
| 6402 | ||
| 6403 | _ = try block.addInst(.{ | |
| 6404 | .tag = .dbg_block_end, | |
| 6405 | .data = undefined, | |
| 6406 | }); | |
| 6407 | } | |
| 6408 | ||
| 6409 | 6422 | fn zirDbgVar( |
| 6410 | 6423 | sema: *Sema, |
| 6411 | 6424 | block: *Block, |
| ... | ... | @@ -6437,6 +6450,15 @@ fn addDbgVar( |
| 6437 | 6450 | if (try sema.typeRequiresComptime(val_ty)) return; |
| 6438 | 6451 | if (!(try sema.typeHasRuntimeBits(val_ty))) return; |
| 6439 | 6452 | |
| 6453 | // To ensure the lexical scoping is known to backends, this alloc must be | |
| 6454 | // within a real runtime block. We set a flag which communicates information | |
| 6455 | // to the closest lexically enclosing block: | |
| 6456 | // * If it is a `block_inline`, communicates to logic in `analyzeBodyInner` | |
| 6457 | // to create a post-hoc block. | |
| 6458 | // * Otherwise, communicates to logic in `resolveBlockBody` to create a | |
| 6459 | // real `block` instruction. | |
| 6460 | if (block.need_debug_scope) |ptr| ptr.* = true; | |
| 6461 | ||
| 6440 | 6462 | try sema.queueFullTypeResolution(operand_ty); |
| 6441 | 6463 | |
| 6442 | 6464 | // Add the name to the AIR. |
| ... | ... | @@ -7590,7 +7612,7 @@ fn analyzeCall( |
| 7590 | 7612 | error.ComptimeReturn => break :result inlining.comptime_result, |
| 7591 | 7613 | else => |e| return e, |
| 7592 | 7614 | }; |
| 7593 | break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); | |
| 7615 | break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges, false); | |
| 7594 | 7616 | }; |
| 7595 | 7617 | |
| 7596 | 7618 | if (!is_comptime_call and !block.is_typeof and |
| ... | ... | @@ -11534,7 +11556,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 11534 | 11556 | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions)); |
| 11535 | 11557 | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items)); |
| 11536 | 11558 | |
| 11537 | return sema.analyzeBlockBody(block, main_src, &child_block, merges); | |
| 11559 | return sema.analyzeBlockBody(block, main_src, &child_block, merges, false); | |
| 11538 | 11560 | } |
| 11539 | 11561 | |
| 11540 | 11562 | fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_ref: bool) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -12156,7 +12178,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 12156 | 12178 | false, |
| 12157 | 12179 | ); |
| 12158 | 12180 | |
| 12159 | return sema.analyzeBlockBody(block, src, &child_block, merges); | |
| 12181 | return sema.analyzeBlockBody(block, src, &child_block, merges, false); | |
| 12160 | 12182 | } |
| 12161 | 12183 | |
| 12162 | 12184 | const SpecialProng = struct { |
| ... | ... | @@ -13169,8 +13191,6 @@ fn validateErrSetSwitch( |
| 13169 | 13191 | const tags = sema.code.instructions.items(.tag); |
| 13170 | 13192 | const datas = sema.code.instructions.items(.data); |
| 13171 | 13193 | for (else_case.body) |else_inst| switch (tags[@intFromEnum(else_inst)]) { |
| 13172 | .dbg_block_begin, | |
| 13173 | .dbg_block_end, | |
| 13174 | 13194 | .dbg_stmt, |
| 13175 | 13195 | .dbg_var_val, |
| 13176 | 13196 | .ret_type, |
| ... | ... | @@ -13422,8 +13442,6 @@ fn maybeErrorUnwrap( |
| 13422 | 13442 | .@"unreachable" => if (!block.wantSafety()) return false, |
| 13423 | 13443 | .err_union_code => if (!allow_err_code_inst) return false, |
| 13424 | 13444 | .save_err_ret_index, |
| 13425 | .dbg_block_begin, | |
| 13426 | .dbg_block_end, | |
| 13427 | 13445 | .dbg_stmt, |
| 13428 | 13446 | .str, |
| 13429 | 13447 | .as_node, |
| ... | ... | @@ -13436,10 +13454,7 @@ fn maybeErrorUnwrap( |
| 13436 | 13454 | |
| 13437 | 13455 | for (body) |inst| { |
| 13438 | 13456 | const air_inst = switch (tags[@intFromEnum(inst)]) { |
| 13439 | .dbg_block_begin, | |
| 13440 | .dbg_block_end, | |
| 13441 | .err_union_code, | |
| 13442 | => continue, | |
| 13457 | .err_union_code => continue, | |
| 13443 | 13458 | .dbg_stmt => { |
| 13444 | 13459 | try sema.zirDbgStmt(block, inst); |
| 13445 | 13460 | continue; |
| ... | ... | @@ -13505,8 +13520,6 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I |
| 13505 | 13520 | const tags = sema.code.instructions.items(.tag); |
| 13506 | 13521 | const inst = for (body) |inst| { |
| 13507 | 13522 | switch (tags[@intFromEnum(inst)]) { |
| 13508 | .dbg_block_begin, | |
| 13509 | .dbg_block_end, | |
| 13510 | 13523 | .dbg_stmt, |
| 13511 | 13524 | .save_err_ret_index, |
| 13512 | 13525 | => {}, |
| ... | ... | @@ -19098,55 +19111,64 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr |
| 19098 | 19111 | return try_inst; |
| 19099 | 19112 | } |
| 19100 | 19113 | |
| 19114 | fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*LabeledBlock { | |
| 19115 | const gop = sema.inst_map.getOrPutAssumeCapacity(dest_block); | |
| 19116 | if (gop.found_existing) existing: { | |
| 19117 | // This may be a *result* from an earlier iteration of an inline loop. | |
| 19118 | // In this case, there will not be a post-hoc block entry, and we can | |
| 19119 | // continue with the logic below. | |
| 19120 | const new_block_inst = gop.value_ptr.*.toIndex() orelse break :existing; | |
| 19121 | return sema.post_hoc_blocks.get(new_block_inst) orelse break :existing; | |
| 19122 | } | |
| 19123 | ||
| 19124 | try sema.post_hoc_blocks.ensureUnusedCapacity(sema.gpa, 1); | |
| 19125 | ||
| 19126 | const new_block_inst: Air.Inst.Index = @enumFromInt(sema.air_instructions.len); | |
| 19127 | gop.value_ptr.* = new_block_inst.toRef(); | |
| 19128 | try sema.air_instructions.append(sema.gpa, .{ | |
| 19129 | .tag = .block, | |
| 19130 | .data = undefined, | |
| 19131 | }); | |
| 19132 | const labeled_block = try sema.gpa.create(LabeledBlock); | |
| 19133 | labeled_block.* = .{ | |
| 19134 | .label = .{ | |
| 19135 | .zir_block = dest_block, | |
| 19136 | .merges = .{ | |
| 19137 | .src_locs = .{}, | |
| 19138 | .results = .{}, | |
| 19139 | .br_list = .{}, | |
| 19140 | .block_inst = new_block_inst, | |
| 19141 | }, | |
| 19142 | }, | |
| 19143 | .block = .{ | |
| 19144 | .parent = block, | |
| 19145 | .sema = sema, | |
| 19146 | .src_decl = block.src_decl, | |
| 19147 | .namespace = block.namespace, | |
| 19148 | .wip_capture_scope = block.wip_capture_scope, | |
| 19149 | .instructions = .{}, | |
| 19150 | .label = &labeled_block.label, | |
| 19151 | .inlining = block.inlining, | |
| 19152 | .is_comptime = block.is_comptime, | |
| 19153 | }, | |
| 19154 | }; | |
| 19155 | sema.post_hoc_blocks.putAssumeCapacityNoClobber(new_block_inst, labeled_block); | |
| 19156 | return labeled_block; | |
| 19157 | } | |
| 19158 | ||
| 19101 | 19159 | // A `break` statement is inside a runtime condition, but trying to |
| 19102 | 19160 | // break from an inline loop. In such case we must convert it to |
| 19103 | 19161 | // a runtime break. |
| 19104 | 19162 | fn addRuntimeBreak(sema: *Sema, child_block: *Block, break_data: BreakData) !void { |
| 19105 | const gop = sema.inst_map.getOrPutAssumeCapacity(break_data.block_inst); | |
| 19106 | const labeled_block = if (!gop.found_existing) blk: { | |
| 19107 | try sema.post_hoc_blocks.ensureUnusedCapacity(sema.gpa, 1); | |
| 19108 | ||
| 19109 | const new_block_inst: Air.Inst.Index = @enumFromInt(sema.air_instructions.len); | |
| 19110 | gop.value_ptr.* = new_block_inst.toRef(); | |
| 19111 | try sema.air_instructions.append(sema.gpa, .{ | |
| 19112 | .tag = .block, | |
| 19113 | .data = undefined, | |
| 19114 | }); | |
| 19115 | const labeled_block = try sema.gpa.create(LabeledBlock); | |
| 19116 | labeled_block.* = .{ | |
| 19117 | .label = .{ | |
| 19118 | .zir_block = break_data.block_inst, | |
| 19119 | .merges = .{ | |
| 19120 | .src_locs = .{}, | |
| 19121 | .results = .{}, | |
| 19122 | .br_list = .{}, | |
| 19123 | .block_inst = new_block_inst, | |
| 19124 | }, | |
| 19125 | }, | |
| 19126 | .block = .{ | |
| 19127 | .parent = child_block, | |
| 19128 | .sema = sema, | |
| 19129 | .src_decl = child_block.src_decl, | |
| 19130 | .namespace = child_block.namespace, | |
| 19131 | .wip_capture_scope = child_block.wip_capture_scope, | |
| 19132 | .instructions = .{}, | |
| 19133 | .label = &labeled_block.label, | |
| 19134 | .inlining = child_block.inlining, | |
| 19135 | .is_comptime = child_block.is_comptime, | |
| 19136 | }, | |
| 19137 | }; | |
| 19138 | sema.post_hoc_blocks.putAssumeCapacityNoClobber(new_block_inst, labeled_block); | |
| 19139 | break :blk labeled_block; | |
| 19140 | } else blk: { | |
| 19141 | const new_block_inst = gop.value_ptr.*.toIndex().?; | |
| 19142 | const labeled_block = sema.post_hoc_blocks.get(new_block_inst).?; | |
| 19143 | break :blk labeled_block; | |
| 19144 | }; | |
| 19163 | const labeled_block = try sema.ensurePostHoc(child_block, break_data.block_inst); | |
| 19145 | 19164 | |
| 19146 | 19165 | const operand = try sema.resolveInst(break_data.operand); |
| 19147 | 19166 | const br_ref = try child_block.addBr(labeled_block.label.merges.block_inst, operand); |
| 19167 | ||
| 19148 | 19168 | try labeled_block.label.merges.results.append(sema.gpa, operand); |
| 19149 | 19169 | try labeled_block.label.merges.br_list.append(sema.gpa, br_ref.toIndex().?); |
| 19170 | try labeled_block.label.merges.src_locs.append(sema.gpa, null); | |
| 19171 | ||
| 19150 | 19172 | labeled_block.block.runtime_index.increment(); |
| 19151 | 19173 | if (labeled_block.block.runtime_cond == null and labeled_block.block.runtime_loop == null) { |
| 19152 | 19174 | labeled_block.block.runtime_cond = child_block.runtime_cond orelse child_block.runtime_loop; |
| ... | ... | @@ -19487,8 +19509,10 @@ fn analyzeRet( |
| 19487 | 19509 | return error.ComptimeReturn; |
| 19488 | 19510 | } |
| 19489 | 19511 | // We are inlining a function call; rewrite the `ret` as a `break`. |
| 19512 | const br_inst = try block.addBr(inlining.merges.block_inst, operand); | |
| 19490 | 19513 | try inlining.merges.results.append(sema.gpa, operand); |
| 19491 | _ = try block.addBr(inlining.merges.block_inst, operand); | |
| 19514 | try inlining.merges.br_list.append(sema.gpa, br_inst.toIndex().?); | |
| 19515 | try inlining.merges.src_locs.append(sema.gpa, operand_src); | |
| 19492 | 19516 | return always_noreturn; |
| 19493 | 19517 | } else if (block.is_comptime) { |
| 19494 | 19518 | return sema.fail(block, src, "function called at runtime cannot return value at comptime", .{}); |
src/Zir.zig-10| ... | ... | @@ -392,10 +392,6 @@ pub const Inst = struct { |
| 392 | 392 | /// Same as `dbg_var_ptr` but the local is always a const and the operand |
| 393 | 393 | /// is the local's value. |
| 394 | 394 | dbg_var_val, |
| 395 | /// Marks the beginning of a semantic scope for debug info variables. | |
| 396 | dbg_block_begin, | |
| 397 | /// Marks the end of a semantic scope for debug info variables. | |
| 398 | dbg_block_end, | |
| 399 | 395 | /// Uses a name to identify a Decl and takes a pointer to it. |
| 400 | 396 | /// Uses the `str_tok` union field. |
| 401 | 397 | decl_ref, |
| ... | ... | @@ -1107,8 +1103,6 @@ pub const Inst = struct { |
| 1107 | 1103 | .dbg_stmt, |
| 1108 | 1104 | .dbg_var_ptr, |
| 1109 | 1105 | .dbg_var_val, |
| 1110 | .dbg_block_begin, | |
| 1111 | .dbg_block_end, | |
| 1112 | 1106 | .decl_ref, |
| 1113 | 1107 | .decl_val, |
| 1114 | 1108 | .load, |
| ... | ... | @@ -1335,8 +1329,6 @@ pub const Inst = struct { |
| 1335 | 1329 | .dbg_stmt, |
| 1336 | 1330 | .dbg_var_ptr, |
| 1337 | 1331 | .dbg_var_val, |
| 1338 | .dbg_block_begin, | |
| 1339 | .dbg_block_end, | |
| 1340 | 1332 | .ensure_result_used, |
| 1341 | 1333 | .ensure_result_non_error, |
| 1342 | 1334 | .ensure_err_union_payload_void, |
| ... | ... | @@ -1663,8 +1655,6 @@ pub const Inst = struct { |
| 1663 | 1655 | .dbg_stmt = .dbg_stmt, |
| 1664 | 1656 | .dbg_var_ptr = .str_op, |
| 1665 | 1657 | .dbg_var_val = .str_op, |
| 1666 | .dbg_block_begin = .tok, | |
| 1667 | .dbg_block_end = .tok, | |
| 1668 | 1658 | .decl_ref = .str_tok, |
| 1669 | 1659 | .decl_val = .str_tok, |
| 1670 | 1660 | .load = .un_node, |
src/arch/aarch64/CodeGen.zig+1-9| ... | ... | @@ -813,10 +813,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 813 | 813 | .dbg_inline_end, |
| 814 | 814 | => try self.airDbgInline(inst), |
| 815 | 815 | |
| 816 | .dbg_block_begin, | |
| 817 | .dbg_block_end, | |
| 818 | => try self.airDbgBlock(inst), | |
| 819 | ||
| 820 | 816 | .call => try self.airCall(inst, .auto), |
| 821 | 817 | .call_always_tail => try self.airCall(inst, .always_tail), |
| 822 | 818 | .call_never_tail => try self.airCall(inst, .never_tail), |
| ... | ... | @@ -4634,11 +4630,6 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { |
| 4634 | 4630 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); |
| 4635 | 4631 | } |
| 4636 | 4632 | |
| 4637 | fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void { | |
| 4638 | // TODO emit debug info lexical block | |
| 4639 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); | |
| 4640 | } | |
| 4641 | ||
| 4642 | 4633 | fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 4643 | 4634 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 4644 | 4635 | const operand = pl_op.operand; |
| ... | ... | @@ -5066,6 +5057,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 5066 | 5057 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 5067 | 5058 | const extra = self.air.extraData(Air.Block, ty_pl.payload); |
| 5068 | 5059 | const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]); |
| 5060 | // TODO emit debug info lexical block | |
| 5069 | 5061 | try self.genBody(body); |
| 5070 | 5062 | |
| 5071 | 5063 | // relocations for `br` instructions |
src/arch/arm/CodeGen.zig+1-9| ... | ... | @@ -799,10 +799,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 799 | 799 | .dbg_inline_end, |
| 800 | 800 | => try self.airDbgInline(inst), |
| 801 | 801 | |
| 802 | .dbg_block_begin, | |
| 803 | .dbg_block_end, | |
| 804 | => try self.airDbgBlock(inst), | |
| 805 | ||
| 806 | 802 | .call => try self.airCall(inst, .auto), |
| 807 | 803 | .call_always_tail => try self.airCall(inst, .always_tail), |
| 808 | 804 | .call_never_tail => try self.airCall(inst, .never_tail), |
| ... | ... | @@ -4587,11 +4583,6 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { |
| 4587 | 4583 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); |
| 4588 | 4584 | } |
| 4589 | 4585 | |
| 4590 | fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void { | |
| 4591 | // TODO emit debug info lexical block | |
| 4592 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); | |
| 4593 | } | |
| 4594 | ||
| 4595 | 4586 | fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 4596 | 4587 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 4597 | 4588 | const operand = pl_op.operand; |
| ... | ... | @@ -4997,6 +4988,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 4997 | 4988 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4998 | 4989 | const extra = self.air.extraData(Air.Block, ty_pl.payload); |
| 4999 | 4990 | const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]); |
| 4991 | // TODO emit debug info lexical block | |
| 5000 | 4992 | try self.genBody(body); |
| 5001 | 4993 | |
| 5002 | 4994 | // relocations for `br` instructions |
src/arch/riscv64/CodeGen.zig+1-9| ... | ... | @@ -632,10 +632,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 632 | 632 | .dbg_inline_end, |
| 633 | 633 | => try self.airDbgInline(inst), |
| 634 | 634 | |
| 635 | .dbg_block_begin, | |
| 636 | .dbg_block_end, | |
| 637 | => try self.airDbgBlock(inst), | |
| 638 | ||
| 639 | 635 | .call => try self.airCall(inst, .auto), |
| 640 | 636 | .call_always_tail => try self.airCall(inst, .always_tail), |
| 641 | 637 | .call_never_tail => try self.airCall(inst, .never_tail), |
| ... | ... | @@ -1894,11 +1890,6 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { |
| 1894 | 1890 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); |
| 1895 | 1891 | } |
| 1896 | 1892 | |
| 1897 | fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void { | |
| 1898 | // TODO emit debug info lexical block | |
| 1899 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); | |
| 1900 | } | |
| 1901 | ||
| 1902 | 1893 | fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 1903 | 1894 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 1904 | 1895 | const name = self.air.nullTerminatedString(pl_op.payload); |
| ... | ... | @@ -2084,6 +2075,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 2084 | 2075 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 2085 | 2076 | const extra = self.air.extraData(Air.Block, ty_pl.payload); |
| 2086 | 2077 | const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]); |
| 2078 | // TODO emit debug info lexical block | |
| 2087 | 2079 | try self.genBody(body); |
| 2088 | 2080 | |
| 2089 | 2081 | for (self.blocks.getPtr(inst).?.relocs.items) |reloc| try self.performReloc(reloc); |
src/arch/sparc64/CodeGen.zig+1-9| ... | ... | @@ -645,10 +645,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 645 | 645 | .dbg_inline_end, |
| 646 | 646 | => try self.airDbgInline(inst), |
| 647 | 647 | |
| 648 | .dbg_block_begin, | |
| 649 | .dbg_block_end, | |
| 650 | => try self.airDbgBlock(inst), | |
| 651 | ||
| 652 | 648 | .call => try self.airCall(inst, .auto), |
| 653 | 649 | .call_always_tail => try self.airCall(inst, .always_tail), |
| 654 | 650 | .call_never_tail => try self.airCall(inst, .never_tail), |
| ... | ... | @@ -1146,6 +1142,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 1146 | 1142 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 1147 | 1143 | const extra = self.air.extraData(Air.Block, ty_pl.payload); |
| 1148 | 1144 | const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]); |
| 1145 | // TODO emit debug info lexical block | |
| 1149 | 1146 | try self.genBody(body); |
| 1150 | 1147 | |
| 1151 | 1148 | // relocations for `bpcc` instructions |
| ... | ... | @@ -1655,11 +1652,6 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 1655 | 1652 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1656 | 1653 | } |
| 1657 | 1654 | |
| 1658 | fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void { | |
| 1659 | // TODO emit debug info lexical block | |
| 1660 | return self.finishAir(inst, .dead, .{ .none, .none, .none }); | |
| 1661 | } | |
| 1662 | ||
| 1663 | 1655 | fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { |
| 1664 | 1656 | const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn; |
| 1665 | 1657 | const mod = self.bin_file.comp.module.?; |
src/arch/wasm/CodeGen.zig-2| ... | ... | @@ -1913,8 +1913,6 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1913 | 1913 | // TODO |
| 1914 | 1914 | .dbg_inline_begin, |
| 1915 | 1915 | .dbg_inline_end, |
| 1916 | .dbg_block_begin, | |
| 1917 | .dbg_block_end, | |
| 1918 | 1916 | => func.finishAir(inst, .none, &.{}), |
| 1919 | 1917 | |
| 1920 | 1918 | .dbg_var_ptr => func.airDbgVar(inst, true), |
src/arch/x86_64/CodeGen.zig+1-10| ... | ... | @@ -2106,10 +2106,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2106 | 2106 | .dbg_inline_end, |
| 2107 | 2107 | => try self.airDbgInline(inst), |
| 2108 | 2108 | |
| 2109 | .dbg_block_begin, | |
| 2110 | .dbg_block_end, | |
| 2111 | => try self.airDbgBlock(inst), | |
| 2112 | ||
| 2113 | 2109 | .call => try self.airCall(inst, .auto), |
| 2114 | 2110 | .call_always_tail => try self.airCall(inst, .always_tail), |
| 2115 | 2111 | .call_never_tail => try self.airCall(inst, .never_tail), |
| ... | ... | @@ -12976,12 +12972,6 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { |
| 12976 | 12972 | self.finishAirBookkeeping(); |
| 12977 | 12973 | } |
| 12978 | 12974 | |
| 12979 | fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void { | |
| 12980 | _ = inst; | |
| 12981 | // TODO emit debug info lexical block | |
| 12982 | self.finishAirBookkeeping(); | |
| 12983 | } | |
| 12984 | ||
| 12985 | 12975 | fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 12986 | 12976 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 12987 | 12977 | const operand = pl_op.operand; |
| ... | ... | @@ -13428,6 +13418,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 13428 | 13418 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 13429 | 13419 | const extra = self.air.extraData(Air.Block, ty_pl.payload); |
| 13430 | 13420 | const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]); |
| 13421 | // TODO emit debug info lexical block | |
| 13431 | 13422 | try self.genBody(body); |
| 13432 | 13423 | |
| 13433 | 13424 | var block_data = self.blocks.fetchRemove(inst).?; |
src/codegen/c.zig-4| ... | ... | @@ -3268,10 +3268,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3268 | 3268 | .dbg_inline_end, |
| 3269 | 3269 | => try airDbgInline(f, inst), |
| 3270 | 3270 | |
| 3271 | .dbg_block_begin, | |
| 3272 | .dbg_block_end, | |
| 3273 | => .none, | |
| 3274 | ||
| 3275 | 3271 | .call => try airCall(f, inst, .auto), |
| 3276 | 3272 | .call_always_tail => .none, |
| 3277 | 3273 | .call_never_tail => try airCall(f, inst, .never_tail), |
src/codegen/llvm.zig+16-28| ... | ... | @@ -4768,8 +4768,6 @@ pub const FuncGen = struct { |
| 4768 | 4768 | scope: Builder.Metadata, |
| 4769 | 4769 | }) = .{}, |
| 4770 | 4770 | |
| 4771 | scope_stack: std.ArrayListUnmanaged(Builder.Metadata) = .{}, | |
| 4772 | ||
| 4773 | 4771 | base_line: u32, |
| 4774 | 4772 | prev_dbg_line: c_uint, |
| 4775 | 4773 | prev_dbg_column: c_uint, |
| ... | ... | @@ -4813,7 +4811,6 @@ pub const FuncGen = struct { |
| 4813 | 4811 | |
| 4814 | 4812 | fn deinit(self: *FuncGen) void { |
| 4815 | 4813 | self.wip.deinit(); |
| 4816 | self.scope_stack.deinit(self.gpa); | |
| 4817 | 4814 | self.inlined.deinit(self.gpa); |
| 4818 | 4815 | self.func_inst_table.deinit(self.gpa); |
| 4819 | 4816 | self.blocks.deinit(self.gpa); |
| ... | ... | @@ -5112,8 +5109,6 @@ pub const FuncGen = struct { |
| 5112 | 5109 | .dbg_stmt => try self.airDbgStmt(inst), |
| 5113 | 5110 | .dbg_inline_begin => try self.airDbgInlineBegin(inst), |
| 5114 | 5111 | .dbg_inline_end => try self.airDbgInlineEnd(inst), |
| 5115 | .dbg_block_begin => try self.airDbgBlockBegin(), | |
| 5116 | .dbg_block_end => try self.airDbgBlockEnd(), | |
| 5117 | 5112 | .dbg_var_ptr => try self.airDbgVarPtr(inst), |
| 5118 | 5113 | .dbg_var_val => try self.airDbgVarVal(inst), |
| 5119 | 5114 | |
| ... | ... | @@ -5131,6 +5126,19 @@ pub const FuncGen = struct { |
| 5131 | 5126 | } |
| 5132 | 5127 | } |
| 5133 | 5128 | |
| 5129 | fn genBodyDebugScope(self: *FuncGen, body: []const Air.Inst.Index) Error!void { | |
| 5130 | if (self.wip.strip) return self.genBody(body); | |
| 5131 | const old_scope = self.scope; | |
| 5132 | self.scope = try self.dg.object.builder.debugLexicalBlock( | |
| 5133 | old_scope, | |
| 5134 | self.file, | |
| 5135 | self.prev_dbg_line, | |
| 5136 | self.prev_dbg_column, | |
| 5137 | ); | |
| 5138 | try self.genBody(body); | |
| 5139 | self.scope = old_scope; | |
| 5140 | } | |
| 5141 | ||
| 5134 | 5142 | pub const CallAttr = enum { |
| 5135 | 5143 | Auto, |
| 5136 | 5144 | NeverTail, |
| ... | ... | @@ -5820,7 +5828,7 @@ pub const FuncGen = struct { |
| 5820 | 5828 | const inst_ty = self.typeOfIndex(inst); |
| 5821 | 5829 | |
| 5822 | 5830 | if (inst_ty.isNoReturn(mod)) { |
| 5823 | try self.genBody(body); | |
| 5831 | try self.genBodyDebugScope(body); | |
| 5824 | 5832 | return .none; |
| 5825 | 5833 | } |
| 5826 | 5834 | |
| ... | ... | @@ -5836,7 +5844,7 @@ pub const FuncGen = struct { |
| 5836 | 5844 | }); |
| 5837 | 5845 | defer assert(self.blocks.remove(inst)); |
| 5838 | 5846 | |
| 5839 | try self.genBody(body); | |
| 5847 | try self.genBodyDebugScope(body); | |
| 5840 | 5848 | |
| 5841 | 5849 | self.wip.cursor = .{ .block = parent_bb }; |
| 5842 | 5850 | |
| ... | ... | @@ -6683,26 +6691,6 @@ pub const FuncGen = struct { |
| 6683 | 6691 | return .none; |
| 6684 | 6692 | } |
| 6685 | 6693 | |
| 6686 | fn airDbgBlockBegin(self: *FuncGen) Allocator.Error!Builder.Value { | |
| 6687 | const o = self.dg.object; | |
| 6688 | ||
| 6689 | try self.scope_stack.append(self.gpa, self.scope); | |
| 6690 | ||
| 6691 | const old = self.scope; | |
| 6692 | self.scope = try o.builder.debugLexicalBlock( | |
| 6693 | old, | |
| 6694 | self.file, | |
| 6695 | self.prev_dbg_line, | |
| 6696 | self.prev_dbg_column, | |
| 6697 | ); | |
| 6698 | return .none; | |
| 6699 | } | |
| 6700 | ||
| 6701 | fn airDbgBlockEnd(self: *FuncGen) !Builder.Value { | |
| 6702 | self.scope = self.scope_stack.pop(); | |
| 6703 | return .none; | |
| 6704 | } | |
| 6705 | ||
| 6706 | 6694 | fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6707 | 6695 | const o = self.dg.object; |
| 6708 | 6696 | const mod = o.module; |
| ... | ... | @@ -7488,7 +7476,7 @@ pub const FuncGen = struct { |
| 7488 | 7476 | for (body_tail[1..]) |body_inst| { |
| 7489 | 7477 | switch (air_tags[@intFromEnum(body_inst)]) { |
| 7490 | 7478 | .ret => return true, |
| 7491 | .dbg_stmt, .dbg_block_end => continue, | |
| 7479 | .dbg_stmt => continue, | |
| 7492 | 7480 | else => return false, |
| 7493 | 7481 | } |
| 7494 | 7482 | } |
src/codegen/spirv.zig-2| ... | ... | @@ -2322,8 +2322,6 @@ const DeclGen = struct { |
| 2322 | 2322 | .dbg_inline_begin => return self.airDbgInlineBegin(inst), |
| 2323 | 2323 | .dbg_inline_end => return self.airDbgInlineEnd(inst), |
| 2324 | 2324 | .dbg_var_ptr, .dbg_var_val => return self.airDbgVar(inst), |
| 2325 | .dbg_block_begin => return, | |
| 2326 | .dbg_block_end => return, | |
| 2327 | 2325 | |
| 2328 | 2326 | .unwrap_errunion_err => try self.airErrUnionErr(inst), |
| 2329 | 2327 | .unwrap_errunion_payload => try self.airErrUnionPayload(inst), |
src/print_air.zig-2| ... | ... | @@ -319,8 +319,6 @@ const Writer = struct { |
| 319 | 319 | .cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst), |
| 320 | 320 | .vector_store_elem => try w.writeVectorStoreElem(s, inst), |
| 321 | 321 | |
| 322 | .dbg_block_begin, .dbg_block_end => {}, | |
| 323 | ||
| 324 | 322 | .work_item_id, |
| 325 | 323 | .work_group_size, |
| 326 | 324 | .work_group_id, |
src/print_zir.zig-4| ... | ... | @@ -510,10 +510,6 @@ const Writer = struct { |
| 510 | 510 | |
| 511 | 511 | .dbg_stmt => try self.writeDbgStmt(stream, inst), |
| 512 | 512 | |
| 513 | .dbg_block_begin, | |
| 514 | .dbg_block_end, | |
| 515 | => try stream.writeAll(")"), | |
| 516 | ||
| 517 | 513 | .closure_get => try self.writeInstNode(stream, inst), |
| 518 | 514 | |
| 519 | 515 | .@"defer" => try self.writeDefer(stream, inst), |
test/behavior/eval.zig+18| ... | ... | @@ -1714,3 +1714,21 @@ test "const with specified type initialized with typed array is comptime-known" |
| 1714 | 1714 | comptime assert(x[1] == 2); |
| 1715 | 1715 | comptime assert(x[2] == 3); |
| 1716 | 1716 | } |
| 1717 | ||
| 1718 | test "block with comptime-known result but possible runtime exit is comptime-known" { | |
| 1719 | var t: bool = true; | |
| 1720 | _ = &t; | |
| 1721 | ||
| 1722 | const a: comptime_int = a: { | |
| 1723 | if (!t) return error.TestFailed; | |
| 1724 | break :a 123; | |
| 1725 | }; | |
| 1726 | ||
| 1727 | const b: comptime_int = b: { | |
| 1728 | if (t) break :b 456; | |
| 1729 | return error.TestFailed; | |
| 1730 | }; | |
| 1731 | ||
| 1732 | comptime assert(a == 123); | |
| 1733 | comptime assert(b == 456); | |
| 1734 | } |