| ... | ... | @@ -603,7 +603,7 @@ pub const Inst = struct { |
| 603 | 603 | /// Uses the `un_node` field. |
| 604 | 604 | typeof, |
| 605 | 605 | /// Implements `@TypeOf` for one operand. |
| 606 | | /// Uses the `pl_node` field. |
| 606 | /// Uses the `pl_node` field. Payload is `Block`. |
| 607 | 607 | typeof_builtin, |
| 608 | 608 | /// Given a value, look at the type of it, which must be an integer type. |
| 609 | 609 | /// Returns the integer type for the RHS of a shift operation. |
| ... | ... | @@ -2727,6 +2727,9 @@ pub const Inst = struct { |
| 2727 | 2727 | field_name_start: NullTerminatedString, |
| 2728 | 2728 | }; |
| 2729 | 2729 | |
| 2730 | /// There is a body of instructions at `extra[body_index..][0..body_len]`. |
| 2731 | /// Trailing: |
| 2732 | /// 0. operand: Ref // for each `operands_len` |
| 2730 | 2733 | pub const TypeOfPeer = struct { |
| 2731 | 2734 | src_node: i32, |
| 2732 | 2735 | body_len: u32, |
| ... | ... | @@ -2844,6 +2847,40 @@ pub const Inst = struct { |
| 2844 | 2847 | src_line: u32, |
| 2845 | 2848 | }; |
| 2846 | 2849 | |
| 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) { ... }`. |
| 2847 | 2884 | pub const SwitchBlockErrUnion = struct { |
| 2848 | 2885 | operand: Ref, |
| 2849 | 2886 | bits: Bits, |
| ... | ... | @@ -3153,7 +3190,7 @@ pub const Inst = struct { |
| 3153 | 3190 | /// 1. captures_len: u32 // if has_captures_len |
| 3154 | 3191 | /// 2. body_len: u32, // if has_body_len |
| 3155 | 3192 | /// 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 |
| 3157 | 3194 | /// 5. capture: Capture // for every captures_len |
| 3158 | 3195 | /// 6. decl: Index, // for every decls_len; points to a `declaration` instruction |
| 3159 | 3196 | /// 7. inst: Index // for every body_len |
| ... | ... | @@ -3624,33 +3661,492 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3624 | 3661 | } |
| 3625 | 3662 | } |
| 3626 | 3663 | |
| 3627 | | /// The iterator would have to allocate memory anyway to iterate. So here we populate |
| 3628 | | /// an ArrayList as the result. |
| 3629 | | pub 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. |
| 3668 | pub fn findDecls(zir: Zir, gpa: Allocator, list: *std.ArrayListUnmanaged(Inst.Index), decl_inst: Zir.Inst.Index) !void { |
| 3630 | 3669 | list.clearRetainingCapacity(); |
| 3631 | 3670 | const declaration, const extra_end = zir.getDeclaration(decl_inst); |
| 3632 | 3671 | const bodies = declaration.getBodies(extra_end, zir); |
| 3633 | 3672 | |
| 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); |
| 3638 | 3682 | } |
| 3639 | 3683 | |
| 3640 | 3684 | fn findDeclsInner( |
| 3641 | 3685 | zir: Zir, |
| 3642 | | list: *std.ArrayList(Inst.Index), |
| 3686 | gpa: Allocator, |
| 3687 | list: *std.ArrayListUnmanaged(Inst.Index), |
| 3688 | defers: *std.AutoHashMapUnmanaged(u32, void), |
| 3643 | 3689 | inst: Inst.Index, |
| 3644 | 3690 | ) Allocator.Error!void { |
| 3645 | 3691 | const tags = zir.instructions.items(.tag); |
| 3646 | 3692 | const datas = zir.instructions.items(.data); |
| 3647 | 3693 | |
| 3648 | 3694 | 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 | |
| 3649 | 4145 | // Functions instructions are interesting and have a body. |
| 3650 | 4146 | .func, |
| 3651 | 4147 | .func_inferred, |
| 3652 | 4148 | => { |
| 3653 | | try list.append(inst); |
| 4149 | try list.append(gpa, inst); |
| 3654 | 4150 | |
| 3655 | 4151 | const inst_data = datas[@intFromEnum(inst)].pl_node; |
| 3656 | 4152 | const extra = zir.extraData(Inst.Func, inst_data.payload_index); |
| ... | ... | @@ -3661,14 +4157,14 @@ fn findDeclsInner( |
| 3661 | 4157 | else => { |
| 3662 | 4158 | const body = zir.bodySlice(extra_index, extra.data.ret_body_len); |
| 3663 | 4159 | extra_index += body.len; |
| 3664 | | try zir.findDeclsBody(list, body); |
| 4160 | try zir.findDeclsBody(gpa, list, defers, body); |
| 3665 | 4161 | }, |
| 3666 | 4162 | } |
| 3667 | 4163 | const body = zir.bodySlice(extra_index, extra.data.body_len); |
| 3668 | | return zir.findDeclsBody(list, body); |
| 4164 | return zir.findDeclsBody(gpa, list, defers, body); |
| 3669 | 4165 | }, |
| 3670 | 4166 | .func_fancy => { |
| 3671 | | try list.append(inst); |
| 4167 | try list.append(gpa, inst); |
| 3672 | 4168 | |
| 3673 | 4169 | const inst_data = datas[@intFromEnum(inst)].pl_node; |
| 3674 | 4170 | const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index); |
| ... | ... | @@ -3679,7 +4175,7 @@ fn findDeclsInner( |
| 3679 | 4175 | const body_len = zir.extra[extra_index]; |
| 3680 | 4176 | extra_index += 1; |
| 3681 | 4177 | const body = zir.bodySlice(extra_index, body_len); |
| 3682 | | try zir.findDeclsBody(list, body); |
| 4178 | try zir.findDeclsBody(gpa, list, defers, body); |
| 3683 | 4179 | extra_index += body.len; |
| 3684 | 4180 | } else if (extra.data.bits.has_align_ref) { |
| 3685 | 4181 | extra_index += 1; |
| ... | ... | @@ -3689,7 +4185,7 @@ fn findDeclsInner( |
| 3689 | 4185 | const body_len = zir.extra[extra_index]; |
| 3690 | 4186 | extra_index += 1; |
| 3691 | 4187 | const body = zir.bodySlice(extra_index, body_len); |
| 3692 | | try zir.findDeclsBody(list, body); |
| 4188 | try zir.findDeclsBody(gpa, list, defers, body); |
| 3693 | 4189 | extra_index += body.len; |
| 3694 | 4190 | } else if (extra.data.bits.has_addrspace_ref) { |
| 3695 | 4191 | extra_index += 1; |
| ... | ... | @@ -3699,7 +4195,7 @@ fn findDeclsInner( |
| 3699 | 4195 | const body_len = zir.extra[extra_index]; |
| 3700 | 4196 | extra_index += 1; |
| 3701 | 4197 | const body = zir.bodySlice(extra_index, body_len); |
| 3702 | | try zir.findDeclsBody(list, body); |
| 4198 | try zir.findDeclsBody(gpa, list, defers, body); |
| 3703 | 4199 | extra_index += body.len; |
| 3704 | 4200 | } else if (extra.data.bits.has_section_ref) { |
| 3705 | 4201 | extra_index += 1; |
| ... | ... | @@ -3709,7 +4205,7 @@ fn findDeclsInner( |
| 3709 | 4205 | const body_len = zir.extra[extra_index]; |
| 3710 | 4206 | extra_index += 1; |
| 3711 | 4207 | const body = zir.bodySlice(extra_index, body_len); |
| 3712 | | try zir.findDeclsBody(list, body); |
| 4208 | try zir.findDeclsBody(gpa, list, defers, body); |
| 3713 | 4209 | extra_index += body.len; |
| 3714 | 4210 | } else if (extra.data.bits.has_cc_ref) { |
| 3715 | 4211 | extra_index += 1; |
| ... | ... | @@ -3719,7 +4215,7 @@ fn findDeclsInner( |
| 3719 | 4215 | const body_len = zir.extra[extra_index]; |
| 3720 | 4216 | extra_index += 1; |
| 3721 | 4217 | const body = zir.bodySlice(extra_index, body_len); |
| 3722 | | try zir.findDeclsBody(list, body); |
| 4218 | try zir.findDeclsBody(gpa, list, defers, body); |
| 3723 | 4219 | extra_index += body.len; |
| 3724 | 4220 | } else if (extra.data.bits.has_ret_ty_ref) { |
| 3725 | 4221 | extra_index += 1; |
| ... | ... | @@ -3728,62 +4224,99 @@ fn findDeclsInner( |
| 3728 | 4224 | extra_index += @intFromBool(extra.data.bits.has_any_noalias); |
| 3729 | 4225 | |
| 3730 | 4226 | 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); |
| 3748 | 4228 | }, |
| 3749 | 4229 | |
| 3750 | 4230 | // Block instructions, recurse over the bodies. |
| 3751 | 4231 | |
| 3752 | | .block, .block_comptime, .block_inline => { |
| 4232 | .block, |
| 4233 | .block_comptime, |
| 4234 | .block_inline, |
| 4235 | .c_import, |
| 4236 | .typeof_builtin, |
| 4237 | .loop, |
| 4238 | => { |
| 3753 | 4239 | const inst_data = datas[@intFromEnum(inst)].pl_node; |
| 3754 | 4240 | const extra = zir.extraData(Inst.Block, inst_data.payload_index); |
| 3755 | 4241 | const body = zir.bodySlice(extra.end, extra.data.body_len); |
| 3756 | | return zir.findDeclsBody(list, body); |
| 4242 | return zir.findDeclsBody(gpa, list, defers, body); |
| 3757 | 4243 | }, |
| 3758 | 4244 | .condbr, .condbr_inline => { |
| 3759 | 4245 | const inst_data = datas[@intFromEnum(inst)].pl_node; |
| 3760 | 4246 | const extra = zir.extraData(Inst.CondBr, inst_data.payload_index); |
| 3761 | 4247 | const then_body = zir.bodySlice(extra.end, extra.data.then_body_len); |
| 3762 | 4248 | 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); |
| 3765 | 4251 | }, |
| 3766 | 4252 | .@"try", .try_ptr => { |
| 3767 | 4253 | const inst_data = datas[@intFromEnum(inst)].pl_node; |
| 3768 | 4254 | const extra = zir.extraData(Inst.Try, inst_data.payload_index); |
| 3769 | 4255 | const body = zir.bodySlice(extra.end, extra.data.body_len); |
| 3770 | | try zir.findDeclsBody(list, body); |
| 4256 | try zir.findDeclsBody(gpa, list, defers, body); |
| 3771 | 4257 | }, |
| 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), |
| 3773 | 4260 | |
| 3774 | 4261 | .suspend_block => @panic("TODO iterate suspend block"), |
| 3775 | 4262 | |
| 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 | }, |
| 3777 | 4303 | } |
| 3778 | 4304 | } |
| 3779 | 4305 | |
| 3780 | 4306 | fn findDeclsSwitch( |
| 3781 | 4307 | zir: Zir, |
| 3782 | | list: *std.ArrayList(Inst.Index), |
| 4308 | gpa: Allocator, |
| 4309 | list: *std.ArrayListUnmanaged(Inst.Index), |
| 4310 | defers: *std.AutoHashMapUnmanaged(u32, void), |
| 3783 | 4311 | inst: Inst.Index, |
| 4312 | /// Distinguishes between `switch_block[_ref]` and `switch_block_err_union`. |
| 4313 | comptime kind: enum { normal, err_union }, |
| 3784 | 4314 | ) Allocator.Error!void { |
| 3785 | 4315 | 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); |
| 3787 | 4320 | |
| 3788 | 4321 | var extra_index: usize = extra.end; |
| 3789 | 4322 | |
| ... | ... | @@ -3793,18 +4326,35 @@ fn findDeclsSwitch( |
| 3793 | 4326 | break :blk multi_cases_len; |
| 3794 | 4327 | } else 0; |
| 3795 | 4328 | |
| 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 | }) { |
| 3797 | 4333 | extra_index += 1; |
| 3798 | 4334 | } |
| 3799 | 4335 | |
| 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) { |
| 3802 | 4352 | const prong_info: Inst.SwitchBlock.ProngInfo = @bitCast(zir.extra[extra_index]); |
| 3803 | 4353 | extra_index += 1; |
| 3804 | 4354 | const body = zir.bodySlice(extra_index, prong_info.body_len); |
| 3805 | 4355 | extra_index += body.len; |
| 3806 | 4356 | |
| 3807 | | try zir.findDeclsBody(list, body); |
| 4357 | try zir.findDeclsBody(gpa, list, defers, body); |
| 3808 | 4358 | } |
| 3809 | 4359 | |
| 3810 | 4360 | { |
| ... | ... | @@ -3816,7 +4366,7 @@ fn findDeclsSwitch( |
| 3816 | 4366 | const body = zir.bodySlice(extra_index, prong_info.body_len); |
| 3817 | 4367 | extra_index += body.len; |
| 3818 | 4368 | |
| 3819 | | try zir.findDeclsBody(list, body); |
| 4369 | try zir.findDeclsBody(gpa, list, defers, body); |
| 3820 | 4370 | } |
| 3821 | 4371 | } |
| 3822 | 4372 | { |
| ... | ... | @@ -3833,18 +4383,20 @@ fn findDeclsSwitch( |
| 3833 | 4383 | const body = zir.bodySlice(extra_index, prong_info.body_len); |
| 3834 | 4384 | extra_index += body.len; |
| 3835 | 4385 | |
| 3836 | | try zir.findDeclsBody(list, body); |
| 4386 | try zir.findDeclsBody(gpa, list, defers, body); |
| 3837 | 4387 | } |
| 3838 | 4388 | } |
| 3839 | 4389 | } |
| 3840 | 4390 | |
| 3841 | 4391 | fn findDeclsBody( |
| 3842 | 4392 | zir: Zir, |
| 3843 | | list: *std.ArrayList(Inst.Index), |
| 4393 | gpa: Allocator, |
| 4394 | list: *std.ArrayListUnmanaged(Inst.Index), |
| 4395 | defers: *std.AutoHashMapUnmanaged(u32, void), |
| 3844 | 4396 | body: []const Inst.Index, |
| 3845 | 4397 | ) Allocator.Error!void { |
| 3846 | 4398 | for (body) |member| { |
| 3847 | | try zir.findDeclsInner(list, member); |
| 4399 | try zir.findDeclsInner(gpa, list, defers, member); |
| 3848 | 4400 | } |
| 3849 | 4401 | } |
| 3850 | 4402 | |
| ... | ... | @@ -4042,7 +4594,7 @@ pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash { |
| 4042 | 4594 | return null; |
| 4043 | 4595 | } |
| 4044 | 4596 | const extra_index = extra.end + |
| 4045 | | 1 + |
| 4597 | extra.data.ret_body_len + |
| 4046 | 4598 | extra.data.body_len + |
| 4047 | 4599 | @typeInfo(Inst.Func.SrcLocs).Struct.fields.len; |
| 4048 | 4600 | return @bitCast([4]u32{ |