╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ Air.zig ──────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
1891 u32 => air.extra.items[i], 1892 InternPool.Index, Inst.Ref => @fromBackingInt(@intCast(air.extra.items[i])), 1893 i32, CondBr.BranchHints, Asm.Flags => @bitCast(air.extra.items[i]), 1894 else => @compileError("bad field type: " ++ @typeName(field_type)), 1895 }; 1896 i += 1; 1897 } 1898 return .{ 1899 .data = result, 1900 .end = i, 1901 }; 1902 } 1903 1904 pub fn deinit(air: *Air, gpa: std.mem.Allocator) void { 1905 air.instructions.deinit(gpa); 1906 air.extra.deinit(gpa); 1907 air.* = undefined; 1908 } 1909 1910 pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref { 1911 return .fromIntern(ip_index); 1912 } 1913 1914 pub const NullTerminatedString = enum(u32) { 1915 none = std.math.maxInt(u32), 1916 _, 1917 1918 pub fn toSlice(nts: NullTerminatedString, air: Air) [:0]const u8 { 1919 if (nts == .none) return ""; 1920 const bytes = std.mem.sliceAsBytes(air.extra.items[@backingInt(nts)..]); 1921 return bytes[0..std.mem.findScalar(u8, bytes, 0).? :0]; 1922 } 1923 }; 1924 1925 /// Returns whether the given instruction must always be lowered, for instance 1926 /// because it can cause side effects. If an instruction does not need to be 1927 /// lowered, and Liveness determines its result is unused, backends should 1928 /// avoid lowering it. 1929 pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { 1930 const data = air.instructions.items(.data)[@backingInt(inst)]; 1931 return switch (air.instructions.items(.tag)[@backingInt(inst)]) { 1932 .arg, 1933 .assembly, 1934 .block, 1935 .loop, 1936 .repeat, 1937 .br, 1938 .trap, 1939 .breakpoint, 1940 .call, 1941 .call_always_tail, 1942 .call_never_tail, 1943 .call_never_inline, 1944 .cond_br, 1945 .switch_br, 1946 .loop_switch_br, 1947 .switch_dispatch, 1948 .@"try", 1949 .try_cold, 1950 .try_ptr, 1951 .try_ptr_cold, 1952 .dbg_stmt, 1953 .dbg_empty_stmt, 1954 .dbg_inline_block, 1955 .dbg_var_ptr, 1956 .dbg_var_val, 1957 .dbg_arg_inline, 1958 .ret, 1959 .ret_safe, 1960 .ret_load, 1961 .store, 1962 .store_safe, 1963 .unreach, 1964 .optional_payload_ptr_set, 1965 .errunion_payload_ptr_set, 1966 .set_union_tag, 1967 .memset, 1968 .memset_safe, 1969 .memcpy, 1970 .memmove, 1971 .cmpxchg_weak, 1972 .cmpxchg_strong, 1973 .atomic_store_unordered, 1974 .atomic_store_monotonic, 1975 .atomic_store_release, 1976 .atomic_store_seq_cst, 1977 .atomic_rmw, 1978 .prefetch, 1979 .wasm_memory_grow, 1980 .set_err_return_trace, 1981 .c_va_arg, 1982 .c_va_copy, 1983 .c_va_end, 1984 .c_va_start, 1985 .add_safe, 1986 .sub_safe, 1987 .mul_safe, 1988 .bit_cast_safe, 1989 .int_cast_safe, 1990 .int_from_float_safe, 1991 .int_from_float_optimized_safe, 1992 .legalize_vec_store_elem, 1993 .legalize_compiler_rt_call, 1994 => true, 1995 1996 .add, 1997 .add_optimized, 1998 .add_wrap, 1999 .add_sat, 2000 .sub, 2001 .sub_optimized, 2002 .sub_wrap, 2003 .sub_sat, 2004 .mul, 2005 .mul_optimized, 2006 .mul_wrap, 2007 .mul_sat, 2008 .div_float, 2009 .div_float_optimized, 2010 .div_trunc, 2011 .div_trunc_optimized, 2012 .div_floor, 2013 .div_floor_optimized, 2014 .div_ceil, 2015 .div_ceil_optimized, 2016 .div_exact, 2017 .div_exact_optimized, 2018 .rem, 2019 .rem_optimized, 2020 .mod, 2021 .mod_optimized, 2022 .ptr_add, 2023 .ptr_sub, 2024 .max, 2025 .min, 2026 .add_with_overflow, 2027 .sub_with_overflow, 2028 .mul_with_overflow, 2029 .shl_with_overflow, 2030 .alloc, 2031 .inferred_alloc, 2032 .inferred_alloc_comptime, 2033 .ret_ptr, 2034 .bit_and, 2035 .bit_or, 2036 .shr, 2037 .shr_exact, 2038 .shl, 2039 .shl_exact, 2040 .shl_sat, 2041 .xor, 2042 .not, 2043 .bit_cast, 2044 .ptr_cast, 2045 .ptr_from_int, 2046 .int_from_ptr, 2047 .error_cast, 2048 .error_from_int, 2049 .int_from_error, 2050 .union_from_enum, 2051 .ret_addr, 2052 .frame_addr, 2053 .clz, 2054 .ctz, 2055 .popcount, 2056 .byte_swap, 2057 .bit_reverse, 2058 .sqrt, 2059 .sin, 2060 .cos, 2061 .tan, 2062 .exp, 2063 .exp2, 2064 .log, 2065 .log2, 2066 .log10, 2067 .abs, 2068 .floor, 2069 .ceil, 2070 .round, 2071 .trunc_float, 2072 .neg, 2073 .neg_optimized, 2074 .cmp_lt, 2075 .cmp_lt_optimized, 2076 .cmp_lte, 2077 .cmp_lte_optimized, 2078 .cmp_eq, 2079 .cmp_eq_optimized, 2080 .cmp_gte, 2081 .cmp_gte_optimized, 2082 .cmp_gt, 2083 .cmp_gt_optimized, 2084 .cmp_neq, 2085 .cmp_neq_optimized, 2086 .cmp_vector, 2087 .cmp_vector_optimized, 2088 .is_null, 2089 .is_non_null, 2090 .is_err, 2091 .is_non_err, 2092 .fptrunc, 2093 .fpext, 2094 .int_cast, 2095 .trunc, 2096 .optional_payload, 2097 .optional_payload_ptr, 2098 .wrap_optional, 2099 .unwrap_errunion_payload, 2100 .unwrap_errunion_err, 2101 .unwrap_errunion_payload_ptr, 2102 .wrap_errunion_payload, 2103 .wrap_errunion_err, 2104 .struct_field_ptr, 2105 .struct_field_ptr_index_0, 2106 .struct_field_ptr_index_1, 2107 .struct_field_ptr_index_2, 2108 .struct_field_ptr_index_3, 2109 .agg_field_val, 2110 .get_union_tag, 2111 .slice, 2112 .slice_len, 2113 .slice_ptr, 2114 .ptr_slice_len_ptr, 2115 .ptr_slice_ptr_ptr, 2116 .array_elem_val, 2117 .slice_elem_ptr, 2118 .ptr_elem_ptr, 2119 .array_to_slice, 2120 .array_to_vector, 2121 .int_from_float, 2122 .int_from_float_optimized, 2123 .float_from_int, 2124 .reduce, 2125 .reduce_optimized, 2126 .splat, 2127 .shuffle_one, 2128 .shuffle_two, 2129 .select, 2130 .is_named_enum_value, 2131 .tag_name, 2132 .error_name, 2133 .error_set_has_value, 2134 .aggregate_init, 2135 .union_init, 2136 .mul_add, 2137 .field_parent_ptr, 2138 .wasm_memory_size, 2139 .cmp_lte_errors_len, 2140 .err_return_trace, 2141 .addrspace_cast, 2142 .save_err_return_trace_index, 2143 .runtime_nav_ptr, 2144 .work_item_id, 2145 .work_group_size, 2146 .work_group_id, 2147 .legalize_vec_elem_val, 2148 .spirv_runtime_array_len, 2149 => false, 2150 2151 .is_non_null_ptr, .is_null_ptr, .is_non_err_ptr, .is_err_ptr => air.typeOf(data.un_op, ip).isVolatilePtrIp(ip), 2152 .load, .unwrap_errunion_err_ptr => air.typeOf(data.ty_op.operand, ip).isVolatilePtrIp(ip), 2153 .slice_elem_val, .ptr_elem_val => air.typeOf(data.bin_op.lhs, ip).isVolatilePtrIp(ip), 2154 .atomic_load => switch (data.atomic_load.order) { 2155 .unordered, .monotonic => air.typeOf(data.atomic_load.ptr, ip).isVolatilePtrIp(ip), 2156 else => true, // Stronger memory orderings have inter-thread side effects. 2157 }, 2158 }; 2159 } 2160 2161 pub const UnwrappedSwitch = struct { 2162 air: *const Air, 2163 operand: Inst.Ref, 2164 cases_len: u32, 2165 else_body_len: u32, 2166 branch_hints_start: u32, 2167 cases_start: u32, 2168 2169 /// Asserts that `case_idx < us.cases_len`. 2170 pub fn getHint(us: UnwrappedSwitch, case_idx: u32) std.lang.BranchHint { 2171 assert(case_idx < us.cases_len); 2172 return us.getHintInner(case_idx); 2173 } 2174 pub fn getElseHint(us: UnwrappedSwitch) std.lang.BranchHint { 2175 return us.getHintInner(us.cases_len); 2176 } 2177 fn getHintInner(us: UnwrappedSwitch, idx: u32) std.lang.BranchHint { 2178 const bag = us.air.extra.items[us.branch_hints_start..][idx / 10]; 2179 const bits: u3 = @truncate(bag >> @intCast(3 * (idx % 10))); 2180 return @fromBackingInt(@intCast(bits)); 2181 } 2182 2183 pub fn iterateCases(us: UnwrappedSwitch) CaseIterator { 2184 return .{ 2185 .air = us.air, 2186 .cases_len = us.cases_len, 2187 .else_body_len = us.else_body_len, 2188 .next_case = 0, 2189 .extra_index = us.cases_start, 2190 }; 2191 } 2192 pub const CaseIterator = struct { 2193 air: *const Air, 2194 cases_len: u32, 2195 else_body_len: u32, 2196 next_case: u32, 2197 extra_index: u32, 2198 2199 pub fn next(it: *CaseIterator) ?Case { 2200 if (it.next_case == it.cases_len) return null; 2201 const idx = it.next_case; 2202 it.next_case += 1; 2203 2204 const extra = it.air.extraData(SwitchBr.Case, it.extra_index); 2205 var extra_index = extra.end; 2206 const items: []const Inst.Ref = @ptrCast(it.air.extra.items[extra_index..][0..extra.data.items_len]); 2207 extra_index += items.len; 2208 // TODO: ptrcast from []const Inst.Ref to []const [2]Inst.Ref when supported 2209 const ranges_ptr: [*]const [2]Inst.Ref = @ptrCast(it.air.extra.items[extra_index..]); 2210 const ranges: []const [2]Inst.Ref = ranges_ptr[0..extra.data.ranges_len]; 2211 extra_index += ranges.len * 2; 2212 const body: []const Inst.Index = @ptrCast(it.air.extra.items[extra_index..][0..extra.data.body_len]); 2213 extra_index += body.len; 2214 it.extra_index = @intCast(extra_index); 2215 2216 return .{ 2217 .idx = idx, 2218 .items = items, 2219 .ranges = ranges, 2220 .body = body, 2221 }; 2222 } 2223 /// Only valid to call once all cases have been iterated, i.e. `next` returns `null`. 2224 /// Returns the body of the "default" (`else`) case. 2225 pub fn elseBody(it: *CaseIterator) []const Inst.Index { 2226 assert(it.next_case == it.cases_len); 2227 return @ptrCast(it.air.extra.items[it.extra_index..][0..it.else_body_len]); 2228 } 2229 pub const Case = struct { 2230 idx: u32, 2231 items: []const Inst.Ref, 2232 ranges: []const [2]Inst.Ref, 2233 body: []const Inst.Index, 2234 }; 2235 }; 2236 }; 2237 2238 pub fn unwrapSwitch(air: *const Air, switch_inst: Inst.Index) UnwrappedSwitch { 2239 const inst = air.instructions.get(@backingInt(switch_inst)); 2240 switch (inst.tag) { 2241 .switch_br, .loop_switch_br => {}, 2242 else => unreachable, // assertion failure 2243 } 2244 const pl_op = inst.data.pl_op; 2245 const extra = air.extraData(SwitchBr, pl_op.payload); 2246 const hint_bag_count = @divCeil(extra.data.cases_len + 1, 10); 2247 return .{ 2248 .air = air, 2249 .operand = pl_op.operand, 2250 .cases_len = extra.data.cases_len, 2251 .else_body_len = extra.data.else_body_len, 2252 .branch_hints_start = @intCast(extra.end), 2253 .cases_start = @intCast(extra.end + hint_bag_count), 2254 }; 2255 } 2256 2257 pub const UnwrappedDbgInlineBlock = struct { 2258 func: InternPool.Index, 2259 body: []const Inst.Index, 2260 ty: Type, 2261 }; 2262 2263 pub fn unwrapDbgBlock(air: *const Air, inst_index: Inst.Index) UnwrappedDbgInlineBlock { 2264 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2265 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2266 assert(tag == .dbg_inline_block); 2267 const payload = data.ty_pl.payload; 2268 const extra = air.extraData(Air.DbgInlineBlock, payload); 2269 return .{ 2270 .func = extra.data.func, 2271 .ty = data.ty_pl.ty, 2272 .body = @ptrCast(air.extra.items[extra.end..][0..extra.data.body_len]), 2273 }; 2274 } 2275 2276 pub const UnwrappedBlock = struct { 2277 body: []const Inst.Index, 2278 ty: Type, 2279 }; 2280 2281 pub fn unwrapBlock(air: *const Air, inst_index: Inst.Index) UnwrappedBlock { 2282 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2283 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2284 const payload = switch (tag) { 2285 .block, .loop => data.ty_pl.payload, 2286 else => unreachable, 2287 }; 2288 const extra = air.extraData(Air.Block, payload); 2289 return .{ 2290 .ty = data.ty_pl.ty, 2291 .body = @ptrCast(air.extra.items[extra.end..][0..extra.data.body_len]), 2292 }; 2293 } 2294 2295 pub const UnwrappedCall = struct { 2296 callee: Inst.Ref, 2297 args: []const Air.Inst.Ref, 2298 }; 2299 2300 pub fn unwrapCall(air: *const Air, inst_index: Inst.Index) UnwrappedCall { 2301 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2302 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2303 const payload = switch (tag) { 2304 .call, .call_always_tail, .call_never_tail, .call_never_inline => data.pl_op.payload, 2305 else => unreachable, 2306 }; 2307 const extra = air.extraData(Air.Call, payload); 2308 return .{ 2309 .callee = data.pl_op.operand, 2310 .args = @ptrCast(air.extra.items[extra.end..][0..extra.data.args_len]), 2311 }; 2312 } 2313 2314 pub const UnwrappedCompilerRtCall = struct { 2315 func: CompilerRtFunc, 2316 args: []const Air.Inst.Ref, 2317 }; 2318 2319 pub fn unwrapCompilerRtCall(air: *const Air, inst_index: Inst.Index) UnwrappedCompilerRtCall { 2320 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2321 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2322 assert(tag == .legalize_compiler_rt_call); 2323 const payload = data.legalize_compiler_rt_call.payload; 2324 const extra = air.extraData(Air.Call, payload); 2325 return .{ 2326 .func = data.legalize_compiler_rt_call.func, 2327 .args = @ptrCast(air.extra.items[extra.end..][0..extra.data.args_len]), 2328 }; 2329 } 2330 2331 pub const UnwrappedCondBr = struct { 2332 condition: Inst.Ref, 2333 then_body: []const Inst.Index, 2334 else_body: []const Inst.Index, 2335 branch_hints: CondBr.BranchHints, 2336 }; 2337 2338 pub fn unwrapCondBr(air: *const Air, inst_index: Inst.Index) UnwrappedCondBr { 2339 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2340 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2341 assert(tag == .cond_br); 2342 const payload = data.pl_op.payload; 2343 const extra = air.extraData(Air.CondBr, payload); 2344 return .{ 2345 .condition = data.pl_op.operand, 2346 .then_body = @ptrCast(air.extra.items[extra.end..][0..extra.data.then_body_len]), 2347 .else_body = @ptrCast(air.extra.items[extra.end + extra.data.then_body_len ..][0..extra.data.else_body_len]), 2348 .branch_hints = extra.data.branch_hints, 2349 }; 2350 } 2351 2352 pub const UnwrappedTry = struct { 2353 error_union: Inst.Ref, 2354 else_body: []const Inst.Index, 2355 }; 2356 2357 pub fn unwrapTry(air: *const Air, inst_index: Inst.Index) UnwrappedTry { 2358 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2359 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2360 assert(tag == .@"try" or tag == .try_cold); 2361 const payload = data.pl_op.payload; 2362 const extra = air.extraData(Air.Try, payload); 2363 return .{ 2364 .error_union = data.pl_op.operand, 2365 .else_body = @ptrCast(air.extra.items[extra.end..][0..extra.data.body_len]), 2366 }; 2367 } 2368 2369 pub const UnwrappedTryPtr = struct { 2370 error_union_payload_ptr_ty: Type, 2371 error_union_ptr: Inst.Ref, 2372 else_body: []const Inst.Index, 2373 }; 2374 2375 pub fn unwrapTryPtr(air: *const Air, inst_index: Inst.Index) UnwrappedTryPtr { 2376 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2377 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2378 assert(tag == .try_ptr or tag == .try_ptr_cold); 2379 const payload = data.ty_pl.payload; 2380 const extra = air.extraData(Air.TryPtr, payload); 2381 return .{ 2382 .error_union_ptr = extra.data.ptr, 2383 .error_union_payload_ptr_ty = data.ty_pl.ty, 2384 .else_body = @ptrCast(air.extra.items[extra.end..][0..extra.data.body_len]), 2385 }; 2386 } 2387 2388 pub const UnwrappedAsm = struct { 2389 outputs: []const Air.Inst.Ref, 2390 inputs: []const Air.Inst.Ref, 2391 source: [:0]u8, 2392 input_constraint_names: []const u32, 2393 output_constraint_names: []const u32, 2394 clobbers: InternPool.Index, 2395 is_volatile: bool, 2396 2397 const AsmIterator = struct { 2398 current: u32, 2399 operands: []const Air.Inst.Ref, 2400 constraint_names: []const u32, 2401 2402 pub fn next(self: *AsmIterator) ?struct { constraint: []const u8, operand: Inst.Ref, name: []const u8, index: u32 } { 2403 if (self.current >= self.operands.len) { 2404 return null; 2405 } 2406 defer { 2407 self.current += 1; 2408 } 2409 2410 const constraint_name = std.mem.sliceAsBytes(self.constraint_names); 2411 const constraint = std.mem.sliceTo(constraint_name, 0); 2412 const name = std.mem.sliceTo(constraint_name[constraint.len + 1 ..], 0); 2413 // This equation accounts for the fact that even if we have exactly 4 bytes 2414 // for the string, we still use the next u32 for the null terminator. 2415 const next_offset = @divCeil(constraint.len + 1 + name.len + 1, @sizeOf(u32)); 2416 self.constraint_names = self.constraint_names[next_offset..]; 2417 2418 return .{ 2419 .constraint = constraint, 2420 .operand = self.operands[self.current], 2421 .name = name, 2422 .index = self.current, 2423 }; 2424 } 2425 }; 2426 2427 pub fn iterateInputs(self: *const UnwrappedAsm) AsmIterator { 2428 return .{ 2429 .current = 0, 2430 .operands = self.inputs, 2431 .constraint_names = self.input_constraint_names, 2432 }; 2433 } 2434 2435 pub fn iterateOutputs(self: *const UnwrappedAsm) AsmIterator { 2436 return .{ 2437 .current = 0, 2438 .operands = self.outputs, 2439 .constraint_names = self.output_constraint_names, 2440 }; 2441 } 2442 }; 2443 2444 pub fn unwrapAsm(air: *const Air, inst_index: Inst.Index) UnwrappedAsm { 2445 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2446 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2447 assert(tag == .assembly); 2448 const payload = data.ty_pl.payload; 2449 const extra = air.extraData(Air.Asm, payload); 2450 const source_start = extra.end + extra.data.flags.outputs_len + extra.data.inputs_len; 2451 const output_constraint_name_start = source_start + (extra.data.source_len / 4) + 1; 2452 const output_constraint_name = air.extra.items[output_constraint_name_start..]; 2453 const outputs: []Inst.Ref = @ptrCast(air.extra.items[extra.end..][0..extra.data.flags.outputs_len]); 2454 // Get the input names and constraints offset place after the output. 2455 var it = UnwrappedAsm.AsmIterator{ 2456 .current = 0, 2457 .constraint_names = output_constraint_name, 2458 .operands = outputs, 2459 }; 2460 while (it.next()) |_| {} 2461 2462 return .{ 2463 .clobbers = extra.data.clobbers, 2464 .is_volatile = extra.data.flags.is_volatile, 2465 .inputs = @ptrCast(air.extra.items[extra.end + extra.data.flags.outputs_len ..][0..extra.data.inputs_len]), 2466 .outputs = outputs, 2467 .source = std.mem.sliceAsBytes(air.extra.items[source_start..])[0..extra.data.source_len :0], 2468 .output_constraint_names = output_constraint_name, 2469 .input_constraint_names = it.constraint_names, 2470 }; 2471 } 2472 2473 pub const UnwrappedShuffleOne = struct { 2474 result_ty: Type, 2475 operand: Inst.Ref, 2476 mask: []const ShuffleOneMask, 2477 }; 2478 2479 pub fn unwrapShuffleOne(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index) UnwrappedShuffleOne { 2480 const inst = air.instructions.get(@backingInt(inst_index)); 2481 switch (inst.tag) { 2482 .shuffle_one => {}, 2483 else => unreachable, // assertion failure 2484 } 2485 const result_ty: Type = inst.data.ty_pl.ty; 2486 const mask_len: u32 = result_ty.vectorLen(zcu); 2487 const extra_idx = inst.data.ty_pl.payload; 2488 return .{ 2489 .result_ty = result_ty, 2490 .operand = @fromBackingInt(@intCast(air.extra.items[extra_idx + mask_len])), 2491 .mask = @ptrCast(air.extra.items[extra_idx..][0..mask_len]), 2492 }; 2493 } 2494 2495 pub const UnwrappedShuffleTwo = struct { 2496 result_ty: Type, 2497 operand_a: Inst.Ref, 2498 operand_b: Inst.Ref, 2499 mask: []const ShuffleTwoMask, 2500 }; 2501 2502 pub fn unwrapShuffleTwo(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index) UnwrappedShuffleTwo { 2503 const inst = air.instructions.get(@backingInt(inst_index)); 2504 switch (inst.tag) { 2505 .shuffle_two => {}, 2506 else => unreachable, // assertion failure 2507 } 2508 const result_ty: Type = inst.data.ty_pl.ty; 2509 const mask_len: u32 = result_ty.vectorLen(zcu); 2510 const extra_idx = inst.data.ty_pl.payload; 2511 return .{ 2512 .result_ty = result_ty, 2513 .operand_a = @fromBackingInt(@intCast(air.extra.items[extra_idx + mask_len + 0])), 2514 .operand_b = @fromBackingInt(@intCast(air.extra.items[extra_idx + mask_len + 1])), 2515 .mask = @ptrCast(air.extra.items[extra_idx..][0..mask_len]), 2516 }; 2517 } 2518 2519 pub const legalize = Legalize.legalize; 2520 pub const write = print.write; 2521 pub const writeInst = print.writeInst; 2522 pub const dump = print.dump; 2523 pub const dumpInst = print.dumpInst; 2524 2525 pub const CoveragePoint = enum(u1) { 2526 /// Indicates the block is not a place of interest corresponding to 2527 /// a source location for coverage purposes. 2528 none, 2529 /// Point of interest. The next instruction emitted corresponds to 2530 /// a source location used for coverage instrumentation. 2531 poi, 2532 }; 2533 2534 pub const CompilerRtFunc = enum(u32) { 2535 // zig fmt: off 2536 2537 // float simple arithmetic 2538 __addhf3, __addsf3, __adddf3, __addxf3, __addtf3, 2539 __subhf3, __subsf3, __subdf3, __subxf3, __subtf3, 2540 __mulhf3, __mulsf3, __muldf3, __mulxf3, __multf3, 2541 __divhf3, __divsf3, __divdf3, __divxf3, __divtf3, 2542 2543 // float minmax 2544 __fminh, fminf, fmin, __fminx, fminq, 2545 __fmaxh, fmaxf, fmax, __fmaxx, fmaxq, 2546 2547 // float round 2548 __ceilh, ceilf, ceil, __ceilx, ceilq, 2549 __floorh, floorf, floor, __floorx, floorq, 2550 __trunch, truncf, trunc, __truncx, truncq, 2551 __roundh, roundf, round, __roundx, roundq, 2552 2553 // float log 2554 __logh, logf, log, __logx, logq, 2555 __log2h, log2f, log2, __log2x, log2q, 2556 __log10h, log10f, log10, __log10x, log10q, 2557 2558 // float exp 2559 __exph, expf, exp, __expx, expq, 2560 __exp2h, exp2f, exp2, __exp2x, exp2q, 2561 2562 // float trigonometry 2563 __sinh, sinf, sin, __sinx, sinq, 2564 __cosh, cosf, cos, __cosx, cosq, 2565 __tanh, tanf, tan, __tanx, tanq, 2566 2567 // float misc ops 2568 __fabsh, fabsf, fabs, __fabsx, fabsq, 2569 __sqrth, sqrtf, sqrt, __sqrtx, sqrtq, 2570 __fmodh, fmodf, fmod, __fmodx, fmodq, 2571 __fmah, fmaf, fma, __fmax, fmaq, 2572 2573 // float comparison 2574 __eqhf2, __eqsf2, __eqdf2, __eqxf2, __eqtf2, // == iff return == 0 2575 __nehf2, __nesf2, __nedf2, __nexf2, __netf2, // != iff return != 0 2576 __lthf2, __ltsf2, __ltdf2, __ltxf2, __lttf2, // < iff return < 0 2577 __lehf2, __lesf2, __ledf2, __lexf2, __letf2, // <= iff return <= 0 2578 __gthf2, __gtsf2, __gtdf2, __gtxf2, __gttf2, // > iff return > 0 2579 __gehf2, __gesf2, __gedf2, __gexf2, __getf2, // >= iff return >= 0 2580 2581 // AEABI float comparison. On ARM, the `sf`/`df` functions above are not available, 2582 // and these must be used instead. They are not just aliases for the above functions 2583 // because they have a different (better) ABI. 2584 __aeabi_fcmpeq, __aeabi_dcmpeq, // ==, returns bool 2585 __aeabi_fcmplt, __aeabi_dcmplt, // <, returns bool 2586 __aeabi_fcmple, __aeabi_dcmple, // <=, returns bool 2587 __aeabi_fcmpgt, __aeabi_dcmpgt, // >, returns bool 2588 __aeabi_fcmpge, __aeabi_dcmpge, // >=, returns bool 2589 2590 // float shortening 2591 // to f16 // to f32 // to f64 // to f80 2592 __trunctfhf2, __trunctfsf2, __trunctfdf2, __trunctfxf2, // from f128 2593 __truncxfhf2, __truncxfsf2, __truncxfdf2, // from f80 2594 __truncdfhf2, __truncdfsf2, // from f64 2595 __truncsfhf2, // from f32 2596 2597 // float widening 2598 // to f128 // to f80 // to f64 // to f32 2599 __extendhftf2, __extendhfxf2, __extendhfdf2, __extendhfsf2, // from f16 2600 __extendsftf2, __extendsfxf2, __extendsfdf2, // from f32 2601 __extenddftf2, __extenddfxf2, // from f64 2602 __extendxftf2, // from f80 2603 2604 // int to float 2605 __floatsihf, __floatsisf, __floatsidf, __floatsixf, __floatsitf, // i32 to float 2606 __floatdihf, __floatdisf, __floatdidf, __floatdixf, __floatditf, // i64 to float 2607 __floattihf, __floattisf, __floattidf, __floattixf, __floattitf, // i128 to float 2608 __floateihf, __floateisf, __floateidf, __floateixf, __floateitf, // arbitrary iN to float 2609 __floatunsihf, __floatunsisf, __floatunsidf, __floatunsixf, __floatunsitf, // u32 to float 2610 __floatundihf, __floatundisf, __floatundidf, __floatundixf, __floatunditf, // u64 to float 2611 __floatuntihf, __floatuntisf, __floatuntidf, __floatuntixf, __floatuntitf, // u128 to float 2612 __floatuneihf, __floatuneisf, __floatuneidf, __floatuneixf, __floatuneitf, // arbitrary uN to float 2613 2614 // float to int 2615 __fixhfsi, __fixsfsi, __fixdfsi, __fixxfsi, __fixtfsi, // float to i32 2616 __fixhfdi, __fixsfdi, __fixdfdi, __fixxfdi, __fixtfdi, // float to i64 2617 __fixhfti, __fixsfti, __fixdfti, __fixxfti, __fixtfti, // float to i128 2618 __fixhfei, __fixsfei, __fixdfei, __fixxfei, __fixtfei, // float to arbitray iN 2619 __fixunshfsi, __fixunssfsi, __fixunsdfsi, __fixunsxfsi, __fixunstfsi, // float to u32 2620 __fixunshfdi, __fixunssfdi, __fixunsdfdi, __fixunsxfdi, __fixunstfdi, // float to u64 2621 __fixunshfti, __fixunssfti, __fixunsdfti, __fixunsxfti, __fixunstfti, // float to u128 2622 __fixunshfei, __fixunssfei, __fixunsdfei, __fixunsxfei, __fixunstfei, // float to arbitray uN 2623 2624 // zig fmt: on 2625 2626 /// Usually, the tag names of `CompilerRtFunc` match the corresponding symbol name, but not 2627 /// always; some target triples have slightly different compiler-rt ABIs for one reason or 2628 /// another. 2629 pub fn name(f: CompilerRtFunc, target: *const std.Target) []const u8 { 2630 const use_gnu_f16_abi = switch (target.cpu.arch) { 2631 .wasm32, 2632 .wasm64, 2633 .riscv64, 2634 .riscv64be, 2635 .riscv32, 2636 .riscv32be, 2637 => false, 2638 .x86, .x86_64 => true, 2639 .arm, .armeb, .thumb, .thumbeb => switch (target.abi) { 2640 .eabi, .eabihf => false, 2641 else => true, 2642 }, 2643 else => !target.os.tag.isDarwin(), 2644 }; 2645 const use_aeabi = target.cpu.arch.isArm() and switch (target.abi) { 2646 .eabi, 2647 .eabihf, 2648 .musleabi, 2649 .musleabihf, 2650 .gnueabi, 2651 .gnueabihf, 2652 .android, 2653 .androideabi, 2654 => true, 2655 else => false, 2656 }; 2657 2658 // GNU didn't like the standard names specifically for conversions between f16 2659 // and f32, so decided to make their own naming convention with blackjack and 2660 // hookers (but only use it on a few random targets of course). This overrides 2661 // the ARM EABI in some cases. I don't like GNU. 2662 if (use_gnu_f16_abi) switch (f) { 2663 .__truncsfhf2 => return "__gnu_f2h_ieee", 2664 .__extendhfsf2 => return "__gnu_h2f_ieee", 2665 else => {}, 2666 }; 2667 2668 if (use_aeabi) return switch (f) { 2669 .__addsf3 => "__aeabi_fadd", 2670 .__adddf3 => "__aeabi_dadd", 2671 .__subsf3 => "__aeabi_fsub", 2672 .__subdf3 => "__aeabi_dsub", 2673 .__mulsf3 => "__aeabi_fmul", 2674 .__muldf3 => "__aeabi_dmul", 2675 .__divsf3 => "__aeabi_fdiv", 2676 .__divdf3 => "__aeabi_ddiv", 2677 .__truncdfhf2 => "__aeabi_d2h", 2678 .__truncdfsf2 => "__aeabi_d2f", 2679 .__truncsfhf2 => "__aeabi_f2h", 2680 .__extendsfdf2 => "__aeabi_f2d", 2681 .__extendhfsf2 => "__aeabi_h2f", 2682 .__floatsisf => "__aeabi_i2f", 2683 .__floatsidf => "__aeabi_i2d", 2684 .__floatdisf => "__aeabi_l2f", 2685 .__floatdidf => "__aeabi_l2d", 2686 .__floatunsisf => "__aeabi_ui2f", 2687 .__floatunsidf => "__aeabi_ui2d", 2688 .__floatundisf => "__aeabi_ul2f", 2689 .__floatundidf => "__aeabi_ul2d", 2690 .__fixsfsi => "__aeabi_f2iz", 2691 .__fixdfsi => "__aeabi_d2iz", 2692 .__fixsfdi => "__aeabi_f2lz", 2693 .__fixdfdi => "__aeabi_d2lz", 2694 .__fixunssfsi => "__aeabi_f2uiz", 2695 .__fixunsdfsi => "__aeabi_d2uiz", 2696 .__fixunssfdi => "__aeabi_f2ulz", 2697 .__fixunsdfdi => "__aeabi_d2ulz", 2698 2699 // These functions are not available on AEABI. The AEABI equivalents are 2700 // separate fields rather than aliases because they have a different ABI. 2701 .__eqsf2, .__eqdf2 => unreachable, 2702 .__nesf2, .__nedf2 => unreachable, 2703 .__ltsf2, .__ltdf2 => unreachable, 2704 .__lesf2, .__ledf2 => unreachable, 2705 .__gtsf2, .__gtdf2 => unreachable, 2706 .__gesf2, .__gedf2 => unreachable, 2707 2708 else => @tagName(f), 2709 }; 2710 2711 return switch (f) { 2712 // These functions are only available on AEABI. 2713 .__aeabi_fcmpeq, .__aeabi_dcmpeq => unreachable, 2714 .__aeabi_fcmplt, .__aeabi_dcmplt => unreachable, 2715 .__aeabi_fcmple, .__aeabi_dcmple => unreachable, 2716 .__aeabi_fcmpgt, .__aeabi_dcmpgt => unreachable, 2717 .__aeabi_fcmpge, .__aeabi_dcmpge => unreachable, 2718 2719 else => @tagName(f), 2720 }; 2721 } 2722 2723 pub fn @"callconv"(f: CompilerRtFunc, target: *const std.Target) std.lang.CallingConvention { 2724 const use_gnu_f16_abi = switch (target.cpu.arch) { 2725 .wasm32, 2726 .wasm64, 2727 .riscv64, 2728 .riscv64be, 2729 .riscv32, 2730 .riscv32be, 2731 => false, 2732 .x86, .x86_64 => true, 2733 .arm, .armeb, .thumb, .thumbeb => switch (target.abi) { 2734 .eabi, .eabihf => false, 2735 else => true, 2736 }, 2737 else => !target.os.tag.isDarwin(), 2738 }; 2739 const use_aeabi = target.cpu.arch.isArm() and switch (target.abi) { 2740 .eabi, 2741 .eabihf, 2742 .musleabi, 2743 .musleabihf, 2744 .gnueabi, 2745 .gnueabihf, 2746 .android, 2747 .androideabi, 2748 => true, 2749 else => false, 2750 }; 2751 2752 if (use_gnu_f16_abi) switch (f) { 2753 .__truncsfhf2, 2754 .__extendhfsf2, 2755 => return target.cCallingConvention().?, 2756 else => {}, 2757 }; 2758 2759 if (use_aeabi) switch (f) { 2760 // zig fmt: off 2761 .__addsf3, .__adddf3, .__subsf3, .__subdf3, 2762 .__mulsf3, .__muldf3, .__divsf3, .__divdf3, 2763 .__truncdfhf2, .__truncdfsf2, .__truncsfhf2, 2764 .__extendsfdf2, .__extendhfsf2, 2765 .__floatsisf, .__floatsidf, .__floatdisf, .__floatdidf, 2766 .__floatunsisf, .__floatunsidf, .__floatundisf, .__floatundidf, 2767 .__fixsfsi, .__fixdfsi, .__fixsfdi, .__fixdfdi, 2768 .__fixunssfsi, .__fixunsdfsi, .__fixunssfdi, .__fixunsdfdi, 2769 => return .{ .arm_aapcs = .{} }, 2770 // zig fmt: on 2771 else => {}, 2772 }; 2773 2774 return target.cCallingConvention().?; 2775 } 2776 2777 pub fn returnType(f: CompilerRtFunc) Type { 2778 return switch (f) { 2779 .__addhf3, .__subhf3, .__mulhf3, .__divhf3 => .f16, 2780 .__addsf3, .__subsf3, .__mulsf3, .__divsf3 => .f32, 2781 .__adddf3, .__subdf3, .__muldf3, .__divdf3 => .f64, 2782 .__addxf3, .__subxf3, .__mulxf3, .__divxf3 => .f80, 2783 .__addtf3, .__subtf3, .__multf3, .__divtf3 => .f128, 2784 2785 // zig fmt: off 2786 .__fminh, .__fmaxh, 2787 .__ceilh, .__floorh, .__trunch, .__roundh, 2788 .__logh, .__log2h, .__log10h, 2789 .__exph, .__exp2h, 2790 .__sinh, .__cosh, .__tanh, 2791 .__fabsh, .__sqrth, .__fmodh, .__fmah, 2792 => .f16, 2793 .fminf, .fmaxf, 2794 .ceilf, .floorf, .truncf, .roundf, 2795 .logf, .log2f, .log10f, 2796 .expf, .exp2f, 2797 .sinf, .cosf, .tanf, 2798 .fabsf, .sqrtf, .fmodf, .fmaf, 2799 => .f32, 2800 .fmin, .fmax, 2801 .ceil, .floor, .trunc, .round, 2802 .log, .log2, .log10, 2803 .exp, .exp2, 2804 .sin, .cos, .tan, 2805 .fabs, .sqrt, .fmod, .fma, 2806 => .f64, 2807 .__fminx, .__fmaxx, 2808 .__ceilx, .__floorx, .__truncx, .__roundx, 2809 .__logx, .__log2x, .__log10x, 2810 .__expx, .__exp2x, 2811 .__sinx, .__cosx, .__tanx, 2812 .__fabsx, .__sqrtx, .__fmodx, .__fmax, 2813 => .f80, 2814 .fminq, .fmaxq, 2815 .ceilq, .floorq, .truncq, .roundq, 2816 .logq, .log2q, .log10q, 2817 .expq, .exp2q, 2818 .sinq, .cosq, .tanq, 2819 .fabsq, .sqrtq, .fmodq, .fmaq, 2820 => .f128, 2821 // zig fmt: on 2822 2823 .__eqhf2, .__eqsf2, .__eqdf2, .__eqxf2, .__eqtf2 => .i32, 2824 .__nehf2, .__nesf2, .__nedf2, .__nexf2, .__netf2 => .i32, 2825 .__lthf2, .__ltsf2, .__ltdf2, .__ltxf2, .__lttf2 => .i32, 2826 .__lehf2, .__lesf2, .__ledf2, .__lexf2, .__letf2 => .i32, 2827 .__gthf2, .__gtsf2, .__gtdf2, .__gtxf2, .__gttf2 => .i32, 2828 .__gehf2, .__gesf2, .__gedf2, .__gexf2, .__getf2 => .i32, 2829 2830 .__aeabi_fcmpeq, .__aeabi_dcmpeq => .i32, 2831 .__aeabi_fcmplt, .__aeabi_dcmplt => .i32, 2832 .__aeabi_fcmple, .__aeabi_dcmple => .i32, 2833 .__aeabi_fcmpgt, .__aeabi_dcmpgt => .i32, 2834 .__aeabi_fcmpge, .__aeabi_dcmpge => .i32, 2835 2836 .__trunctfhf2, .__truncxfhf2, .__truncdfhf2, .__truncsfhf2 => .f16, 2837 .__trunctfsf2, .__truncxfsf2, .__truncdfsf2 => .f32, 2838 .__trunctfdf2, .__truncxfdf2 => .f64, 2839 .__trunctfxf2 => .f80, 2840 2841 .__extendhftf2, .__extendsftf2, .__extenddftf2, .__extendxftf2 => .f128, 2842 .__extendhfxf2, .__extendsfxf2, .__extenddfxf2 => .f80, 2843 .__extendhfdf2, .__extendsfdf2 => .f64, 2844 .__extendhfsf2 => .f32, 2845 2846 .__floatsihf, .__floatdihf, .__floattihf, .__floateihf => .f16, 2847 .__floatsisf, .__floatdisf, .__floattisf, .__floateisf => .f32, 2848 .__floatsidf, .__floatdidf, .__floattidf, .__floateidf => .f64, 2849 .__floatsixf, .__floatdixf, .__floattixf, .__floateixf => .f80, 2850 .__floatsitf, .__floatditf, .__floattitf, .__floateitf => .f128, 2851 .__floatunsihf, .__floatundihf, .__floatuntihf, .__floatuneihf => .f16, 2852 .__floatunsisf, .__floatundisf, .__floatuntisf, .__floatuneisf => .f32, 2853 .__floatunsidf, .__floatundidf, .__floatuntidf, .__floatuneidf => .f64, 2854 .__floatunsixf, .__floatundixf, .__floatuntixf, .__floatuneixf => .f80, 2855 .__floatunsitf, .__floatunditf, .__floatuntitf, .__floatuneitf => .f128, 2856 2857 .__fixhfsi, .__fixsfsi, .__fixdfsi, .__fixxfsi, .__fixtfsi => .i32, 2858 .__fixhfdi, .__fixsfdi, .__fixdfdi, .__fixxfdi, .__fixtfdi => .i64, 2859 .__fixhfti, .__fixsfti, .__fixdfti, .__fixxfti, .__fixtfti => .i128, 2860 .__fixhfei, .__fixsfei, .__fixdfei, .__fixxfei, .__fixtfei => .void, 2861 .__fixunshfsi, .__fixunssfsi, .__fixunsdfsi, .__fixunsxfsi, .__fixunstfsi => .u32, 2862 .__fixunshfdi, .__fixunssfdi, .__fixunsdfdi, .__fixunsxfdi, .__fixunstfdi => .u64, 2863 .__fixunshfti, .__fixunssfti, .__fixunsdfti, .__fixunsxfti, .__fixunstfti => .u128, 2864 .__fixunshfei, .__fixunssfei, .__fixunsdfei, .__fixunsxfei, .__fixunstfei => .void, 2865 }; 2866 } 2867 }; 2868