authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-11-01 13:28:40-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-11-01 13:28:40-04:00
log1780d7a348e0f4abfaa71e70eb4cf410a89c00c0
tree416fb7f6f3a01e2a083ac02d0c1dd36ce72967a4
parent2943df016e62554ef4677acb5bd15e6c7263f108
parentff83296256fffb7aba0515abb715a4537a85e054
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13368 from jacobly0/fix-aarch64-c


6 files changed, 534 insertions(+), 234 deletions(-)

lib/include/zig.h+312-135
......@@ -20,7 +20,7 @@
2020
2121#if __STDC_VERSION__ >= 201112L
2222#define zig_threadlocal thread_local
23#elif __GNUC__
23#elif defined(__GNUC__)
2424#define zig_threadlocal __thread
2525#elif _MSC_VER
2626#define zig_threadlocal __declspec(thread)
......@@ -28,7 +28,7 @@
2828#define zig_threadlocal zig_threadlocal_unavailable
2929#endif
3030
31#if zig_has_attribute(naked)
31#if zig_has_attribute(naked) || defined(__GNUC__)
3232#define zig_naked __attribute__((naked))
3333#elif defined(_MSC_VER)
3434#define zig_naked __declspec(naked)
......@@ -128,7 +128,7 @@
128128#define zig_atomic_store(obj, arg, order) atomic_store_explicit (obj, arg, order)
129129#define zig_atomic_load(obj, order) atomic_load_explicit (obj, order)
130130#define zig_fence(order) atomic_thread_fence(order)
131#elif __GNUC__
131#elif defined(__GNUC__)
132132#define memory_order_relaxed __ATOMIC_RELAXED
133133#define memory_order_consume __ATOMIC_CONSUME
134134#define memory_order_acquire __ATOMIC_ACQUIRE
......@@ -176,7 +176,7 @@
176176
177177#if __STDC_VERSION__ >= 201112L
178178#define zig_noreturn _Noreturn void
179#elif zig_has_attribute(noreturn)
179#elif zig_has_attribute(noreturn) || defined(__GNUC__)
180180#define zig_noreturn __attribute__((noreturn)) void
181181#elif _MSC_VER
182182#define zig_noreturn __declspec(noreturn) void
......@@ -184,6 +184,9 @@
184184#define zig_noreturn void
185185#endif
186186
187#define zig_concat(lhs, rhs) lhs##rhs
188#define zig_expand_concat(lhs, rhs) zig_concat(lhs, rhs)
189
187190#define zig_bitSizeOf(T) (CHAR_BIT * sizeof(T))
188191
189192typedef void zig_void;
......@@ -250,110 +253,17 @@ typedef int64_t zig_i64;
250253#define zig_minInt_i64 INT64_MIN
251254#define zig_maxInt_i64 INT64_MAX
252255
253#define zig_builtin_f16(name) __##name##h
254#define zig_builtin_constant_f16(name) zig_suffix_f16(__builtin_##name)
255#if FLT_MANT_DIG == 11
256typedef float zig_f16;
257#define zig_suffix_f16(x) x##f
258#elif DBL_MANT_DIG == 11
259typedef double zig_f16;
260#define zig_suffix_f16(x) x
261#elif LDBL_MANT_DIG == 11
262typedef long double zig_f16;
263#define zig_suffix_f16(x) x##l
264#elif FLT16_MANT_DIG == 11
265typedef _Float16 zig_f16;
266#define zig_suffix_f16(x) x##f16
267#elif defined(__SIZEOF_FP16__)
268typedef __fp16 zig_f16;
269#define zig_suffix_f16(x) x##f16
270#endif
271
272#define zig_builtin_f32(name) name##f
273#define zig_builtin_constant_f32(name) zig_suffix_f32(__builtin_##name)
274#if FLT_MANT_DIG == 24
275typedef float zig_f32;
276#define zig_suffix_f32(x) x##f
277#elif DBL_MANT_DIG == 24
278typedef double zig_f32;
279#define zig_suffix_f32(x) x
280#elif LDBL_MANT_DIG == 24
281typedef long double zig_f32;
282#define zig_suffix_f32(x) x##l
283#elif FLT32_MANT_DIG == 24
284typedef _Float32 zig_f32;
285#define zig_suffix_f32(x) x##f32
286#endif
287
288#define zig_builtin_f64(name) name
289#define zig_builtin_constant_f64(name) zig_suffix_f64(__builtin_##name)
290#if FLT_MANT_DIG == 53
291typedef float zig_f64;
292#define zig_suffix_f64(x) x##f
293#elif DBL_MANT_DIG == 53
294typedef double zig_f64;
295#define zig_suffix_f64(x) x
296#elif LDBL_MANT_DIG == 53
297typedef long double zig_f64;
298#define zig_suffix_f64(x) x##l
299#elif FLT64_MANT_DIG == 53
300typedef _Float64 zig_f64;
301#define zig_suffix_f64(x) x##f64
302#elif FLT32X_MANT_DIG == 53
303typedef _Float32x zig_f64;
304#define zig_suffix_f64(x) x##f32x
305#endif
306
307#define zig_builtin_f80(name) __##name##x
308#define zig_builtin_constant_f80(name) zig_suffix_f80(__builtin_##name)
309#if FLT_MANT_DIG == 64
310typedef float zig_f80;
311#define zig_suffix_f80(x) x##f
312#elif DBL_MANT_DIG == 64
313typedef double zig_f80;
314#define zig_suffix_f80(x) x
315#elif LDBL_MANT_DIG == 64
316typedef long double zig_f80;
317#define zig_suffix_f80(x) x##l
318#elif FLT80_MANT_DIG == 64
319typedef _Float80 zig_f80;
320#define zig_suffix_f80(x) x##f80
321#elif FLT64X_MANT_DIG == 64
322typedef _Float64x zig_f80;
323#define zig_suffix_f80(x) x##f64x
324#elif defined(__SIZEOF_FLOAT80__)
325typedef __float80 zig_f80;
326#define zig_suffix_f80(x) x##l
327#endif
328
329#define zig_builtin_f128(name) name##q
330#define zig_builtin_constant_f128(name) zig_suffix_f80(__builtin_##name)
331#if FLT_MANT_DIG == 113
332typedef float zig_f128;
333#define zig_suffix_f128(x) x##f
334#elif DBL_MANT_DIG == 113
335typedef double zig_f128;
336#define zig_suffix_f128(x) x
337#elif LDBL_MANT_DIG == 113
338typedef long double zig_f128;
339#define zig_suffix_f128(x) x##l
340#elif FLT128_MANT_DIG == 113
341typedef _Float128 zig_f128;
342#define zig_suffix_f128(x) x##f128
343#elif FLT64X_MANT_DIG == 113
344typedef _Float64x zig_f128;
345#define zig_suffix_f128(x) x##f64x
346#elif defined(__SIZEOF_FLOAT128__)
347typedef __float128 zig_f128;
348#define zig_suffix_f128(x) x##q
349#undef zig_builtin_constant_f128
350#define zig_builtin_constant_f128(name) __builtin_##name##f128
351#endif
352
353typedef long double zig_c_longdouble;
354#define zig_suffix_c_longdouble(x) x##l
355#define zig_builtin_c_longdouble(name) zig_suffix_c_longdouble(name)
356#define zig_builtin_constant_c_longdouble(name) zig_suffix_c_longdouble(__builtin_##name)
256#define zig_compiler_rt_abbrev_u32 si
257#define zig_compiler_rt_abbrev_i32 si
258#define zig_compiler_rt_abbrev_u64 di
259#define zig_compiler_rt_abbrev_i64 di
260#define zig_compiler_rt_abbrev_u128 ti
261#define zig_compiler_rt_abbrev_i128 ti
262#define zig_compiler_rt_abbrev_f16 hf
263#define zig_compiler_rt_abbrev_f32 sf
264#define zig_compiler_rt_abbrev_f64 df
265#define zig_compiler_rt_abbrev_f80 xf
266#define zig_compiler_rt_abbrev_f128 tf
357267
358268zig_extern_c void *memcpy (void *zig_restrict, void const *zig_restrict, zig_usize);
359269zig_extern_c void *memset (void *, int, zig_usize);
......@@ -361,7 +271,9 @@ zig_extern_c void *memset (void *, int, zig_usize);
361271/* ==================== 8/16/32/64-bit Integer Routines ===================== */
362272
363273#define zig_maxInt(Type, bits) zig_shr_##Type(zig_maxInt_##Type, (zig_bitSizeOf(zig_##Type) - bits))
274#define zig_expand_maxInt(Type, bits) zig_maxInt(Type, bits)
364275#define zig_minInt(Type, bits) zig_not_##Type(zig_maxInt(Type, bits), bits)
276#define zig_expand_minInt(Type, bits) zig_minInt(Type, bits)
365277
366278#define zig_int_operator(Type, RhsType, operation, operator) \
367279 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) {
954866#if zig_has_builtin(bitreverse16)
955867 full_res = __builtin_bitreverse16(val);
956868#else
957 full_res = (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 0)) << 8 |
958 (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 8)) >> 0;
869 full_res = (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 0), 8) << 8 |
870 (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 8), 8) >> 0;
959871#endif
960872 return zig_wrap_u16(full_res >> (16 - bits), bits);
961873}
......@@ -969,8 +881,8 @@ static inline zig_u32 zig_bit_reverse_u32(zig_u32 val, zig_u8 bits) {
969881#if zig_has_builtin(bitreverse32)
970882 full_res = __builtin_bitreverse32(val);
971883#else
972 full_res = (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 0)) << 16 |
973 (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 16)) >> 0;
884 full_res = (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 0), 16) << 16 |
885 (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 16), 16) >> 0;
974886#endif
975887 return zig_wrap_u32(full_res >> (32 - bits), bits);
976888}
......@@ -984,8 +896,8 @@ static inline zig_u64 zig_bit_reverse_u64(zig_u64 val, zig_u8 bits) {
984896#if zig_has_builtin(bitreverse64)
985897 full_res = __builtin_bitreverse64(val);
986898#else
987 full_res = (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 0)) << 32 |
988 (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 32)) >> 0;
899 full_res = (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 0), 32) << 32 |
900 (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 32), 32) >> 0;
989901#endif
990902 return zig_wrap_u64(full_res >> (64 - bits), bits);
991903}
......@@ -1019,7 +931,7 @@ typedef signed __int128 zig_i128;
1019931#define zig_bitcast_i128(val) ((zig_i128)(val))
1020932#define zig_cmp_int128(Type) \
1021933 static inline zig_i8 zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
1022 return (lhs > rhs) - (lhs < rhs); \
934 return (zig_i8)((lhs > rhs) - (lhs < rhs)); \
1023935 }
1024936#define zig_bit_int128(Type, operation, operator) \
1025937 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) {
12111123#define zig_div_floor_u128 zig_div_trunc_u128
12121124#define zig_mod_u128 zig_rem_u128
12131125
1126static inline zig_u128 zig_min_u128(zig_u128 lhs, zig_u128 rhs) {
1127 return zig_cmp_u128(lhs, rhs) < 0 ? lhs : rhs;
1128}
1129
1130static inline zig_i128 zig_min_i128(zig_i128 lhs, zig_i128 rhs) {
1131 return zig_cmp_i128(lhs, rhs) < 0 ? lhs : rhs;
1132}
1133
1134static inline zig_u128 zig_max_u128(zig_u128 lhs, zig_u128 rhs) {
1135 return zig_cmp_u128(lhs, rhs) > 0 ? lhs : rhs;
1136}
1137
1138static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {
1139 return zig_cmp_i128(lhs, rhs) > 0 ? lhs : rhs;
1140}
1141
12141142static inline zig_i128 zig_shr_i128(zig_i128 lhs, zig_u8 rhs) {
12151143 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);
12161144 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) {
14601388 return zig_bit_reverse_u128(zig_bitcast_u128(val), bits);
14611389}
14621390
1463/* ========================== Float Point Routines ========================== */
1391/* ========================= Floating Point Support ========================= */
1392
1393#define zig_has_f16 1
1394#define zig_bitSizeOf_f16 16
1395#define zig_libc_name_f16(name) __##name##h
1396#define zig_as_special_f16(sign, name, arg, repr) sign zig_as_f16(__builtin_##name, )(arg)
1397#if FLT_MANT_DIG == 11
1398typedef float zig_f16;
1399#define zig_as_f16(fp, repr) fp##f
1400#elif DBL_MANT_DIG == 11
1401typedef double zig_f16;
1402#define zig_as_f16(fp, repr) fp
1403#elif LDBL_MANT_DIG == 11
1404#define zig_bitSizeOf_c_longdouble 16
1405typedef long double zig_f16;
1406#define zig_as_f16(fp, repr) fp##l
1407#elif FLT16_MANT_DIG == 11
1408typedef _Float16 zig_f16;
1409#define zig_as_f16(fp, repr) fp##f16
1410#elif defined(__SIZEOF_FP16__)
1411typedef __fp16 zig_f16;
1412#define zig_as_f16(fp, repr) fp##f16
1413#else
1414#undef zig_has_f16
1415#define zig_has_f16 0
1416#define zig_repr_f16 i16
1417typedef zig_i16 zig_f16;
1418#define zig_as_f16(fp, repr) repr
1419#undef zig_as_special_f16
1420#define zig_as_special_f16(sign, name, arg, repr) repr
1421#endif
1422
1423#define zig_has_f32 1
1424#define zig_bitSizeOf_f32 32
1425#define zig_libc_name_f32(name) name##f
1426#define zig_as_special_f32(sign, name, arg, repr) sign zig_as_f32(__builtin_##name, )(arg)
1427#if FLT_MANT_DIG == 24
1428typedef float zig_f32;
1429#define zig_as_f32(fp, repr) fp##f
1430#elif DBL_MANT_DIG == 24
1431typedef double zig_f32;
1432#define zig_as_f32(fp, repr) fp
1433#elif LDBL_MANT_DIG == 24
1434#define zig_bitSizeOf_c_longdouble 32
1435typedef long double zig_f32;
1436#define zig_as_f32(fp, repr) fp##l
1437#elif FLT32_MANT_DIG == 24
1438typedef _Float32 zig_f32;
1439#define zig_as_f32(fp, repr) fp##f32
1440#else
1441#undef zig_has_f32
1442#define zig_has_f32 0
1443#define zig_repr_f32 i32
1444typedef zig_i32 zig_f32;
1445#define zig_as_f32(fp, repr) repr
1446#undef zig_as_special_f32
1447#define zig_as_special_f32(sign, name, arg, repr) repr
1448#endif
1449
1450#define zig_has_f64 1
1451#define zig_bitSizeOf_f64 64
1452#define zig_libc_name_f64(name) name
1453#define zig_as_special_f64(sign, name, arg, repr) sign zig_as_f64(__builtin_##name, )(arg)
1454#if FLT_MANT_DIG == 53
1455typedef float zig_f64;
1456#define zig_as_f64(fp, repr) fp##f
1457#elif DBL_MANT_DIG == 53
1458typedef double zig_f64;
1459#define zig_as_f64(fp, repr) fp
1460#elif LDBL_MANT_DIG == 53
1461#define zig_bitSizeOf_c_longdouble 64
1462typedef long double zig_f64;
1463#define zig_as_f64(fp, repr) fp##l
1464#elif FLT64_MANT_DIG == 53
1465typedef _Float64 zig_f64;
1466#define zig_as_f64(fp, repr) fp##f64
1467#elif FLT32X_MANT_DIG == 53
1468typedef _Float32x zig_f64;
1469#define zig_as_f64(fp, repr) fp##f32x
1470#else
1471#undef zig_has_f64
1472#define zig_has_f64 0
1473#define zig_repr_f64 i64
1474typedef zig_i64 zig_f64;
1475#define zig_as_f64(fp, repr) repr
1476#undef zig_as_special_f64
1477#define zig_as_special_f64(sign, name, arg, repr) repr
1478#endif
1479
1480#define zig_has_f80 1
1481#define zig_bitSizeOf_f80 80
1482#define zig_libc_name_f80(name) __##name##x
1483#define zig_as_special_f80(sign, name, arg, repr) sign zig_as_f80(__builtin_##name, )(arg)
1484#if FLT_MANT_DIG == 64
1485typedef float zig_f80;
1486#define zig_as_f80(fp, repr) fp##f
1487#elif DBL_MANT_DIG == 64
1488typedef double zig_f80;
1489#define zig_as_f80(fp, repr) fp
1490#elif LDBL_MANT_DIG == 64
1491#define zig_bitSizeOf_c_longdouble 80
1492typedef long double zig_f80;
1493#define zig_as_f80(fp, repr) fp##l
1494#elif FLT80_MANT_DIG == 64
1495typedef _Float80 zig_f80;
1496#define zig_as_f80(fp, repr) fp##f80
1497#elif FLT64X_MANT_DIG == 64
1498typedef _Float64x zig_f80;
1499#define zig_as_f80(fp, repr) fp##f64x
1500#elif defined(__SIZEOF_FLOAT80__)
1501typedef __float80 zig_f80;
1502#define zig_as_f80(fp, repr) fp##l
1503#else
1504#undef zig_has_f80
1505#define zig_has_f80 0
1506#define zig_repr_f80 i128
1507typedef zig_i128 zig_f80;
1508#define zig_as_f80(fp, repr) repr
1509#undef zig_as_special_f80
1510#define zig_as_special_f80(sign, name, arg, repr) repr
1511#endif
1512
1513#define zig_has_f128 1
1514#define zig_bitSizeOf_f128 128
1515#define zig_libc_name_f128(name) name##q
1516#define zig_as_special_f128(sign, name, arg, repr) sign zig_as_f128(__builtin_##name, )(arg)
1517#if FLT_MANT_DIG == 113
1518typedef float zig_f128;
1519#define zig_as_f128(fp, repr) fp##f
1520#elif DBL_MANT_DIG == 113
1521typedef double zig_f128;
1522#define zig_as_f128(fp, repr) fp
1523#elif LDBL_MANT_DIG == 113
1524#define zig_bitSizeOf_c_longdouble 128
1525typedef long double zig_f128;
1526#define zig_as_f128(fp, repr) fp##l
1527#elif FLT128_MANT_DIG == 113
1528typedef _Float128 zig_f128;
1529#define zig_as_f128(fp, repr) fp##f128
1530#elif FLT64X_MANT_DIG == 113
1531typedef _Float64x zig_f128;
1532#define zig_as_f128(fp, repr) fp##f64x
1533#elif defined(__SIZEOF_FLOAT128__)
1534typedef __float128 zig_f128;
1535#define zig_as_f128(fp, repr) fp##q
1536#undef zig_as_special_f128
1537#define zig_as_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)
1538#else
1539#undef zig_has_f128
1540#define zig_has_f128 0
1541#define zig_repr_f128 i128
1542typedef zig_i128 zig_f128;
1543#define zig_as_f128(fp, repr) repr
1544#undef zig_as_special_f128
1545#define zig_as_special_f128(sign, name, arg, repr) repr
1546#endif
1547
1548#define zig_has_c_longdouble 1
1549typedef long double zig_c_longdouble;
1550#define zig_as_c_longdouble(fp, repr) fp##l
1551#define zig_libc_name_c_longdouble(name) name##l
1552#define zig_as_special_c_longdouble(sign, name, arg, repr) sign __builtin_##name##l(arg)
1553
1554#define zig_convert_builtin(ResType, operation, ArgType, version) \
1555 zig_extern_c zig_##ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
1556 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(zig_##ArgType);
1557zig_convert_builtin(f16, trunc, f32, 2)
1558zig_convert_builtin(f16, trunc, f64, 2)
1559zig_convert_builtin(f16, trunc, f80, 2)
1560zig_convert_builtin(f16, trunc, f128, 2)
1561zig_convert_builtin(f32, extend, f16, 2)
1562zig_convert_builtin(f32, trunc, f64, 2)
1563zig_convert_builtin(f32, trunc, f80, 2)
1564zig_convert_builtin(f32, trunc, f128, 2)
1565zig_convert_builtin(f64, extend, f16, 2)
1566zig_convert_builtin(f64, extend, f32, 2)
1567zig_convert_builtin(f64, trunc, f80, 2)
1568zig_convert_builtin(f64, trunc, f128, 2)
1569zig_convert_builtin(f80, extend, f16, 2)
1570zig_convert_builtin(f80, extend, f32, 2)
1571zig_convert_builtin(f80, extend, f64, 2)
1572zig_convert_builtin(f80, trunc, f128, 2)
1573zig_convert_builtin(f128, extend, f16, 2)
1574zig_convert_builtin(f128, extend, f32, 2)
1575zig_convert_builtin(f128, extend, f64, 2)
1576zig_convert_builtin(f128, extend, f80, 2)
1577
1578#define zig_float_negate_builtin_0(Type) \
1579 static inline zig_##Type zig_neg_##Type(zig_##Type arg) { \
1580 return zig_expand_concat(zig_xor_, zig_repr_##Type)(arg, zig_expand_minInt(zig_repr_##Type, zig_bitSizeOf_##Type)); \
1581 }
1582#define zig_float_negate_builtin_1(Type) \
1583 static inline zig_##Type zig_neg_##Type(zig_##Type arg) { \
1584 return -arg; \
1585 }
1586
1587#define zig_float_less_builtin_0(Type, operation) \
1588 zig_extern_c zig_i8 zig_expand_concat(zig_expand_concat(__##operation, \
1589 zig_compiler_rt_abbrev_##Type), 2)(zig_##Type, zig_##Type); \
1590 static inline zig_i8 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
1591 return (zig_i8)zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_##Type), 2)(lhs, rhs); \
1592 }
1593#define zig_float_less_builtin_1(Type, operation) \
1594 static inline zig_i8 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
1595 return (zig_i8)(!(lhs <= rhs) - (lhs < rhs)); \
1596 }
1597
1598#define zig_float_greater_builtin_0(Type, operation) \
1599 zig_float_less_builtin_0(Type, operation)
1600#define zig_float_greater_builtin_1(Type, operation) \
1601 static inline zig_i8 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
1602 return (zig_i8)((lhs > rhs) - !(lhs >= rhs)); \
1603 }
1604
1605#define zig_float_binary_builtin_0(Type, operation, operator) \
1606 zig_extern_c zig_##Type zig_expand_concat(zig_expand_concat(__##operation, \
1607 zig_compiler_rt_abbrev_##Type), 3)(zig_##Type, zig_##Type); \
1608 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
1609 return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_##Type), 3)(lhs, rhs); \
1610 }
1611#define zig_float_binary_builtin_1(Type, operation, operator) \
1612 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
1613 return lhs operator rhs; \
1614 }
14641615
14651616#define zig_float_builtins(Type) \
1466 zig_extern_c zig_##Type zig_builtin_##Type(sqrt)(zig_##Type); \
1467 zig_extern_c zig_##Type zig_builtin_##Type(sin)(zig_##Type); \
1468 zig_extern_c zig_##Type zig_builtin_##Type(cos)(zig_##Type); \
1469 zig_extern_c zig_##Type zig_builtin_##Type(tan)(zig_##Type); \
1470 zig_extern_c zig_##Type zig_builtin_##Type(exp)(zig_##Type); \
1471 zig_extern_c zig_##Type zig_builtin_##Type(exp2)(zig_##Type); \
1472 zig_extern_c zig_##Type zig_builtin_##Type(log)(zig_##Type); \
1473 zig_extern_c zig_##Type zig_builtin_##Type(log2)(zig_##Type); \
1474 zig_extern_c zig_##Type zig_builtin_##Type(log10)(zig_##Type); \
1475 zig_extern_c zig_##Type zig_builtin_##Type(fabs)(zig_##Type); \
1476 zig_extern_c zig_##Type zig_builtin_##Type(floor)(zig_##Type); \
1477 zig_extern_c zig_##Type zig_builtin_##Type(ceil)(zig_##Type); \
1478 zig_extern_c zig_##Type zig_builtin_##Type(round)(zig_##Type); \
1479 zig_extern_c zig_##Type zig_builtin_##Type(trunc)(zig_##Type); \
1480 zig_extern_c zig_##Type zig_builtin_##Type(fmod)(zig_##Type, zig_##Type); \
1481 zig_extern_c zig_##Type zig_builtin_##Type(fma)(zig_##Type, zig_##Type, zig_##Type); \
1617 zig_convert_builtin(i32, fix, Type, ) \
1618 zig_convert_builtin(u32, fixuns, Type, ) \
1619 zig_convert_builtin(i64, fix, Type, ) \
1620 zig_convert_builtin(u64, fixuns, Type, ) \
1621 zig_convert_builtin(i128, fix, Type, ) \
1622 zig_convert_builtin(u128, fixuns, Type, ) \
1623 zig_convert_builtin(Type, float, i32, ) \
1624 zig_convert_builtin(Type, floatun, u32, ) \
1625 zig_convert_builtin(Type, float, i64, ) \
1626 zig_convert_builtin(Type, floatun, u64, ) \
1627 zig_convert_builtin(Type, float, i128, ) \
1628 zig_convert_builtin(Type, floatun, u128, ) \
1629 zig_expand_concat(zig_float_negate_builtin_, zig_has_##Type)(Type) \
1630 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, cmp) \
1631 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, ne) \
1632 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, eq) \
1633 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, lt) \
1634 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, le) \
1635 zig_expand_concat(zig_float_greater_builtin_, zig_has_##Type)(Type, gt) \
1636 zig_expand_concat(zig_float_greater_builtin_, zig_has_##Type)(Type, ge) \
1637 zig_expand_concat(zig_float_binary_builtin_, zig_has_##Type)(Type, add, +) \
1638 zig_expand_concat(zig_float_binary_builtin_, zig_has_##Type)(Type, sub, -) \
1639 zig_expand_concat(zig_float_binary_builtin_, zig_has_##Type)(Type, mul, *) \
1640 zig_expand_concat(zig_float_binary_builtin_, zig_has_##Type)(Type, div, /) \
1641 zig_extern_c zig_##Type zig_libc_name_##Type(sqrt)(zig_##Type); \
1642 zig_extern_c zig_##Type zig_libc_name_##Type(sin)(zig_##Type); \
1643 zig_extern_c zig_##Type zig_libc_name_##Type(cos)(zig_##Type); \
1644 zig_extern_c zig_##Type zig_libc_name_##Type(tan)(zig_##Type); \
1645 zig_extern_c zig_##Type zig_libc_name_##Type(exp)(zig_##Type); \
1646 zig_extern_c zig_##Type zig_libc_name_##Type(exp2)(zig_##Type); \
1647 zig_extern_c zig_##Type zig_libc_name_##Type(log)(zig_##Type); \
1648 zig_extern_c zig_##Type zig_libc_name_##Type(log2)(zig_##Type); \
1649 zig_extern_c zig_##Type zig_libc_name_##Type(log10)(zig_##Type); \
1650 zig_extern_c zig_##Type zig_libc_name_##Type(fabs)(zig_##Type); \
1651 zig_extern_c zig_##Type zig_libc_name_##Type(floor)(zig_##Type); \
1652 zig_extern_c zig_##Type zig_libc_name_##Type(ceil)(zig_##Type); \
1653 zig_extern_c zig_##Type zig_libc_name_##Type(round)(zig_##Type); \
1654 zig_extern_c zig_##Type zig_libc_name_##Type(trunc)(zig_##Type); \
1655 zig_extern_c zig_##Type zig_libc_name_##Type(fmod)(zig_##Type, zig_##Type); \
1656 zig_extern_c zig_##Type zig_libc_name_##Type(fmin)(zig_##Type, zig_##Type); \
1657 zig_extern_c zig_##Type zig_libc_name_##Type(fmax)(zig_##Type, zig_##Type); \
1658 zig_extern_c zig_##Type zig_libc_name_##Type(fma)(zig_##Type, zig_##Type, zig_##Type); \
14821659\
14831660 static inline zig_##Type zig_div_trunc_##Type(zig_##Type lhs, zig_##Type rhs) { \
1484 return zig_builtin_##Type(trunc)(lhs / rhs); \
1661 return zig_libc_name_##Type(trunc)(zig_div_##Type(lhs, rhs)); \
14851662 } \
14861663\
14871664 static inline zig_##Type zig_div_floor_##Type(zig_##Type lhs, zig_##Type rhs) { \
1488 return zig_builtin_##Type(floor)(lhs / rhs); \
1665 return zig_libc_name_##Type(floor)(zig_div_##Type(lhs, rhs)); \
14891666 } \
14901667\
14911668 static inline zig_##Type zig_mod_##Type(zig_##Type lhs, zig_##Type rhs) { \
1492 return lhs - zig_div_floor_##Type(lhs, rhs) * rhs; \
1669 return zig_sub_##Type(lhs, zig_mul_##Type(zig_div_floor_##Type(lhs, rhs), rhs)); \
14931670 }
14941671zig_float_builtins(f16)
14951672zig_float_builtins(f32)
lib/std/start.zig+9-1
......@@ -281,7 +281,15 @@ fn _start() callconv(.Naked) noreturn {
281281 \\ andl $-16, %%esp
282282 \\ jmp _posixCallMainAndExit
283283 ),
284 .aarch64, .aarch64_be, .arm, .armeb, .thumb => asm volatile (
284 .aarch64, .aarch64_be => asm volatile (
285 \\ mov fp, #0
286 \\ mov lr, #0
287 \\ mov x0, sp
288 \\ adrp x1, argc_argv_ptr
289 \\ str x0, [x1, :lo12:argc_argv_ptr]
290 \\ b _posixCallMainAndExit
291 ),
292 .arm, .armeb, .thumb => asm volatile (
285293 \\ mov fp, #0
286294 \\ mov lr, #0
287295 \\ str sp, argc_argv_ptr
lib/test_runner.zig+2-1
......@@ -130,7 +130,8 @@ pub fn main2() anyerror!void {
130130 }
131131 if (builtin.zig_backend == .stage2_wasm or
132132 builtin.zig_backend == .stage2_x86_64 or
133 builtin.zig_backend == .stage2_llvm)
133 builtin.zig_backend == .stage2_llvm or
134 builtin.zig_backend == .stage2_c)
134135 {
135136 const passed = builtin.test_functions.len - skipped - failed;
136137 const stderr = std.io.getStdErr();
src/codegen/c.zig+201-91
......@@ -19,6 +19,7 @@ const Liveness = @import("../Liveness.zig");
1919const CType = @import("../type.zig").CType;
2020
2121const Mutability = enum { Const, ConstArgument, Mut };
22const BigIntLimb = std.math.big.Limb;
2223const BigInt = std.math.big.int;
2324
2425pub const CValue = union(enum) {
......@@ -608,19 +609,25 @@ pub const DeclGen = struct {
608609 .Bool => return dg.renderValue(writer, ty, Value.@"false", location),
609610 .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}),
610611 .Float => {
612 const bits = ty.floatBits(target);
613 var int_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits };
614 const int_ty = Type.initPayload(&int_pl.base);
615
611616 try writer.writeByte('(');
612617 try dg.renderTypecast(writer, ty);
613 try writer.writeAll(")zig_suffix_");
618 try writer.writeAll(")zig_as_");
614619 try dg.renderTypeForBuiltinFnName(writer, ty);
615620 try writer.writeByte('(');
616 switch (ty.floatBits(target)) {
617 16 => try writer.print("{x}", .{@bitCast(f16, undefPattern(u16))}),
618 32 => try writer.print("{x}", .{@bitCast(f32, undefPattern(u32))}),
619 64 => try writer.print("{x}", .{@bitCast(f64, undefPattern(u64))}),
620 80 => try writer.print("{x}", .{@bitCast(f80, undefPattern(u80))}),
621 128 => try writer.print("{x}", .{@bitCast(f128, undefPattern(u128))}),
621 switch (bits) {
622 16 => try writer.print("{x}", .{@bitCast(f16, undefPattern(i16))}),
623 32 => try writer.print("{x}", .{@bitCast(f32, undefPattern(i32))}),
624 64 => try writer.print("{x}", .{@bitCast(f64, undefPattern(i64))}),
625 80 => try writer.print("{x}", .{@bitCast(f80, undefPattern(i80))}),
626 128 => try writer.print("{x}", .{@bitCast(f128, undefPattern(i128))}),
622627 else => unreachable,
623628 }
629 try writer.writeAll(", ");
630 try dg.renderValue(writer, int_ty, Value.undef, .FunctionArgument);
624631 return writer.writeByte(')');
625632 },
626633 .Pointer => if (ty.isSlice()) {
......@@ -770,21 +777,48 @@ pub const DeclGen = struct {
770777 else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val)}),
771778 },
772779 .Float => {
780 const bits = ty.floatBits(target);
781 const f128_val = val.toFloat(f128);
782
783 var int_ty_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits };
784 const int_ty = Type.initPayload(&int_ty_pl.base);
785
786 assert(bits <= 128);
787 var int_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;
788 var int_val_big = BigInt.Mutable{
789 .limbs = &int_val_limbs,
790 .len = undefined,
791 .positive = undefined,
792 };
793
794 switch (bits) {
795 16 => int_val_big.set(@bitCast(i16, val.toFloat(f16))),
796 32 => int_val_big.set(@bitCast(i32, val.toFloat(f32))),
797 64 => int_val_big.set(@bitCast(i64, val.toFloat(f64))),
798 80 => int_val_big.set(@bitCast(i80, val.toFloat(f80))),
799 128 => int_val_big.set(@bitCast(i128, f128_val)),
800 else => unreachable,
801 }
802
803 var int_val_pl = Value.Payload.BigInt{
804 .base = .{ .tag = if (int_val_big.positive) .int_big_positive else .int_big_negative },
805 .data = int_val_big.limbs[0..int_val_big.len],
806 };
807 const int_val = Value.initPayload(&int_val_pl.base);
808
773809 try writer.writeByte('(');
774810 try dg.renderTypecast(writer, ty);
775811 try writer.writeByte(')');
776 const f128_val = val.toFloat(f128);
777 if (std.math.signbit(f128_val)) try writer.writeByte('-');
778812 if (std.math.isFinite(f128_val)) {
779 try writer.writeAll("zig_suffix_");
813 try writer.writeAll("zig_as_");
780814 try dg.renderTypeForBuiltinFnName(writer, ty);
781815 try writer.writeByte('(');
782 switch (ty.floatBits(target)) {
783 16 => try writer.print("{x}", .{@fabs(val.toFloat(f16))}),
784 32 => try writer.print("{x}", .{@fabs(val.toFloat(f32))}),
785 64 => try writer.print("{x}", .{@fabs(val.toFloat(f64))}),
786 80 => try writer.print("{x}", .{@fabs(val.toFloat(f80))}),
787 128 => try writer.print("{x}", .{@fabs(f128_val)}),
816 switch (bits) {
817 16 => try writer.print("{x}", .{val.toFloat(f16)}),
818 32 => try writer.print("{x}", .{val.toFloat(f32)}),
819 64 => try writer.print("{x}", .{val.toFloat(f64)}),
820 80 => try writer.print("{x}", .{val.toFloat(f80)}),
821 128 => try writer.print("{x}", .{f128_val}),
788822 else => unreachable,
789823 }
790824 } else {
......@@ -796,23 +830,26 @@ pub const DeclGen = struct {
796830 "inf"
797831 else
798832 unreachable;
799 try writer.writeAll("zig_builtin_constant_");
833
834 try writer.writeAll("zig_as_special_");
800835 try dg.renderTypeForBuiltinFnName(writer, ty);
801836 try writer.writeByte('(');
837 if (std.math.signbit(f128_val)) try writer.writeByte('-');
838 try writer.writeAll(", ");
802839 try writer.writeAll(operation);
803 try writer.writeAll(")(");
804 if (std.math.isNan(f128_val)) switch (ty.floatBits(target)) {
840 try writer.writeAll(", ");
841 if (std.math.isNan(f128_val)) switch (bits) {
805842 // We only actually need to pass the significand, but it will get
806843 // properly masked anyway, so just pass the whole value.
807 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, @fabs(val.toFloat(f16)))}),
808 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, @fabs(val.toFloat(f32)))}),
809 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, @fabs(val.toFloat(f64)))}),
810 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, @fabs(val.toFloat(f80)))}),
811 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, @fabs(f128_val))}),
844 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, val.toFloat(f16))}),
845 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, val.toFloat(f32))}),
846 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, val.toFloat(f64))}),
847 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, val.toFloat(f80))}),
848 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}),
812849 else => unreachable,
813850 };
814851 }
815 return writer.writeByte(')');
852 return writer.print(", {x})", .{try dg.fmtIntLiteral(int_ty, int_val)});
816853 },
817854 .Pointer => switch (val.tag()) {
818855 .null_value, .zero => if (ty.isSlice()) {
......@@ -2299,11 +2336,14 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
22992336
23002337 // TODO use a different strategy for add, sub, mul, div
23012338 // that communicates to the optimizer that wrapping is UB.
2302 .add => try airBinOp(f, inst, "+", "add", .None),
2303 .sub => try airBinOp(f, inst, "-", "sub", .None),
2304 .mul => try airBinOp(f, inst, "*", "mul", .None),
2305 .div_float, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None),
2339 .add => try airBinOp(f, inst, "+", "add", .None),
2340 .sub => try airBinOp(f, inst, "-", "sub", .None),
2341 .mul => try airBinOp(f, inst, "*", "mul", .None),
2342
2343 .neg => try airFloatNeg(f, inst),
2344 .div_float => try airBinBuiltinCall(f, inst, "div", .None),
23062345
2346 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None),
23072347 .rem => blk: {
23082348 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
23092349 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
23142354 else
23152355 try airBinFloatOp(f, inst, "fmod");
23162356 },
2317 .div_trunc => blk: {
2318 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2319 const lhs_ty = f.air.typeOf(bin_op.lhs);
2320 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
2321 // so we only check one.
2322 break :blk if (lhs_ty.isInt())
2323 try airBinOp(f, inst, "/", "div_trunc", .None)
2324 else
2325 try airBinBuiltinCall(f, inst, "div_trunc", .None);
2326 },
23272357 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None),
23282358 .mod => try airBinBuiltinCall(f, inst, "mod", .None),
23292359
......@@ -2336,8 +2366,6 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
23362366 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits),
23372367 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits),
23382368
2339 .neg => try airNeg(f, inst),
2340
23412369 .sqrt,
23422370 .sin,
23432371 .cos,
......@@ -2361,18 +2389,18 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
23612389 .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits),
23622390 .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits),
23632391
2364 .min => try airMinMax(f, inst, '<'),
2365 .max => try airMinMax(f, inst, '>'),
2392 .min => try airMinMax(f, inst, '<', "fmin"),
2393 .max => try airMinMax(f, inst, '>', "fmax"),
23662394
23672395 .slice => try airSlice(f, inst),
23682396
2369 .cmp_gt => try airCmpOp(f, inst, ">"),
2370 .cmp_gte => try airCmpOp(f, inst, ">="),
2371 .cmp_lt => try airCmpOp(f, inst, "<"),
2372 .cmp_lte => try airCmpOp(f, inst, "<="),
2397 .cmp_gt => try airCmpOp(f, inst, ">", "gt"),
2398 .cmp_gte => try airCmpOp(f, inst, ">=", "ge"),
2399 .cmp_lt => try airCmpOp(f, inst, "<", "lt"),
2400 .cmp_lte => try airCmpOp(f, inst, "<=", "le"),
23732401
2374 .cmp_eq => try airEquality(f, inst, "((", "=="),
2375 .cmp_neq => try airEquality(f, inst, "!((", "!="),
2402 .cmp_eq => try airEquality(f, inst, "((", "==", "eq"),
2403 .cmp_neq => try airEquality(f, inst, "!((", "!=", "ne"),
23762404
23772405 .cmp_vector => return f.fail("TODO: C backend: implement cmp_vector", .{}),
23782406 .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst),
......@@ -2468,7 +2496,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
24682496 .float_to_int,
24692497 .fptrunc,
24702498 .fpext,
2471 => try airSimpleCast(f, inst),
2499 => try airFloatCast(f, inst),
24722500
24732501 .ptrtoint => try airPtrToInt(f, inst),
24742502
......@@ -2973,8 +3001,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
29733001
29743002 const src_bits = src_ty.bitSize(target);
29753003
2976 const Limb = std.math.big.Limb;
2977 const ExpectedContents = [BigInt.Managed.default_capacity]Limb;
3004 const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb;
29783005 var stack align(@alignOf(ExpectedContents)) =
29793006 std.heap.stackFallback(@sizeOf(ExpectedContents), f.object.dg.gpa);
29803007
......@@ -3003,6 +3030,11 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
30033030 try writer.writeAll("((");
30043031 try f.renderTypecast(writer, host_ty);
30053032 try writer.writeByte(')');
3033 if (src_ty.isPtrAtRuntime()) {
3034 try writer.writeByte('(');
3035 try f.renderTypecast(writer, Type.usize);
3036 try writer.writeByte(')');
3037 }
30063038 try f.writeCValue(writer, src_val, .Other);
30073039 try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)});
30083040 } else {
......@@ -3081,7 +3113,7 @@ fn airBinOp(
30813113
30823114 const operand_ty = f.air.typeOf(bin_op.lhs);
30833115 const target = f.object.dg.module.getTarget();
3084 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)
3116 if ((operand_ty.isInt() and operand_ty.bitSize(target) > 64) or operand_ty.isRuntimeFloat())
30853117 return try airBinBuiltinCall(f, inst, operation, info);
30863118
30873119 const inst_ty = f.air.typeOfIndex(inst);
......@@ -3102,7 +3134,7 @@ fn airBinOp(
31023134 return local;
31033135}
31043136
3105fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue {
3137fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: []const u8) !CValue {
31063138 if (f.liveness.isUnused(inst)) return CValue.none;
31073139
31083140 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 {
31103142 const operand_ty = f.air.typeOf(bin_op.lhs);
31113143 const target = f.object.dg.module.getTarget();
31123144 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)
3113 return try airCmpBuiltinCall(f, inst, operator);
3145 return try airCmpBuiltinCall(f, inst, operator, "cmp");
3146 if (operand_ty.isRuntimeFloat())
3147 return try airCmpBuiltinCall(f, inst, operator, operation);
31143148
31153149 const inst_ty = f.air.typeOfIndex(inst);
31163150 const lhs = try f.resolveInst(bin_op.lhs);
......@@ -3134,11 +3168,20 @@ fn airEquality(
31343168 f: *Function,
31353169 inst: Air.Inst.Index,
31363170 negate_prefix: []const u8,
3137 eq_op_str: []const u8,
3171 operator: []const u8,
3172 operation: []const u8,
31383173) !CValue {
31393174 if (f.liveness.isUnused(inst)) return CValue.none;
31403175
31413176 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3177
3178 const operand_ty = f.air.typeOf(bin_op.lhs);
3179 const target = f.object.dg.module.getTarget();
3180 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)
3181 return try airCmpBuiltinCall(f, inst, operator, "cmp");
3182 if (operand_ty.isRuntimeFloat())
3183 return try airCmpBuiltinCall(f, inst, operator, operation);
3184
31423185 const lhs = try f.resolveInst(bin_op.lhs);
31433186 const rhs = try f.resolveInst(bin_op.rhs);
31443187
......@@ -3148,8 +3191,7 @@ fn airEquality(
31483191
31493192 try writer.writeAll(" = ");
31503193
3151 const lhs_ty = f.air.typeOf(bin_op.lhs);
3152 if (lhs_ty.tag() == .optional) {
3194 if (operand_ty.tag() == .optional) {
31533195 // (A && B) || (C && (A == B))
31543196 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload
31553197
......@@ -3172,7 +3214,7 @@ fn airEquality(
31723214
31733215 try f.writeCValue(writer, lhs, .Other);
31743216 try writer.writeByte(' ');
3175 try writer.writeAll(eq_op_str);
3217 try writer.writeAll(operator);
31763218 try writer.writeByte(' ');
31773219 try f.writeCValue(writer, rhs, .Other);
31783220 try writer.writeAll(";\n");
......@@ -3231,15 +3273,22 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
32313273 return local;
32323274}
32333275
3234fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
3276fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue {
32353277 if (f.liveness.isUnused(inst)) return CValue.none;
32363278
32373279 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3280
3281 const inst_ty = f.air.typeOfIndex(inst);
3282 const target = f.object.dg.module.getTarget();
3283 if (inst_ty.isInt() and inst_ty.bitSize(target) > 64)
3284 return try airBinBuiltinCall(f, inst, operation[1..], .None);
3285 if (inst_ty.isRuntimeFloat())
3286 return try airBinFloatOp(f, inst, operation);
3287
32383288 const lhs = try f.resolveInst(bin_op.lhs);
32393289 const rhs = try f.resolveInst(bin_op.rhs);
32403290
32413291 const writer = f.object.writer();
3242 const inst_ty = f.air.typeOfIndex(inst);
32433292 const local = try f.allocLocal(inst_ty, .Const);
32443293
32453294 // (lhs <> rhs) ? lhs : rhs
......@@ -4518,19 +4567,44 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
45184567 return local;
45194568}
45204569
4521/// Emits a local variable with the result type and initializes it
4522/// with the operand.
4523fn airSimpleCast(f: *Function, inst: Air.Inst.Index) !CValue {
4570fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
45244571 if (f.liveness.isUnused(inst)) return CValue.none;
45254572
45264573 const inst_ty = f.air.typeOfIndex(inst);
4527 const local = try f.allocLocal(inst_ty, .Const);
45284574 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
4529 const writer = f.object.writer();
45304575 const operand = try f.resolveInst(ty_op.operand);
4576 const operand_ty = f.air.typeOf(ty_op.operand);
4577 const target = f.object.dg.module.getTarget();
4578 const operation = if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat())
4579 if (inst_ty.floatBits(target) < operand_ty.floatBits(target)) "trunc" else "extend"
4580 else if (inst_ty.isInt() and operand_ty.isRuntimeFloat())
4581 if (inst_ty.isSignedInt()) "fix" else "fixuns"
4582 else if (inst_ty.isRuntimeFloat() and operand_ty.isInt())
4583 if (operand_ty.isSignedInt()) "float" else "floatun"
4584 else
4585 unreachable;
4586
4587 const local = try f.allocLocal(inst_ty, .Const);
4588 const writer = f.object.writer();
45314589
45324590 try writer.writeAll(" = ");
4533 try f.writeCValue(writer, operand, .Other);
4591 if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) {
4592 try writer.writeAll("zig_wrap_");
4593 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
4594 try writer.writeByte('(');
4595 }
4596 try writer.writeAll("__");
4597 try writer.writeAll(operation);
4598 try writer.writeAll(compilerRtAbbrev(operand_ty, target));
4599 try writer.writeAll(compilerRtAbbrev(inst_ty, target));
4600 if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat()) try writer.writeByte('2');
4601 try writer.writeByte('(');
4602 try f.writeCValue(writer, operand, .FunctionArgument);
4603 try writer.writeByte(')');
4604 if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) {
4605 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits);
4606 try writer.writeByte(')');
4607 }
45344608 try writer.writeAll(";\n");
45354609 return local;
45364610}
......@@ -4604,7 +4678,12 @@ fn airBinBuiltinCall(
46044678 return local;
46054679}
46064680
4607fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue {
4681fn airCmpBuiltinCall(
4682 f: *Function,
4683 inst: Air.Inst.Index,
4684 operator: []const u8,
4685 operation: []const u8,
4686) !CValue {
46084687 if (f.liveness.isUnused(inst)) return CValue.none;
46094688
46104689 const inst_ty = f.air.typeOfIndex(inst);
......@@ -4613,7 +4692,9 @@ fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) !
46134692
46144693 const local = try f.allocLocal(inst_ty, .Const);
46154694 const writer = f.object.writer();
4616 try writer.writeAll(" = zig_cmp_");
4695 try writer.writeAll(" = zig_");
4696 try writer.writeAll(operation);
4697 try writer.writeByte('_');
46174698 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
46184699 try writer.writeByte('(');
46194700 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);
......@@ -5045,6 +5126,14 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
50455126 try writer.writeAll("((");
50465127 try f.renderTypecast(writer, inst_ty);
50475128 try writer.writeByte(')');
5129 if (field_ty.isPtrAtRuntime()) {
5130 try writer.writeByte('(');
5131 try f.renderTypecast(writer, switch (int_info.signedness) {
5132 .unsigned => Type.usize,
5133 .signed => Type.isize,
5134 });
5135 try writer.writeByte(')');
5136 }
50485137 try f.writeCValue(writer, try f.resolveInst(element), .Other);
50495138 try writer.writeAll(", ");
50505139 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 {
51575246 return local;
51585247}
51595248
5160fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue {
5249fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
51615250 if (f.liveness.isUnused(inst)) return CValue.none;
51625251
5163 const un_op = f.air.instructions.items(.data)[inst].un_op;
5164 const writer = f.object.writer();
51655252 const inst_ty = f.air.typeOfIndex(inst);
5253 const un_op = f.air.instructions.items(.data)[inst].un_op;
51665254 const operand = try f.resolveInst(un_op);
5255 const operand_ty = f.air.typeOf(un_op);
5256
51675257 const local = try f.allocLocal(inst_ty, .Const);
5168 try writer.writeAll(" = -");
5169 try f.writeCValue(writer, operand, .Other);
5170 try writer.writeAll(";\n");
5258 const writer = f.object.writer();
5259 try writer.writeAll(" = zig_neg_");
5260 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
5261 try writer.writeByte('(');
5262 try f.writeCValue(writer, operand, .FunctionArgument);
5263 try writer.writeAll(");\n");
51715264 return local;
51725265}
51735266
......@@ -5178,7 +5271,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
51785271 const inst_ty = f.air.typeOfIndex(inst);
51795272 const operand = try f.resolveInst(un_op);
51805273 const local = try f.allocLocal(inst_ty, .Const);
5181 try writer.writeAll(" = zig_builtin_");
5274 try writer.writeAll(" = zig_libc_name_");
51825275 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
51835276 try writer.writeByte('(');
51845277 try writer.writeAll(operation);
......@@ -5196,7 +5289,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
51965289 const lhs = try f.resolveInst(bin_op.lhs);
51975290 const rhs = try f.resolveInst(bin_op.rhs);
51985291 const local = try f.allocLocal(inst_ty, .Const);
5199 try writer.writeAll(" = zig_builtin_");
5292 try writer.writeAll(" = zig_libc_name_");
52005293 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
52015294 try writer.writeByte('(');
52025295 try writer.writeAll(operation);
......@@ -5218,7 +5311,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
52185311 const addend = try f.resolveInst(pl_op.operand);
52195312 const writer = f.object.writer();
52205313 const local = try f.allocLocal(inst_ty, .Const);
5221 try writer.writeAll(" = zig_builtin_");
5314 try writer.writeAll(" = zig_libc_name_");
52225315 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
52235316 try writer.writeAll("(fma)(");
52245317 try f.writeCValue(writer, mulend1, .FunctionArgument);
......@@ -5328,6 +5421,22 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 {
53285421 };
53295422}
53305423
5424fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 {
5425 return if (ty.isInt()) switch (ty.intInfo(target).bits) {
5426 1...32 => "si",
5427 33...64 => "di",
5428 65...128 => "ti",
5429 else => unreachable,
5430 } else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) {
5431 16 => "hf",
5432 32 => "sf",
5433 64 => "df",
5434 80 => "xf",
5435 128 => "tf",
5436 else => unreachable,
5437 } else unreachable;
5438}
5439
53315440fn formatStringLiteral(
53325441 str: []const u8,
53335442 comptime fmt: []const u8,
......@@ -5356,8 +5465,10 @@ fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) {
53565465 return .{ .data = str };
53575466}
53585467
5359fn undefPattern(comptime T: type) T {
5360 return (1 << (@bitSizeOf(T) | 1)) / 3;
5468fn undefPattern(comptime IntType: type) IntType {
5469 const int_info = @typeInfo(IntType).Int;
5470 const UnsignedType = std.meta.Int(.unsigned, int_info.bits);
5471 return @bitCast(IntType, @as(UnsignedType, (1 << (int_info.bits | 1)) / 3));
53615472}
53625473
53635474const FormatIntLiteralContext = struct {
......@@ -5374,30 +5485,29 @@ fn formatIntLiteral(
53745485 const target = data.mod.getTarget();
53755486 const int_info = data.ty.intInfo(target);
53765487
5377 const Limb = std.math.big.Limb;
53785488 const ExpectedContents = struct {
53795489 const base = 10;
53805490 const limbs_count_128 = BigInt.calcTwosCompLimbCount(128);
53815491 const expected_needed_limbs_count = BigInt.calcToStringLimbsBufferLen(limbs_count_128, base);
53825492 const worst_case_int = BigInt.Const{
5383 .limbs = &([1]Limb{std.math.maxInt(Limb)} ** expected_needed_limbs_count),
5493 .limbs = &([1]BigIntLimb{std.math.maxInt(BigIntLimb)} ** expected_needed_limbs_count),
53845494 .positive = false,
53855495 };
53865496
5387 undef_limbs: [limbs_count_128]Limb,
5388 wrap_limbs: [limbs_count_128]Limb,
5497 undef_limbs: [limbs_count_128]BigIntLimb,
5498 wrap_limbs: [limbs_count_128]BigIntLimb,
53895499 };
53905500 var stack align(@alignOf(ExpectedContents)) =
53915501 std.heap.stackFallback(@sizeOf(ExpectedContents), data.mod.gpa);
53925502 const allocator = stack.get();
53935503
5394 var undef_limbs: []Limb = &.{};
5504 var undef_limbs: []BigIntLimb = &.{};
53955505 defer allocator.free(undef_limbs);
53965506
53975507 var int_buf: Value.BigIntSpace = undefined;
53985508 const int = if (data.val.isUndefDeep()) blk: {
5399 undef_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(int_info.bits));
5400 std.mem.set(Limb, undef_limbs, undefPattern(Limb));
5509 undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(int_info.bits));
5510 std.mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb));
54015511
54025512 var undef_int = BigInt.Mutable{
54035513 .limbs = undef_limbs,
......@@ -5410,10 +5520,10 @@ fn formatIntLiteral(
54105520 assert(int.fitsInTwosComp(int_info.signedness, int_info.bits));
54115521
54125522 const c_bits = toCIntBits(int_info.bits) orelse unreachable;
5413 var one_limbs: [BigInt.calcLimbLen(1)]Limb = undefined;
5523 var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined;
54145524 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
54155525
5416 const wrap_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(c_bits));
5526 const wrap_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits));
54175527 defer allocator.free(wrap_limbs);
54185528 var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined };
54195529 if (wrap.addWrap(int, one, int_info.signedness, c_bits) or
......@@ -5439,7 +5549,7 @@ fn formatIntLiteral(
54395549 else => try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }),
54405550 }
54415551
5442 const limbs_count_64 = @divExact(64, @bitSizeOf(Limb));
5552 const limbs_count_64 = @divExact(64, @bitSizeOf(BigIntLimb));
54435553 if (c_bits <= 64) {
54445554 var base: u8 = undefined;
54455555 var case: std.fmt.Case = undefined;
......@@ -5471,7 +5581,7 @@ fn formatIntLiteral(
54715581 }
54725582
54735583 var str: [64]u8 = undefined;
5474 var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]Limb = undefined;
5584 var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]BigIntLimb = undefined;
54755585 try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]);
54765586 } else {
54775587 assert(c_bits == 128);
test/behavior/atomics.zig+10-2
......@@ -220,8 +220,8 @@ test "atomicrmw with floats" {
220220 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
221221 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
222222
223 if ((builtin.zig_backend == .stage1 or builtin.zig_backend == .stage2_llvm) and
224 builtin.cpu.arch == .aarch64)
223 if ((builtin.zig_backend == .stage1 or builtin.zig_backend == .stage2_llvm or
224 builtin.zig_backend == .stage2_c) and builtin.cpu.arch == .aarch64)
225225 {
226226 // https://github.com/ziglang/zig/issues/10627
227227 return error.SkipZigTest;
......@@ -248,6 +248,10 @@ test "atomicrmw with ints" {
248248 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
249249 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
250250
251 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .aarch64) {
252 return error.SkipZigTest;
253 }
254
251255 try testAtomicRmwInt();
252256 comptime try testAtomicRmwInt();
253257}
......@@ -282,6 +286,10 @@ test "atomics with different types" {
282286 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
283287 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
284288
289 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .aarch64) {
290 return error.SkipZigTest;
291 }
292
285293 try testAtomicsWithType(bool, true, false);
286294
287295 try testAtomicsWithType(u1, 0, 1);
test/tests.zig-4
......@@ -678,10 +678,6 @@ pub fn addPkgTests(
678678 // https://github.com/ziglang/zig/issues/12415
679679 continue;
680680 }
681 if (backend == .stage2_c and builtin.cpu.arch == .aarch64) {
682 // https://github.com/ziglang/zig/issues/13357
683 continue;
684 }
685681 }
686682
687683 const libc_prefix = if (test_target.target.getOs().requiresLibC())