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,3 +1,7 @@
1 * defer
2 - `break`
3 - `continue`
4 * nested function decl: how to refer to params?
1 * look for cached zir code5 * look for cached zir code
2 * save zir code to cache6 * save zir code to cache
3 * keep track of file dependencies/dependants7 * keep track of file dependencies/dependants
...@@ -13,6 +17,15 @@...@@ -13,6 +17,15 @@
13 on each usingnamespace decl17 on each usingnamespace decl
14 * handle usingnamespace cycles18 * 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
16 * have failed_trees and just put the file in there29 * have failed_trees and just put the file in there
17 - this way we can emit all the parse errors not just the first one30 - this way we can emit all the parse errors not just the first one
18 - but maybe we want just the first one?31 - but maybe we want just the first one?
src/AstGen.zig+464-308
...@@ -37,6 +37,8 @@ string_table: std.StringHashMapUnmanaged(u32) = .{},...@@ -37,6 +37,8 @@ string_table: std.StringHashMapUnmanaged(u32) = .{},
37compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{},37compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{},
38/// String table indexes, keeps track of all `@import` operands.38/// String table indexes, keeps track of all `@import` operands.
39imports: std.AutoArrayHashMapUnmanaged(u32, void) = .{},39imports: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
40/// The topmost block of the current function.
41fn_block: ?*GenZir = null,
4042
41pub fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {43pub fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {
42 const fields = std.meta.fields(@TypeOf(extra));44 const fields = std.meta.fields(@TypeOf(extra));
...@@ -82,7 +84,7 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {...@@ -82,7 +84,7 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {
82 // First few indexes of extra are reserved and set at the end.84 // First few indexes of extra are reserved and set at the end.
83 try astgen.extra.resize(gpa, @typeInfo(Zir.ExtraIndex).Enum.fields.len);85 try astgen.extra.resize(gpa, @typeInfo(Zir.ExtraIndex).Enum.fields.len);
8486
85 var gen_scope: Scope.GenZir = .{87 var gen_scope: GenZir = .{
86 .force_comptime = true,88 .force_comptime = true,
87 .parent = &file.base,89 .parent = &file.base,
88 .decl_node_index = 0,90 .decl_node_index = 0,
...@@ -461,6 +463,8 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -461,6 +463,8 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
461 .local_var_decl => unreachable, // Handled in `blockExpr`.463 .local_var_decl => unreachable, // Handled in `blockExpr`.
462 .simple_var_decl => unreachable, // Handled in `blockExpr`.464 .simple_var_decl => unreachable, // Handled in `blockExpr`.
463 .aligned_var_decl => unreachable, // Handled in `blockExpr`.465 .aligned_var_decl => unreachable, // Handled in `blockExpr`.
466 .@"defer" => unreachable, // Handled in `blockExpr`.
467 .@"errdefer" => unreachable, // Handled in `blockExpr`.
464468
465 .switch_case => unreachable, // Handled in `switchExpr`.469 .switch_case => unreachable, // Handled in `switchExpr`.
466 .switch_case_one => unreachable, // Handled in `switchExpr`.470 .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...@@ -818,8 +822,6 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
818 .@"await" => return astgen.failNode(node, "async and related features are not yet supported", .{}),822 .@"await" => return astgen.failNode(node, "async and related features are not yet supported", .{}),
819 .@"resume" => return astgen.failNode(node, "async and related features are not yet supported", .{}),823 .@"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", .{}),
823 .@"try" => return tryExpr(gz, scope, rl, node_datas[node].lhs),825 .@"try" => return tryExpr(gz, scope, rl, node_datas[node].lhs),
824826
825 .array_init_one, .array_init_one_comma => {827 .array_init_one, .array_init_one_comma => {
...@@ -1245,6 +1247,8 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn...@@ -1245,6 +1247,8 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn
1245 },1247 },
1246 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,1248 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
1247 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,1249 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1250 .defer_normal => @panic("TODO break/defer"),
1251 .defer_error => @panic("TODO break/defer"),
1248 else => if (break_label != 0) {1252 else => if (break_label != 0) {
1249 const label_name = try astgen.identifierTokenString(break_label);1253 const label_name = try astgen.identifierTokenString(break_label);
1250 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});1254 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)...@@ -1290,6 +1294,8 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)
1290 },1294 },
1291 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,1295 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
1292 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,1296 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1297 .defer_normal => @panic("TODO continue/defer"),
1298 .defer_error => @panic("TODO continue/defer"),
1293 else => if (break_label != 0) {1299 else => if (break_label != 0) {
1294 const label_name = try astgen.identifierTokenString(break_label);1300 const label_name = try astgen.identifierTokenString(break_label);
1295 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});1301 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...@@ -1354,6 +1360,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: ast.Toke
1354 },1360 },
1355 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,1361 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
1356 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,1362 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1363 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1357 else => return,1364 else => return,
1358 }1365 }
1359 }1366 }
...@@ -1393,6 +1400,7 @@ fn labeledBlockExpr(...@@ -1393,6 +1400,7 @@ fn labeledBlockExpr(
1393 .decl_node_index = gz.decl_node_index,1400 .decl_node_index = gz.decl_node_index,
1394 .astgen = gz.astgen,1401 .astgen = gz.astgen,
1395 .force_comptime = gz.force_comptime,1402 .force_comptime = gz.force_comptime,
1403 .ref_start_index = gz.ref_start_index,
1396 .instructions = .{},1404 .instructions = .{},
1397 // TODO @as here is working around a stage1 miscompilation bug :(1405 // TODO @as here is working around a stage1 miscompilation bug :(
1398 .label = @as(?GenZir.Label, GenZir.Label{1406 .label = @as(?GenZir.Label, GenZir.Label{
...@@ -1463,16 +1471,16 @@ fn blockExprStmts(...@@ -1463,16 +1471,16 @@ fn blockExprStmts(
14631471
1464 var scope = parent_scope;1472 var scope = parent_scope;
1465 for (statements) |statement| {1473 for (statements) |statement| {
1466 if (!gz.force_comptime) {
1467 _ = try gz.addNode(.dbg_stmt_node, statement);
1468 }
1469 switch (node_tags[statement]) {1474 switch (node_tags[statement]) {
1470 .global_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.globalVarDecl(statement)),1475 // zig fmt: off
1471 .local_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.localVarDecl(statement)),1476 .global_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.globalVarDecl(statement)),
1472 .simple_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.simpleVarDecl(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)),
1473 .aligned_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.alignedVarDecl(statement)),1479 .aligned_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.alignedVarDecl(statement)),
14741480
1475 // zig fmt: off1481 .@"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
1476 .assign => try assign(gz, scope, statement),1484 .assign => try assign(gz, scope, statement),
14771485
1478 .assign_bit_shift_left => try assignShift(gz, scope, statement, .shl),1486 .assign_bit_shift_left => try assignShift(gz, scope, statement, .shl),
...@@ -1489,302 +1497,357 @@ fn blockExprStmts(...@@ -1489,302 +1497,357 @@ fn blockExprStmts(
1489 .assign_add_wrap => try assignOp(gz, scope, statement, .addwrap),1497 .assign_add_wrap => try assignOp(gz, scope, statement, .addwrap),
1490 .assign_mul => try assignOp(gz, scope, statement, .mul),1498 .assign_mul => try assignOp(gz, scope, statement, .mul),
1491 .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),1499 .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),
1500
1501 else => try unusedResultExpr(gz, scope, statement),
1492 // zig fmt: on1502 // zig fmt: on
1503 }
1504 }
14931505
1494 else => {1506 try genDefers(gz, parent_scope, scope, .none);
1495 // We need to emit an error if the result is not `noreturn` or `void`, but1507}
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 },
15151508
1516 // ZIR instructions that might be a type other than `noreturn` or `void`.1509fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) InnerError!void {
1517 .add,1510 try emitDbgNode(gz, statement);
1518 .addwrap,1511 // We need to emit an error if the result is not `noreturn` or `void`, but
1519 .alloc,1512 // we want to avoid adding the ZIR instruction if possible for performance.
1520 .alloc_mut,1513 const maybe_unused_result = try expr(gz, scope, .none, statement);
1521 .alloc_inferred,1514 const elide_check = if (gz.refToIndex(maybe_unused_result)) |inst| b: {
1522 .alloc_inferred_mut,1515 // Note that this array becomes invalid after appending more items to it
1523 .array_cat,1516 // in the above while loop.
1524 .array_mul,1517 const zir_tags = gz.astgen.instructions.items(.tag);
1525 .array_type,1518 switch (zir_tags[inst]) {
1526 .array_type_sentinel,1519 // For some instructions, swap in a slightly different ZIR tag
1527 .elem_type,1520 // so we can avoid a separate ensure_result_used instruction.
1528 .indexable_ptr_len,1521 .call_none_chkused => unreachable,
1529 .as,1522 .call_none => {
1530 .as_node,1523 zir_tags[inst] = .call_none_chkused;
1531 .@"asm",1524 break :b true;
1532 .asm_volatile,1525 },
1533 .bit_and,1526 .call_chkused => unreachable,
1534 .bitcast,1527 .call => {
1535 .bitcast_result_ptr,1528 zir_tags[inst] = .call_chkused;
1536 .bit_or,1529 break :b true;
1537 .block,1530 },
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,
17731531
1774 .void_value,1532 // ZIR instructions that might be a type other than `noreturn` or `void`.
1775 .unreachable_value,1533 .add,
1776 => true,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,1790 .void_value,
1779 };1791 .unreachable_value,
1780 if (!elide_check) {1792 => true,
1781 _ = try gz.addUnNode(.ensure_result_used, maybe_unused_result, statement);1793
1782 }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);
1783 },1822 },
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,
1784 }1831 }
1785 }1832 }
1786}1833}
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
1788fn varDecl(1851fn varDecl(
1789 gz: *GenZir,1852 gz: *GenZir,
1790 scope: *Scope,1853 scope: *Scope,
...@@ -1792,6 +1855,7 @@ fn varDecl(...@@ -1792,6 +1855,7 @@ fn varDecl(
1792 block_arena: *Allocator,1855 block_arena: *Allocator,
1793 var_decl: ast.full.VarDecl,1856 var_decl: ast.full.VarDecl,
1794) InnerError!*Scope {1857) InnerError!*Scope {
1858 try emitDbgNode(gz, node);
1795 const astgen = gz.astgen;1859 const astgen = gz.astgen;
1796 if (var_decl.comptime_token) |comptime_token| {1860 if (var_decl.comptime_token) |comptime_token| {
1797 return astgen.failTok(comptime_token, "TODO implement comptime locals", .{});1861 return astgen.failTok(comptime_token, "TODO implement comptime locals", .{});
...@@ -1841,6 +1905,7 @@ fn varDecl(...@@ -1841,6 +1905,7 @@ fn varDecl(
1841 s = local_ptr.parent;1905 s = local_ptr.parent;
1842 },1906 },
1843 .gen_zir => s = s.cast(GenZir).?.parent,1907 .gen_zir => s = s.cast(GenZir).?.parent,
1908 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
1844 .file => break,1909 .file => break,
1845 else => unreachable,1910 else => unreachable,
1846 };1911 };
...@@ -1877,6 +1942,7 @@ fn varDecl(...@@ -1877,6 +1942,7 @@ fn varDecl(
1877 .parent = scope,1942 .parent = scope,
1878 .decl_node_index = gz.decl_node_index,1943 .decl_node_index = gz.decl_node_index,
1879 .force_comptime = gz.force_comptime,1944 .force_comptime = gz.force_comptime,
1945 .ref_start_index = gz.ref_start_index,
1880 .astgen = astgen,1946 .astgen = astgen,
1881 };1947 };
1882 defer init_scope.instructions.deinit(gpa);1948 defer init_scope.instructions.deinit(gpa);
...@@ -1984,7 +2050,14 @@ fn varDecl(...@@ -1984,7 +2050,14 @@ fn varDecl(
1984 }2050 }
1985}2051}
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
1987fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void {2059fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void {
2060 try emitDbgNode(gz, infix_node);
1988 const astgen = gz.astgen;2061 const astgen = gz.astgen;
1989 const tree = &astgen.file.tree;2062 const tree = &astgen.file.tree;
1990 const node_datas = tree.nodes.items(.data);2063 const node_datas = tree.nodes.items(.data);
...@@ -2011,6 +2084,7 @@ fn assignOp(...@@ -2011,6 +2084,7 @@ fn assignOp(
2011 infix_node: ast.Node.Index,2084 infix_node: ast.Node.Index,
2012 op_inst_tag: Zir.Inst.Tag,2085 op_inst_tag: Zir.Inst.Tag,
2013) InnerError!void {2086) InnerError!void {
2087 try emitDbgNode(gz, infix_node);
2014 const astgen = gz.astgen;2088 const astgen = gz.astgen;
2015 const tree = &astgen.file.tree;2089 const tree = &astgen.file.tree;
2016 const node_datas = tree.nodes.items(.data);2090 const node_datas = tree.nodes.items(.data);
...@@ -2033,6 +2107,7 @@ fn assignShift(...@@ -2033,6 +2107,7 @@ fn assignShift(
2033 infix_node: ast.Node.Index,2107 infix_node: ast.Node.Index,
2034 op_inst_tag: Zir.Inst.Tag,2108 op_inst_tag: Zir.Inst.Tag,
2035) InnerError!void {2109) InnerError!void {
2110 try emitDbgNode(gz, infix_node);
2036 const astgen = gz.astgen;2111 const astgen = gz.astgen;
2037 const tree = &astgen.file.tree;2112 const tree = &astgen.file.tree;
2038 const node_datas = tree.nodes.items(.data);2113 const node_datas = tree.nodes.items(.data);
...@@ -2257,12 +2332,12 @@ fn fnDecl(...@@ -2257,12 +2332,12 @@ fn fnDecl(
2257 const param_types = try gpa.alloc(Zir.Inst.Ref, param_count);2332 const param_types = try gpa.alloc(Zir.Inst.Ref, param_count);
2258 defer gpa.free(param_types);2333 defer gpa.free(param_types);
22592334
2260 var decl_gz: Scope.GenZir = .{2335 var decl_gz: GenZir = .{
2261 .force_comptime = true,2336 .force_comptime = true,
2262 .decl_node_index = fn_proto.ast.proto_node,2337 .decl_node_index = fn_proto.ast.proto_node,
2263 .parent = &gz.base,2338 .parent = &gz.base,
2264 .astgen = astgen,2339 .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),
2266 };2341 };
2267 defer decl_gz.instructions.deinit(gpa);2342 defer decl_gz.instructions.deinit(gpa);
22682343
...@@ -2357,7 +2432,7 @@ fn fnDecl(...@@ -2357,7 +2432,7 @@ fn fnDecl(
2357 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{});2432 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{});
2358 }2433 }
23592434
2360 var fn_gz: Scope.GenZir = .{2435 var fn_gz: GenZir = .{
2361 .force_comptime = false,2436 .force_comptime = false,
2362 .decl_node_index = fn_proto.ast.proto_node,2437 .decl_node_index = fn_proto.ast.proto_node,
2363 .parent = &decl_gz.base,2438 .parent = &decl_gz.base,
...@@ -2366,6 +2441,9 @@ fn fnDecl(...@@ -2366,6 +2441,9 @@ fn fnDecl(
2366 };2441 };
2367 defer fn_gz.instructions.deinit(gpa);2442 defer fn_gz.instructions.deinit(gpa);
23682443
2444 const prev_fn_block = astgen.fn_block;
2445 astgen.fn_block = &fn_gz;
2446
2369 // Iterate over the parameters. We put the param names as the first N2447 // Iterate over the parameters. We put the param names as the first N
2370 // items inside `extra` so that debug info later can refer to the parameter names2448 // items inside `extra` so that debug info later can refer to the parameter names
2371 // even while the respective source code is unloaded.2449 // even while the respective source code is unloaded.
...@@ -2406,6 +2484,8 @@ fn fnDecl(...@@ -2406,6 +2484,8 @@ fn fnDecl(
2406 _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));2484 _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
2407 }2485 }
24082486
2487 astgen.fn_block = prev_fn_block;
2488
2409 break :func try decl_gz.addFunc(.{2489 break :func try decl_gz.addFunc(.{
2410 .src_node = fn_proto.ast.proto_node,2490 .src_node = fn_proto.ast.proto_node,
2411 .ret_ty = return_type_inst,2491 .ret_ty = return_type_inst,
...@@ -2580,9 +2660,18 @@ fn testDecl(...@@ -2580,9 +2660,18 @@ fn testDecl(
2580 scope: *Scope,2660 scope: *Scope,
2581 node: ast.Node.Index,2661 node: ast.Node.Index,
2582) InnerError!void {2662) InnerError!void {
2663 const gpa = astgen.gpa;
2583 const tree = &astgen.file.tree;2664 const tree = &astgen.file.tree;
2584 const node_datas = tree.nodes.items(.data);2665 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
2587 const test_name: u32 = blk: {2676 const test_name: u32 = blk: {
2588 const main_tokens = tree.nodes.items(.main_token);2677 const main_tokens = tree.nodes.items(.main_token);
...@@ -2590,13 +2679,49 @@ fn testDecl(...@@ -2590,13 +2679,49 @@ fn testDecl(
2590 const test_token = main_tokens[node];2679 const test_token = main_tokens[node];
2591 const str_lit_token = test_token + 1;2680 const str_lit_token = test_token + 1;
2592 if (token_tags[str_lit_token] == .string_literal) {2681 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;
2594 }2683 }
2595 break :blk 0;2684 break :blk 0;
2596 };2685 };
25972686
2598 // TODO probably we want to put these into a block and store a list of them2687 var fn_block: GenZir = .{
2599 const block_inst = try expr(gz, scope, .none, test_expr);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;
2600}2725}
26012726
2602fn structDeclInner(2727fn structDeclInner(
...@@ -2628,6 +2753,7 @@ fn structDeclInner(...@@ -2628,6 +2753,7 @@ fn structDeclInner(
2628 .decl_node_index = node,2753 .decl_node_index = node,
2629 .astgen = astgen,2754 .astgen = astgen,
2630 .force_comptime = true,2755 .force_comptime = true,
2756 .ref_start_index = gz.ref_start_index,
2631 };2757 };
2632 defer block_scope.instructions.deinit(gpa);2758 defer block_scope.instructions.deinit(gpa);
26332759
...@@ -2943,6 +3069,7 @@ fn containerDecl(...@@ -2943,6 +3069,7 @@ fn containerDecl(
2943 .decl_node_index = node,3069 .decl_node_index = node,
2944 .astgen = astgen,3070 .astgen = astgen,
2945 .force_comptime = true,3071 .force_comptime = true,
3072 .ref_start_index = gz.ref_start_index,
2946 };3073 };
2947 defer block_scope.instructions.deinit(gpa);3074 defer block_scope.instructions.deinit(gpa);
29483075
...@@ -3168,6 +3295,7 @@ fn tryExpr(...@@ -3168,6 +3295,7 @@ fn tryExpr(
3168 .decl_node_index = parent_gz.decl_node_index,3295 .decl_node_index = parent_gz.decl_node_index,
3169 .astgen = astgen,3296 .astgen = astgen,
3170 .force_comptime = parent_gz.force_comptime,3297 .force_comptime = parent_gz.force_comptime,
3298 .ref_start_index = parent_gz.ref_start_index,
3171 .instructions = .{},3299 .instructions = .{},
3172 };3300 };
3173 block_scope.setBreakResultLoc(rl);3301 block_scope.setBreakResultLoc(rl);
...@@ -3200,11 +3328,13 @@ fn tryExpr(...@@ -3200,11 +3328,13 @@ fn tryExpr(
3200 .decl_node_index = parent_gz.decl_node_index,3328 .decl_node_index = parent_gz.decl_node_index,
3201 .astgen = astgen,3329 .astgen = astgen,
3202 .force_comptime = block_scope.force_comptime,3330 .force_comptime = block_scope.force_comptime,
3331 .ref_start_index = parent_gz.ref_start_index,
3203 .instructions = .{},3332 .instructions = .{},
3204 };3333 };
3205 defer then_scope.instructions.deinit(astgen.gpa);3334 defer then_scope.instructions.deinit(astgen.gpa);
32063335
3207 const err_code = try then_scope.addUnNode(err_ops[1], operand, node);3336 const err_code = try then_scope.addUnNode(err_ops[1], operand, node);
3337 try genDefers(&then_scope, &astgen.fn_block.?.base, scope, err_code);
3208 const then_result = try then_scope.addUnNode(.ret_node, err_code, node);3338 const then_result = try then_scope.addUnNode(.ret_node, err_code, node);
32093339
3210 var else_scope: GenZir = .{3340 var else_scope: GenZir = .{
...@@ -3212,6 +3342,7 @@ fn tryExpr(...@@ -3212,6 +3342,7 @@ fn tryExpr(
3212 .decl_node_index = parent_gz.decl_node_index,3342 .decl_node_index = parent_gz.decl_node_index,
3213 .astgen = astgen,3343 .astgen = astgen,
3214 .force_comptime = block_scope.force_comptime,3344 .force_comptime = block_scope.force_comptime,
3345 .ref_start_index = parent_gz.ref_start_index,
3215 .instructions = .{},3346 .instructions = .{},
3216 };3347 };
3217 defer else_scope.instructions.deinit(astgen.gpa);3348 defer else_scope.instructions.deinit(astgen.gpa);
...@@ -3264,6 +3395,7 @@ fn orelseCatchExpr(...@@ -3264,6 +3395,7 @@ fn orelseCatchExpr(
3264 .decl_node_index = parent_gz.decl_node_index,3395 .decl_node_index = parent_gz.decl_node_index,
3265 .astgen = astgen,3396 .astgen = astgen,
3266 .force_comptime = parent_gz.force_comptime,3397 .force_comptime = parent_gz.force_comptime,
3398 .ref_start_index = parent_gz.ref_start_index,
3267 .instructions = .{},3399 .instructions = .{},
3268 };3400 };
3269 block_scope.setBreakResultLoc(rl);3401 block_scope.setBreakResultLoc(rl);
...@@ -3300,6 +3432,7 @@ fn orelseCatchExpr(...@@ -3300,6 +3432,7 @@ fn orelseCatchExpr(
3300 .decl_node_index = parent_gz.decl_node_index,3432 .decl_node_index = parent_gz.decl_node_index,
3301 .astgen = astgen,3433 .astgen = astgen,
3302 .force_comptime = block_scope.force_comptime,3434 .force_comptime = block_scope.force_comptime,
3435 .ref_start_index = parent_gz.ref_start_index,
3303 .instructions = .{},3436 .instructions = .{},
3304 };3437 };
3305 defer then_scope.instructions.deinit(astgen.gpa);3438 defer then_scope.instructions.deinit(astgen.gpa);
...@@ -3332,6 +3465,7 @@ fn orelseCatchExpr(...@@ -3332,6 +3465,7 @@ fn orelseCatchExpr(
3332 .decl_node_index = parent_gz.decl_node_index,3465 .decl_node_index = parent_gz.decl_node_index,
3333 .astgen = astgen,3466 .astgen = astgen,
3334 .force_comptime = block_scope.force_comptime,3467 .force_comptime = block_scope.force_comptime,
3468 .ref_start_index = parent_gz.ref_start_index,
3335 .instructions = .{},3469 .instructions = .{},
3336 };3470 };
3337 defer else_scope.instructions.deinit(astgen.gpa);3471 defer else_scope.instructions.deinit(astgen.gpa);
...@@ -3532,6 +3666,7 @@ fn boolBinOp(...@@ -3532,6 +3666,7 @@ fn boolBinOp(
3532 .decl_node_index = gz.decl_node_index,3666 .decl_node_index = gz.decl_node_index,
3533 .astgen = gz.astgen,3667 .astgen = gz.astgen,
3534 .force_comptime = gz.force_comptime,3668 .force_comptime = gz.force_comptime,
3669 .ref_start_index = gz.ref_start_index,
3535 };3670 };
3536 defer rhs_scope.instructions.deinit(gz.astgen.gpa);3671 defer rhs_scope.instructions.deinit(gz.astgen.gpa);
3537 const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs);3672 const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs);
...@@ -3558,6 +3693,7 @@ fn ifExpr(...@@ -3558,6 +3693,7 @@ fn ifExpr(
3558 .decl_node_index = parent_gz.decl_node_index,3693 .decl_node_index = parent_gz.decl_node_index,
3559 .astgen = astgen,3694 .astgen = astgen,
3560 .force_comptime = parent_gz.force_comptime,3695 .force_comptime = parent_gz.force_comptime,
3696 .ref_start_index = parent_gz.ref_start_index,
3561 .instructions = .{},3697 .instructions = .{},
3562 };3698 };
3563 block_scope.setBreakResultLoc(rl);3699 block_scope.setBreakResultLoc(rl);
...@@ -3608,6 +3744,7 @@ fn ifExpr(...@@ -3608,6 +3744,7 @@ fn ifExpr(
3608 .decl_node_index = parent_gz.decl_node_index,3744 .decl_node_index = parent_gz.decl_node_index,
3609 .astgen = astgen,3745 .astgen = astgen,
3610 .force_comptime = block_scope.force_comptime,3746 .force_comptime = block_scope.force_comptime,
3747 .ref_start_index = parent_gz.ref_start_index,
3611 .instructions = .{},3748 .instructions = .{},
3612 };3749 };
3613 defer then_scope.instructions.deinit(astgen.gpa);3750 defer then_scope.instructions.deinit(astgen.gpa);
...@@ -3662,6 +3799,7 @@ fn ifExpr(...@@ -3662,6 +3799,7 @@ fn ifExpr(
3662 .decl_node_index = parent_gz.decl_node_index,3799 .decl_node_index = parent_gz.decl_node_index,
3663 .astgen = astgen,3800 .astgen = astgen,
3664 .force_comptime = block_scope.force_comptime,3801 .force_comptime = block_scope.force_comptime,
3802 .ref_start_index = parent_gz.ref_start_index,
3665 .instructions = .{},3803 .instructions = .{},
3666 };3804 };
3667 defer else_scope.instructions.deinit(astgen.gpa);3805 defer else_scope.instructions.deinit(astgen.gpa);
...@@ -3812,6 +3950,7 @@ fn whileExpr(...@@ -3812,6 +3950,7 @@ fn whileExpr(
3812 .decl_node_index = parent_gz.decl_node_index,3950 .decl_node_index = parent_gz.decl_node_index,
3813 .astgen = astgen,3951 .astgen = astgen,
3814 .force_comptime = parent_gz.force_comptime,3952 .force_comptime = parent_gz.force_comptime,
3953 .ref_start_index = parent_gz.ref_start_index,
3815 .instructions = .{},3954 .instructions = .{},
3816 };3955 };
3817 loop_scope.setBreakResultLoc(rl);3956 loop_scope.setBreakResultLoc(rl);
...@@ -3822,6 +3961,7 @@ fn whileExpr(...@@ -3822,6 +3961,7 @@ fn whileExpr(
3822 .decl_node_index = parent_gz.decl_node_index,3961 .decl_node_index = parent_gz.decl_node_index,
3823 .astgen = astgen,3962 .astgen = astgen,
3824 .force_comptime = loop_scope.force_comptime,3963 .force_comptime = loop_scope.force_comptime,
3964 .ref_start_index = parent_gz.ref_start_index,
3825 .instructions = .{},3965 .instructions = .{},
3826 };3966 };
3827 defer continue_scope.instructions.deinit(astgen.gpa);3967 defer continue_scope.instructions.deinit(astgen.gpa);
...@@ -3891,6 +4031,7 @@ fn whileExpr(...@@ -3891,6 +4031,7 @@ fn whileExpr(
3891 .decl_node_index = parent_gz.decl_node_index,4031 .decl_node_index = parent_gz.decl_node_index,
3892 .astgen = astgen,4032 .astgen = astgen,
3893 .force_comptime = continue_scope.force_comptime,4033 .force_comptime = continue_scope.force_comptime,
4034 .ref_start_index = parent_gz.ref_start_index,
3894 .instructions = .{},4035 .instructions = .{},
3895 };4036 };
3896 defer then_scope.instructions.deinit(astgen.gpa);4037 defer then_scope.instructions.deinit(astgen.gpa);
...@@ -3942,6 +4083,7 @@ fn whileExpr(...@@ -3942,6 +4083,7 @@ fn whileExpr(
3942 .decl_node_index = parent_gz.decl_node_index,4083 .decl_node_index = parent_gz.decl_node_index,
3943 .astgen = astgen,4084 .astgen = astgen,
3944 .force_comptime = continue_scope.force_comptime,4085 .force_comptime = continue_scope.force_comptime,
4086 .ref_start_index = parent_gz.ref_start_index,
3945 .instructions = .{},4087 .instructions = .{},
3946 };4088 };
3947 defer else_scope.instructions.deinit(astgen.gpa);4089 defer else_scope.instructions.deinit(astgen.gpa);
...@@ -4043,6 +4185,7 @@ fn forExpr(...@@ -4043,6 +4185,7 @@ fn forExpr(
4043 .decl_node_index = parent_gz.decl_node_index,4185 .decl_node_index = parent_gz.decl_node_index,
4044 .astgen = astgen,4186 .astgen = astgen,
4045 .force_comptime = parent_gz.force_comptime,4187 .force_comptime = parent_gz.force_comptime,
4188 .ref_start_index = parent_gz.ref_start_index,
4046 .instructions = .{},4189 .instructions = .{},
4047 };4190 };
4048 loop_scope.setBreakResultLoc(rl);4191 loop_scope.setBreakResultLoc(rl);
...@@ -4053,6 +4196,7 @@ fn forExpr(...@@ -4053,6 +4196,7 @@ fn forExpr(
4053 .decl_node_index = parent_gz.decl_node_index,4196 .decl_node_index = parent_gz.decl_node_index,
4054 .astgen = astgen,4197 .astgen = astgen,
4055 .force_comptime = loop_scope.force_comptime,4198 .force_comptime = loop_scope.force_comptime,
4199 .ref_start_index = parent_gz.ref_start_index,
4056 .instructions = .{},4200 .instructions = .{},
4057 };4201 };
4058 defer cond_scope.instructions.deinit(astgen.gpa);4202 defer cond_scope.instructions.deinit(astgen.gpa);
...@@ -4096,6 +4240,7 @@ fn forExpr(...@@ -4096,6 +4240,7 @@ fn forExpr(
4096 .decl_node_index = parent_gz.decl_node_index,4240 .decl_node_index = parent_gz.decl_node_index,
4097 .astgen = astgen,4241 .astgen = astgen,
4098 .force_comptime = cond_scope.force_comptime,4242 .force_comptime = cond_scope.force_comptime,
4243 .ref_start_index = parent_gz.ref_start_index,
4099 .instructions = .{},4244 .instructions = .{},
4100 };4245 };
4101 defer then_scope.instructions.deinit(astgen.gpa);4246 defer then_scope.instructions.deinit(astgen.gpa);
...@@ -4141,6 +4286,7 @@ fn forExpr(...@@ -4141,6 +4286,7 @@ fn forExpr(
4141 .decl_node_index = parent_gz.decl_node_index,4286 .decl_node_index = parent_gz.decl_node_index,
4142 .astgen = astgen,4287 .astgen = astgen,
4143 .force_comptime = cond_scope.force_comptime,4288 .force_comptime = cond_scope.force_comptime,
4289 .ref_start_index = parent_gz.ref_start_index,
4144 .instructions = .{},4290 .instructions = .{},
4145 };4291 };
4146 defer else_scope.instructions.deinit(astgen.gpa);4292 defer else_scope.instructions.deinit(astgen.gpa);
...@@ -4443,6 +4589,7 @@ fn switchExpr(...@@ -4443,6 +4589,7 @@ fn switchExpr(
4443 .decl_node_index = parent_gz.decl_node_index,4589 .decl_node_index = parent_gz.decl_node_index,
4444 .astgen = astgen,4590 .astgen = astgen,
4445 .force_comptime = parent_gz.force_comptime,4591 .force_comptime = parent_gz.force_comptime,
4592 .ref_start_index = parent_gz.ref_start_index,
4446 .instructions = .{},4593 .instructions = .{},
4447 };4594 };
4448 block_scope.setBreakResultLoc(rl);4595 block_scope.setBreakResultLoc(rl);
...@@ -4457,6 +4604,7 @@ fn switchExpr(...@@ -4457,6 +4604,7 @@ fn switchExpr(
4457 .decl_node_index = parent_gz.decl_node_index,4604 .decl_node_index = parent_gz.decl_node_index,
4458 .astgen = astgen,4605 .astgen = astgen,
4459 .force_comptime = parent_gz.force_comptime,4606 .force_comptime = parent_gz.force_comptime,
4607 .ref_start_index = parent_gz.ref_start_index,
4460 .instructions = .{},4608 .instructions = .{},
4461 };4609 };
4462 defer case_scope.instructions.deinit(gpa);4610 defer case_scope.instructions.deinit(gpa);
...@@ -4900,15 +5048,21 @@ fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -4900,15 +5048,21 @@ fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref
4900 const main_tokens = tree.nodes.items(.main_token);5048 const main_tokens = tree.nodes.items(.main_token);
49015049
4902 const operand_node = node_datas[node].lhs;5050 const operand_node = node_datas[node].lhs;
4903 const operand: Zir.Inst.Ref = if (operand_node != 0) operand: {5051 if (operand_node != 0) {
4904 const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node)) .{5052 const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node)) .{
4905 .ptr = try gz.addNodeExtended(.ret_ptr, node),5053 .ptr = try gz.addNodeExtended(.ret_ptr, node),
4906 } else .{5054 } else .{
4907 .ty = try gz.addNodeExtended(.ret_type, node),5055 .ty = try gz.addNodeExtended(.ret_type, node),
4908 };5056 };
4909 break :operand try expr(gz, scope, rl, operand_node);5057 const operand = try expr(gz, scope, rl, operand_node);
4910 } else .void_value;5058 // TODO check operand to see if we need to generate errdefers
4911 _ = try gz.addUnNode(.ret_node, operand, node);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);
4912 return Zir.Inst.Ref.unreachable_value;5066 return Zir.Inst.Ref.unreachable_value;
4913}5067}
49145068
...@@ -5309,6 +5463,7 @@ fn asRlPtr(...@@ -5309,6 +5463,7 @@ fn asRlPtr(
5309 .decl_node_index = parent_gz.decl_node_index,5463 .decl_node_index = parent_gz.decl_node_index,
5310 .astgen = astgen,5464 .astgen = astgen,
5311 .force_comptime = parent_gz.force_comptime,5465 .force_comptime = parent_gz.force_comptime,
5466 .ref_start_index = parent_gz.ref_start_index,
5312 .instructions = .{},5467 .instructions = .{},
5313 };5468 };
5314 defer as_scope.instructions.deinit(astgen.gpa);5469 defer as_scope.instructions.deinit(astgen.gpa);
...@@ -5998,6 +6153,7 @@ fn cImport(...@@ -5998,6 +6153,7 @@ fn cImport(
5998 .decl_node_index = gz.decl_node_index,6153 .decl_node_index = gz.decl_node_index,
5999 .astgen = astgen,6154 .astgen = astgen,
6000 .force_comptime = true,6155 .force_comptime = true,
6156 .ref_start_index = gz.ref_start_index,
6001 .instructions = .{},6157 .instructions = .{},
6002 };6158 };
6003 defer block_scope.instructions.deinit(gpa);6159 defer block_scope.instructions.deinit(gpa);
...@@ -6454,7 +6610,7 @@ fn rvalue(...@@ -6454,7 +6610,7 @@ fn rvalue(
64546610
6455/// Given an identifier token, obtain the string for it.6611/// Given an identifier token, obtain the string for it.
6456/// If the token uses @"" syntax, parses as a string, reports errors if applicable,6612/// 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`.
6458/// Otherwise, returns a reference to the source code bytes directly.6614/// Otherwise, returns a reference to the source code bytes directly.
6459/// See also `appendIdentStr` and `parseStrLit`.6615/// See also `appendIdentStr` and `parseStrLit`.
6460pub fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError![]const u8 {6616pub fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError![]const u8 {
src/Module.zig+31-32
...@@ -514,31 +514,26 @@ pub const Scope = struct {...@@ -514,31 +514,26 @@ pub const Scope = struct {
514 pub const NameHash = [16]u8;514 pub const NameHash = [16]u8;
515515
516 pub fn cast(base: *Scope, comptime T: type) ?*T {516 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 }
517 if (base.tag != T.base_tag)523 if (base.tag != T.base_tag)
518 return null;524 return null;
519525
520 return @fieldParentPtr(T, "base", base);526 return @fieldParentPtr(T, "base", base);
521 }527 }
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
536 pub fn ownerDecl(scope: *Scope) ?*Decl {529 pub fn ownerDecl(scope: *Scope) ?*Decl {
537 return switch (scope.tag) {530 return switch (scope.tag) {
538 .block => scope.cast(Block).?.sema.owner_decl,531 .block => scope.cast(Block).?.sema.owner_decl,
539 .gen_zir => unreachable,532 .gen_zir => unreachable,
540 .local_val => unreachable,533 .local_val => unreachable,
541 .local_ptr => unreachable,534 .local_ptr => unreachable,
535 .defer_normal => unreachable,
536 .defer_error => unreachable,
542 .file => null,537 .file => null,
543 .namespace => null,538 .namespace => null,
544 .decl_ref => scope.cast(DeclRef).?.decl,539 .decl_ref => scope.cast(DeclRef).?.decl,
...@@ -551,6 +546,8 @@ pub const Scope = struct {...@@ -551,6 +546,8 @@ pub const Scope = struct {
551 .gen_zir => unreachable,546 .gen_zir => unreachable,
552 .local_val => unreachable,547 .local_val => unreachable,
553 .local_ptr => unreachable,548 .local_ptr => unreachable,
549 .defer_normal => unreachable,
550 .defer_error => unreachable,
554 .file => null,551 .file => null,
555 .namespace => null,552 .namespace => null,
556 .decl_ref => scope.cast(DeclRef).?.decl,553 .decl_ref => scope.cast(DeclRef).?.decl,
...@@ -564,25 +561,14 @@ pub const Scope = struct {...@@ -564,25 +561,14 @@ pub const Scope = struct {
564 .gen_zir => unreachable,561 .gen_zir => unreachable,
565 .local_val => unreachable,562 .local_val => unreachable,
566 .local_ptr => unreachable,563 .local_ptr => unreachable,
564 .defer_normal => unreachable,
565 .defer_error => unreachable,
567 .file => return scope.cast(File).?.namespace,566 .file => return scope.cast(File).?.namespace,
568 .namespace => return scope.cast(Namespace).?,567 .namespace => return scope.cast(Namespace).?,
569 .decl_ref => return scope.cast(DeclRef).?.decl.namespace,568 .decl_ref => return scope.cast(DeclRef).?.decl.namespace,
570 }569 }
571 }570 }
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
586 /// Asserts the scope has a parent which is a Namespace or File and572 /// Asserts the scope has a parent which is a Namespace or File and
587 /// returns the sub_file_path field.573 /// returns the sub_file_path field.
588 pub fn subFilePath(base: *Scope) []const u8 {574 pub fn subFilePath(base: *Scope) []const u8 {
...@@ -593,6 +579,8 @@ pub const Scope = struct {...@@ -593,6 +579,8 @@ pub const Scope = struct {
593 .gen_zir => unreachable,579 .gen_zir => unreachable,
594 .local_val => unreachable,580 .local_val => unreachable,
595 .local_ptr => unreachable,581 .local_ptr => unreachable,
582 .defer_normal => unreachable,
583 .defer_error => unreachable,
596 .decl_ref => unreachable,584 .decl_ref => unreachable,
597 }585 }
598 }586 }
...@@ -604,9 +592,11 @@ pub const Scope = struct {...@@ -604,9 +592,11 @@ pub const Scope = struct {
604 cur = switch (cur.tag) {592 cur = switch (cur.tag) {
605 .namespace => return @fieldParentPtr(Namespace, "base", cur).file_scope,593 .namespace => return @fieldParentPtr(Namespace, "base", cur).file_scope,
606 .file => return @fieldParentPtr(File, "base", cur),594 .file => return @fieldParentPtr(File, "base", cur),
607 .gen_zir => @fieldParentPtr(GenZir, "base", cur).parent,595 .gen_zir => return @fieldParentPtr(GenZir, "base", cur).astgen.file,
608 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,596 .local_val => return @fieldParentPtr(LocalVal, "base", cur).gen_zir.astgen.file,
609 .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent,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,
610 .block => return @fieldParentPtr(Block, "base", cur).src_decl.namespace.file_scope,600 .block => return @fieldParentPtr(Block, "base", cur).src_decl.namespace.file_scope,
611 .decl_ref => return @fieldParentPtr(DeclRef, "base", cur).decl.namespace.file_scope,601 .decl_ref => return @fieldParentPtr(DeclRef, "base", cur).decl.namespace.file_scope,
612 };602 };
...@@ -634,6 +624,8 @@ pub const Scope = struct {...@@ -634,6 +624,8 @@ pub const Scope = struct {
634 /// `Decl` for use with `srcDecl` and `ownerDecl`.624 /// `Decl` for use with `srcDecl` and `ownerDecl`.
635 /// Has no parents or children.625 /// Has no parents or children.
636 decl_ref,626 decl_ref,
627 defer_normal,
628 defer_error,
637 };629 };
638630
639 /// The container that structs, enums, unions, and opaques have.631 /// The container that structs, enums, unions, and opaques have.
...@@ -1709,7 +1701,7 @@ pub const Scope = struct {...@@ -1709,7 +1701,7 @@ pub const Scope = struct {
1709 pub const LocalVal = struct {1701 pub const LocalVal = struct {
1710 pub const base_tag: Tag = .local_val;1702 pub const base_tag: Tag = .local_val;
1711 base: Scope = Scope{ .tag = base_tag },1703 base: Scope = Scope{ .tag = base_tag },
1712 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`.1704 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
1713 parent: *Scope,1705 parent: *Scope,
1714 gen_zir: *GenZir,1706 gen_zir: *GenZir,
1715 name: []const u8,1707 name: []const u8,
...@@ -1724,7 +1716,7 @@ pub const Scope = struct {...@@ -1724,7 +1716,7 @@ pub const Scope = struct {
1724 pub const LocalPtr = struct {1716 pub const LocalPtr = struct {
1725 pub const base_tag: Tag = .local_ptr;1717 pub const base_tag: Tag = .local_ptr;
1726 base: Scope = Scope{ .tag = base_tag },1718 base: Scope = Scope{ .tag = base_tag },
1727 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`.1719 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
1728 parent: *Scope,1720 parent: *Scope,
1729 gen_zir: *GenZir,1721 gen_zir: *GenZir,
1730 name: []const u8,1722 name: []const u8,
...@@ -1733,6 +1725,13 @@ pub const Scope = struct {...@@ -1733,6 +1725,13 @@ pub const Scope = struct {
1733 token_src: ast.TokenIndex,1725 token_src: ast.TokenIndex,
1734 };1726 };
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
1736 pub const DeclRef = struct {1735 pub const DeclRef = struct {
1737 pub const base_tag: Tag = .decl_ref;1736 pub const base_tag: Tag = .decl_ref;
1738 base: Scope = Scope{ .tag = base_tag },1737 base: Scope = Scope{ .tag = base_tag },
...@@ -3821,7 +3820,7 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) In...@@ -3821,7 +3820,7 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) In
3821 }3820 }
3822 mod.failed_decls.putAssumeCapacityNoClobber(block.sema.owner_decl, err_msg);3821 mod.failed_decls.putAssumeCapacityNoClobber(block.sema.owner_decl, err_msg);
3823 },3822 },
3824 .gen_zir, .local_val, .local_ptr => unreachable,3823 .gen_zir, .local_val, .local_ptr, .defer_normal, .defer_error => unreachable,
3825 .file => unreachable,3824 .file => unreachable,
3826 .namespace => unreachable,3825 .namespace => unreachable,
3827 .decl_ref => {3826 .decl_ref => {
src/Zir.zig+33-4
...@@ -2304,6 +2304,7 @@ const Writer = struct {...@@ -2304,6 +2304,7 @@ const Writer = struct {
2304 .byte_swap,2304 .byte_swap,
2305 .bit_reverse,2305 .bit_reverse,
2306 .elem_type,2306 .elem_type,
2307 .bitcast_result_ptr,
2307 => try self.writeUnNode(stream, inst),2308 => try self.writeUnNode(stream, inst),
23082309
2309 .ref,2310 .ref,
...@@ -2424,6 +2425,7 @@ const Writer = struct {...@@ -2424,6 +2425,7 @@ const Writer = struct {
2424 .splat,2425 .splat,
2425 .reduce,2426 .reduce,
2426 .atomic_load,2427 .atomic_load,
2428 .bitcast,
2427 => try self.writePlNodeBin(stream, inst),2429 => try self.writePlNodeBin(stream, inst),
24282430
2429 .call,2431 .call,
...@@ -2509,13 +2511,40 @@ const Writer = struct {...@@ -2509,13 +2511,40 @@ const Writer = struct {
2509 .switch_capture_else_ref,2511 .switch_capture_else_ref,
2510 => try self.writeSwitchCapture(stream, inst),2512 => try self.writeSwitchCapture(stream, inst),
25112513
2512 .bitcast,2514 .extended => try self.writeExtended(stream, inst),
2513 .bitcast_result_ptr,2515 }
2514 .extended,2516 }
2515 => try stream.writeAll("TODO)"),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))"),
2516 }2539 }
2517 }2540 }
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
2519 fn writeBin(self: *Writer, stream: anytype, inst: Inst.Index) !void {2548 fn writeBin(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2520 const inst_data = self.code.instructions.items(.data)[inst].bin;2549 const inst_data = self.code.instructions.items(.data)[inst].bin;
2521 try self.writeInstRef(stream, inst_data.lhs);2550 try self.writeInstRef(stream, inst_data.lhs);