authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-08-16 17:34:30+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-08-17 18:50:10-04:00
log89f02d1c107a159dc6433863c7d9167872b4c0c8
treee5d8f33f6b6e534118c1fec59eff9f05a0cc4a0f
parent84c2ebd6c6b16752d8d030d5904d0a525283cbf5

std.zig.Zir: fix declaration traversal

The old logic here had bitrotted, largely because there were some incorrect `else` cases. This is now implemented correctly for all current ZIR instructions. This prevents instructions being lost in incremental updates, which is important for updates to be minimal.

2 files changed, 614 insertions(+), 62 deletions(-)

lib/std/zig/Zir.zig+606-54
......@@ -603,7 +603,7 @@ pub const Inst = struct {
603603 /// Uses the `un_node` field.
604604 typeof,
605605 /// Implements `@TypeOf` for one operand.
606 /// Uses the `pl_node` field.
606 /// Uses the `pl_node` field. Payload is `Block`.
607607 typeof_builtin,
608608 /// Given a value, look at the type of it, which must be an integer type.
609609 /// Returns the integer type for the RHS of a shift operation.
......@@ -2727,6 +2727,9 @@ pub const Inst = struct {
27272727 field_name_start: NullTerminatedString,
27282728 };
27292729
2730 /// There is a body of instructions at `extra[body_index..][0..body_len]`.
2731 /// Trailing:
2732 /// 0. operand: Ref // for each `operands_len`
27302733 pub const TypeOfPeer = struct {
27312734 src_node: i32,
27322735 body_len: u32,
......@@ -2844,6 +2847,40 @@ pub const Inst = struct {
28442847 src_line: u32,
28452848 };
28462849
2850 /// Trailing:
2851 /// 0. multi_cases_len: u32 // if `has_multi_cases`
2852 /// 1. err_capture_inst: u32 // if `any_uses_err_capture`
2853 /// 2. non_err_body {
2854 /// info: ProngInfo,
2855 /// inst: Index // for every `info.body_len`
2856 /// }
2857 /// 3. else_body { // if `has_else`
2858 /// info: ProngInfo,
2859 /// inst: Index // for every `info.body_len`
2860 /// }
2861 /// 4. scalar_cases: { // for every `scalar_cases_len`
2862 /// item: Ref,
2863 /// info: ProngInfo,
2864 /// inst: Index // for every `info.body_len`
2865 /// }
2866 /// 5. multi_cases: { // for every `multi_cases_len`
2867 /// items_len: u32,
2868 /// ranges_len: u32,
2869 /// info: ProngInfo,
2870 /// item: Ref // for every `items_len`
2871 /// ranges: { // for every `ranges_len`
2872 /// item_first: Ref,
2873 /// item_last: Ref,
2874 /// }
2875 /// inst: Index // for every `info.body_len`
2876 /// }
2877 ///
2878 /// When analyzing a case body, the switch instruction itself refers to the
2879 /// captured error, or to the success value in `non_err_body`. Whether this
2880 /// is captured by reference or by value depends on whether the `byref` bit
2881 /// is set for the corresponding body. `err_capture_inst` refers to the error
2882 /// capture outside of the `switch`, i.e. `err` in
2883 /// `x catch |err| switch (err) { ... }`.
28472884 pub const SwitchBlockErrUnion = struct {
28482885 operand: Ref,
28492886 bits: Bits,
......@@ -3153,7 +3190,7 @@ pub const Inst = struct {
31533190 /// 1. captures_len: u32 // if has_captures_len
31543191 /// 2. body_len: u32, // if has_body_len
31553192 /// 3. fields_len: u32, // if has_fields_len
3156 /// 4. decls_len: u37, // if has_decls_len
3193 /// 4. decls_len: u32, // if has_decls_len
31573194 /// 5. capture: Capture // for every captures_len
31583195 /// 6. decl: Index, // for every decls_len; points to a `declaration` instruction
31593196 /// 7. inst: Index // for every body_len
......@@ -3624,33 +3661,492 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
36243661 }
36253662}
36263663
3627/// The iterator would have to allocate memory anyway to iterate. So here we populate
3628/// an ArrayList as the result.
3629pub fn findDecls(zir: Zir, list: *std.ArrayList(Inst.Index), decl_inst: Zir.Inst.Index) !void {
3664/// Find all type declarations, recursively, within a `declaration` instruction. Does not recurse through
3665/// said type declarations' declarations; to find all declarations, call this function on the declarations
3666/// of the discovered types recursively.
3667/// The iterator would have to allocate memory anyway to iterate, so an `ArrayList` is populated as the result.
3668pub fn findDecls(zir: Zir, gpa: Allocator, list: *std.ArrayListUnmanaged(Inst.Index), decl_inst: Zir.Inst.Index) !void {
36303669 list.clearRetainingCapacity();
36313670 const declaration, const extra_end = zir.getDeclaration(decl_inst);
36323671 const bodies = declaration.getBodies(extra_end, zir);
36333672
3634 try zir.findDeclsBody(list, bodies.value_body);
3635 if (bodies.align_body) |b| try zir.findDeclsBody(list, b);
3636 if (bodies.linksection_body) |b| try zir.findDeclsBody(list, b);
3637 if (bodies.addrspace_body) |b| try zir.findDeclsBody(list, b);
3673 // `defer` instructions duplicate the same body arbitrarily many times, but we only want to traverse
3674 // their contents once per defer. So, we store the extra index of the body here to deduplicate.
3675 var found_defers: std.AutoHashMapUnmanaged(u32, void) = .{};
3676 defer found_defers.deinit(gpa);
3677
3678 try zir.findDeclsBody(gpa, list, &found_defers, bodies.value_body);
3679 if (bodies.align_body) |b| try zir.findDeclsBody(gpa, list, &found_defers, b);
3680 if (bodies.linksection_body) |b| try zir.findDeclsBody(gpa, list, &found_defers, b);
3681 if (bodies.addrspace_body) |b| try zir.findDeclsBody(gpa, list, &found_defers, b);
36383682}
36393683
36403684fn findDeclsInner(
36413685 zir: Zir,
3642 list: *std.ArrayList(Inst.Index),
3686 gpa: Allocator,
3687 list: *std.ArrayListUnmanaged(Inst.Index),
3688 defers: *std.AutoHashMapUnmanaged(u32, void),
36433689 inst: Inst.Index,
36443690) Allocator.Error!void {
36453691 const tags = zir.instructions.items(.tag);
36463692 const datas = zir.instructions.items(.data);
36473693
36483694 switch (tags[@intFromEnum(inst)]) {
3695 .declaration => unreachable,
3696
3697 // Boring instruction tags first. These have no body and are not declarations or type declarations.
3698 .add,
3699 .addwrap,
3700 .add_sat,
3701 .add_unsafe,
3702 .sub,
3703 .subwrap,
3704 .sub_sat,
3705 .mul,
3706 .mulwrap,
3707 .mul_sat,
3708 .div_exact,
3709 .div_floor,
3710 .div_trunc,
3711 .mod,
3712 .rem,
3713 .mod_rem,
3714 .shl,
3715 .shl_exact,
3716 .shl_sat,
3717 .shr,
3718 .shr_exact,
3719 .param_anytype,
3720 .param_anytype_comptime,
3721 .array_cat,
3722 .array_mul,
3723 .array_type,
3724 .array_type_sentinel,
3725 .vector_type,
3726 .elem_type,
3727 .indexable_ptr_elem_type,
3728 .vector_elem_type,
3729 .indexable_ptr_len,
3730 .anyframe_type,
3731 .as_node,
3732 .as_shift_operand,
3733 .bit_and,
3734 .bitcast,
3735 .bit_not,
3736 .bit_or,
3737 .bool_not,
3738 .bool_br_and,
3739 .bool_br_or,
3740 .@"break",
3741 .break_inline,
3742 .check_comptime_control_flow,
3743 .builtin_call,
3744 .cmp_lt,
3745 .cmp_lte,
3746 .cmp_eq,
3747 .cmp_gte,
3748 .cmp_gt,
3749 .cmp_neq,
3750 .error_set_decl,
3751 .dbg_stmt,
3752 .dbg_var_ptr,
3753 .dbg_var_val,
3754 .decl_ref,
3755 .decl_val,
3756 .load,
3757 .div,
3758 .elem_ptr_node,
3759 .elem_ptr,
3760 .elem_val_node,
3761 .elem_val,
3762 .elem_val_imm,
3763 .ensure_result_used,
3764 .ensure_result_non_error,
3765 .ensure_err_union_payload_void,
3766 .error_union_type,
3767 .error_value,
3768 .@"export",
3769 .export_value,
3770 .field_ptr,
3771 .field_val,
3772 .field_ptr_named,
3773 .field_val_named,
3774 .import,
3775 .int,
3776 .int_big,
3777 .float,
3778 .float128,
3779 .int_type,
3780 .is_non_null,
3781 .is_non_null_ptr,
3782 .is_non_err,
3783 .is_non_err_ptr,
3784 .ret_is_non_err,
3785 .repeat,
3786 .repeat_inline,
3787 .for_len,
3788 .merge_error_sets,
3789 .ref,
3790 .ret_node,
3791 .ret_load,
3792 .ret_implicit,
3793 .ret_err_value,
3794 .ret_err_value_code,
3795 .ret_ptr,
3796 .ret_type,
3797 .ptr_type,
3798 .slice_start,
3799 .slice_end,
3800 .slice_sentinel,
3801 .slice_length,
3802 .store_node,
3803 .store_to_inferred_ptr,
3804 .str,
3805 .negate,
3806 .negate_wrap,
3807 .typeof,
3808 .typeof_log2_int_type,
3809 .@"unreachable",
3810 .xor,
3811 .optional_type,
3812 .optional_payload_safe,
3813 .optional_payload_unsafe,
3814 .optional_payload_safe_ptr,
3815 .optional_payload_unsafe_ptr,
3816 .err_union_payload_unsafe,
3817 .err_union_payload_unsafe_ptr,
3818 .err_union_code,
3819 .err_union_code_ptr,
3820 .enum_literal,
3821 .validate_deref,
3822 .validate_destructure,
3823 .field_type_ref,
3824 .opt_eu_base_ptr_init,
3825 .coerce_ptr_elem_ty,
3826 .validate_ref_ty,
3827 .struct_init_empty,
3828 .struct_init_empty_result,
3829 .struct_init_empty_ref_result,
3830 .struct_init_anon,
3831 .struct_init,
3832 .struct_init_ref,
3833 .validate_struct_init_ty,
3834 .validate_struct_init_result_ty,
3835 .validate_ptr_struct_init,
3836 .struct_init_field_type,
3837 .struct_init_field_ptr,
3838 .array_init_anon,
3839 .array_init,
3840 .array_init_ref,
3841 .validate_array_init_ty,
3842 .validate_array_init_result_ty,
3843 .validate_array_init_ref_ty,
3844 .validate_ptr_array_init,
3845 .array_init_elem_type,
3846 .array_init_elem_ptr,
3847 .union_init,
3848 .type_info,
3849 .size_of,
3850 .bit_size_of,
3851 .int_from_ptr,
3852 .compile_error,
3853 .set_eval_branch_quota,
3854 .int_from_enum,
3855 .align_of,
3856 .int_from_bool,
3857 .embed_file,
3858 .error_name,
3859 .panic,
3860 .trap,
3861 .set_runtime_safety,
3862 .sqrt,
3863 .sin,
3864 .cos,
3865 .tan,
3866 .exp,
3867 .exp2,
3868 .log,
3869 .log2,
3870 .log10,
3871 .abs,
3872 .floor,
3873 .ceil,
3874 .trunc,
3875 .round,
3876 .tag_name,
3877 .type_name,
3878 .frame_type,
3879 .frame_size,
3880 .int_from_float,
3881 .float_from_int,
3882 .ptr_from_int,
3883 .enum_from_int,
3884 .float_cast,
3885 .int_cast,
3886 .ptr_cast,
3887 .truncate,
3888 .has_decl,
3889 .has_field,
3890 .clz,
3891 .ctz,
3892 .pop_count,
3893 .byte_swap,
3894 .bit_reverse,
3895 .bit_offset_of,
3896 .offset_of,
3897 .splat,
3898 .reduce,
3899 .shuffle,
3900 .atomic_load,
3901 .atomic_rmw,
3902 .atomic_store,
3903 .mul_add,
3904 .memcpy,
3905 .memset,
3906 .min,
3907 .max,
3908 .alloc,
3909 .alloc_mut,
3910 .alloc_comptime_mut,
3911 .alloc_inferred,
3912 .alloc_inferred_mut,
3913 .alloc_inferred_comptime,
3914 .alloc_inferred_comptime_mut,
3915 .resolve_inferred_alloc,
3916 .make_ptr_const,
3917 .@"resume",
3918 .@"await",
3919 .save_err_ret_index,
3920 .restore_err_ret_index_unconditional,
3921 .restore_err_ret_index_fn_entry,
3922 => return,
3923
3924 .extended => {
3925 const extended = datas[@intFromEnum(inst)].extended;
3926 switch (extended.opcode) {
3927 .value_placeholder => unreachable,
3928
3929 // Once again, we start with the boring tags.
3930 .variable,
3931 .this,
3932 .ret_addr,
3933 .builtin_src,
3934 .error_return_trace,
3935 .frame,
3936 .frame_address,
3937 .alloc,
3938 .builtin_extern,
3939 .@"asm",
3940 .asm_expr,
3941 .compile_log,
3942 .min_multi,
3943 .max_multi,
3944 .add_with_overflow,
3945 .sub_with_overflow,
3946 .mul_with_overflow,
3947 .shl_with_overflow,
3948 .c_undef,
3949 .c_include,
3950 .c_define,
3951 .wasm_memory_size,
3952 .wasm_memory_grow,
3953 .prefetch,
3954 .fence,
3955 .set_float_mode,
3956 .set_align_stack,
3957 .set_cold,
3958 .error_cast,
3959 .await_nosuspend,
3960 .breakpoint,
3961 .disable_instrumentation,
3962 .select,
3963 .int_from_error,
3964 .error_from_int,
3965 .builtin_async_call,
3966 .cmpxchg,
3967 .c_va_arg,
3968 .c_va_copy,
3969 .c_va_end,
3970 .c_va_start,
3971 .ptr_cast_full,
3972 .ptr_cast_no_dest,
3973 .work_item_id,
3974 .work_group_size,
3975 .work_group_id,
3976 .in_comptime,
3977 .restore_err_ret_index,
3978 .closure_get,
3979 .field_parent_ptr,
3980 => return,
3981
3982 // `@TypeOf` has a body.
3983 .typeof_peer => {
3984 const extra = zir.extraData(Zir.Inst.TypeOfPeer, extended.operand);
3985 const body = zir.bodySlice(extra.data.body_index, extra.data.body_len);
3986 try zir.findDeclsBody(gpa, list, defers, body);
3987 },
3988
3989 // Reifications and opaque declarations need tracking, but have no body.
3990 .reify, .opaque_decl => return list.append(gpa, inst),
3991
3992 // Struct declarations need tracking and have bodies.
3993 .struct_decl => {
3994 try list.append(gpa, inst);
3995
3996 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
3997 const extra = zir.extraData(Zir.Inst.StructDecl, extended.operand);
3998 var extra_index = extra.end;
3999 const captures_len = if (small.has_captures_len) blk: {
4000 const captures_len = zir.extra[extra_index];
4001 extra_index += 1;
4002 break :blk captures_len;
4003 } else 0;
4004 const fields_len = if (small.has_fields_len) blk: {
4005 const fields_len = zir.extra[extra_index];
4006 extra_index += 1;
4007 break :blk fields_len;
4008 } else 0;
4009 const decls_len = if (small.has_decls_len) blk: {
4010 const decls_len = zir.extra[extra_index];
4011 extra_index += 1;
4012 break :blk decls_len;
4013 } else 0;
4014 extra_index += captures_len;
4015 if (small.has_backing_int) {
4016 const backing_int_body_len = zir.extra[extra_index];
4017 extra_index += 1;
4018 if (backing_int_body_len == 0) {
4019 extra_index += 1; // backing_int_ref
4020 } else {
4021 const body = zir.bodySlice(extra_index, backing_int_body_len);
4022 extra_index += backing_int_body_len;
4023 try zir.findDeclsBody(gpa, list, defers, body);
4024 }
4025 }
4026 extra_index += decls_len;
4027
4028 // This ZIR is structured in a slightly awkward way, so we have to split up the iteration.
4029 // `extra_index` iterates `flags` (bags of bits).
4030 // `fields_extra_index` iterates `fields`.
4031 // We accumulate the total length of bodies into `total_bodies_len`. This is sufficient because
4032 // the bodies are packed together in `extra` and we only need to traverse their instructions (we
4033 // don't really care about the structure).
4034
4035 const bits_per_field = 4;
4036 const fields_per_u32 = 32 / bits_per_field;
4037 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
4038 var cur_bit_bag: u32 = undefined;
4039
4040 var fields_extra_index = extra_index + bit_bags_count;
4041 var total_bodies_len: u32 = 0;
4042
4043 for (0..fields_len) |field_i| {
4044 if (field_i % fields_per_u32 == 0) {
4045 cur_bit_bag = zir.extra[extra_index];
4046 extra_index += 1;
4047 }
4048
4049 const has_align = @as(u1, @truncate(cur_bit_bag)) != 0;
4050 cur_bit_bag >>= 1;
4051 const has_init = @as(u1, @truncate(cur_bit_bag)) != 0;
4052 cur_bit_bag >>= 2; // also skip `is_comptime`; we don't care
4053 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;
4054 cur_bit_bag >>= 1;
4055
4056 fields_extra_index += @intFromBool(!small.is_tuple); // field_name
4057 fields_extra_index += 1; // doc_comment
4058
4059 if (has_type_body) {
4060 const field_type_body_len = zir.extra[fields_extra_index];
4061 total_bodies_len += field_type_body_len;
4062 }
4063 fields_extra_index += 1; // field_type or field_type_body_len
4064
4065 if (has_align) {
4066 const align_body_len = zir.extra[fields_extra_index];
4067 fields_extra_index += 1;
4068 total_bodies_len += align_body_len;
4069 }
4070
4071 if (has_init) {
4072 const init_body_len = zir.extra[fields_extra_index];
4073 fields_extra_index += 1;
4074 total_bodies_len += init_body_len;
4075 }
4076 }
4077
4078 // Now, `fields_extra_index` points to `bodies`. Let's treat this as one big body.
4079 const merged_bodies = zir.bodySlice(fields_extra_index, total_bodies_len);
4080 try zir.findDeclsBody(gpa, list, defers, merged_bodies);
4081 },
4082
4083 // Union declarations need tracking and have a body.
4084 .union_decl => {
4085 try list.append(gpa, inst);
4086
4087 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);
4088 const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand);
4089 var extra_index = extra.end;
4090 extra_index += @intFromBool(small.has_tag_type);
4091 const captures_len = if (small.has_captures_len) blk: {
4092 const captures_len = zir.extra[extra_index];
4093 extra_index += 1;
4094 break :blk captures_len;
4095 } else 0;
4096 const body_len = if (small.has_body_len) blk: {
4097 const body_len = zir.extra[extra_index];
4098 extra_index += 1;
4099 break :blk body_len;
4100 } else 0;
4101 extra_index += @intFromBool(small.has_fields_len);
4102 const decls_len = if (small.has_decls_len) blk: {
4103 const decls_len = zir.extra[extra_index];
4104 extra_index += 1;
4105 break :blk decls_len;
4106 } else 0;
4107 extra_index += captures_len;
4108 extra_index += decls_len;
4109 const body = zir.bodySlice(extra_index, body_len);
4110 try zir.findDeclsBody(gpa, list, defers, body);
4111 },
4112
4113 // Enum declarations need tracking and have a body.
4114 .enum_decl => {
4115 try list.append(gpa, inst);
4116
4117 const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small);
4118 const extra = zir.extraData(Zir.Inst.EnumDecl, extended.operand);
4119 var extra_index = extra.end;
4120 extra_index += @intFromBool(small.has_tag_type);
4121 const captures_len = if (small.has_captures_len) blk: {
4122 const captures_len = zir.extra[extra_index];
4123 extra_index += 1;
4124 break :blk captures_len;
4125 } else 0;
4126 const body_len = if (small.has_body_len) blk: {
4127 const body_len = zir.extra[extra_index];
4128 extra_index += 1;
4129 break :blk body_len;
4130 } else 0;
4131 extra_index += @intFromBool(small.has_fields_len);
4132 const decls_len = if (small.has_decls_len) blk: {
4133 const decls_len = zir.extra[extra_index];
4134 extra_index += 1;
4135 break :blk decls_len;
4136 } else 0;
4137 extra_index += captures_len;
4138 extra_index += decls_len;
4139 const body = zir.bodySlice(extra_index, body_len);
4140 try zir.findDeclsBody(gpa, list, defers, body);
4141 },
4142 }
4143 },
4144
36494145 // Functions instructions are interesting and have a body.
36504146 .func,
36514147 .func_inferred,
36524148 => {
3653 try list.append(inst);
4149 try list.append(gpa, inst);
36544150
36554151 const inst_data = datas[@intFromEnum(inst)].pl_node;
36564152 const extra = zir.extraData(Inst.Func, inst_data.payload_index);
......@@ -3661,14 +4157,14 @@ fn findDeclsInner(
36614157 else => {
36624158 const body = zir.bodySlice(extra_index, extra.data.ret_body_len);
36634159 extra_index += body.len;
3664 try zir.findDeclsBody(list, body);
4160 try zir.findDeclsBody(gpa, list, defers, body);
36654161 },
36664162 }
36674163 const body = zir.bodySlice(extra_index, extra.data.body_len);
3668 return zir.findDeclsBody(list, body);
4164 return zir.findDeclsBody(gpa, list, defers, body);
36694165 },
36704166 .func_fancy => {
3671 try list.append(inst);
4167 try list.append(gpa, inst);
36724168
36734169 const inst_data = datas[@intFromEnum(inst)].pl_node;
36744170 const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index);
......@@ -3679,7 +4175,7 @@ fn findDeclsInner(
36794175 const body_len = zir.extra[extra_index];
36804176 extra_index += 1;
36814177 const body = zir.bodySlice(extra_index, body_len);
3682 try zir.findDeclsBody(list, body);
4178 try zir.findDeclsBody(gpa, list, defers, body);
36834179 extra_index += body.len;
36844180 } else if (extra.data.bits.has_align_ref) {
36854181 extra_index += 1;
......@@ -3689,7 +4185,7 @@ fn findDeclsInner(
36894185 const body_len = zir.extra[extra_index];
36904186 extra_index += 1;
36914187 const body = zir.bodySlice(extra_index, body_len);
3692 try zir.findDeclsBody(list, body);
4188 try zir.findDeclsBody(gpa, list, defers, body);
36934189 extra_index += body.len;
36944190 } else if (extra.data.bits.has_addrspace_ref) {
36954191 extra_index += 1;
......@@ -3699,7 +4195,7 @@ fn findDeclsInner(
36994195 const body_len = zir.extra[extra_index];
37004196 extra_index += 1;
37014197 const body = zir.bodySlice(extra_index, body_len);
3702 try zir.findDeclsBody(list, body);
4198 try zir.findDeclsBody(gpa, list, defers, body);
37034199 extra_index += body.len;
37044200 } else if (extra.data.bits.has_section_ref) {
37054201 extra_index += 1;
......@@ -3709,7 +4205,7 @@ fn findDeclsInner(
37094205 const body_len = zir.extra[extra_index];
37104206 extra_index += 1;
37114207 const body = zir.bodySlice(extra_index, body_len);
3712 try zir.findDeclsBody(list, body);
4208 try zir.findDeclsBody(gpa, list, defers, body);
37134209 extra_index += body.len;
37144210 } else if (extra.data.bits.has_cc_ref) {
37154211 extra_index += 1;
......@@ -3719,7 +4215,7 @@ fn findDeclsInner(
37194215 const body_len = zir.extra[extra_index];
37204216 extra_index += 1;
37214217 const body = zir.bodySlice(extra_index, body_len);
3722 try zir.findDeclsBody(list, body);
4218 try zir.findDeclsBody(gpa, list, defers, body);
37234219 extra_index += body.len;
37244220 } else if (extra.data.bits.has_ret_ty_ref) {
37254221 extra_index += 1;
......@@ -3728,62 +4224,99 @@ fn findDeclsInner(
37284224 extra_index += @intFromBool(extra.data.bits.has_any_noalias);
37294225
37304226 const body = zir.bodySlice(extra_index, extra.data.body_len);
3731 return zir.findDeclsBody(list, body);
3732 },
3733 .extended => {
3734 const extended = datas[@intFromEnum(inst)].extended;
3735 switch (extended.opcode) {
3736
3737 // Decl instructions are interesting but have no body.
3738 // TODO yes they do have a body actually. recurse over them just like block instructions.
3739 .struct_decl,
3740 .union_decl,
3741 .enum_decl,
3742 .opaque_decl,
3743 .reify,
3744 => return list.append(inst),
3745
3746 else => return,
3747 }
4227 return zir.findDeclsBody(gpa, list, defers, body);
37484228 },
37494229
37504230 // Block instructions, recurse over the bodies.
37514231
3752 .block, .block_comptime, .block_inline => {
4232 .block,
4233 .block_comptime,
4234 .block_inline,
4235 .c_import,
4236 .typeof_builtin,
4237 .loop,
4238 => {
37534239 const inst_data = datas[@intFromEnum(inst)].pl_node;
37544240 const extra = zir.extraData(Inst.Block, inst_data.payload_index);
37554241 const body = zir.bodySlice(extra.end, extra.data.body_len);
3756 return zir.findDeclsBody(list, body);
4242 return zir.findDeclsBody(gpa, list, defers, body);
37574243 },
37584244 .condbr, .condbr_inline => {
37594245 const inst_data = datas[@intFromEnum(inst)].pl_node;
37604246 const extra = zir.extraData(Inst.CondBr, inst_data.payload_index);
37614247 const then_body = zir.bodySlice(extra.end, extra.data.then_body_len);
37624248 const else_body = zir.bodySlice(extra.end + then_body.len, extra.data.else_body_len);
3763 try zir.findDeclsBody(list, then_body);
3764 try zir.findDeclsBody(list, else_body);
4249 try zir.findDeclsBody(gpa, list, defers, then_body);
4250 try zir.findDeclsBody(gpa, list, defers, else_body);
37654251 },
37664252 .@"try", .try_ptr => {
37674253 const inst_data = datas[@intFromEnum(inst)].pl_node;
37684254 const extra = zir.extraData(Inst.Try, inst_data.payload_index);
37694255 const body = zir.bodySlice(extra.end, extra.data.body_len);
3770 try zir.findDeclsBody(list, body);
4256 try zir.findDeclsBody(gpa, list, defers, body);
37714257 },
3772 .switch_block => return findDeclsSwitch(zir, list, inst),
4258 .switch_block, .switch_block_ref => return zir.findDeclsSwitch(gpa, list, defers, inst, .normal),
4259 .switch_block_err_union => return zir.findDeclsSwitch(gpa, list, defers, inst, .err_union),
37734260
37744261 .suspend_block => @panic("TODO iterate suspend block"),
37754262
3776 else => return, // Regular instruction, not interesting.
4263 .param, .param_comptime => {
4264 const inst_data = datas[@intFromEnum(inst)].pl_tok;
4265 const extra = zir.extraData(Inst.Param, inst_data.payload_index);
4266 const body = zir.bodySlice(extra.end, extra.data.body_len);
4267 try zir.findDeclsBody(gpa, list, defers, body);
4268 },
4269
4270 inline .call, .field_call => |tag| {
4271 const inst_data = datas[@intFromEnum(inst)].pl_node;
4272 const extra = zir.extraData(switch (tag) {
4273 .call => Inst.Call,
4274 .field_call => Inst.FieldCall,
4275 else => unreachable,
4276 }, inst_data.payload_index);
4277 // It's easiest to just combine all the arg bodies into one body, like we do above for `struct_decl`.
4278 const args_len = extra.data.flags.args_len;
4279 if (args_len > 0) {
4280 const first_arg_start_off = args_len;
4281 const final_arg_end_off = zir.extra[extra.end + args_len - 1];
4282 const args_body = zir.bodySlice(extra.end + first_arg_start_off, final_arg_end_off - first_arg_start_off);
4283 try zir.findDeclsBody(gpa, list, defers, args_body);
4284 }
4285 },
4286 .@"defer" => {
4287 const inst_data = datas[@intFromEnum(inst)].@"defer";
4288 const gop = try defers.getOrPut(gpa, inst_data.index);
4289 if (!gop.found_existing) {
4290 const body = zir.bodySlice(inst_data.index, inst_data.len);
4291 try zir.findDeclsBody(gpa, list, defers, body);
4292 }
4293 },
4294 .defer_err_code => {
4295 const inst_data = datas[@intFromEnum(inst)].defer_err_code;
4296 const extra = zir.extraData(Inst.DeferErrCode, inst_data.payload_index).data;
4297 const gop = try defers.getOrPut(gpa, extra.index);
4298 if (!gop.found_existing) {
4299 const body = zir.bodySlice(extra.index, extra.len);
4300 try zir.findDeclsBody(gpa, list, defers, body);
4301 }
4302 },
37774303 }
37784304}
37794305
37804306fn findDeclsSwitch(
37814307 zir: Zir,
3782 list: *std.ArrayList(Inst.Index),
4308 gpa: Allocator,
4309 list: *std.ArrayListUnmanaged(Inst.Index),
4310 defers: *std.AutoHashMapUnmanaged(u32, void),
37834311 inst: Inst.Index,
4312 /// Distinguishes between `switch_block[_ref]` and `switch_block_err_union`.
4313 comptime kind: enum { normal, err_union },
37844314) Allocator.Error!void {
37854315 const inst_data = zir.instructions.items(.data)[@intFromEnum(inst)].pl_node;
3786 const extra = zir.extraData(Inst.SwitchBlock, inst_data.payload_index);
4316 const extra = zir.extraData(switch (kind) {
4317 .normal => Inst.SwitchBlock,
4318 .err_union => Inst.SwitchBlockErrUnion,
4319 }, inst_data.payload_index);
37874320
37884321 var extra_index: usize = extra.end;
37894322
......@@ -3793,18 +4326,35 @@ fn findDeclsSwitch(
37934326 break :blk multi_cases_len;
37944327 } else 0;
37954328
3796 if (extra.data.bits.any_has_tag_capture) {
4329 if (switch (kind) {
4330 .normal => extra.data.bits.any_has_tag_capture,
4331 .err_union => extra.data.bits.any_uses_err_capture,
4332 }) {
37974333 extra_index += 1;
37984334 }
37994335
3800 const special_prong = extra.data.bits.specialProng();
3801 if (special_prong != .none) {
4336 const has_special = switch (kind) {
4337 .normal => extra.data.bits.specialProng() != .none,
4338 .err_union => has_special: {
4339 // Handle `non_err_body` first.
4340 const prong_info: Inst.SwitchBlock.ProngInfo = @bitCast(zir.extra[extra_index]);
4341 extra_index += 1;
4342 const body = zir.bodySlice(extra_index, prong_info.body_len);
4343 extra_index += body.len;
4344
4345 try zir.findDeclsBody(gpa, list, defers, body);
4346
4347 break :has_special extra.data.bits.has_else;
4348 },
4349 };
4350
4351 if (has_special) {
38024352 const prong_info: Inst.SwitchBlock.ProngInfo = @bitCast(zir.extra[extra_index]);
38034353 extra_index += 1;
38044354 const body = zir.bodySlice(extra_index, prong_info.body_len);
38054355 extra_index += body.len;
38064356
3807 try zir.findDeclsBody(list, body);
4357 try zir.findDeclsBody(gpa, list, defers, body);
38084358 }
38094359
38104360 {
......@@ -3816,7 +4366,7 @@ fn findDeclsSwitch(
38164366 const body = zir.bodySlice(extra_index, prong_info.body_len);
38174367 extra_index += body.len;
38184368
3819 try zir.findDeclsBody(list, body);
4369 try zir.findDeclsBody(gpa, list, defers, body);
38204370 }
38214371 }
38224372 {
......@@ -3833,18 +4383,20 @@ fn findDeclsSwitch(
38334383 const body = zir.bodySlice(extra_index, prong_info.body_len);
38344384 extra_index += body.len;
38354385
3836 try zir.findDeclsBody(list, body);
4386 try zir.findDeclsBody(gpa, list, defers, body);
38374387 }
38384388 }
38394389}
38404390
38414391fn findDeclsBody(
38424392 zir: Zir,
3843 list: *std.ArrayList(Inst.Index),
4393 gpa: Allocator,
4394 list: *std.ArrayListUnmanaged(Inst.Index),
4395 defers: *std.AutoHashMapUnmanaged(u32, void),
38444396 body: []const Inst.Index,
38454397) Allocator.Error!void {
38464398 for (body) |member| {
3847 try zir.findDeclsInner(list, member);
4399 try zir.findDeclsInner(gpa, list, defers, member);
38484400 }
38494401}
38504402
......@@ -4042,7 +4594,7 @@ pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash {
40424594 return null;
40434595 }
40444596 const extra_index = extra.end +
4045 1 +
4597 extra.data.ret_body_len +
40464598 extra.data.body_len +
40474599 @typeInfo(Inst.Func.SrcLocs).Struct.fields.len;
40484600 return @bitCast([4]u32{
src/Zcu.zig+8-8
......@@ -2557,10 +2557,10 @@ pub fn mapOldZirToNew(
25572557 });
25582558
25592559 // Used as temporary buffers for namespace declaration instructions
2560 var old_decls = std.ArrayList(Zir.Inst.Index).init(gpa);
2561 defer old_decls.deinit();
2562 var new_decls = std.ArrayList(Zir.Inst.Index).init(gpa);
2563 defer new_decls.deinit();
2560 var old_decls: std.ArrayListUnmanaged(Zir.Inst.Index) = .{};
2561 defer old_decls.deinit(gpa);
2562 var new_decls: std.ArrayListUnmanaged(Zir.Inst.Index) = .{};
2563 defer new_decls.deinit(gpa);
25642564
25652565 while (match_stack.popOrNull()) |match_item| {
25662566 // Match the namespace declaration itself
......@@ -2647,11 +2647,11 @@ pub fn mapOldZirToNew(
26472647 // Match the `declaration` instruction
26482648 try inst_map.put(gpa, old_decl_inst, new_decl_inst);
26492649
2650 // Find namespace declarations within this declaration
2651 try old_zir.findDecls(&old_decls, old_decl_inst);
2652 try new_zir.findDecls(&new_decls, new_decl_inst);
2650 // Find container type declarations within this declaration
2651 try old_zir.findDecls(gpa, &old_decls, old_decl_inst);
2652 try new_zir.findDecls(gpa, &new_decls, new_decl_inst);
26532653
2654 // We don't have any smart way of matching up these namespace declarations, so we always
2654 // We don't have any smart way of matching up these type declarations, so we always
26552655 // correlate them based on source order.
26562656 const n = @min(old_decls.items.len, new_decls.items.len);
26572657 try match_stack.ensureUnusedCapacity(gpa, n);