╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ Type.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
2723 2724 pub fn arrayBase(ty: Type, zcu: *const Zcu) struct { Type, u64 } { 2725 var cur_ty: Type = ty; 2726 var cur_len: u64 = 1; 2727 while (cur_ty.zigTypeTag(zcu) == .array) { 2728 cur_len *= cur_ty.arrayLenIncludingSentinel(zcu); 2729 cur_ty = cur_ty.childType(zcu); 2730 } 2731 return .{ cur_ty, cur_len }; 2732 } 2733 2734 /// Asserts that `loaded_union.layout` is not `.@"packed"`. 2735 pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) Zcu.UnionLayout { 2736 assert(loaded_union.layout != .@"packed"); 2737 2738 const ip = &zcu.intern_pool; 2739 var most_aligned_field: u32 = 0; 2740 var most_aligned_field_align: InternPool.Alignment = .@"1"; 2741 var most_aligned_field_size: u64 = 0; 2742 var biggest_field: u32 = 0; 2743 var payload_size: u64 = 0; 2744 var payload_align: InternPool.Alignment = .@"1"; 2745 for (loaded_union.field_types.get(ip), 0..) |field_ty_ip_index, field_index| { 2746 const field_ty: Type = .fromInterned(field_ty_ip_index); 2747 if (field_ty.isNoReturn(zcu)) continue; 2748 2749 const field_align: InternPool.Alignment = a: { 2750 const explicit_aligns = loaded_union.field_aligns.get(ip); 2751 if (explicit_aligns.len > 0) { 2752 const a = explicit_aligns[field_index]; 2753 if (a != .none) break :a a; 2754 } 2755 break :a field_ty.abiAlignment(zcu); 2756 }; 2757 if (field_ty.hasRuntimeBits(zcu)) { 2758 const field_size = field_ty.abiSize(zcu); 2759 if (field_size > payload_size) { 2760 payload_size = field_size; 2761 biggest_field = @intCast(field_index); 2762 } 2763 if (field_size > 0 and field_align.compare(.gte, most_aligned_field_align)) { 2764 most_aligned_field = @intCast(field_index); 2765 most_aligned_field_align = field_align; 2766 most_aligned_field_size = field_size; 2767 } 2768 } 2769 payload_align = payload_align.max(field_align); 2770 } 2771 if (!loaded_union.has_runtime_tag or 2772 !Type.fromInterned(loaded_union.enum_tag_type).hasRuntimeBits(zcu)) 2773 { 2774 return .{ 2775 .abi_size = payload_align.forward(payload_size), 2776 .abi_align = payload_align, 2777 .most_aligned_field = most_aligned_field, 2778 .most_aligned_field_size = most_aligned_field_size, 2779 .biggest_field = biggest_field, 2780 .payload_size = payload_size, 2781 .payload_align = payload_align, 2782 .tag_align = .none, 2783 .tag_size = 0, 2784 .padding = 0, 2785 }; 2786 } 2787 2788 const tag_size = Type.fromInterned(loaded_union.enum_tag_type).abiSize(zcu); 2789 const tag_align = Type.fromInterned(loaded_union.enum_tag_type).abiAlignment(zcu).max(.@"1"); 2790 return .{ 2791 .abi_size = loaded_union.size, 2792 .abi_align = tag_align.max(payload_align), 2793 .most_aligned_field = most_aligned_field, 2794 .most_aligned_field_size = most_aligned_field_size, 2795 .biggest_field = biggest_field, 2796 .payload_size = payload_size, 2797 .payload_align = payload_align, 2798 .tag_align = tag_align, 2799 .tag_size = tag_size, 2800 .padding = loaded_union.padding, 2801 }; 2802 } 2803 2804 /// Asserts that `ptr_ty` is either a many-item pointer, a slice, a C pointer, or a single pointer 2805 /// to array (in other words, a pointer which is indexed by pointer arithmetic), and returns the 2806 /// type of the element pointer at the given index. 2807 /// 2808 /// Asserts that the layout of the pointer element type is resolved. 2809 /// 2810 /// If `index` is `null`, the index is an arbitrary runtime-known value. 2811 pub fn elemPtrType(ptr_ty: Type, index: ?u64, pt: Zcu.PerThread) Allocator.Error!Type { 2812 const zcu = pt.zcu; 2813 const ip = &zcu.intern_pool; 2814 const ptr_info = ip.indexToKey(ptr_ty.toIntern()).ptr_type; 2815 const elem_ty: Type = switch (ptr_info.flags.size) { 2816 .slice, .many, .c => .fromInterned(ptr_info.child), 2817 .one => switch (ip.indexToKey(ptr_info.child)) { 2818 .array_type => |array_type| .fromInterned(array_type.child), 2819 .spirv_type => Type.fromInterned(ptr_info.child).childType(zcu), 2820 else => unreachable, 2821 }, 2822 }; 2823 elem_ty.assertHasLayout(zcu); 2824 const elem_align: Alignment = switch (elem_ty.classify(zcu)) { 2825 .no_possible_value, 2826 .one_possible_value, 2827 => ptr_info.flags.alignment, 2828 2829 .partially_comptime, 2830 .fully_comptime, 2831 => switch (ptr_info.flags.alignment) { 2832 .none => .none, 2833 else => |array_align| .minStrict(array_align, elem_ty.abiAlignment(zcu)), 2834 }, 2835 2836 .runtime => switch (ptr_info.flags.alignment) { 2837 .none => .none, 2838 else => |array_align| elem_align: { 2839 // If the index is runtime-known, use 1 as it gives the minimum possible alignment. 2840 const effective_index = index orelse 1; 2841 if (effective_index == 0) break :elem_align array_align; 2842 const byte_offset = effective_index * elem_ty.abiSize(zcu); 2843 break :elem_align .minStrict(array_align, .fromLog2Units(@ctz(byte_offset))); 2844 }, 2845 }, 2846 }; 2847 return pt.ptrType(.{ 2848 .child = elem_ty.toIntern(), 2849 .flags = .{ 2850 .size = .one, 2851 .is_const = ptr_info.flags.is_const, 2852 .is_volatile = ptr_info.flags.is_volatile, 2853 .is_allowzero = ptr_info.flags.is_allowzero and (index == null or index == 0), 2854 .address_space = ptr_info.flags.address_space, 2855 .alignment = elem_align, 2856 }, 2857 }); 2858 } 2859 2860 /// Asserts that `ptr_ty` is a pointer (single-item or C) to a struct, union, tuple, or slice, and 2861 /// returns the type of a pointer to the field at `field_index`. 2862 /// 2863 /// Asserts that the layout of the pointer child type is resolved. 2864 /// 2865 /// For slices, `Value.slice_ptr_index` and `Value.slice_len_index` are used for the field index. 2866 pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator.Error!Type { 2867 const zcu = pt.zcu; 2868 const ip = &zcu.intern_pool; 2869 const ptr_info = ip.indexToKey(ptr_ty.toIntern()).ptr_type; 2870 assert(ptr_info.flags.size == .one or ptr_info.flags.size == .c); 2871 const aggregate_ty: Type = .fromInterned(ptr_info.child); 2872 aggregate_ty.assertHasLayout(zcu); 2873 // We only exit this `switch` for default-layout aggregates, where the field pointer alignment 2874 // is a simple minimum of the aggregate pointer alignment and the field alignment. 2875 // `field_align` is `.none` if there is no explicit alignment annotation. 2876 const field_ty: Type, const field_align: Alignment = switch (aggregate_ty.zigTypeTag(zcu)) { 2877 .@"struct" => switch (aggregate_ty.containerLayout(zcu)) { 2878 .auto => field: { 2879 if (aggregate_ty.isTuple(zcu)) { 2880 break :field .{ aggregate_ty.fieldType(field_index, zcu), .none }; 2881 } 2882 const struct_obj = ip.loadStructType(aggregate_ty.toIntern()); 2883 break :field .{ 2884 .fromInterned(struct_obj.field_types.get(ip)[field_index]), 2885 struct_obj.field_aligns.getOrNone(ip, field_index), 2886 }; 2887 }, 2888 .@"extern" => { 2889 // Field alignment is determined based on the actual field offset. For instance, in 2890 // `extern struct { x: u32, y: u16 }`, the `y` field is 4-byte aligned. 2891 const field_ty = aggregate_ty.fieldType(field_index, zcu); 2892 const field_offset = aggregate_ty.structFieldOffset(field_index, zcu); 2893 const parent_align = switch (ptr_info.flags.alignment) { 2894 .none => aggregate_ty.abiAlignment(zcu), 2895 else => |a| a, 2896 }; 2897 const actual_field_align = switch (field_offset) { 2898 0 => parent_align, 2899 else => parent_align.minStrict(.fromLog2Units(@ctz(field_offset))), 2900 }; 2901 const field_ptr_align: Alignment = a: { 2902 if (ptr_info.flags.alignment == .none and 2903 aggregate_ty.explicitFieldAlignment(field_index, zcu) == .none and 2904 actual_field_align == field_ty.abiAlignment(zcu)) 2905 { 2906 // There's no user-specified 'align' in sight, and the alignment from the 2907 // field offset matches the field type's natural alignment, so just use a 2908 // default-aligned pointer. 2909 break :a .none; 2910 } 2911 break :a actual_field_align; 2912 }; 2913 var field_ptr_info = ptr_info; 2914 field_ptr_info.child = field_ty.toIntern(); 2915 field_ptr_info.flags.alignment = field_ptr_align; 2916 return pt.ptrType(field_ptr_info); 2917 }, 2918 .@"packed" => { 2919 var field_ptr_info = ptr_info; 2920 if (field_ptr_info.flags.alignment == .none) { 2921 field_ptr_info.flags.alignment = aggregate_ty.abiAlignment(zcu); 2922 } 2923 field_ptr_info.packed_offset = packed_offset: { 2924 comptime assert(Type.packed_struct_layout_version == 2); 2925 const bit_offset = zcu.structPackedFieldBitOffset( 2926 ip.loadStructType(aggregate_ty.toIntern()), 2927 field_index, 2928 ); 2929 break :packed_offset if (ptr_info.packed_offset.host_size != 0) .{ 2930 .host_size = ptr_info.packed_offset.host_size, 2931 .bit_offset = ptr_info.packed_offset.bit_offset + bit_offset, 2932 } else .{ 2933 .host_size = switch (zcu.comp.getZigBackend()) { 2934 else => @intCast((aggregate_ty.bitSize(zcu) + 7) / 8), 2935 .stage2_x86_64, .stage2_c => @intCast(aggregate_ty.abiSize(zcu)), 2936 }, 2937 .bit_offset = ptr_info.packed_offset.bit_offset + bit_offset, 2938 }; 2939 }; 2940 field_ptr_info.child = aggregate_ty.fieldType(field_index, zcu).toIntern(); 2941 return pt.ptrType(field_ptr_info); 2942 }, 2943 }, 2944 .@"union" => switch (aggregate_ty.containerLayout(zcu)) { 2945 .auto => field: { 2946 const union_obj = ip.loadUnionType(aggregate_ty.toIntern()); 2947 break :field .{ 2948 .fromInterned(union_obj.field_types.get(ip)[field_index]), 2949 union_obj.field_aligns.getOrNone(ip, field_index), 2950 }; 2951 }, 2952 .@"extern" => { 2953 // The alignment always matches that of the union pointer. If the union pointer is 2954 // default aligned (`.none`), we may need to explicitly align the result pointer. 2955 const field_ty = aggregate_ty.fieldType(field_index, zcu); 2956 var field_ptr_info = ptr_info; 2957 field_ptr_info.child = field_ty.toIntern(); 2958 if (field_ptr_info.flags.alignment == .none and 2959 Alignment.compareStrict(field_ty.abiAlignment(zcu), .neq, aggregate_ty.abiAlignment(zcu))) 2960 { 2961 field_ptr_info.flags.alignment = aggregate_ty.abiAlignment(zcu); 2962 } 2963 return pt.ptrType(field_ptr_info); 2964 }, 2965 .@"packed" => { 2966 const field_ty = aggregate_ty.fieldType(field_index, zcu); 2967 var field_ptr_info = ptr_info; 2968 if (field_ptr_info.flags.alignment == .none) { 2969 const resolved_align = aggregate_ty.abiAlignment(zcu); 2970 if (field_ty.abiAlignment(zcu) != resolved_align) { 2971 field_ptr_info.flags.alignment = resolved_align; 2972 } 2973 } 2974 field_ptr_info.child = aggregate_ty.fieldType(field_index, zcu).toIntern(); 2975 return pt.ptrType(field_ptr_info); 2976 }, 2977 }, 2978 .pointer => field: { 2979 assert(aggregate_ty.isSlice(zcu)); 2980 break :field switch (field_index) { 2981 Value.slice_ptr_index => .{ aggregate_ty.slicePtrFieldType(zcu), .none }, 2982 Value.slice_len_index => .{ .usize, .none }, 2983 else => unreachable, 2984 }; 2985 }, 2986 else => unreachable, 2987 }; 2988 const field_ptr_align: Alignment = a: { 2989 if (aggregate_ty.zigTypeTag(zcu) == .@"struct" and aggregate_ty.structFieldIsComptime(field_index, zcu)) { 2990 // For `comptime` fields, just use exactly what was specified, or ABI alignment if nothing was specified. 2991 break :a field_align; 2992 } 2993 const actual_field_align = switch (field_align) { 2994 .none => switch (ip.indexToKey(aggregate_ty.toIntern())) { 2995 .struct_type, .tuple_type, .union_type => field_ty.abiAlignment(zcu), 2996 .ptr_type => Type.usize.abiAlignment(zcu), 2997 else => unreachable, 2998 }, 2999 else => |a| a, 3000 }; 3001 const actual_aggregate_align = switch (ptr_info.flags.alignment) { 3002 .none => aggregate_ty.abiAlignment(zcu), 3003 else => |a| a, 3004 }; 3005 if (actual_aggregate_align.compareStrict(.lt, actual_field_align)) { 3006 // Underaligned aggregate; use that alignment. 3007 assert(ptr_info.flags.alignment != .none); 3008 break :a actual_aggregate_align; 3009 } 3010 if (field_align == .none and actual_field_align == field_ty.abiAlignment(zcu)) { 3011 // No explicit annotation on the field (nor an unusual default), and the aggregate 3012 // alignment is irrelevant to us, so return an un-annotated pointer. 3013 break :a .none; 3014 } 3015 break :a actual_field_align; 3016 }; 3017 var field_ptr_info = ptr_info; 3018 field_ptr_info.flags.alignment = field_ptr_align; 3019 field_ptr_info.child = field_ty.toIntern(); 3020 return pt.ptrType(field_ptr_info); 3021 } 3022 3023 pub fn containerTypeName(ty: Type, ip: *const InternPool) struct { 3024 name: InternPool.NullTerminatedString, 3025 fqn: InternPool.NullTerminatedString, 3026 } { 3027 switch (ip.indexToKey(ty.toIntern())) { 3028 .struct_type => { 3029 const loaded_struct = ip.loadStructType(ty.toIntern()); 3030 return .{ .name = loaded_struct.name, .fqn = loaded_struct.fqn }; 3031 }, 3032 .union_type => { 3033 const loaded_union = ip.loadUnionType(ty.toIntern()); 3034 return .{ .name = loaded_union.name, .fqn = loaded_union.fqn }; 3035 }, 3036 .enum_type => { 3037 const loaded_enum = ip.loadEnumType(ty.toIntern()); 3038 return .{ .name = loaded_enum.name, .fqn = loaded_enum.fqn }; 3039 }, 3040 .opaque_type => { 3041 const loaded_opaque = ip.loadOpaqueType(ty.toIntern()); 3042 return .{ .name = loaded_opaque.name, .fqn = loaded_opaque.fqn }; 3043 }, 3044 else => unreachable, 3045 } 3046 } 3047 3048 pub fn destructurable(ty: Type, zcu: *const Zcu) bool { 3049 return switch (ty.zigTypeTag(zcu)) { 3050 .array, .vector => true, 3051 .@"struct" => ty.isTuple(zcu), 3052 else => false, 3053 }; 3054 } 3055 3056 pub const UnpackableReason = union(enum) { 3057 comptime_only, 3058 pointer, 3059 enum_inferred_int_tag: Type, 3060 non_packed_struct: Type, 3061 non_packed_union: Type, 3062 slice, 3063 other, 3064 }; 3065 3066 /// Returns `null` iff `ty` is allowed in packed types. 3067 pub fn unpackable(ty: Type, zcu: *const Zcu) ?UnpackableReason { 3068 return switch (ty.zigTypeTag(zcu)) { 3069 .void, 3070 .bool, 3071 .float, 3072 .int, 3073 => null, 3074 3075 .type, 3076 .comptime_float, 3077 .comptime_int, 3078 .enum_literal, 3079 .undefined, 3080 .null, 3081 => .comptime_only, 3082 3083 .noreturn, 3084 .@"opaque", 3085 .spirv, 3086 .error_union, 3087 .error_set, 3088 .frame, 3089 .@"anyframe", 3090 .@"fn", 3091 .array, 3092 .vector, 3093 => .other, 3094 3095 .optional => if (ty.isPtrLikeOptional(zcu)) 3096 .pointer 3097 else 3098 .other, 3099 3100 .pointer => switch (ty.ptrSize(zcu)) { 3101 .slice => .slice, 3102 .one, .many, .c => .pointer, 3103 }, 3104 3105 .@"enum" => switch (ty.backingIntMode(zcu)) { 3106 .explicit => switch (ty.backingIntType(zcu).toIntern()) { 3107 else => null, 3108 .noreturn_type => .other, 3109 }, 3110 .auto => .{ .enum_inferred_int_tag = ty }, 3111 }, 3112 3113 .@"struct" => switch (ty.containerLayout(zcu)) { 3114 .@"packed" => null, 3115 .auto, .@"extern" => .{ .non_packed_struct = ty }, 3116 }, 3117 .@"union" => switch (ty.containerLayout(zcu)) { 3118 .@"packed" => null, 3119 .auto, .@"extern" => .{ .non_packed_union = ty }, 3120 }, 3121 }; 3122 } 3123 3124 pub const ExternPosition = enum { 3125 ret_ty, 3126 param_ty, 3127 union_field, 3128 struct_field, 3129 element, 3130 other, 3131 }; 3132 3133 /// Returns true if `ty` is allowed in extern types. 3134 /// Asserts that `ty` is fully resolved. 3135 /// Keep in sync with `Sema.explainWhyTypeIsNotExtern`. 3136 pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool { 3137 ty.assertHasLayout(zcu); 3138 return switch (ty.zigTypeTag(zcu)) { 3139 .type, 3140 .comptime_float, 3141 .comptime_int, 3142 .enum_literal, 3143 .undefined, 3144 .null, 3145 .error_union, 3146 .error_set, 3147 .frame, 3148 => false, 3149 3150 .vector => { 3151 if (zcu.getTarget().cpu.arch.isSpirV()) return true; 3152 return position == .param_ty or position == .ret_ty; 3153 }, 3154 3155 .void => switch (position) { 3156 .ret_ty, 3157 .union_field, 3158 .struct_field, 3159 .element, 3160 => true, 3161 .param_ty, 3162 .other, 3163 => false, 3164 }, 3165 3166 .noreturn => position == .ret_ty, 3167 3168 .@"opaque", 3169 .bool, 3170 .@"anyframe", 3171 => true, 3172 3173 .spirv => switch (position) { 3174 .struct_field, .union_field => true, 3175 .ret_ty, .param_ty, .element => !ty.isSpirvRuntimeArray(zcu), 3176 .other => !ty.isSpirvRuntimeArray(zcu) or zcu.getTarget().cpu.has(.spirv, .runtime_descriptor_array), 3177 }, 3178 3179 .pointer => { 3180 if (ty.isSlice(zcu)) return false; 3181 const child_ty = ty.childType(zcu); 3182 if (child_ty.zigTypeTag(zcu) == .@"fn") { 3183 return ty.isConstPtr(zcu) and validateExternCallconv(child_ty.fnCallingConvention(zcu)); 3184 } 3185 return true; 3186 }, 3187 .int => switch (ty.intInfo(zcu).bits) { 3188 0, 8, 16, 32, 64, 128 => true, 3189 24, 48 => zcu.getTarget().cpu.arch == .ez80, 3190 else => false, 3191 }, 3192 .float => switch (ty.floatBits(zcu.getTarget())) { 3193 else => true, 3194 80 => |bits| std.zig.target.compilerRtFloatAbi(zcu.getTarget(), bits) == .hard, 3195 }, 3196 .@"fn" => { 3197 if (position != .other) return false; 3198 return validateExternCallconv(ty.fnCallingConvention(zcu)); 3199 }, 3200 .@"enum" => { 3201 const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern()); 3202 return switch (enum_obj.int_tag_mode) { 3203 .auto => false, 3204 .explicit => Type.fromInterned(enum_obj.int_tag_type).validateExtern(position, zcu), 3205 }; 3206 }, 3207 .@"struct" => { 3208 if (ty.isTuple(zcu)) return false; 3209 const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern()); 3210 return switch (struct_obj.layout) { 3211 .auto => false, 3212 .@"extern" => true, 3213 .@"packed" => switch (struct_obj.packed_backing_mode) { 3214 .auto => false, 3215 .explicit => Type.fromInterned(struct_obj.packed_backing_int_type).validateExtern(position, zcu), 3216 }, 3217 }; 3218 }, 3219 .@"union" => { 3220 const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); 3221 return switch (union_obj.layout) { 3222 .auto => false, 3223 .@"extern" => true, 3224 .@"packed" => switch (union_obj.packed_backing_mode) { 3225 .auto => false, 3226 .explicit => Type.fromInterned(union_obj.packed_backing_int_type).validateExtern(position, zcu), 3227 }, 3228 }; 3229 }, 3230 .array => switch (position) { 3231 .ret_ty, 3232 .param_ty, 3233 => false, 3234 3235 .union_field, 3236 .struct_field, 3237 .element, 3238 .other, 3239 => ty.childType(zcu).validateExtern(.element, zcu), 3240 }, 3241 .optional => ty.isPtrLikeOptional(zcu), 3242 }; 3243 } 3244 fn validateExternCallconv(cc: std.lang.CallingConvention) bool { 3245 return switch (cc) { 3246 // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI. 3247 // The goal is to experiment with more integrated CPU/GPU code. 3248 .nvptx_kernel => true, 3249 else => !target_util.fnCallConvAllowsZigTypes(cc), 3250 }; 3251 } 3252 3253 /// Returns whether `ty` is considered by Zig to have a bit-level representation, meaning it is 3254 /// allowed as the operand to `@bitSizeOf`. This is a superset of packable types. 3255 pub fn hasBitRepresentation(ty: Type, zcu: *const Zcu) bool { 3256 return switch (ty.zigTypeTag(zcu)) { 3257 .@"fn", 3258 .noreturn, 3259 .undefined, 3260 .null, 3261 .@"opaque", 3262 .spirv, 3263 .type, 3264 .enum_literal, 3265 .comptime_float, 3266 .comptime_int, 3267 .error_set, 3268 .error_union, 3269 .frame, 3270 .@"anyframe", 3271 => false, 3272 3273 .void, 3274 .bool, 3275 .int, 3276 .float, 3277 => true, 3278 3279 .@"enum" => { 3280 const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern()); 3281 return enum_obj.int_tag_mode == .explicit and 3282 enum_obj.int_tag_type != .noreturn_type; 3283 }, 3284 .pointer, .optional => ty.isPtrAtRuntime(zcu), 3285 .@"struct", .@"union" => ty.containerLayout(zcu) == .@"packed", 3286 3287 .array, .vector => ty.childType(zcu).hasBitRepresentation(zcu), 3288 }; 3289 } 3290 3291 /// Asserts that `ty` has resolved layout. 3292 pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { 3293 if (!std.debug.runtime_safety) { 3294 // This early exit isn't necessary (`Zcu.assertUpToDate` checks `std.debug.runtime_safety` 3295 // itself), but LLVM has been observed to fail at optimizing away this safety check, which 3296 // has a major performance impact on ReleaseFast compiler builds. 3297 return; 3298 } 3299 switch (zcu.intern_pool.indexToKey(ty.toIntern())) { 3300 .int_type, 3301 .ptr_type, 3302 .anyframe_type, 3303 .simple_type, 3304 .opaque_type, 3305 .error_set_type, 3306 .spirv_type, 3307 .inferred_error_set_type, 3308 => {}, 3309 .func_type => |func_type| { 3310 for (func_type.param_types.get(&zcu.intern_pool)) |param_ty| { 3311 assertHasLayout(.fromInterned(param_ty), zcu); 3312 } 3313 assertHasLayout(.fromInterned(func_type.return_type), zcu); 3314 }, 3315 .array_type => |arr| assertHasLayout(.fromInterned(arr.child), zcu), 3316 .vector_type => |vec| assertHasLayout(.fromInterned(vec.child), zcu), 3317 .opt_type => |child| assertHasLayout(.fromInterned(child), zcu), 3318 .error_union_type => |eu| assertHasLayout(.fromInterned(eu.payload_type), zcu), 3319 .tuple_type => |tuple| for (tuple.types.get(&zcu.intern_pool)) |field_ty| { 3320 assertHasLayout(.fromInterned(field_ty), zcu); 3321 }, 3322 .struct_type => { 3323 assert(zcu.intern_pool.loadStructType(ty.toIntern()).want_layout); 3324 zcu.assertUpToDate(.wrap(.{ .type_layout = ty.toIntern() })); 3325 }, 3326 .union_type => { 3327 assert(zcu.intern_pool.loadUnionType(ty.toIntern()).want_layout); 3328 zcu.assertUpToDate(.wrap(.{ .type_layout = ty.toIntern() })); 3329 }, 3330 .enum_type => { 3331 assert(zcu.intern_pool.loadEnumType(ty.toIntern()).want_layout); 3332 zcu.assertUpToDate(.wrap(.{ .type_layout = ty.toIntern() })); 3333 }, 3334 3335 // values, not types 3336 .simple_value, 3337 .@"extern", 3338 .func, 3339 .int, 3340 .err, 3341 .error_union, 3342 .enum_literal, 3343 .enum_tag, 3344 .float, 3345 .ptr, 3346 .slice, 3347 .opt, 3348 .aggregate, 3349 .un, 3350 .bitpack, 3351 .undef, 3352 // memoization, not types 3353 .memoized_call, 3354 => unreachable, 3355 } 3356 } 3357 3358 /// Recursively walks the type and marks for each subtype how many times it has been seen 3359 fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.array_hash_map.Auto(Type, u16)) error{OutOfMemory}!void { 3360 const zcu = pt.zcu; 3361 const ip = &zcu.intern_pool; 3362 3363 const gop = try visited.getOrPut(zcu.gpa, ty); 3364 if (gop.found_existing) { 3365 gop.value_ptr.* += 1; 3366 } else { 3367 gop.value_ptr.* = 1; 3368 } 3369 3370 switch (ip.indexToKey(ty.toIntern())) { 3371 .ptr_type => try collectSubtypes(Type.fromInterned(ty.ptrInfo(zcu).child), pt, visited), 3372 .array_type => |array_type| try collectSubtypes(Type.fromInterned(array_type.child), pt, visited), 3373 .vector_type => |vector_type| try collectSubtypes(Type.fromInterned(vector_type.child), pt, visited), 3374 .opt_type => |child| try collectSubtypes(Type.fromInterned(child), pt, visited), 3375 .error_union_type => |error_union_type| { 3376 try collectSubtypes(Type.fromInterned(error_union_type.error_set_type), pt, visited); 3377 if (error_union_type.payload_type != .generic_poison_type) { 3378 try collectSubtypes(Type.fromInterned(error_union_type.payload_type), pt, visited); 3379 } 3380 }, 3381 .tuple_type => |tuple| { 3382 for (tuple.types.get(ip)) |field_ty| { 3383 try collectSubtypes(Type.fromInterned(field_ty), pt, visited); 3384 } 3385 }, 3386 .func_type => |fn_info| { 3387 const param_types = fn_info.param_types.get(&zcu.intern_pool); 3388 for (param_types) |param_ty| { 3389 if (param_ty != .generic_poison_type) { 3390 try collectSubtypes(Type.fromInterned(param_ty), pt, visited); 3391 } 3392 } 3393 3394 if (fn_info.return_type != .generic_poison_type) { 3395 try collectSubtypes(Type.fromInterned(fn_info.return_type), pt, visited); 3396 } 3397 }, 3398 .anyframe_type => |child| try collectSubtypes(Type.fromInterned(child), pt, visited), 3399 3400 // leaf types 3401 .undef, 3402 .inferred_error_set_type, 3403 .error_set_type, 3404 .struct_type, 3405 .union_type, 3406 .opaque_type, 3407 .enum_type, 3408 .spirv_type, 3409 .simple_type, 3410 .int_type, 3411 => {}, 3412 3413 // values, not types 3414 .simple_value, 3415 .@"extern", 3416 .func, 3417 .int, 3418 .err, 3419 .error_union, 3420 .enum_literal, 3421 .enum_tag, 3422 .float, 3423 .ptr, 3424 .slice, 3425 .opt, 3426 .aggregate, 3427 .un, 3428 .bitpack, 3429 // memoization, not types 3430 .memoized_call, 3431 => unreachable, 3432 } 3433 } 3434 3435 fn shouldDedupeType(ty: Type, ctx: *Comparison, pt: Zcu.PerThread) error{OutOfMemory}!Comparison.DedupeEntry { 3436 if (ctx.type_occurrences.get(ty)) |occ| { 3437 if (ctx.type_dedupe_cache.get(ty)) |cached| { 3438 return cached; 3439 } 3440 3441 var discarding: std.Io.Writer.Discarding = .init(&.{}); 3442 3443 print(ty, &discarding.writer, pt, null) catch 3444 unreachable; // we are writing into a discarding writer, it should never fail 3445 3446 const type_len: i32 = @intCast(discarding.count); 3447 3448 const placeholder_len: i32 = 1; 3449 const min_saved_bytes: i32 = 20; 3450 3451 const saved_bytes = (type_len - placeholder_len) * (occ - 1); 3452 const max_placeholders = 7; // T to Z 3453 const should_dedupe = saved_bytes >= min_saved_bytes and ctx.placeholder_index < max_placeholders; 3454 3455 const entry: Comparison.DedupeEntry = if (should_dedupe) b: { 3456 ctx.placeholder_index += 1; 3457 break :b .{ .dedupe = .{ .index = ctx.placeholder_index - 1 } }; 3458 } else .dont_dedupe; 3459 3460 try ctx.type_dedupe_cache.put(pt.zcu.gpa, ty, entry); 3461 3462 return entry; 3463 } else { 3464 return .{ .dont_dedupe = {} }; 3465 } 3466 } 3467 3468 /// The comparison recursively walks all types given and notes how many times 3469 /// each subtype occurs. It then while recursively printing decides for each 3470 /// subtype whether to print the type inline or create a placeholder based on 3471 /// the subtype length and number of occurences. Placeholders are then found by 3472 /// iterating `type_dedupe_cache` which caches the inline/placeholder decisions. 3473 pub const Comparison = struct { 3474 type_occurrences: std.array_hash_map.Auto(Type, u16), 3475 type_dedupe_cache: std.array_hash_map.Auto(Type, DedupeEntry), 3476 placeholder_index: u8, 3477 3478 pub const Placeholder = struct { 3479 index: u8, 3480 3481 pub fn format(p: Placeholder, writer: *std.Io.Writer) error{WriteFailed}!void { 3482 return writer.print("{c}", .{p.index + 'T'}); 3483 } 3484 }; 3485 3486 pub const DedupeEntry = union(enum) { 3487 dont_dedupe: void, 3488 dedupe: Placeholder, 3489 }; 3490 3491 pub fn init(types: []const Type, pt: Zcu.PerThread) error{OutOfMemory}!Comparison { 3492 var cmp: Comparison = .{ 3493 .type_occurrences = .empty, 3494 .type_dedupe_cache = .empty, 3495 .placeholder_index = 0, 3496 }; 3497 3498 errdefer cmp.deinit(pt); 3499 3500 for (types) |ty| { 3501 try collectSubtypes(ty, pt, &cmp.type_occurrences); 3502 } 3503 3504 return cmp; 3505 } 3506 3507 pub fn deinit(cmp: *Comparison, pt: Zcu.PerThread) void { 3508 const gpa = pt.zcu.gpa; 3509 cmp.type_occurrences.deinit(gpa); 3510 cmp.type_dedupe_cache.deinit(gpa); 3511 } 3512 3513 pub fn fmtType(ctx: *Comparison, ty: Type, pt: Zcu.PerThread) Comparison.Formatter { 3514 return .{ .ty = ty, .ctx = ctx, .pt = pt }; 3515 } 3516 pub const Formatter = struct { 3517 ty: Type, 3518 ctx: *Comparison, 3519 pt: Zcu.PerThread, 3520 3521 pub fn format(self: Comparison.Formatter, writer: anytype) error{WriteFailed}!void { 3522 print(self.ty, writer, self.pt, self.ctx) catch return error.WriteFailed; 3523 } 3524 }; 3525 }; 3526 3527 pub const @"u0": Type = .{ .ip_index = .u0_type }; 3528 pub const @"u1": Type = .{ .ip_index = .u1_type }; 3529 pub const @"u8": Type = .{ .ip_index = .u8_type }; 3530 pub const @"u16": Type = .{ .ip_index = .u16_type }; 3531 pub const @"u29": Type = .{ .ip_index = .u29_type }; 3532 pub const @"u32": Type = .{ .ip_index = .u32_type }; 3533 pub const @"u64": Type = .{ .ip_index = .u64_type }; 3534 pub const @"u80": Type = .{ .ip_index = .u80_type }; 3535 pub const @"u128": Type = .{ .ip_index = .u128_type }; 3536 pub const @"u256": Type = .{ .ip_index = .u256_type }; 3537 3538 pub const @"i8": Type = .{ .ip_index = .i8_type }; 3539 pub const @"i16": Type = .{ .ip_index = .i16_type }; 3540 pub const @"i32": Type = .{ .ip_index = .i32_type }; 3541 pub const @"i64": Type = .{ .ip_index = .i64_type }; 3542 pub const @"i128": Type = .{ .ip_index = .i128_type }; 3543 3544 pub const @"f16": Type = .{ .ip_index = .f16_type }; 3545 pub const @"f32": Type = .{ .ip_index = .f32_type }; 3546 pub const @"f64": Type = .{ .ip_index = .f64_type }; 3547 pub const @"f80": Type = .{ .ip_index = .f80_type }; 3548 pub const @"f128": Type = .{ .ip_index = .f128_type }; 3549 3550 pub const @"bool": Type = .{ .ip_index = .bool_type }; 3551 pub const @"usize": Type = .{ .ip_index = .usize_type }; 3552 pub const @"isize": Type = .{ .ip_index = .isize_type }; 3553 pub const @"comptime_int": Type = .{ .ip_index = .comptime_int_type }; 3554 pub const @"comptime_float": Type = .{ .ip_index = .comptime_float_type }; 3555 pub const @"void": Type = .{ .ip_index = .void_type }; 3556 pub const @"type": Type = .{ .ip_index = .type_type }; 3557 pub const @"anyerror": Type = .{ .ip_index = .anyerror_type }; 3558 pub const @"anyopaque": Type = .{ .ip_index = .anyopaque_type }; 3559 pub const @"anyframe": Type = .{ .ip_index = .anyframe_type }; 3560 pub const @"null": Type = .{ .ip_index = .null_type }; 3561 pub const @"undefined": Type = .{ .ip_index = .undefined_type }; 3562 pub const @"noreturn": Type = .{ .ip_index = .noreturn_type }; 3563 pub const enum_literal: Type = .{ .ip_index = .enum_literal_type }; 3564 3565 pub const @"c_char": Type = .{ .ip_index = .c_char_type }; 3566 pub const @"c_short": Type = .{ .ip_index = .c_short_type }; 3567 pub const @"c_ushort": Type = .{ .ip_index = .c_ushort_type }; 3568 pub const @"c_int": Type = .{ .ip_index = .c_int_type }; 3569 pub const @"c_uint": Type = .{ .ip_index = .c_uint_type }; 3570 pub const @"c_long": Type = .{ .ip_index = .c_long_type }; 3571 pub const @"c_ulong": Type = .{ .ip_index = .c_ulong_type }; 3572 pub const @"c_longlong": Type = .{ .ip_index = .c_longlong_type }; 3573 pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type }; 3574 pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type }; 3575 3576 pub const ptr_usize: Type = .{ .ip_index = .ptr_usize_type }; 3577 pub const ptr_const_comptime_int: Type = .{ .ip_index = .ptr_const_comptime_int_type }; 3578 pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type }; 3579 pub const manyptr_const_u8: Type = .{ .ip_index = .manyptr_const_u8_type }; 3580 pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type }; 3581 pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type }; 3582 pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type }; 3583 pub const slice_const_slice_const_u8: Type = .{ .ip_index = .slice_const_slice_const_u8_type }; 3584 pub const slice_const_type: Type = .{ .ip_index = .slice_const_type_type }; 3585 pub const optional_type: Type = .{ .ip_index = .optional_type_type }; 3586 pub const optional_noreturn: Type = .{ .ip_index = .optional_noreturn_type }; 3587 3588 pub const vector_8_i8: Type = .{ .ip_index = .vector_8_i8_type }; 3589 pub const vector_16_i8: Type = .{ .ip_index = .vector_16_i8_type }; 3590 pub const vector_32_i8: Type = .{ .ip_index = .vector_32_i8_type }; 3591 pub const vector_64_i8: Type = .{ .ip_index = .vector_64_i8_type }; 3592 pub const vector_1_u8: Type = .{ .ip_index = .vector_1_u8_type }; 3593 pub const vector_2_u8: Type = .{ .ip_index = .vector_2_u8_type }; 3594 pub const vector_4_u8: Type = .{ .ip_index = .vector_4_u8_type }; 3595 pub const vector_8_u8: Type = .{ .ip_index = .vector_8_u8_type }; 3596 pub const vector_16_u8: Type = .{ .ip_index = .vector_16_u8_type }; 3597 pub const vector_32_u8: Type = .{ .ip_index = .vector_32_u8_type }; 3598 pub const vector_64_u8: Type = .{ .ip_index = .vector_64_u8_type }; 3599 pub const vector_2_i16: Type = .{ .ip_index = .vector_2_i16_type }; 3600 pub const vector_4_i16: Type = .{ .ip_index = .vector_4_i16_type }; 3601 pub const vector_8_i16: Type = .{ .ip_index = .vector_8_i16_type }; 3602 pub const vector_16_i16: Type = .{ .ip_index = .vector_16_i16_type }; 3603 pub const vector_32_i16: Type = .{ .ip_index = .vector_32_i16_type }; 3604 pub const vector_4_u16: Type = .{ .ip_index = .vector_4_u16_type }; 3605 pub const vector_8_u16: Type = .{ .ip_index = .vector_8_u16_type }; 3606 pub const vector_16_u16: Type = .{ .ip_index = .vector_16_u16_type }; 3607 pub const vector_32_u16: Type = .{ .ip_index = .vector_32_u16_type }; 3608 pub const vector_2_i32: Type = .{ .ip_index = .vector_2_i32_type }; 3609 pub const vector_4_i32: Type = .{ .ip_index = .vector_4_i32_type }; 3610 pub const vector_8_i32: Type = .{ .ip_index = .vector_8_i32_type }; 3611 pub const vector_16_i32: Type = .{ .ip_index = .vector_16_i32_type }; 3612 pub const vector_4_u32: Type = .{ .ip_index = .vector_4_u32_type }; 3613 pub const vector_8_u32: Type = .{ .ip_index = .vector_8_u32_type }; 3614 pub const vector_16_u32: Type = .{ .ip_index = .vector_16_u32_type }; 3615 pub const vector_2_i64: Type = .{ .ip_index = .vector_2_i64_type }; 3616 pub const vector_4_i64: Type = .{ .ip_index = .vector_4_i64_type }; 3617 pub const vector_8_i64: Type = .{ .ip_index = .vector_8_i64_type }; 3618 pub const vector_2_u64: Type = .{ .ip_index = .vector_2_u64_type }; 3619 pub const vector_4_u64: Type = .{ .ip_index = .vector_4_u64_type }; 3620 pub const vector_8_u64: Type = .{ .ip_index = .vector_8_u64_type }; 3621 pub const vector_1_u128: Type = .{ .ip_index = .vector_1_u128_type }; 3622 pub const vector_2_u128: Type = .{ .ip_index = .vector_2_u128_type }; 3623 pub const vector_1_u256: Type = .{ .ip_index = .vector_1_u256_type }; 3624 pub const vector_4_f16: Type = .{ .ip_index = .vector_4_f16_type }; 3625 pub const vector_8_f16: Type = .{ .ip_index = .vector_8_f16_type }; 3626 pub const vector_16_f16: Type = .{ .ip_index = .vector_16_f16_type }; 3627 pub const vector_32_f16: Type = .{ .ip_index = .vector_32_f16_type }; 3628 pub const vector_2_f32: Type = .{ .ip_index = .vector_2_f32_type }; 3629 pub const vector_4_f32: Type = .{ .ip_index = .vector_4_f32_type }; 3630 pub const vector_8_f32: Type = .{ .ip_index = .vector_8_f32_type }; 3631 pub const vector_16_f32: Type = .{ .ip_index = .vector_16_f32_type }; 3632 pub const vector_2_f64: Type = .{ .ip_index = .vector_2_f64_type }; 3633 pub const vector_4_f64: Type = .{ .ip_index = .vector_4_f64_type }; 3634 pub const vector_8_f64: Type = .{ .ip_index = .vector_8_f64_type }; 3635 3636 pub const empty_tuple: Type = .{ .ip_index = .empty_tuple_type }; 3637 3638 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type }; 3639 3640 pub fn smallestUnsignedBits(max: u64) u16 { 3641 return switch (max) { 3642 0 => 0, 3643 else => @as(u16, 1) + std.math.log2_int(u64, max), 3644 }; 3645 } 3646 3647 /// This is only used for comptime asserts. Bump this number when you make a change 3648 /// to packed struct layout to find out all the places in the codebase you need to edit! 3649 pub const packed_struct_layout_version = 2; 3650 3651 fn cTypeAlign(target: *const Target, c_type: Target.CType) Alignment { 3652 return .fromByteUnits(target.cTypeAlignment(c_type).?); 3653 } 3654