diff --git a/lib/include/zig.h b/lib/include/zig.h index ea2bbca132..32d0c8277e 100644 --- a/lib/include/zig.h +++ b/lib/include/zig.h @@ -20,7 +20,7 @@ #if __STDC_VERSION__ >= 201112L #define zig_threadlocal thread_local -#elif __GNUC__ +#elif defined(__GNUC__) #define zig_threadlocal __thread #elif _MSC_VER #define zig_threadlocal __declspec(thread) @@ -28,7 +28,7 @@ #define zig_threadlocal zig_threadlocal_unavailable #endif -#if zig_has_attribute(naked) +#if zig_has_attribute(naked) || defined(__GNUC__) #define zig_naked __attribute__((naked)) #elif defined(_MSC_VER) #define zig_naked __declspec(naked) @@ -128,7 +128,7 @@ #define zig_atomic_store(obj, arg, order) atomic_store_explicit (obj, arg, order) #define zig_atomic_load(obj, order) atomic_load_explicit (obj, order) #define zig_fence(order) atomic_thread_fence(order) -#elif __GNUC__ +#elif defined(__GNUC__) #define memory_order_relaxed __ATOMIC_RELAXED #define memory_order_consume __ATOMIC_CONSUME #define memory_order_acquire __ATOMIC_ACQUIRE @@ -176,7 +176,7 @@ #if __STDC_VERSION__ >= 201112L #define zig_noreturn _Noreturn void -#elif zig_has_attribute(noreturn) +#elif zig_has_attribute(noreturn) || defined(__GNUC__) #define zig_noreturn __attribute__((noreturn)) void #elif _MSC_VER #define zig_noreturn __declspec(noreturn) void @@ -184,6 +184,9 @@ #define zig_noreturn void #endif +#define zig_concat(lhs, rhs) lhs##rhs +#define zig_expand_concat(lhs, rhs) zig_concat(lhs, rhs) + #define zig_bitSizeOf(T) (CHAR_BIT * sizeof(T)) typedef void zig_void; @@ -250,110 +253,17 @@ typedef int64_t zig_i64; #define zig_minInt_i64 INT64_MIN #define zig_maxInt_i64 INT64_MAX -#define zig_builtin_f16(name) __##name##h -#define zig_builtin_constant_f16(name) zig_suffix_f16(__builtin_##name) -#if FLT_MANT_DIG == 11 -typedef float zig_f16; -#define zig_suffix_f16(x) x##f -#elif DBL_MANT_DIG == 11 -typedef double zig_f16; -#define zig_suffix_f16(x) x -#elif LDBL_MANT_DIG == 11 -typedef long double zig_f16; -#define zig_suffix_f16(x) x##l -#elif FLT16_MANT_DIG == 11 -typedef _Float16 zig_f16; -#define zig_suffix_f16(x) x##f16 -#elif defined(__SIZEOF_FP16__) -typedef __fp16 zig_f16; -#define zig_suffix_f16(x) x##f16 -#endif - -#define zig_builtin_f32(name) name##f -#define zig_builtin_constant_f32(name) zig_suffix_f32(__builtin_##name) -#if FLT_MANT_DIG == 24 -typedef float zig_f32; -#define zig_suffix_f32(x) x##f -#elif DBL_MANT_DIG == 24 -typedef double zig_f32; -#define zig_suffix_f32(x) x -#elif LDBL_MANT_DIG == 24 -typedef long double zig_f32; -#define zig_suffix_f32(x) x##l -#elif FLT32_MANT_DIG == 24 -typedef _Float32 zig_f32; -#define zig_suffix_f32(x) x##f32 -#endif - -#define zig_builtin_f64(name) name -#define zig_builtin_constant_f64(name) zig_suffix_f64(__builtin_##name) -#if FLT_MANT_DIG == 53 -typedef float zig_f64; -#define zig_suffix_f64(x) x##f -#elif DBL_MANT_DIG == 53 -typedef double zig_f64; -#define zig_suffix_f64(x) x -#elif LDBL_MANT_DIG == 53 -typedef long double zig_f64; -#define zig_suffix_f64(x) x##l -#elif FLT64_MANT_DIG == 53 -typedef _Float64 zig_f64; -#define zig_suffix_f64(x) x##f64 -#elif FLT32X_MANT_DIG == 53 -typedef _Float32x zig_f64; -#define zig_suffix_f64(x) x##f32x -#endif - -#define zig_builtin_f80(name) __##name##x -#define zig_builtin_constant_f80(name) zig_suffix_f80(__builtin_##name) -#if FLT_MANT_DIG == 64 -typedef float zig_f80; -#define zig_suffix_f80(x) x##f -#elif DBL_MANT_DIG == 64 -typedef double zig_f80; -#define zig_suffix_f80(x) x -#elif LDBL_MANT_DIG == 64 -typedef long double zig_f80; -#define zig_suffix_f80(x) x##l -#elif FLT80_MANT_DIG == 64 -typedef _Float80 zig_f80; -#define zig_suffix_f80(x) x##f80 -#elif FLT64X_MANT_DIG == 64 -typedef _Float64x zig_f80; -#define zig_suffix_f80(x) x##f64x -#elif defined(__SIZEOF_FLOAT80__) -typedef __float80 zig_f80; -#define zig_suffix_f80(x) x##l -#endif - -#define zig_builtin_f128(name) name##q -#define zig_builtin_constant_f128(name) zig_suffix_f80(__builtin_##name) -#if FLT_MANT_DIG == 113 -typedef float zig_f128; -#define zig_suffix_f128(x) x##f -#elif DBL_MANT_DIG == 113 -typedef double zig_f128; -#define zig_suffix_f128(x) x -#elif LDBL_MANT_DIG == 113 -typedef long double zig_f128; -#define zig_suffix_f128(x) x##l -#elif FLT128_MANT_DIG == 113 -typedef _Float128 zig_f128; -#define zig_suffix_f128(x) x##f128 -#elif FLT64X_MANT_DIG == 113 -typedef _Float64x zig_f128; -#define zig_suffix_f128(x) x##f64x -#elif defined(__SIZEOF_FLOAT128__) -typedef __float128 zig_f128; -#define zig_suffix_f128(x) x##q -#undef zig_builtin_constant_f128 -#define zig_builtin_constant_f128(name) __builtin_##name##f128 -#endif - -typedef long double zig_c_longdouble; -#define zig_suffix_c_longdouble(x) x##l -#define zig_builtin_c_longdouble(name) zig_suffix_c_longdouble(name) -#define zig_builtin_constant_c_longdouble(name) zig_suffix_c_longdouble(__builtin_##name) +#define zig_compiler_rt_abbrev_u32 si +#define zig_compiler_rt_abbrev_i32 si +#define zig_compiler_rt_abbrev_u64 di +#define zig_compiler_rt_abbrev_i64 di +#define zig_compiler_rt_abbrev_u128 ti +#define zig_compiler_rt_abbrev_i128 ti +#define zig_compiler_rt_abbrev_f16 hf +#define zig_compiler_rt_abbrev_f32 sf +#define zig_compiler_rt_abbrev_f64 df +#define zig_compiler_rt_abbrev_f80 xf +#define zig_compiler_rt_abbrev_f128 tf zig_extern_c void *memcpy (void *zig_restrict, void const *zig_restrict, zig_usize); zig_extern_c void *memset (void *, int, zig_usize); @@ -361,7 +271,9 @@ zig_extern_c void *memset (void *, int, zig_usize); /* ==================== 8/16/32/64-bit Integer Routines ===================== */ #define zig_maxInt(Type, bits) zig_shr_##Type(zig_maxInt_##Type, (zig_bitSizeOf(zig_##Type) - bits)) +#define zig_expand_maxInt(Type, bits) zig_maxInt(Type, bits) #define zig_minInt(Type, bits) zig_not_##Type(zig_maxInt(Type, bits), bits) +#define zig_expand_minInt(Type, bits) zig_minInt(Type, bits) #define zig_int_operator(Type, RhsType, operation, operator) \ static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##RhsType rhs) { \ @@ -954,8 +866,8 @@ static inline zig_u16 zig_bit_reverse_u16(zig_u16 val, zig_u8 bits) { #if zig_has_builtin(bitreverse16) full_res = __builtin_bitreverse16(val); #else - full_res = (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 0)) << 8 | - (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 8)) >> 0; + full_res = (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 0), 8) << 8 | + (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 8), 8) >> 0; #endif return zig_wrap_u16(full_res >> (16 - bits), bits); } @@ -969,8 +881,8 @@ static inline zig_u32 zig_bit_reverse_u32(zig_u32 val, zig_u8 bits) { #if zig_has_builtin(bitreverse32) full_res = __builtin_bitreverse32(val); #else - full_res = (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 0)) << 16 | - (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 16)) >> 0; + full_res = (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 0), 16) << 16 | + (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 16), 16) >> 0; #endif return zig_wrap_u32(full_res >> (32 - bits), bits); } @@ -984,8 +896,8 @@ static inline zig_u64 zig_bit_reverse_u64(zig_u64 val, zig_u8 bits) { #if zig_has_builtin(bitreverse64) full_res = __builtin_bitreverse64(val); #else - full_res = (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 0)) << 32 | - (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 32)) >> 0; + full_res = (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 0), 32) << 32 | + (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 32), 32) >> 0; #endif return zig_wrap_u64(full_res >> (64 - bits), bits); } @@ -1019,7 +931,7 @@ typedef signed __int128 zig_i128; #define zig_bitcast_i128(val) ((zig_i128)(val)) #define zig_cmp_int128(Type) \ static inline zig_i8 zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ - return (lhs > rhs) - (lhs < rhs); \ + return (zig_i8)((lhs > rhs) - (lhs < rhs)); \ } #define zig_bit_int128(Type, operation, operator) \ static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ @@ -1211,6 +1123,22 @@ static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) { #define zig_div_floor_u128 zig_div_trunc_u128 #define zig_mod_u128 zig_rem_u128 +static inline zig_u128 zig_min_u128(zig_u128 lhs, zig_u128 rhs) { + return zig_cmp_u128(lhs, rhs) < 0 ? lhs : rhs; +} + +static inline zig_i128 zig_min_i128(zig_i128 lhs, zig_i128 rhs) { + return zig_cmp_i128(lhs, rhs) < 0 ? lhs : rhs; +} + +static inline zig_u128 zig_max_u128(zig_u128 lhs, zig_u128 rhs) { + return zig_cmp_u128(lhs, rhs) > 0 ? lhs : rhs; +} + +static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) { + return zig_cmp_i128(lhs, rhs) > 0 ? lhs : rhs; +} + static inline zig_i128 zig_shr_i128(zig_i128 lhs, zig_u8 rhs) { zig_i128 sign_mask = zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i8(0) ? -zig_as_i128(0, 1) : zig_as_i128(0, 0); return zig_xor_i128(zig_bitcast_i128(zig_shr_u128(zig_bitcast_u128(zig_xor_i128(lhs, sign_mask)), rhs)), sign_mask); @@ -1460,36 +1388,285 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) { return zig_bit_reverse_u128(zig_bitcast_u128(val), bits); } -/* ========================== Float Point Routines ========================== */ +/* ========================= Floating Point Support ========================= */ + +#define zig_has_f16 1 +#define zig_bitSizeOf_f16 16 +#define zig_libc_name_f16(name) __##name##h +#define zig_as_special_f16(sign, name, arg, repr) sign zig_as_f16(__builtin_##name, )(arg) +#if FLT_MANT_DIG == 11 +typedef float zig_f16; +#define zig_as_f16(fp, repr) fp##f +#elif DBL_MANT_DIG == 11 +typedef double zig_f16; +#define zig_as_f16(fp, repr) fp +#elif LDBL_MANT_DIG == 11 +#define zig_bitSizeOf_c_longdouble 16 +typedef long double zig_f16; +#define zig_as_f16(fp, repr) fp##l +#elif FLT16_MANT_DIG == 11 +typedef _Float16 zig_f16; +#define zig_as_f16(fp, repr) fp##f16 +#elif defined(__SIZEOF_FP16__) +typedef __fp16 zig_f16; +#define zig_as_f16(fp, repr) fp##f16 +#else +#undef zig_has_f16 +#define zig_has_f16 0 +#define zig_repr_f16 i16 +typedef zig_i16 zig_f16; +#define zig_as_f16(fp, repr) repr +#undef zig_as_special_f16 +#define zig_as_special_f16(sign, name, arg, repr) repr +#endif + +#define zig_has_f32 1 +#define zig_bitSizeOf_f32 32 +#define zig_libc_name_f32(name) name##f +#define zig_as_special_f32(sign, name, arg, repr) sign zig_as_f32(__builtin_##name, )(arg) +#if FLT_MANT_DIG == 24 +typedef float zig_f32; +#define zig_as_f32(fp, repr) fp##f +#elif DBL_MANT_DIG == 24 +typedef double zig_f32; +#define zig_as_f32(fp, repr) fp +#elif LDBL_MANT_DIG == 24 +#define zig_bitSizeOf_c_longdouble 32 +typedef long double zig_f32; +#define zig_as_f32(fp, repr) fp##l +#elif FLT32_MANT_DIG == 24 +typedef _Float32 zig_f32; +#define zig_as_f32(fp, repr) fp##f32 +#else +#undef zig_has_f32 +#define zig_has_f32 0 +#define zig_repr_f32 i32 +typedef zig_i32 zig_f32; +#define zig_as_f32(fp, repr) repr +#undef zig_as_special_f32 +#define zig_as_special_f32(sign, name, arg, repr) repr +#endif + +#define zig_has_f64 1 +#define zig_bitSizeOf_f64 64 +#define zig_libc_name_f64(name) name +#define zig_as_special_f64(sign, name, arg, repr) sign zig_as_f64(__builtin_##name, )(arg) +#if FLT_MANT_DIG == 53 +typedef float zig_f64; +#define zig_as_f64(fp, repr) fp##f +#elif DBL_MANT_DIG == 53 +typedef double zig_f64; +#define zig_as_f64(fp, repr) fp +#elif LDBL_MANT_DIG == 53 +#define zig_bitSizeOf_c_longdouble 64 +typedef long double zig_f64; +#define zig_as_f64(fp, repr) fp##l +#elif FLT64_MANT_DIG == 53 +typedef _Float64 zig_f64; +#define zig_as_f64(fp, repr) fp##f64 +#elif FLT32X_MANT_DIG == 53 +typedef _Float32x zig_f64; +#define zig_as_f64(fp, repr) fp##f32x +#else +#undef zig_has_f64 +#define zig_has_f64 0 +#define zig_repr_f64 i64 +typedef zig_i64 zig_f64; +#define zig_as_f64(fp, repr) repr +#undef zig_as_special_f64 +#define zig_as_special_f64(sign, name, arg, repr) repr +#endif + +#define zig_has_f80 1 +#define zig_bitSizeOf_f80 80 +#define zig_libc_name_f80(name) __##name##x +#define zig_as_special_f80(sign, name, arg, repr) sign zig_as_f80(__builtin_##name, )(arg) +#if FLT_MANT_DIG == 64 +typedef float zig_f80; +#define zig_as_f80(fp, repr) fp##f +#elif DBL_MANT_DIG == 64 +typedef double zig_f80; +#define zig_as_f80(fp, repr) fp +#elif LDBL_MANT_DIG == 64 +#define zig_bitSizeOf_c_longdouble 80 +typedef long double zig_f80; +#define zig_as_f80(fp, repr) fp##l +#elif FLT80_MANT_DIG == 64 +typedef _Float80 zig_f80; +#define zig_as_f80(fp, repr) fp##f80 +#elif FLT64X_MANT_DIG == 64 +typedef _Float64x zig_f80; +#define zig_as_f80(fp, repr) fp##f64x +#elif defined(__SIZEOF_FLOAT80__) +typedef __float80 zig_f80; +#define zig_as_f80(fp, repr) fp##l +#else +#undef zig_has_f80 +#define zig_has_f80 0 +#define zig_repr_f80 i128 +typedef zig_i128 zig_f80; +#define zig_as_f80(fp, repr) repr +#undef zig_as_special_f80 +#define zig_as_special_f80(sign, name, arg, repr) repr +#endif + +#define zig_has_f128 1 +#define zig_bitSizeOf_f128 128 +#define zig_libc_name_f128(name) name##q +#define zig_as_special_f128(sign, name, arg, repr) sign zig_as_f128(__builtin_##name, )(arg) +#if FLT_MANT_DIG == 113 +typedef float zig_f128; +#define zig_as_f128(fp, repr) fp##f +#elif DBL_MANT_DIG == 113 +typedef double zig_f128; +#define zig_as_f128(fp, repr) fp +#elif LDBL_MANT_DIG == 113 +#define zig_bitSizeOf_c_longdouble 128 +typedef long double zig_f128; +#define zig_as_f128(fp, repr) fp##l +#elif FLT128_MANT_DIG == 113 +typedef _Float128 zig_f128; +#define zig_as_f128(fp, repr) fp##f128 +#elif FLT64X_MANT_DIG == 113 +typedef _Float64x zig_f128; +#define zig_as_f128(fp, repr) fp##f64x +#elif defined(__SIZEOF_FLOAT128__) +typedef __float128 zig_f128; +#define zig_as_f128(fp, repr) fp##q +#undef zig_as_special_f128 +#define zig_as_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg) +#else +#undef zig_has_f128 +#define zig_has_f128 0 +#define zig_repr_f128 i128 +typedef zig_i128 zig_f128; +#define zig_as_f128(fp, repr) repr +#undef zig_as_special_f128 +#define zig_as_special_f128(sign, name, arg, repr) repr +#endif + +#define zig_has_c_longdouble 1 +typedef long double zig_c_longdouble; +#define zig_as_c_longdouble(fp, repr) fp##l +#define zig_libc_name_c_longdouble(name) name##l +#define zig_as_special_c_longdouble(sign, name, arg, repr) sign __builtin_##name##l(arg) + +#define zig_convert_builtin(ResType, operation, ArgType, version) \ + zig_extern_c zig_##ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(zig_##ArgType); +zig_convert_builtin(f16, trunc, f32, 2) +zig_convert_builtin(f16, trunc, f64, 2) +zig_convert_builtin(f16, trunc, f80, 2) +zig_convert_builtin(f16, trunc, f128, 2) +zig_convert_builtin(f32, extend, f16, 2) +zig_convert_builtin(f32, trunc, f64, 2) +zig_convert_builtin(f32, trunc, f80, 2) +zig_convert_builtin(f32, trunc, f128, 2) +zig_convert_builtin(f64, extend, f16, 2) +zig_convert_builtin(f64, extend, f32, 2) +zig_convert_builtin(f64, trunc, f80, 2) +zig_convert_builtin(f64, trunc, f128, 2) +zig_convert_builtin(f80, extend, f16, 2) +zig_convert_builtin(f80, extend, f32, 2) +zig_convert_builtin(f80, extend, f64, 2) +zig_convert_builtin(f80, trunc, f128, 2) +zig_convert_builtin(f128, extend, f16, 2) +zig_convert_builtin(f128, extend, f32, 2) +zig_convert_builtin(f128, extend, f64, 2) +zig_convert_builtin(f128, extend, f80, 2) + +#define zig_float_negate_builtin_0(Type) \ + static inline zig_##Type zig_neg_##Type(zig_##Type arg) { \ + return zig_expand_concat(zig_xor_, zig_repr_##Type)(arg, zig_expand_minInt(zig_repr_##Type, zig_bitSizeOf_##Type)); \ + } +#define zig_float_negate_builtin_1(Type) \ + static inline zig_##Type zig_neg_##Type(zig_##Type arg) { \ + return -arg; \ + } + +#define zig_float_less_builtin_0(Type, operation) \ + zig_extern_c zig_i8 zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##Type), 2)(zig_##Type, zig_##Type); \ + static inline zig_i8 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ + return (zig_i8)zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_##Type), 2)(lhs, rhs); \ + } +#define zig_float_less_builtin_1(Type, operation) \ + static inline zig_i8 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ + return (zig_i8)(!(lhs <= rhs) - (lhs < rhs)); \ + } + +#define zig_float_greater_builtin_0(Type, operation) \ + zig_float_less_builtin_0(Type, operation) +#define zig_float_greater_builtin_1(Type, operation) \ + static inline zig_i8 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ + return (zig_i8)((lhs > rhs) - !(lhs >= rhs)); \ + } + +#define zig_float_binary_builtin_0(Type, operation, operator) \ + zig_extern_c zig_##Type zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##Type), 3)(zig_##Type, zig_##Type); \ + static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ + return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_##Type), 3)(lhs, rhs); \ + } +#define zig_float_binary_builtin_1(Type, operation, operator) \ + static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ + return lhs operator rhs; \ + } #define zig_float_builtins(Type) \ - zig_extern_c zig_##Type zig_builtin_##Type(sqrt)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(sin)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(cos)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(tan)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(exp)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(exp2)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(log)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(log2)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(log10)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(fabs)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(floor)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(ceil)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(round)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(trunc)(zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(fmod)(zig_##Type, zig_##Type); \ - zig_extern_c zig_##Type zig_builtin_##Type(fma)(zig_##Type, zig_##Type, zig_##Type); \ + zig_convert_builtin(i32, fix, Type, ) \ + zig_convert_builtin(u32, fixuns, Type, ) \ + zig_convert_builtin(i64, fix, Type, ) \ + zig_convert_builtin(u64, fixuns, Type, ) \ + zig_convert_builtin(i128, fix, Type, ) \ + zig_convert_builtin(u128, fixuns, Type, ) \ + zig_convert_builtin(Type, float, i32, ) \ + zig_convert_builtin(Type, floatun, u32, ) \ + zig_convert_builtin(Type, float, i64, ) \ + zig_convert_builtin(Type, floatun, u64, ) \ + zig_convert_builtin(Type, float, i128, ) \ + zig_convert_builtin(Type, floatun, u128, ) \ + zig_expand_concat(zig_float_negate_builtin_, zig_has_##Type)(Type) \ + zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, cmp) \ + zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, ne) \ + zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, eq) \ + zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, lt) \ + zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, le) \ + zig_expand_concat(zig_float_greater_builtin_, zig_has_##Type)(Type, gt) \ + zig_expand_concat(zig_float_greater_builtin_, zig_has_##Type)(Type, ge) \ + zig_expand_concat(zig_float_binary_builtin_, zig_has_##Type)(Type, add, +) \ + zig_expand_concat(zig_float_binary_builtin_, zig_has_##Type)(Type, sub, -) \ + zig_expand_concat(zig_float_binary_builtin_, zig_has_##Type)(Type, mul, *) \ + zig_expand_concat(zig_float_binary_builtin_, zig_has_##Type)(Type, div, /) \ + zig_extern_c zig_##Type zig_libc_name_##Type(sqrt)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(sin)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(cos)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(tan)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(exp)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(exp2)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(log)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(log2)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(log10)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(fabs)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(floor)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(ceil)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(round)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(trunc)(zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(fmod)(zig_##Type, zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(fmin)(zig_##Type, zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(fmax)(zig_##Type, zig_##Type); \ + zig_extern_c zig_##Type zig_libc_name_##Type(fma)(zig_##Type, zig_##Type, zig_##Type); \ \ static inline zig_##Type zig_div_trunc_##Type(zig_##Type lhs, zig_##Type rhs) { \ - return zig_builtin_##Type(trunc)(lhs / rhs); \ + return zig_libc_name_##Type(trunc)(zig_div_##Type(lhs, rhs)); \ } \ \ static inline zig_##Type zig_div_floor_##Type(zig_##Type lhs, zig_##Type rhs) { \ - return zig_builtin_##Type(floor)(lhs / rhs); \ + return zig_libc_name_##Type(floor)(zig_div_##Type(lhs, rhs)); \ } \ \ static inline zig_##Type zig_mod_##Type(zig_##Type lhs, zig_##Type rhs) { \ - return lhs - zig_div_floor_##Type(lhs, rhs) * rhs; \ + return zig_sub_##Type(lhs, zig_mul_##Type(zig_div_floor_##Type(lhs, rhs), rhs)); \ } zig_float_builtins(f16) zig_float_builtins(f32) diff --git a/lib/std/start.zig b/lib/std/start.zig index 14903b0bc9..7ba24ad78c 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -281,7 +281,15 @@ fn _start() callconv(.Naked) noreturn { \\ andl $-16, %%esp \\ jmp _posixCallMainAndExit ), - .aarch64, .aarch64_be, .arm, .armeb, .thumb => asm volatile ( + .aarch64, .aarch64_be => asm volatile ( + \\ mov fp, #0 + \\ mov lr, #0 + \\ mov x0, sp + \\ adrp x1, argc_argv_ptr + \\ str x0, [x1, :lo12:argc_argv_ptr] + \\ b _posixCallMainAndExit + ), + .arm, .armeb, .thumb => asm volatile ( \\ mov fp, #0 \\ mov lr, #0 \\ str sp, argc_argv_ptr diff --git a/lib/test_runner.zig b/lib/test_runner.zig index 079d9c813a..83ac378daf 100644 --- a/lib/test_runner.zig +++ b/lib/test_runner.zig @@ -130,7 +130,8 @@ pub fn main2() anyerror!void { } if (builtin.zig_backend == .stage2_wasm or builtin.zig_backend == .stage2_x86_64 or - builtin.zig_backend == .stage2_llvm) + builtin.zig_backend == .stage2_llvm or + builtin.zig_backend == .stage2_c) { const passed = builtin.test_functions.len - skipped - failed; const stderr = std.io.getStdErr(); diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 83debd1af3..f8fa2a1003 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -19,6 +19,7 @@ const Liveness = @import("../Liveness.zig"); const CType = @import("../type.zig").CType; const Mutability = enum { Const, ConstArgument, Mut }; +const BigIntLimb = std.math.big.Limb; const BigInt = std.math.big.int; pub const CValue = union(enum) { @@ -608,19 +609,25 @@ pub const DeclGen = struct { .Bool => return dg.renderValue(writer, ty, Value.@"false", location), .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}), .Float => { + const bits = ty.floatBits(target); + var int_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits }; + const int_ty = Type.initPayload(&int_pl.base); + try writer.writeByte('('); try dg.renderTypecast(writer, ty); - try writer.writeAll(")zig_suffix_"); + try writer.writeAll(")zig_as_"); try dg.renderTypeForBuiltinFnName(writer, ty); try writer.writeByte('('); - switch (ty.floatBits(target)) { - 16 => try writer.print("{x}", .{@bitCast(f16, undefPattern(u16))}), - 32 => try writer.print("{x}", .{@bitCast(f32, undefPattern(u32))}), - 64 => try writer.print("{x}", .{@bitCast(f64, undefPattern(u64))}), - 80 => try writer.print("{x}", .{@bitCast(f80, undefPattern(u80))}), - 128 => try writer.print("{x}", .{@bitCast(f128, undefPattern(u128))}), + switch (bits) { + 16 => try writer.print("{x}", .{@bitCast(f16, undefPattern(i16))}), + 32 => try writer.print("{x}", .{@bitCast(f32, undefPattern(i32))}), + 64 => try writer.print("{x}", .{@bitCast(f64, undefPattern(i64))}), + 80 => try writer.print("{x}", .{@bitCast(f80, undefPattern(i80))}), + 128 => try writer.print("{x}", .{@bitCast(f128, undefPattern(i128))}), else => unreachable, } + try writer.writeAll(", "); + try dg.renderValue(writer, int_ty, Value.undef, .FunctionArgument); return writer.writeByte(')'); }, .Pointer => if (ty.isSlice()) { @@ -770,21 +777,48 @@ pub const DeclGen = struct { else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val)}), }, .Float => { + const bits = ty.floatBits(target); + const f128_val = val.toFloat(f128); + + var int_ty_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits }; + const int_ty = Type.initPayload(&int_ty_pl.base); + + assert(bits <= 128); + var int_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; + var int_val_big = BigInt.Mutable{ + .limbs = &int_val_limbs, + .len = undefined, + .positive = undefined, + }; + + switch (bits) { + 16 => int_val_big.set(@bitCast(i16, val.toFloat(f16))), + 32 => int_val_big.set(@bitCast(i32, val.toFloat(f32))), + 64 => int_val_big.set(@bitCast(i64, val.toFloat(f64))), + 80 => int_val_big.set(@bitCast(i80, val.toFloat(f80))), + 128 => int_val_big.set(@bitCast(i128, f128_val)), + else => unreachable, + } + + var int_val_pl = Value.Payload.BigInt{ + .base = .{ .tag = if (int_val_big.positive) .int_big_positive else .int_big_negative }, + .data = int_val_big.limbs[0..int_val_big.len], + }; + const int_val = Value.initPayload(&int_val_pl.base); + try writer.writeByte('('); try dg.renderTypecast(writer, ty); try writer.writeByte(')'); - const f128_val = val.toFloat(f128); - if (std.math.signbit(f128_val)) try writer.writeByte('-'); if (std.math.isFinite(f128_val)) { - try writer.writeAll("zig_suffix_"); + try writer.writeAll("zig_as_"); try dg.renderTypeForBuiltinFnName(writer, ty); try writer.writeByte('('); - switch (ty.floatBits(target)) { - 16 => try writer.print("{x}", .{@fabs(val.toFloat(f16))}), - 32 => try writer.print("{x}", .{@fabs(val.toFloat(f32))}), - 64 => try writer.print("{x}", .{@fabs(val.toFloat(f64))}), - 80 => try writer.print("{x}", .{@fabs(val.toFloat(f80))}), - 128 => try writer.print("{x}", .{@fabs(f128_val)}), + switch (bits) { + 16 => try writer.print("{x}", .{val.toFloat(f16)}), + 32 => try writer.print("{x}", .{val.toFloat(f32)}), + 64 => try writer.print("{x}", .{val.toFloat(f64)}), + 80 => try writer.print("{x}", .{val.toFloat(f80)}), + 128 => try writer.print("{x}", .{f128_val}), else => unreachable, } } else { @@ -796,23 +830,26 @@ pub const DeclGen = struct { "inf" else unreachable; - try writer.writeAll("zig_builtin_constant_"); + + try writer.writeAll("zig_as_special_"); try dg.renderTypeForBuiltinFnName(writer, ty); try writer.writeByte('('); + if (std.math.signbit(f128_val)) try writer.writeByte('-'); + try writer.writeAll(", "); try writer.writeAll(operation); - try writer.writeAll(")("); - if (std.math.isNan(f128_val)) switch (ty.floatBits(target)) { + try writer.writeAll(", "); + if (std.math.isNan(f128_val)) switch (bits) { // We only actually need to pass the significand, but it will get // properly masked anyway, so just pass the whole value. - 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, @fabs(val.toFloat(f16)))}), - 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, @fabs(val.toFloat(f32)))}), - 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, @fabs(val.toFloat(f64)))}), - 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, @fabs(val.toFloat(f80)))}), - 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, @fabs(f128_val))}), + 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, val.toFloat(f16))}), + 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, val.toFloat(f32))}), + 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, val.toFloat(f64))}), + 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, val.toFloat(f80))}), + 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}), else => unreachable, }; } - return writer.writeByte(')'); + return writer.print(", {x})", .{try dg.fmtIntLiteral(int_ty, int_val)}); }, .Pointer => switch (val.tag()) { .null_value, .zero => if (ty.isSlice()) { @@ -2299,11 +2336,14 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO // TODO use a different strategy for add, sub, mul, div // that communicates to the optimizer that wrapping is UB. - .add => try airBinOp(f, inst, "+", "add", .None), - .sub => try airBinOp(f, inst, "-", "sub", .None), - .mul => try airBinOp(f, inst, "*", "mul", .None), - .div_float, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None), + .add => try airBinOp(f, inst, "+", "add", .None), + .sub => try airBinOp(f, inst, "-", "sub", .None), + .mul => try airBinOp(f, inst, "*", "mul", .None), + .neg => try airFloatNeg(f, inst), + .div_float => try airBinBuiltinCall(f, inst, "div", .None), + + .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None), .rem => blk: { const bin_op = f.air.instructions.items(.data)[inst].bin_op; const lhs_ty = f.air.typeOf(bin_op.lhs); @@ -2314,16 +2354,6 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO else try airBinFloatOp(f, inst, "fmod"); }, - .div_trunc => blk: { - const bin_op = f.air.instructions.items(.data)[inst].bin_op; - const lhs_ty = f.air.typeOf(bin_op.lhs); - // For binary operations @TypeOf(lhs)==@TypeOf(rhs), - // so we only check one. - break :blk if (lhs_ty.isInt()) - try airBinOp(f, inst, "/", "div_trunc", .None) - else - try airBinBuiltinCall(f, inst, "div_trunc", .None); - }, .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None), .mod => try airBinBuiltinCall(f, inst, "mod", .None), @@ -2336,8 +2366,6 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits), .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits), - .neg => try airNeg(f, inst), - .sqrt, .sin, .cos, @@ -2361,18 +2389,18 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits), .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits), - .min => try airMinMax(f, inst, '<'), - .max => try airMinMax(f, inst, '>'), + .min => try airMinMax(f, inst, '<', "fmin"), + .max => try airMinMax(f, inst, '>', "fmax"), .slice => try airSlice(f, inst), - .cmp_gt => try airCmpOp(f, inst, ">"), - .cmp_gte => try airCmpOp(f, inst, ">="), - .cmp_lt => try airCmpOp(f, inst, "<"), - .cmp_lte => try airCmpOp(f, inst, "<="), + .cmp_gt => try airCmpOp(f, inst, ">", "gt"), + .cmp_gte => try airCmpOp(f, inst, ">=", "ge"), + .cmp_lt => try airCmpOp(f, inst, "<", "lt"), + .cmp_lte => try airCmpOp(f, inst, "<=", "le"), - .cmp_eq => try airEquality(f, inst, "((", "=="), - .cmp_neq => try airEquality(f, inst, "!((", "!="), + .cmp_eq => try airEquality(f, inst, "((", "==", "eq"), + .cmp_neq => try airEquality(f, inst, "!((", "!=", "ne"), .cmp_vector => return f.fail("TODO: C backend: implement cmp_vector", .{}), .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst), @@ -2468,7 +2496,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .float_to_int, .fptrunc, .fpext, - => try airSimpleCast(f, inst), + => try airFloatCast(f, inst), .ptrtoint => try airPtrToInt(f, inst), @@ -2973,8 +3001,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { const src_bits = src_ty.bitSize(target); - const Limb = std.math.big.Limb; - const ExpectedContents = [BigInt.Managed.default_capacity]Limb; + const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb; var stack align(@alignOf(ExpectedContents)) = std.heap.stackFallback(@sizeOf(ExpectedContents), f.object.dg.gpa); @@ -3003,6 +3030,11 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll("(("); try f.renderTypecast(writer, host_ty); try writer.writeByte(')'); + if (src_ty.isPtrAtRuntime()) { + try writer.writeByte('('); + try f.renderTypecast(writer, Type.usize); + try writer.writeByte(')'); + } try f.writeCValue(writer, src_val, .Other); try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)}); } else { @@ -3081,7 +3113,7 @@ fn airBinOp( const operand_ty = f.air.typeOf(bin_op.lhs); const target = f.object.dg.module.getTarget(); - if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) + if ((operand_ty.isInt() and operand_ty.bitSize(target) > 64) or operand_ty.isRuntimeFloat()) return try airBinBuiltinCall(f, inst, operation, info); const inst_ty = f.air.typeOfIndex(inst); @@ -3102,7 +3134,7 @@ fn airBinOp( return local; } -fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue { +fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: []const u8) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; const bin_op = f.air.instructions.items(.data)[inst].bin_op; @@ -3110,7 +3142,9 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue { const operand_ty = f.air.typeOf(bin_op.lhs); const target = f.object.dg.module.getTarget(); if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) - return try airCmpBuiltinCall(f, inst, operator); + return try airCmpBuiltinCall(f, inst, operator, "cmp"); + if (operand_ty.isRuntimeFloat()) + return try airCmpBuiltinCall(f, inst, operator, operation); const inst_ty = f.air.typeOfIndex(inst); const lhs = try f.resolveInst(bin_op.lhs); @@ -3134,11 +3168,20 @@ fn airEquality( f: *Function, inst: Air.Inst.Index, negate_prefix: []const u8, - eq_op_str: []const u8, + operator: []const u8, + operation: []const u8, ) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; const bin_op = f.air.instructions.items(.data)[inst].bin_op; + + const operand_ty = f.air.typeOf(bin_op.lhs); + const target = f.object.dg.module.getTarget(); + if (operand_ty.isInt() and operand_ty.bitSize(target) > 64) + return try airCmpBuiltinCall(f, inst, operator, "cmp"); + if (operand_ty.isRuntimeFloat()) + return try airCmpBuiltinCall(f, inst, operator, operation); + const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -3148,8 +3191,7 @@ fn airEquality( try writer.writeAll(" = "); - const lhs_ty = f.air.typeOf(bin_op.lhs); - if (lhs_ty.tag() == .optional) { + if (operand_ty.tag() == .optional) { // (A && B) || (C && (A == B)) // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload @@ -3172,7 +3214,7 @@ fn airEquality( try f.writeCValue(writer, lhs, .Other); try writer.writeByte(' '); - try writer.writeAll(eq_op_str); + try writer.writeAll(operator); try writer.writeByte(' '); try f.writeCValue(writer, rhs, .Other); try writer.writeAll(";\n"); @@ -3231,15 +3273,22 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { return local; } -fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { +fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; const bin_op = f.air.instructions.items(.data)[inst].bin_op; + + const inst_ty = f.air.typeOfIndex(inst); + const target = f.object.dg.module.getTarget(); + if (inst_ty.isInt() and inst_ty.bitSize(target) > 64) + return try airBinBuiltinCall(f, inst, operation[1..], .None); + if (inst_ty.isRuntimeFloat()) + return try airBinFloatOp(f, inst, operation); + const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); const writer = f.object.writer(); - const inst_ty = f.air.typeOfIndex(inst); const local = try f.allocLocal(inst_ty, .Const); // (lhs <> rhs) ? lhs : rhs @@ -4518,19 +4567,44 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { return local; } -/// Emits a local variable with the result type and initializes it -/// with the operand. -fn airSimpleCast(f: *Function, inst: Air.Inst.Index) !CValue { +fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; const inst_ty = f.air.typeOfIndex(inst); - const local = try f.allocLocal(inst_ty, .Const); const ty_op = f.air.instructions.items(.data)[inst].ty_op; - const writer = f.object.writer(); const operand = try f.resolveInst(ty_op.operand); + const operand_ty = f.air.typeOf(ty_op.operand); + const target = f.object.dg.module.getTarget(); + const operation = if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat()) + if (inst_ty.floatBits(target) < operand_ty.floatBits(target)) "trunc" else "extend" + else if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) + if (inst_ty.isSignedInt()) "fix" else "fixuns" + else if (inst_ty.isRuntimeFloat() and operand_ty.isInt()) + if (operand_ty.isSignedInt()) "float" else "floatun" + else + unreachable; + + const local = try f.allocLocal(inst_ty, .Const); + const writer = f.object.writer(); try writer.writeAll(" = "); - try f.writeCValue(writer, operand, .Other); + if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) { + try writer.writeAll("zig_wrap_"); + try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); + try writer.writeByte('('); + } + try writer.writeAll("__"); + try writer.writeAll(operation); + try writer.writeAll(compilerRtAbbrev(operand_ty, target)); + try writer.writeAll(compilerRtAbbrev(inst_ty, target)); + if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat()) try writer.writeByte('2'); + try writer.writeByte('('); + try f.writeCValue(writer, operand, .FunctionArgument); + try writer.writeByte(')'); + if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) { + try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits); + try writer.writeByte(')'); + } try writer.writeAll(";\n"); return local; } @@ -4604,7 +4678,12 @@ fn airBinBuiltinCall( return local; } -fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue { +fn airCmpBuiltinCall( + f: *Function, + inst: Air.Inst.Index, + operator: []const u8, + operation: []const u8, +) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; const inst_ty = f.air.typeOfIndex(inst); @@ -4613,7 +4692,9 @@ fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) ! const local = try f.allocLocal(inst_ty, .Const); const writer = f.object.writer(); - try writer.writeAll(" = zig_cmp_"); + try writer.writeAll(" = zig_"); + try writer.writeAll(operation); + try writer.writeByte('_'); try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); try writer.writeByte('('); try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument); @@ -5045,6 +5126,14 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll("(("); try f.renderTypecast(writer, inst_ty); try writer.writeByte(')'); + if (field_ty.isPtrAtRuntime()) { + try writer.writeByte('('); + try f.renderTypecast(writer, switch (int_info.signedness) { + .unsigned => Type.usize, + .signed => Type.isize, + }); + try writer.writeByte(')'); + } try f.writeCValue(writer, try f.resolveInst(element), .Other); try writer.writeAll(", "); try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); @@ -5157,17 +5246,21 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { return local; } -fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue { +fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; - const un_op = f.air.instructions.items(.data)[inst].un_op; - const writer = f.object.writer(); const inst_ty = f.air.typeOfIndex(inst); + const un_op = f.air.instructions.items(.data)[inst].un_op; const operand = try f.resolveInst(un_op); + const operand_ty = f.air.typeOf(un_op); + const local = try f.allocLocal(inst_ty, .Const); - try writer.writeAll(" = -"); - try f.writeCValue(writer, operand, .Other); - try writer.writeAll(";\n"); + const writer = f.object.writer(); + try writer.writeAll(" = zig_neg_"); + try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); + try writer.writeByte('('); + try f.writeCValue(writer, operand, .FunctionArgument); + try writer.writeAll(");\n"); return local; } @@ -5178,7 +5271,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal const inst_ty = f.air.typeOfIndex(inst); const operand = try f.resolveInst(un_op); const local = try f.allocLocal(inst_ty, .Const); - try writer.writeAll(" = zig_builtin_"); + try writer.writeAll(" = zig_libc_name_"); try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); try writer.writeByte('('); try writer.writeAll(operation); @@ -5196,7 +5289,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); const local = try f.allocLocal(inst_ty, .Const); - try writer.writeAll(" = zig_builtin_"); + try writer.writeAll(" = zig_libc_name_"); try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); try writer.writeByte('('); try writer.writeAll(operation); @@ -5218,7 +5311,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { const addend = try f.resolveInst(pl_op.operand); const writer = f.object.writer(); const local = try f.allocLocal(inst_ty, .Const); - try writer.writeAll(" = zig_builtin_"); + try writer.writeAll(" = zig_libc_name_"); try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); try writer.writeAll("(fma)("); try f.writeCValue(writer, mulend1, .FunctionArgument); @@ -5328,6 +5421,22 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 { }; } +fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 { + return if (ty.isInt()) switch (ty.intInfo(target).bits) { + 1...32 => "si", + 33...64 => "di", + 65...128 => "ti", + else => unreachable, + } else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) { + 16 => "hf", + 32 => "sf", + 64 => "df", + 80 => "xf", + 128 => "tf", + else => unreachable, + } else unreachable; +} + fn formatStringLiteral( str: []const u8, comptime fmt: []const u8, @@ -5356,8 +5465,10 @@ fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) { return .{ .data = str }; } -fn undefPattern(comptime T: type) T { - return (1 << (@bitSizeOf(T) | 1)) / 3; +fn undefPattern(comptime IntType: type) IntType { + const int_info = @typeInfo(IntType).Int; + const UnsignedType = std.meta.Int(.unsigned, int_info.bits); + return @bitCast(IntType, @as(UnsignedType, (1 << (int_info.bits | 1)) / 3)); } const FormatIntLiteralContext = struct { @@ -5374,30 +5485,29 @@ fn formatIntLiteral( const target = data.mod.getTarget(); const int_info = data.ty.intInfo(target); - const Limb = std.math.big.Limb; const ExpectedContents = struct { const base = 10; const limbs_count_128 = BigInt.calcTwosCompLimbCount(128); const expected_needed_limbs_count = BigInt.calcToStringLimbsBufferLen(limbs_count_128, base); const worst_case_int = BigInt.Const{ - .limbs = &([1]Limb{std.math.maxInt(Limb)} ** expected_needed_limbs_count), + .limbs = &([1]BigIntLimb{std.math.maxInt(BigIntLimb)} ** expected_needed_limbs_count), .positive = false, }; - undef_limbs: [limbs_count_128]Limb, - wrap_limbs: [limbs_count_128]Limb, + undef_limbs: [limbs_count_128]BigIntLimb, + wrap_limbs: [limbs_count_128]BigIntLimb, }; var stack align(@alignOf(ExpectedContents)) = std.heap.stackFallback(@sizeOf(ExpectedContents), data.mod.gpa); const allocator = stack.get(); - var undef_limbs: []Limb = &.{}; + var undef_limbs: []BigIntLimb = &.{}; defer allocator.free(undef_limbs); var int_buf: Value.BigIntSpace = undefined; const int = if (data.val.isUndefDeep()) blk: { - undef_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(int_info.bits)); - std.mem.set(Limb, undef_limbs, undefPattern(Limb)); + undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(int_info.bits)); + std.mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb)); var undef_int = BigInt.Mutable{ .limbs = undef_limbs, @@ -5410,10 +5520,10 @@ fn formatIntLiteral( assert(int.fitsInTwosComp(int_info.signedness, int_info.bits)); const c_bits = toCIntBits(int_info.bits) orelse unreachable; - var one_limbs: [BigInt.calcLimbLen(1)]Limb = undefined; + var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); - const wrap_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(c_bits)); + const wrap_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)); defer allocator.free(wrap_limbs); var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined }; if (wrap.addWrap(int, one, int_info.signedness, c_bits) or @@ -5439,7 +5549,7 @@ fn formatIntLiteral( else => try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }), } - const limbs_count_64 = @divExact(64, @bitSizeOf(Limb)); + const limbs_count_64 = @divExact(64, @bitSizeOf(BigIntLimb)); if (c_bits <= 64) { var base: u8 = undefined; var case: std.fmt.Case = undefined; @@ -5471,7 +5581,7 @@ fn formatIntLiteral( } var str: [64]u8 = undefined; - var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]Limb = undefined; + var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]BigIntLimb = undefined; try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]); } else { assert(c_bits == 128); diff --git a/test/behavior/atomics.zig b/test/behavior/atomics.zig index 365df09928..1fca1f6ea2 100644 --- a/test/behavior/atomics.zig +++ b/test/behavior/atomics.zig @@ -220,8 +220,8 @@ test "atomicrmw with floats" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if ((builtin.zig_backend == .stage1 or builtin.zig_backend == .stage2_llvm) and - builtin.cpu.arch == .aarch64) + if ((builtin.zig_backend == .stage1 or builtin.zig_backend == .stage2_llvm or + builtin.zig_backend == .stage2_c) and builtin.cpu.arch == .aarch64) { // https://github.com/ziglang/zig/issues/10627 return error.SkipZigTest; @@ -248,6 +248,10 @@ test "atomicrmw with ints" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .aarch64) { + return error.SkipZigTest; + } + try testAtomicRmwInt(); comptime try testAtomicRmwInt(); } @@ -282,6 +286,10 @@ test "atomics with different types" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .aarch64) { + return error.SkipZigTest; + } + try testAtomicsWithType(bool, true, false); try testAtomicsWithType(u1, 0, 1); diff --git a/test/tests.zig b/test/tests.zig index eec7e1fdf1..266d2a37d0 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -678,10 +678,6 @@ pub fn addPkgTests( // https://github.com/ziglang/zig/issues/12415 continue; } - if (backend == .stage2_c and builtin.cpu.arch == .aarch64) { - // https://github.com/ziglang/zig/issues/13357 - continue; - } } const libc_prefix = if (test_target.target.getOs().requiresLibC())