authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-20 16:32:10-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-20 17:04:11-07:00
loga59bcae59f1b45ef6585793e6b90e490593c4d31
tree065a1d7239c6fa8baf8e9ee1e9543eb0789754be
parentb4aec0e31db2c9ea7bc2c892f0e557a0de8f4735

AstGen: basic defer implementation


4 files changed, 541 insertions(+), 344 deletions(-)

BRANCH_TODO+13
......@@ -1,3 +1,7 @@
1 * defer
2 - `break`
3 - `continue`
4 * nested function decl: how to refer to params?
15 * look for cached zir code
26 * save zir code to cache
37 * keep track of file dependencies/dependants
......@@ -13,6 +17,15 @@
1317 on each usingnamespace decl
1418 * handle usingnamespace cycles
1519
20 * compile error for return inside defer expression
21
22 * when block has noreturn statement
23 - avoid emitting defers
24 - compile error for unreachable code
25
26 * detect `return error.Foo` and emit ZIR that unconditionally generates errdefers
27 * `return`: check return operand and generate errdefers if necessary
28
1629 * have failed_trees and just put the file in there
1730 - this way we can emit all the parse errors not just the first one
1831 - but maybe we want just the first one?
src/AstGen.zig+464-308
......@@ -37,6 +37,8 @@ string_table: std.StringHashMapUnmanaged(u32) = .{},
3737compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{},
3838/// String table indexes, keeps track of all `@import` operands.
3939imports: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
40/// The topmost block of the current function.
41fn_block: ?*GenZir = null,
4042
4143pub fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {
4244 const fields = std.meta.fields(@TypeOf(extra));
......@@ -82,7 +84,7 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {
8284 // First few indexes of extra are reserved and set at the end.
8385 try astgen.extra.resize(gpa, @typeInfo(Zir.ExtraIndex).Enum.fields.len);
8486
85 var gen_scope: Scope.GenZir = .{
87 var gen_scope: GenZir = .{
8688 .force_comptime = true,
8789 .parent = &file.base,
8890 .decl_node_index = 0,
......@@ -461,6 +463,8 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
461463 .local_var_decl => unreachable, // Handled in `blockExpr`.
462464 .simple_var_decl => unreachable, // Handled in `blockExpr`.
463465 .aligned_var_decl => unreachable, // Handled in `blockExpr`.
466 .@"defer" => unreachable, // Handled in `blockExpr`.
467 .@"errdefer" => unreachable, // Handled in `blockExpr`.
464468
465469 .switch_case => unreachable, // Handled in `switchExpr`.
466470 .switch_case_one => unreachable, // Handled in `switchExpr`.
......@@ -818,8 +822,6 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
818822 .@"await" => return astgen.failNode(node, "async and related features are not yet supported", .{}),
819823 .@"resume" => return astgen.failNode(node, "async and related features are not yet supported", .{}),
820824
821 .@"defer" => return astgen.failNode(node, "TODO implement astgen.expr for .defer", .{}),
822 .@"errdefer" => return astgen.failNode(node, "TODO implement astgen.expr for .errdefer", .{}),
823825 .@"try" => return tryExpr(gz, scope, rl, node_datas[node].lhs),
824826
825827 .array_init_one, .array_init_one_comma => {
......@@ -1245,6 +1247,8 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn
12451247 },
12461248 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
12471249 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1250 .defer_normal => @panic("TODO break/defer"),
1251 .defer_error => @panic("TODO break/defer"),
12481252 else => if (break_label != 0) {
12491253 const label_name = try astgen.identifierTokenString(break_label);
12501254 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
......@@ -1290,6 +1294,8 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)
12901294 },
12911295 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
12921296 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1297 .defer_normal => @panic("TODO continue/defer"),
1298 .defer_error => @panic("TODO continue/defer"),
12931299 else => if (break_label != 0) {
12941300 const label_name = try astgen.identifierTokenString(break_label);
12951301 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
......@@ -1354,6 +1360,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: ast.Toke
13541360 },
13551361 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
13561362 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1363 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
13571364 else => return,
13581365 }
13591366 }
......@@ -1393,6 +1400,7 @@ fn labeledBlockExpr(
13931400 .decl_node_index = gz.decl_node_index,
13941401 .astgen = gz.astgen,
13951402 .force_comptime = gz.force_comptime,
1403 .ref_start_index = gz.ref_start_index,
13961404 .instructions = .{},
13971405 // TODO @as here is working around a stage1 miscompilation bug :(
13981406 .label = @as(?GenZir.Label, GenZir.Label{
......@@ -1463,16 +1471,16 @@ fn blockExprStmts(
14631471
14641472 var scope = parent_scope;
14651473 for (statements) |statement| {
1466 if (!gz.force_comptime) {
1467 _ = try gz.addNode(.dbg_stmt_node, statement);
1468 }
14691474 switch (node_tags[statement]) {
1470 .global_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.globalVarDecl(statement)),
1471 .local_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.localVarDecl(statement)),
1472 .simple_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.simpleVarDecl(statement)),
1475 // zig fmt: off
1476 .global_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.globalVarDecl(statement)),
1477 .local_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.localVarDecl(statement)),
1478 .simple_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.simpleVarDecl(statement)),
14731479 .aligned_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.alignedVarDecl(statement)),
14741480
1475 // zig fmt: off
1481 .@"defer" => scope = try deferStmt(gz, scope, statement, &block_arena.allocator, .defer_normal),
1482 .@"errdefer" => scope = try deferStmt(gz, scope, statement, &block_arena.allocator, .defer_error),
1483
14761484 .assign => try assign(gz, scope, statement),
14771485
14781486 .assign_bit_shift_left => try assignShift(gz, scope, statement, .shl),
......@@ -1489,302 +1497,357 @@ fn blockExprStmts(
14891497 .assign_add_wrap => try assignOp(gz, scope, statement, .addwrap),
14901498 .assign_mul => try assignOp(gz, scope, statement, .mul),
14911499 .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),
1500
1501 else => try unusedResultExpr(gz, scope, statement),
14921502 // zig fmt: on
1503 }
1504 }
14931505
1494 else => {
1495 // We need to emit an error if the result is not `noreturn` or `void`, but
1496 // we want to avoid adding the ZIR instruction if possible for performance.
1497 const maybe_unused_result = try expr(gz, scope, .none, statement);
1498 const elide_check = if (gz.refToIndex(maybe_unused_result)) |inst| b: {
1499 // Note that this array becomes invalid after appending more items to it
1500 // in the above while loop.
1501 const zir_tags = gz.astgen.instructions.items(.tag);
1502 switch (zir_tags[inst]) {
1503 // For some instructions, swap in a slightly different ZIR tag
1504 // so we can avoid a separate ensure_result_used instruction.
1505 .call_none_chkused => unreachable,
1506 .call_none => {
1507 zir_tags[inst] = .call_none_chkused;
1508 break :b true;
1509 },
1510 .call_chkused => unreachable,
1511 .call => {
1512 zir_tags[inst] = .call_chkused;
1513 break :b true;
1514 },
1506 try genDefers(gz, parent_scope, scope, .none);
1507}
15151508
1516 // ZIR instructions that might be a type other than `noreturn` or `void`.
1517 .add,
1518 .addwrap,
1519 .alloc,
1520 .alloc_mut,
1521 .alloc_inferred,
1522 .alloc_inferred_mut,
1523 .array_cat,
1524 .array_mul,
1525 .array_type,
1526 .array_type_sentinel,
1527 .elem_type,
1528 .indexable_ptr_len,
1529 .as,
1530 .as_node,
1531 .@"asm",
1532 .asm_volatile,
1533 .bit_and,
1534 .bitcast,
1535 .bitcast_result_ptr,
1536 .bit_or,
1537 .block,
1538 .block_inline,
1539 .block_inline_var,
1540 .loop,
1541 .bool_br_and,
1542 .bool_br_or,
1543 .bool_not,
1544 .bool_and,
1545 .bool_or,
1546 .call_compile_time,
1547 .cmp_lt,
1548 .cmp_lte,
1549 .cmp_eq,
1550 .cmp_gte,
1551 .cmp_gt,
1552 .cmp_neq,
1553 .coerce_result_ptr,
1554 .decl_ref,
1555 .decl_val,
1556 .load,
1557 .div,
1558 .elem_ptr,
1559 .elem_val,
1560 .elem_ptr_node,
1561 .elem_val_node,
1562 .field_ptr,
1563 .field_val,
1564 .field_ptr_named,
1565 .field_val_named,
1566 .func,
1567 .func_inferred,
1568 .int,
1569 .float,
1570 .float128,
1571 .intcast,
1572 .int_type,
1573 .is_non_null,
1574 .is_null,
1575 .is_non_null_ptr,
1576 .is_null_ptr,
1577 .is_err,
1578 .is_err_ptr,
1579 .mod_rem,
1580 .mul,
1581 .mulwrap,
1582 .param_type,
1583 .ptrtoint,
1584 .ref,
1585 .shl,
1586 .shr,
1587 .str,
1588 .sub,
1589 .subwrap,
1590 .negate,
1591 .negate_wrap,
1592 .typeof,
1593 .typeof_elem,
1594 .xor,
1595 .optional_type,
1596 .optional_type_from_ptr_elem,
1597 .optional_payload_safe,
1598 .optional_payload_unsafe,
1599 .optional_payload_safe_ptr,
1600 .optional_payload_unsafe_ptr,
1601 .err_union_payload_safe,
1602 .err_union_payload_unsafe,
1603 .err_union_payload_safe_ptr,
1604 .err_union_payload_unsafe_ptr,
1605 .err_union_code,
1606 .err_union_code_ptr,
1607 .ptr_type,
1608 .ptr_type_simple,
1609 .enum_literal,
1610 .enum_literal_small,
1611 .merge_error_sets,
1612 .error_union_type,
1613 .bit_not,
1614 .error_value,
1615 .error_to_int,
1616 .int_to_error,
1617 .slice_start,
1618 .slice_end,
1619 .slice_sentinel,
1620 .import,
1621 .typeof_peer,
1622 .switch_block,
1623 .switch_block_multi,
1624 .switch_block_else,
1625 .switch_block_else_multi,
1626 .switch_block_under,
1627 .switch_block_under_multi,
1628 .switch_block_ref,
1629 .switch_block_ref_multi,
1630 .switch_block_ref_else,
1631 .switch_block_ref_else_multi,
1632 .switch_block_ref_under,
1633 .switch_block_ref_under_multi,
1634 .switch_capture,
1635 .switch_capture_ref,
1636 .switch_capture_multi,
1637 .switch_capture_multi_ref,
1638 .switch_capture_else,
1639 .switch_capture_else_ref,
1640 .struct_init_empty,
1641 .struct_init,
1642 .struct_init_anon,
1643 .array_init,
1644 .array_init_anon,
1645 .array_init_ref,
1646 .array_init_anon_ref,
1647 .union_init_ptr,
1648 .field_type,
1649 .field_type_ref,
1650 .struct_decl,
1651 .struct_decl_packed,
1652 .struct_decl_extern,
1653 .union_decl,
1654 .enum_decl,
1655 .enum_decl_nonexhaustive,
1656 .opaque_decl,
1657 .error_set_decl,
1658 .int_to_enum,
1659 .enum_to_int,
1660 .type_info,
1661 .size_of,
1662 .bit_size_of,
1663 .add_with_overflow,
1664 .sub_with_overflow,
1665 .mul_with_overflow,
1666 .shl_with_overflow,
1667 .log2_int_type,
1668 .typeof_log2_int_type,
1669 .ptr_to_int,
1670 .align_of,
1671 .bool_to_int,
1672 .embed_file,
1673 .error_name,
1674 .sqrt,
1675 .sin,
1676 .cos,
1677 .exp,
1678 .exp2,
1679 .log,
1680 .log2,
1681 .log10,
1682 .fabs,
1683 .floor,
1684 .ceil,
1685 .trunc,
1686 .round,
1687 .tag_name,
1688 .reify,
1689 .type_name,
1690 .frame_type,
1691 .frame_size,
1692 .float_to_int,
1693 .int_to_float,
1694 .int_to_ptr,
1695 .float_cast,
1696 .int_cast,
1697 .err_set_cast,
1698 .ptr_cast,
1699 .truncate,
1700 .align_cast,
1701 .has_decl,
1702 .has_field,
1703 .clz,
1704 .ctz,
1705 .pop_count,
1706 .byte_swap,
1707 .bit_reverse,
1708 .div_exact,
1709 .div_floor,
1710 .div_trunc,
1711 .mod,
1712 .rem,
1713 .shl_exact,
1714 .shr_exact,
1715 .bit_offset_of,
1716 .byte_offset_of,
1717 .cmpxchg_strong,
1718 .cmpxchg_weak,
1719 .splat,
1720 .reduce,
1721 .shuffle,
1722 .atomic_load,
1723 .atomic_rmw,
1724 .atomic_store,
1725 .mul_add,
1726 .builtin_call,
1727 .field_ptr_type,
1728 .field_parent_ptr,
1729 .memcpy,
1730 .memset,
1731 .builtin_async_call,
1732 .c_import,
1733 .extended,
1734 => break :b false,
1735
1736 // ZIR instructions that are always either `noreturn` or `void`.
1737 .breakpoint,
1738 .fence,
1739 .dbg_stmt_node,
1740 .ensure_result_used,
1741 .ensure_result_non_error,
1742 .@"export",
1743 .set_eval_branch_quota,
1744 .compile_log,
1745 .ensure_err_payload_void,
1746 .@"break",
1747 .break_inline,
1748 .condbr,
1749 .condbr_inline,
1750 .compile_error,
1751 .ret_node,
1752 .ret_tok,
1753 .ret_coerce,
1754 .@"unreachable",
1755 .store,
1756 .store_node,
1757 .store_to_block_ptr,
1758 .store_to_inferred_ptr,
1759 .resolve_inferred_alloc,
1760 .repeat,
1761 .repeat_inline,
1762 .validate_struct_init_ptr,
1763 .validate_array_init_ptr,
1764 .panic,
1765 .set_align_stack,
1766 .set_cold,
1767 .set_float_mode,
1768 .set_runtime_safety,
1769 => break :b true,
1770 }
1771 } else switch (maybe_unused_result) {
1772 .none => unreachable,
1509fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) InnerError!void {
1510 try emitDbgNode(gz, statement);
1511 // We need to emit an error if the result is not `noreturn` or `void`, but
1512 // we want to avoid adding the ZIR instruction if possible for performance.
1513 const maybe_unused_result = try expr(gz, scope, .none, statement);
1514 const elide_check = if (gz.refToIndex(maybe_unused_result)) |inst| b: {
1515 // Note that this array becomes invalid after appending more items to it
1516 // in the above while loop.
1517 const zir_tags = gz.astgen.instructions.items(.tag);
1518 switch (zir_tags[inst]) {
1519 // For some instructions, swap in a slightly different ZIR tag
1520 // so we can avoid a separate ensure_result_used instruction.
1521 .call_none_chkused => unreachable,
1522 .call_none => {
1523 zir_tags[inst] = .call_none_chkused;
1524 break :b true;
1525 },
1526 .call_chkused => unreachable,
1527 .call => {
1528 zir_tags[inst] = .call_chkused;
1529 break :b true;
1530 },
17731531
1774 .void_value,
1775 .unreachable_value,
1776 => true,
1532 // ZIR instructions that might be a type other than `noreturn` or `void`.
1533 .add,
1534 .addwrap,
1535 .alloc,
1536 .alloc_mut,
1537 .alloc_inferred,
1538 .alloc_inferred_mut,
1539 .array_cat,
1540 .array_mul,
1541 .array_type,
1542 .array_type_sentinel,
1543 .elem_type,
1544 .indexable_ptr_len,
1545 .as,
1546 .as_node,
1547 .@"asm",
1548 .asm_volatile,
1549 .bit_and,
1550 .bitcast,
1551 .bitcast_result_ptr,
1552 .bit_or,
1553 .block,
1554 .block_inline,
1555 .block_inline_var,
1556 .loop,
1557 .bool_br_and,
1558 .bool_br_or,
1559 .bool_not,
1560 .bool_and,
1561 .bool_or,
1562 .call_compile_time,
1563 .cmp_lt,
1564 .cmp_lte,
1565 .cmp_eq,
1566 .cmp_gte,
1567 .cmp_gt,
1568 .cmp_neq,
1569 .coerce_result_ptr,
1570 .decl_ref,
1571 .decl_val,
1572 .load,
1573 .div,
1574 .elem_ptr,
1575 .elem_val,
1576 .elem_ptr_node,
1577 .elem_val_node,
1578 .field_ptr,
1579 .field_val,
1580 .field_ptr_named,
1581 .field_val_named,
1582 .func,
1583 .func_inferred,
1584 .int,
1585 .float,
1586 .float128,
1587 .intcast,
1588 .int_type,
1589 .is_non_null,
1590 .is_null,
1591 .is_non_null_ptr,
1592 .is_null_ptr,
1593 .is_err,
1594 .is_err_ptr,
1595 .mod_rem,
1596 .mul,
1597 .mulwrap,
1598 .param_type,
1599 .ptrtoint,
1600 .ref,
1601 .shl,
1602 .shr,
1603 .str,
1604 .sub,
1605 .subwrap,
1606 .negate,
1607 .negate_wrap,
1608 .typeof,
1609 .typeof_elem,
1610 .xor,
1611 .optional_type,
1612 .optional_type_from_ptr_elem,
1613 .optional_payload_safe,
1614 .optional_payload_unsafe,
1615 .optional_payload_safe_ptr,
1616 .optional_payload_unsafe_ptr,
1617 .err_union_payload_safe,
1618 .err_union_payload_unsafe,
1619 .err_union_payload_safe_ptr,
1620 .err_union_payload_unsafe_ptr,
1621 .err_union_code,
1622 .err_union_code_ptr,
1623 .ptr_type,
1624 .ptr_type_simple,
1625 .enum_literal,
1626 .enum_literal_small,
1627 .merge_error_sets,
1628 .error_union_type,
1629 .bit_not,
1630 .error_value,
1631 .error_to_int,
1632 .int_to_error,
1633 .slice_start,
1634 .slice_end,
1635 .slice_sentinel,
1636 .import,
1637 .typeof_peer,
1638 .switch_block,
1639 .switch_block_multi,
1640 .switch_block_else,
1641 .switch_block_else_multi,
1642 .switch_block_under,
1643 .switch_block_under_multi,
1644 .switch_block_ref,
1645 .switch_block_ref_multi,
1646 .switch_block_ref_else,
1647 .switch_block_ref_else_multi,
1648 .switch_block_ref_under,
1649 .switch_block_ref_under_multi,
1650 .switch_capture,
1651 .switch_capture_ref,
1652 .switch_capture_multi,
1653 .switch_capture_multi_ref,
1654 .switch_capture_else,
1655 .switch_capture_else_ref,
1656 .struct_init_empty,
1657 .struct_init,
1658 .struct_init_anon,
1659 .array_init,
1660 .array_init_anon,
1661 .array_init_ref,
1662 .array_init_anon_ref,
1663 .union_init_ptr,
1664 .field_type,
1665 .field_type_ref,
1666 .struct_decl,
1667 .struct_decl_packed,
1668 .struct_decl_extern,
1669 .union_decl,
1670 .enum_decl,
1671 .enum_decl_nonexhaustive,
1672 .opaque_decl,
1673 .error_set_decl,
1674 .int_to_enum,
1675 .enum_to_int,
1676 .type_info,
1677 .size_of,
1678 .bit_size_of,
1679 .add_with_overflow,
1680 .sub_with_overflow,
1681 .mul_with_overflow,
1682 .shl_with_overflow,
1683 .log2_int_type,
1684 .typeof_log2_int_type,
1685 .ptr_to_int,
1686 .align_of,
1687 .bool_to_int,
1688 .embed_file,
1689 .error_name,
1690 .sqrt,
1691 .sin,
1692 .cos,
1693 .exp,
1694 .exp2,
1695 .log,
1696 .log2,
1697 .log10,
1698 .fabs,
1699 .floor,
1700 .ceil,
1701 .trunc,
1702 .round,
1703 .tag_name,
1704 .reify,
1705 .type_name,
1706 .frame_type,
1707 .frame_size,
1708 .float_to_int,
1709 .int_to_float,
1710 .int_to_ptr,
1711 .float_cast,
1712 .int_cast,
1713 .err_set_cast,
1714 .ptr_cast,
1715 .truncate,
1716 .align_cast,
1717 .has_decl,
1718 .has_field,
1719 .clz,
1720 .ctz,
1721 .pop_count,
1722 .byte_swap,
1723 .bit_reverse,
1724 .div_exact,
1725 .div_floor,
1726 .div_trunc,
1727 .mod,
1728 .rem,
1729 .shl_exact,
1730 .shr_exact,
1731 .bit_offset_of,
1732 .byte_offset_of,
1733 .cmpxchg_strong,
1734 .cmpxchg_weak,
1735 .splat,
1736 .reduce,
1737 .shuffle,
1738 .atomic_load,
1739 .atomic_rmw,
1740 .atomic_store,
1741 .mul_add,
1742 .builtin_call,
1743 .field_ptr_type,
1744 .field_parent_ptr,
1745 .memcpy,
1746 .memset,
1747 .builtin_async_call,
1748 .c_import,
1749 .extended,
1750 => break :b false,
1751
1752 // ZIR instructions that are always either `noreturn` or `void`.
1753 .breakpoint,
1754 .fence,
1755 .dbg_stmt_node,
1756 .ensure_result_used,
1757 .ensure_result_non_error,
1758 .@"export",
1759 .set_eval_branch_quota,
1760 .compile_log,
1761 .ensure_err_payload_void,
1762 .@"break",
1763 .break_inline,
1764 .condbr,
1765 .condbr_inline,
1766 .compile_error,
1767 .ret_node,
1768 .ret_tok,
1769 .ret_coerce,
1770 .@"unreachable",
1771 .store,
1772 .store_node,
1773 .store_to_block_ptr,
1774 .store_to_inferred_ptr,
1775 .resolve_inferred_alloc,
1776 .repeat,
1777 .repeat_inline,
1778 .validate_struct_init_ptr,
1779 .validate_array_init_ptr,
1780 .panic,
1781 .set_align_stack,
1782 .set_cold,
1783 .set_float_mode,
1784 .set_runtime_safety,
1785 => break :b true,
1786 }
1787 } else switch (maybe_unused_result) {
1788 .none => unreachable,
17771789
1778 else => false,
1779 };
1780 if (!elide_check) {
1781 _ = try gz.addUnNode(.ensure_result_used, maybe_unused_result, statement);
1782 }
1790 .void_value,
1791 .unreachable_value,
1792 => true,
1793
1794 else => false,
1795 };
1796 if (!elide_check) {
1797 _ = try gz.addUnNode(.ensure_result_used, maybe_unused_result, statement);
1798 }
1799}
1800
1801fn genDefers(
1802 gz: *GenZir,
1803 outer_scope: *Scope,
1804 inner_scope: *Scope,
1805 err_code: Zir.Inst.Ref,
1806) InnerError!void {
1807 const astgen = gz.astgen;
1808 const tree = &astgen.file.tree;
1809 const node_datas = tree.nodes.items(.data);
1810
1811 var scope = inner_scope;
1812 while (scope != outer_scope) {
1813 switch (scope.tag) {
1814 .gen_zir => scope = scope.cast(GenZir).?.parent,
1815 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
1816 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1817 .defer_normal => {
1818 const defer_scope = scope.cast(Scope.Defer).?;
1819 scope = defer_scope.parent;
1820 const expr_node = node_datas[defer_scope.defer_node].rhs;
1821 try unusedResultExpr(gz, defer_scope.parent, expr_node);
17831822 },
1823 .defer_error => {
1824 const defer_scope = scope.cast(Scope.Defer).?;
1825 scope = defer_scope.parent;
1826 if (err_code == .none) continue;
1827 const expr_node = node_datas[defer_scope.defer_node].rhs;
1828 try unusedResultExpr(gz, defer_scope.parent, expr_node);
1829 },
1830 else => unreachable,
17841831 }
17851832 }
17861833}
17871834
1835fn deferStmt(
1836 gz: *GenZir,
1837 scope: *Scope,
1838 node: ast.Node.Index,
1839 block_arena: *Allocator,
1840 scope_tag: Scope.Tag,
1841) InnerError!*Scope {
1842 const defer_scope = try block_arena.create(Scope.Defer);
1843 defer_scope.* = .{
1844 .base = .{ .tag = scope_tag },
1845 .parent = scope,
1846 .defer_node = node,
1847 };
1848 return &defer_scope.base;
1849}
1850
17881851fn varDecl(
17891852 gz: *GenZir,
17901853 scope: *Scope,
......@@ -1792,6 +1855,7 @@ fn varDecl(
17921855 block_arena: *Allocator,
17931856 var_decl: ast.full.VarDecl,
17941857) InnerError!*Scope {
1858 try emitDbgNode(gz, node);
17951859 const astgen = gz.astgen;
17961860 if (var_decl.comptime_token) |comptime_token| {
17971861 return astgen.failTok(comptime_token, "TODO implement comptime locals", .{});
......@@ -1841,6 +1905,7 @@ fn varDecl(
18411905 s = local_ptr.parent;
18421906 },
18431907 .gen_zir => s = s.cast(GenZir).?.parent,
1908 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
18441909 .file => break,
18451910 else => unreachable,
18461911 };
......@@ -1877,6 +1942,7 @@ fn varDecl(
18771942 .parent = scope,
18781943 .decl_node_index = gz.decl_node_index,
18791944 .force_comptime = gz.force_comptime,
1945 .ref_start_index = gz.ref_start_index,
18801946 .astgen = astgen,
18811947 };
18821948 defer init_scope.instructions.deinit(gpa);
......@@ -1984,7 +2050,14 @@ fn varDecl(
19842050 }
19852051}
19862052
2053fn emitDbgNode(gz: *GenZir, node: ast.Node.Index) !void {
2054 if (!gz.force_comptime) {
2055 _ = try gz.addNode(.dbg_stmt_node, node);
2056 }
2057}
2058
19872059fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void {
2060 try emitDbgNode(gz, infix_node);
19882061 const astgen = gz.astgen;
19892062 const tree = &astgen.file.tree;
19902063 const node_datas = tree.nodes.items(.data);
......@@ -2011,6 +2084,7 @@ fn assignOp(
20112084 infix_node: ast.Node.Index,
20122085 op_inst_tag: Zir.Inst.Tag,
20132086) InnerError!void {
2087 try emitDbgNode(gz, infix_node);
20142088 const astgen = gz.astgen;
20152089 const tree = &astgen.file.tree;
20162090 const node_datas = tree.nodes.items(.data);
......@@ -2033,6 +2107,7 @@ fn assignShift(
20332107 infix_node: ast.Node.Index,
20342108 op_inst_tag: Zir.Inst.Tag,
20352109) InnerError!void {
2110 try emitDbgNode(gz, infix_node);
20362111 const astgen = gz.astgen;
20372112 const tree = &astgen.file.tree;
20382113 const node_datas = tree.nodes.items(.data);
......@@ -2257,12 +2332,12 @@ fn fnDecl(
22572332 const param_types = try gpa.alloc(Zir.Inst.Ref, param_count);
22582333 defer gpa.free(param_types);
22592334
2260 var decl_gz: Scope.GenZir = .{
2335 var decl_gz: GenZir = .{
22612336 .force_comptime = true,
22622337 .decl_node_index = fn_proto.ast.proto_node,
22632338 .parent = &gz.base,
22642339 .astgen = astgen,
2265 .ref_start_index = @intCast(u32, Zir.Inst.Ref.typed_value_map.len + param_count),
2340 .ref_start_index = @intCast(u32, Zir.Inst.Ref.typed_value_map.len),
22662341 };
22672342 defer decl_gz.instructions.deinit(gpa);
22682343
......@@ -2357,7 +2432,7 @@ fn fnDecl(
23572432 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{});
23582433 }
23592434
2360 var fn_gz: Scope.GenZir = .{
2435 var fn_gz: GenZir = .{
23612436 .force_comptime = false,
23622437 .decl_node_index = fn_proto.ast.proto_node,
23632438 .parent = &decl_gz.base,
......@@ -2366,6 +2441,9 @@ fn fnDecl(
23662441 };
23672442 defer fn_gz.instructions.deinit(gpa);
23682443
2444 const prev_fn_block = astgen.fn_block;
2445 astgen.fn_block = &fn_gz;
2446
23692447 // Iterate over the parameters. We put the param names as the first N
23702448 // items inside `extra` so that debug info later can refer to the parameter names
23712449 // even while the respective source code is unloaded.
......@@ -2406,6 +2484,8 @@ fn fnDecl(
24062484 _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
24072485 }
24082486
2487 astgen.fn_block = prev_fn_block;
2488
24092489 break :func try decl_gz.addFunc(.{
24102490 .src_node = fn_proto.ast.proto_node,
24112491 .ret_ty = return_type_inst,
......@@ -2580,9 +2660,18 @@ fn testDecl(
25802660 scope: *Scope,
25812661 node: ast.Node.Index,
25822662) InnerError!void {
2663 const gpa = astgen.gpa;
25832664 const tree = &astgen.file.tree;
25842665 const node_datas = tree.nodes.items(.data);
2585 const test_expr = node_datas[node].rhs;
2666 const body_node = node_datas[node].rhs;
2667
2668 var decl_block: GenZir = .{
2669 .force_comptime = true,
2670 .decl_node_index = node,
2671 .parent = &gz.base,
2672 .astgen = astgen,
2673 };
2674 defer decl_block.instructions.deinit(gpa);
25862675
25872676 const test_name: u32 = blk: {
25882677 const main_tokens = tree.nodes.items(.main_token);
......@@ -2590,13 +2679,49 @@ fn testDecl(
25902679 const test_token = main_tokens[node];
25912680 const str_lit_token = test_token + 1;
25922681 if (token_tags[str_lit_token] == .string_literal) {
2593 break :blk (try gz.strLitAsString(str_lit_token)).index;
2682 break :blk (try decl_block.strLitAsString(str_lit_token)).index;
25942683 }
25952684 break :blk 0;
25962685 };
25972686
2598 // TODO probably we want to put these into a block and store a list of them
2599 const block_inst = try expr(gz, scope, .none, test_expr);
2687 var fn_block: GenZir = .{
2688 .force_comptime = false,
2689 .decl_node_index = node,
2690 .parent = &decl_block.base,
2691 .astgen = astgen,
2692 };
2693 defer fn_block.instructions.deinit(gpa);
2694
2695 const prev_fn_block = astgen.fn_block;
2696 astgen.fn_block = &fn_block;
2697
2698 const block_result = try expr(&fn_block, &fn_block.base, .none, body_node);
2699 if (fn_block.instructions.items.len == 0 or !fn_block.refIsNoReturn(block_result)) {
2700 // Since we are adding the return instruction here, we must handle the coercion.
2701 // We do this by using the `ret_coerce` instruction.
2702 _ = try fn_block.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
2703 }
2704
2705 astgen.fn_block = prev_fn_block;
2706
2707 const func_inst = try decl_block.addFunc(.{
2708 .src_node = node,
2709 .ret_ty = .void_type,
2710 .param_types = &[0]Zir.Inst.Ref{},
2711 .body = fn_block.instructions.items,
2712 .cc = .none,
2713 .lib_name = 0,
2714 .is_var_args = false,
2715 .is_inferred_error = true,
2716 });
2717
2718 const block_inst = try gz.addBlock(.block_inline, node);
2719 _ = try decl_block.addBreak(.break_inline, block_inst, func_inst);
2720 try decl_block.setBlockBody(block_inst);
2721
2722 // TODO collect these into a test decl list
2723 _ = test_name;
2724 _ = block_inst;
26002725}
26012726
26022727fn structDeclInner(
......@@ -2628,6 +2753,7 @@ fn structDeclInner(
26282753 .decl_node_index = node,
26292754 .astgen = astgen,
26302755 .force_comptime = true,
2756 .ref_start_index = gz.ref_start_index,
26312757 };
26322758 defer block_scope.instructions.deinit(gpa);
26332759
......@@ -2943,6 +3069,7 @@ fn containerDecl(
29433069 .decl_node_index = node,
29443070 .astgen = astgen,
29453071 .force_comptime = true,
3072 .ref_start_index = gz.ref_start_index,
29463073 };
29473074 defer block_scope.instructions.deinit(gpa);
29483075
......@@ -3168,6 +3295,7 @@ fn tryExpr(
31683295 .decl_node_index = parent_gz.decl_node_index,
31693296 .astgen = astgen,
31703297 .force_comptime = parent_gz.force_comptime,
3298 .ref_start_index = parent_gz.ref_start_index,
31713299 .instructions = .{},
31723300 };
31733301 block_scope.setBreakResultLoc(rl);
......@@ -3200,11 +3328,13 @@ fn tryExpr(
32003328 .decl_node_index = parent_gz.decl_node_index,
32013329 .astgen = astgen,
32023330 .force_comptime = block_scope.force_comptime,
3331 .ref_start_index = parent_gz.ref_start_index,
32033332 .instructions = .{},
32043333 };
32053334 defer then_scope.instructions.deinit(astgen.gpa);
32063335
32073336 const err_code = try then_scope.addUnNode(err_ops[1], operand, node);
3337 try genDefers(&then_scope, &astgen.fn_block.?.base, scope, err_code);
32083338 const then_result = try then_scope.addUnNode(.ret_node, err_code, node);
32093339
32103340 var else_scope: GenZir = .{
......@@ -3212,6 +3342,7 @@ fn tryExpr(
32123342 .decl_node_index = parent_gz.decl_node_index,
32133343 .astgen = astgen,
32143344 .force_comptime = block_scope.force_comptime,
3345 .ref_start_index = parent_gz.ref_start_index,
32153346 .instructions = .{},
32163347 };
32173348 defer else_scope.instructions.deinit(astgen.gpa);
......@@ -3264,6 +3395,7 @@ fn orelseCatchExpr(
32643395 .decl_node_index = parent_gz.decl_node_index,
32653396 .astgen = astgen,
32663397 .force_comptime = parent_gz.force_comptime,
3398 .ref_start_index = parent_gz.ref_start_index,
32673399 .instructions = .{},
32683400 };
32693401 block_scope.setBreakResultLoc(rl);
......@@ -3300,6 +3432,7 @@ fn orelseCatchExpr(
33003432 .decl_node_index = parent_gz.decl_node_index,
33013433 .astgen = astgen,
33023434 .force_comptime = block_scope.force_comptime,
3435 .ref_start_index = parent_gz.ref_start_index,
33033436 .instructions = .{},
33043437 };
33053438 defer then_scope.instructions.deinit(astgen.gpa);
......@@ -3332,6 +3465,7 @@ fn orelseCatchExpr(
33323465 .decl_node_index = parent_gz.decl_node_index,
33333466 .astgen = astgen,
33343467 .force_comptime = block_scope.force_comptime,
3468 .ref_start_index = parent_gz.ref_start_index,
33353469 .instructions = .{},
33363470 };
33373471 defer else_scope.instructions.deinit(astgen.gpa);
......@@ -3532,6 +3666,7 @@ fn boolBinOp(
35323666 .decl_node_index = gz.decl_node_index,
35333667 .astgen = gz.astgen,
35343668 .force_comptime = gz.force_comptime,
3669 .ref_start_index = gz.ref_start_index,
35353670 };
35363671 defer rhs_scope.instructions.deinit(gz.astgen.gpa);
35373672 const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs);
......@@ -3558,6 +3693,7 @@ fn ifExpr(
35583693 .decl_node_index = parent_gz.decl_node_index,
35593694 .astgen = astgen,
35603695 .force_comptime = parent_gz.force_comptime,
3696 .ref_start_index = parent_gz.ref_start_index,
35613697 .instructions = .{},
35623698 };
35633699 block_scope.setBreakResultLoc(rl);
......@@ -3608,6 +3744,7 @@ fn ifExpr(
36083744 .decl_node_index = parent_gz.decl_node_index,
36093745 .astgen = astgen,
36103746 .force_comptime = block_scope.force_comptime,
3747 .ref_start_index = parent_gz.ref_start_index,
36113748 .instructions = .{},
36123749 };
36133750 defer then_scope.instructions.deinit(astgen.gpa);
......@@ -3662,6 +3799,7 @@ fn ifExpr(
36623799 .decl_node_index = parent_gz.decl_node_index,
36633800 .astgen = astgen,
36643801 .force_comptime = block_scope.force_comptime,
3802 .ref_start_index = parent_gz.ref_start_index,
36653803 .instructions = .{},
36663804 };
36673805 defer else_scope.instructions.deinit(astgen.gpa);
......@@ -3812,6 +3950,7 @@ fn whileExpr(
38123950 .decl_node_index = parent_gz.decl_node_index,
38133951 .astgen = astgen,
38143952 .force_comptime = parent_gz.force_comptime,
3953 .ref_start_index = parent_gz.ref_start_index,
38153954 .instructions = .{},
38163955 };
38173956 loop_scope.setBreakResultLoc(rl);
......@@ -3822,6 +3961,7 @@ fn whileExpr(
38223961 .decl_node_index = parent_gz.decl_node_index,
38233962 .astgen = astgen,
38243963 .force_comptime = loop_scope.force_comptime,
3964 .ref_start_index = parent_gz.ref_start_index,
38253965 .instructions = .{},
38263966 };
38273967 defer continue_scope.instructions.deinit(astgen.gpa);
......@@ -3891,6 +4031,7 @@ fn whileExpr(
38914031 .decl_node_index = parent_gz.decl_node_index,
38924032 .astgen = astgen,
38934033 .force_comptime = continue_scope.force_comptime,
4034 .ref_start_index = parent_gz.ref_start_index,
38944035 .instructions = .{},
38954036 };
38964037 defer then_scope.instructions.deinit(astgen.gpa);
......@@ -3942,6 +4083,7 @@ fn whileExpr(
39424083 .decl_node_index = parent_gz.decl_node_index,
39434084 .astgen = astgen,
39444085 .force_comptime = continue_scope.force_comptime,
4086 .ref_start_index = parent_gz.ref_start_index,
39454087 .instructions = .{},
39464088 };
39474089 defer else_scope.instructions.deinit(astgen.gpa);
......@@ -4043,6 +4185,7 @@ fn forExpr(
40434185 .decl_node_index = parent_gz.decl_node_index,
40444186 .astgen = astgen,
40454187 .force_comptime = parent_gz.force_comptime,
4188 .ref_start_index = parent_gz.ref_start_index,
40464189 .instructions = .{},
40474190 };
40484191 loop_scope.setBreakResultLoc(rl);
......@@ -4053,6 +4196,7 @@ fn forExpr(
40534196 .decl_node_index = parent_gz.decl_node_index,
40544197 .astgen = astgen,
40554198 .force_comptime = loop_scope.force_comptime,
4199 .ref_start_index = parent_gz.ref_start_index,
40564200 .instructions = .{},
40574201 };
40584202 defer cond_scope.instructions.deinit(astgen.gpa);
......@@ -4096,6 +4240,7 @@ fn forExpr(
40964240 .decl_node_index = parent_gz.decl_node_index,
40974241 .astgen = astgen,
40984242 .force_comptime = cond_scope.force_comptime,
4243 .ref_start_index = parent_gz.ref_start_index,
40994244 .instructions = .{},
41004245 };
41014246 defer then_scope.instructions.deinit(astgen.gpa);
......@@ -4141,6 +4286,7 @@ fn forExpr(
41414286 .decl_node_index = parent_gz.decl_node_index,
41424287 .astgen = astgen,
41434288 .force_comptime = cond_scope.force_comptime,
4289 .ref_start_index = parent_gz.ref_start_index,
41444290 .instructions = .{},
41454291 };
41464292 defer else_scope.instructions.deinit(astgen.gpa);
......@@ -4443,6 +4589,7 @@ fn switchExpr(
44434589 .decl_node_index = parent_gz.decl_node_index,
44444590 .astgen = astgen,
44454591 .force_comptime = parent_gz.force_comptime,
4592 .ref_start_index = parent_gz.ref_start_index,
44464593 .instructions = .{},
44474594 };
44484595 block_scope.setBreakResultLoc(rl);
......@@ -4457,6 +4604,7 @@ fn switchExpr(
44574604 .decl_node_index = parent_gz.decl_node_index,
44584605 .astgen = astgen,
44594606 .force_comptime = parent_gz.force_comptime,
4607 .ref_start_index = parent_gz.ref_start_index,
44604608 .instructions = .{},
44614609 };
44624610 defer case_scope.instructions.deinit(gpa);
......@@ -4900,15 +5048,21 @@ fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref
49005048 const main_tokens = tree.nodes.items(.main_token);
49015049
49025050 const operand_node = node_datas[node].lhs;
4903 const operand: Zir.Inst.Ref = if (operand_node != 0) operand: {
5051 if (operand_node != 0) {
49045052 const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node)) .{
49055053 .ptr = try gz.addNodeExtended(.ret_ptr, node),
49065054 } else .{
49075055 .ty = try gz.addNodeExtended(.ret_type, node),
49085056 };
4909 break :operand try expr(gz, scope, rl, operand_node);
4910 } else .void_value;
4911 _ = try gz.addUnNode(.ret_node, operand, node);
5057 const operand = try expr(gz, scope, rl, operand_node);
5058 // TODO check operand to see if we need to generate errdefers
5059 try genDefers(gz, &astgen.fn_block.?.base, scope, .none);
5060 _ = try gz.addUnNode(.ret_node, operand, node);
5061 return Zir.Inst.Ref.unreachable_value;
5062 }
5063 // Returning a void value; skip error defers.
5064 try genDefers(gz, &astgen.fn_block.?.base, scope, .none);
5065 _ = try gz.addUnNode(.ret_node, .void_value, node);
49125066 return Zir.Inst.Ref.unreachable_value;
49135067}
49145068
......@@ -5309,6 +5463,7 @@ fn asRlPtr(
53095463 .decl_node_index = parent_gz.decl_node_index,
53105464 .astgen = astgen,
53115465 .force_comptime = parent_gz.force_comptime,
5466 .ref_start_index = parent_gz.ref_start_index,
53125467 .instructions = .{},
53135468 };
53145469 defer as_scope.instructions.deinit(astgen.gpa);
......@@ -5998,6 +6153,7 @@ fn cImport(
59986153 .decl_node_index = gz.decl_node_index,
59996154 .astgen = astgen,
60006155 .force_comptime = true,
6156 .ref_start_index = gz.ref_start_index,
60016157 .instructions = .{},
60026158 };
60036159 defer block_scope.instructions.deinit(gpa);
......@@ -6454,7 +6610,7 @@ fn rvalue(
64546610
64556611/// Given an identifier token, obtain the string for it.
64566612/// If the token uses @"" syntax, parses as a string, reports errors if applicable,
6457/// and allocates the result within `scope.arena()`.
6613/// and allocates the result within `astgen.arena`.
64586614/// Otherwise, returns a reference to the source code bytes directly.
64596615/// See also `appendIdentStr` and `parseStrLit`.
64606616pub fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError![]const u8 {
src/Module.zig+31-32
......@@ -514,31 +514,26 @@ pub const Scope = struct {
514514 pub const NameHash = [16]u8;
515515
516516 pub fn cast(base: *Scope, comptime T: type) ?*T {
517 if (T == Defer) {
518 switch (base.tag) {
519 .defer_normal, .defer_error => return @fieldParentPtr(T, "base", base),
520 else => return null,
521 }
522 }
517523 if (base.tag != T.base_tag)
518524 return null;
519525
520526 return @fieldParentPtr(T, "base", base);
521527 }
522528
523 /// Returns the arena Allocator associated with the Decl of the Scope.
524 pub fn arena(scope: *Scope) *Allocator {
525 switch (scope.tag) {
526 .block => return scope.cast(Block).?.sema.arena,
527 .gen_zir => return scope.cast(GenZir).?.astgen.arena,
528 .local_val => return scope.cast(LocalVal).?.gen_zir.astgen.arena,
529 .local_ptr => return scope.cast(LocalPtr).?.gen_zir.astgen.arena,
530 .file => unreachable,
531 .namespace => unreachable,
532 .decl_ref => unreachable,
533 }
534 }
535
536529 pub fn ownerDecl(scope: *Scope) ?*Decl {
537530 return switch (scope.tag) {
538531 .block => scope.cast(Block).?.sema.owner_decl,
539532 .gen_zir => unreachable,
540533 .local_val => unreachable,
541534 .local_ptr => unreachable,
535 .defer_normal => unreachable,
536 .defer_error => unreachable,
542537 .file => null,
543538 .namespace => null,
544539 .decl_ref => scope.cast(DeclRef).?.decl,
......@@ -551,6 +546,8 @@ pub const Scope = struct {
551546 .gen_zir => unreachable,
552547 .local_val => unreachable,
553548 .local_ptr => unreachable,
549 .defer_normal => unreachable,
550 .defer_error => unreachable,
554551 .file => null,
555552 .namespace => null,
556553 .decl_ref => scope.cast(DeclRef).?.decl,
......@@ -564,25 +561,14 @@ pub const Scope = struct {
564561 .gen_zir => unreachable,
565562 .local_val => unreachable,
566563 .local_ptr => unreachable,
564 .defer_normal => unreachable,
565 .defer_error => unreachable,
567566 .file => return scope.cast(File).?.namespace,
568567 .namespace => return scope.cast(Namespace).?,
569568 .decl_ref => return scope.cast(DeclRef).?.decl.namespace,
570569 }
571570 }
572571
573 /// Asserts the scope is a child of a `GenZir` and returns it.
574 pub fn getGenZir(scope: *Scope) *GenZir {
575 return switch (scope.tag) {
576 .block => unreachable,
577 .gen_zir => scope.cast(GenZir).?,
578 .local_val => return scope.cast(LocalVal).?.gen_zir,
579 .local_ptr => return scope.cast(LocalPtr).?.gen_zir,
580 .file => unreachable,
581 .namespace => unreachable,
582 .decl_ref => unreachable,
583 };
584 }
585
586572 /// Asserts the scope has a parent which is a Namespace or File and
587573 /// returns the sub_file_path field.
588574 pub fn subFilePath(base: *Scope) []const u8 {
......@@ -593,6 +579,8 @@ pub const Scope = struct {
593579 .gen_zir => unreachable,
594580 .local_val => unreachable,
595581 .local_ptr => unreachable,
582 .defer_normal => unreachable,
583 .defer_error => unreachable,
596584 .decl_ref => unreachable,
597585 }
598586 }
......@@ -604,9 +592,11 @@ pub const Scope = struct {
604592 cur = switch (cur.tag) {
605593 .namespace => return @fieldParentPtr(Namespace, "base", cur).file_scope,
606594 .file => return @fieldParentPtr(File, "base", cur),
607 .gen_zir => @fieldParentPtr(GenZir, "base", cur).parent,
608 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,
609 .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent,
595 .gen_zir => return @fieldParentPtr(GenZir, "base", cur).astgen.file,
596 .local_val => return @fieldParentPtr(LocalVal, "base", cur).gen_zir.astgen.file,
597 .local_ptr => return @fieldParentPtr(LocalPtr, "base", cur).gen_zir.astgen.file,
598 .defer_normal => @fieldParentPtr(Defer, "base", cur).parent,
599 .defer_error => @fieldParentPtr(Defer, "base", cur).parent,
610600 .block => return @fieldParentPtr(Block, "base", cur).src_decl.namespace.file_scope,
611601 .decl_ref => return @fieldParentPtr(DeclRef, "base", cur).decl.namespace.file_scope,
612602 };
......@@ -634,6 +624,8 @@ pub const Scope = struct {
634624 /// `Decl` for use with `srcDecl` and `ownerDecl`.
635625 /// Has no parents or children.
636626 decl_ref,
627 defer_normal,
628 defer_error,
637629 };
638630
639631 /// The container that structs, enums, unions, and opaques have.
......@@ -1709,7 +1701,7 @@ pub const Scope = struct {
17091701 pub const LocalVal = struct {
17101702 pub const base_tag: Tag = .local_val;
17111703 base: Scope = Scope{ .tag = base_tag },
1712 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`.
1704 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
17131705 parent: *Scope,
17141706 gen_zir: *GenZir,
17151707 name: []const u8,
......@@ -1724,7 +1716,7 @@ pub const Scope = struct {
17241716 pub const LocalPtr = struct {
17251717 pub const base_tag: Tag = .local_ptr;
17261718 base: Scope = Scope{ .tag = base_tag },
1727 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`.
1719 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
17281720 parent: *Scope,
17291721 gen_zir: *GenZir,
17301722 name: []const u8,
......@@ -1733,6 +1725,13 @@ pub const Scope = struct {
17331725 token_src: ast.TokenIndex,
17341726 };
17351727
1728 pub const Defer = struct {
1729 base: Scope,
1730 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
1731 parent: *Scope,
1732 defer_node: ast.Node.Index,
1733 };
1734
17361735 pub const DeclRef = struct {
17371736 pub const base_tag: Tag = .decl_ref;
17381737 base: Scope = Scope{ .tag = base_tag },
......@@ -3821,7 +3820,7 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) In
38213820 }
38223821 mod.failed_decls.putAssumeCapacityNoClobber(block.sema.owner_decl, err_msg);
38233822 },
3824 .gen_zir, .local_val, .local_ptr => unreachable,
3823 .gen_zir, .local_val, .local_ptr, .defer_normal, .defer_error => unreachable,
38253824 .file => unreachable,
38263825 .namespace => unreachable,
38273826 .decl_ref => {
src/Zir.zig+33-4
......@@ -2304,6 +2304,7 @@ const Writer = struct {
23042304 .byte_swap,
23052305 .bit_reverse,
23062306 .elem_type,
2307 .bitcast_result_ptr,
23072308 => try self.writeUnNode(stream, inst),
23082309
23092310 .ref,
......@@ -2424,6 +2425,7 @@ const Writer = struct {
24242425 .splat,
24252426 .reduce,
24262427 .atomic_load,
2428 .bitcast,
24272429 => try self.writePlNodeBin(stream, inst),
24282430
24292431 .call,
......@@ -2509,13 +2511,40 @@ const Writer = struct {
25092511 .switch_capture_else_ref,
25102512 => try self.writeSwitchCapture(stream, inst),
25112513
2512 .bitcast,
2513 .bitcast_result_ptr,
2514 .extended,
2515 => try stream.writeAll("TODO)"),
2514 .extended => try self.writeExtended(stream, inst),
2515 }
2516 }
2517
2518 fn writeExtended(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2519 const extended = self.code.instructions.items(.data)[inst].extended;
2520 try stream.print("{s}(", .{@tagName(extended.opcode)});
2521 switch (extended.opcode) {
2522 .ret_ptr,
2523 .ret_type,
2524 .this,
2525 .ret_addr,
2526 .error_return_trace,
2527 .frame,
2528 .frame_address,
2529 .builtin_src,
2530 => try self.writeExtNode(stream, extended),
2531
2532 .func,
2533 .c_undef,
2534 .c_include,
2535 .c_define,
2536 .wasm_memory_size,
2537 .wasm_memory_grow,
2538 => try stream.writeAll("TODO))"),
25162539 }
25172540 }
25182541
2542 fn writeExtNode(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
2543 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
2544 try stream.writeAll(")) ");
2545 try self.writeSrc(stream, src);
2546 }
2547
25192548 fn writeBin(self: *Writer, stream: anytype, inst: Inst.Index) !void {
25202549 const inst_data = self.code.instructions.items(.data)[inst].bin;
25212550 try self.writeInstRef(stream, inst_data.lhs);