authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-05 14:48:06-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-03-05 14:48:06-05:00
log7b01af2bfd4cf9232fb0157c26d7c59642452fab
tree733810a59ad5a4177198d60b9058e2951567a94a
parenta63134a4a56e8683aeee292b641b4e943cbfb999
parent1efd36cd5c9a1128ae702b081d60ee32f21bc258
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #14745 from jacobly0/bigint

CBE: add support for integers larger than 128 bits (and apparently vectors too)

21 files changed, 2445 insertions(+), 857 deletions(-)

lib/std/math/big/int.zig+1
......@@ -1674,6 +1674,7 @@ pub const Mutable = struct {
16741674
16751675 /// If a is positive, this passes through to truncate.
16761676 /// If a is negative, then r is set to positive with the bit pattern ~(a - 1).
1677 /// r may alias a.
16771678 ///
16781679 /// Asserts `r` has enough storage to store the result.
16791680 /// The upper bound is `calcTwosCompLimbCount(a.len)`.
lib/zig.h+1035-212
......@@ -37,6 +37,14 @@ typedef char bool;
3737#define zig_has_attribute(attribute) 0
3838#endif
3939
40#if __LITTLE_ENDIAN__ || _MSC_VER
41#define zig_little_endian 1
42#define zig_big_endian 0
43#else
44#define zig_little_endian 0
45#define zig_big_endian 1
46#endif
47
4048#if __STDC_VERSION__ >= 201112L
4149#define zig_threadlocal _Thread_local
4250#elif defined(__GNUC__)
......@@ -604,12 +612,6 @@ static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8
604612#endif
605613}
606614
607static inline void zig_vaddo_u32(uint8_t *ov, uint32_t *res, int n,
608 const uint32_t *lhs, const uint32_t *rhs, uint8_t bits)
609{
610 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u32(&res[i], lhs[i], rhs[i], bits);
611}
612
613615zig_extern int32_t __addosi4(int32_t lhs, int32_t rhs, int *overflow);
614616static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
615617#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
......@@ -624,12 +626,6 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
624626 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
625627}
626628
627static inline void zig_vaddo_i32(uint8_t *ov, int32_t *res, int n,
628 const int32_t *lhs, const int32_t *rhs, uint8_t bits)
629{
630 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i32(&res[i], lhs[i], rhs[i], bits);
631}
632
633629static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
634630#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
635631 uint64_t full_res;
......@@ -642,12 +638,6 @@ static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
642638#endif
643639}
644640
645static inline void zig_vaddo_u64(uint8_t *ov, uint64_t *res, int n,
646 const uint64_t *lhs, const uint64_t *rhs, uint8_t bits)
647{
648 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u64(&res[i], lhs[i], rhs[i], bits);
649}
650
651641zig_extern int64_t __addodi4(int64_t lhs, int64_t rhs, int *overflow);
652642static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
653643#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
......@@ -662,12 +652,6 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
662652 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
663653}
664654
665static inline void zig_vaddo_i64(uint8_t *ov, int64_t *res, int n,
666 const int64_t *lhs, const int64_t *rhs, uint8_t bits)
667{
668 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i64(&res[i], lhs[i], rhs[i], bits);
669}
670
671655static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
672656#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
673657 uint8_t full_res;
......@@ -682,12 +666,6 @@ static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b
682666#endif
683667}
684668
685static inline void zig_vaddo_u8(uint8_t *ov, uint8_t *res, int n,
686 const uint8_t *lhs, const uint8_t *rhs, uint8_t bits)
687{
688 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u8(&res[i], lhs[i], rhs[i], bits);
689}
690
691669static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) {
692670#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
693671 int8_t full_res;
......@@ -702,12 +680,6 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
702680#endif
703681}
704682
705static inline void zig_vaddo_i8(uint8_t *ov, int8_t *res, int n,
706 const int8_t *lhs, const int8_t *rhs, uint8_t bits)
707{
708 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i8(&res[i], lhs[i], rhs[i], bits);
709}
710
711683static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) {
712684#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
713685 uint16_t full_res;
......@@ -722,12 +694,6 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
722694#endif
723695}
724696
725static inline void zig_vaddo_u16(uint8_t *ov, uint16_t *res, int n,
726 const uint16_t *lhs, const uint16_t *rhs, uint8_t bits)
727{
728 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u16(&res[i], lhs[i], rhs[i], bits);
729}
730
731697static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) {
732698#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
733699 int16_t full_res;
......@@ -742,12 +708,6 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
742708#endif
743709}
744710
745static inline void zig_vaddo_i16(uint8_t *ov, int16_t *res, int n,
746 const int16_t *lhs, const int16_t *rhs, uint8_t bits)
747{
748 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i16(&res[i], lhs[i], rhs[i], bits);
749}
750
751711static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
752712#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
753713 uint32_t full_res;
......@@ -760,12 +720,6 @@ static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8
760720#endif
761721}
762722
763static inline void zig_vsubo_u32(uint8_t *ov, uint32_t *res, int n,
764 const uint32_t *lhs, const uint32_t *rhs, uint8_t bits)
765{
766 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u32(&res[i], lhs[i], rhs[i], bits);
767}
768
769723zig_extern int32_t __subosi4(int32_t lhs, int32_t rhs, int *overflow);
770724static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
771725#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
......@@ -780,12 +734,6 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
780734 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
781735}
782736
783static inline void zig_vsubo_i32(uint8_t *ov, int32_t *res, int n,
784 const int32_t *lhs, const int32_t *rhs, uint8_t bits)
785{
786 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i32(&res[i], lhs[i], rhs[i], bits);
787}
788
789737static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
790738#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
791739 uint64_t full_res;
......@@ -798,12 +746,6 @@ static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
798746#endif
799747}
800748
801static inline void zig_vsubo_u64(uint8_t *ov, uint64_t *res, int n,
802 const uint64_t *lhs, const uint64_t *rhs, uint8_t bits)
803{
804 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u64(&res[i], lhs[i], rhs[i], bits);
805}
806
807749zig_extern int64_t __subodi4(int64_t lhs, int64_t rhs, int *overflow);
808750static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
809751#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
......@@ -818,12 +760,6 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
818760 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
819761}
820762
821static inline void zig_vsubo_i64(uint8_t *ov, int64_t *res, int n,
822 const int64_t *lhs, const int64_t *rhs, uint8_t bits)
823{
824 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i64(&res[i], lhs[i], rhs[i], bits);
825}
826
827763static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
828764#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
829765 uint8_t full_res;
......@@ -838,12 +774,6 @@ static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b
838774#endif
839775}
840776
841static inline void zig_vsubo_u8(uint8_t *ov, uint8_t *res, int n,
842 const uint8_t *lhs, const uint8_t *rhs, uint8_t bits)
843{
844 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u8(&res[i], lhs[i], rhs[i], bits);
845}
846
847777static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) {
848778#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
849779 int8_t full_res;
......@@ -858,13 +788,6 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
858788#endif
859789}
860790
861static inline void zig_vsubo_i8(uint8_t *ov, int8_t *res, int n,
862 const int8_t *lhs, const int8_t *rhs, uint8_t bits)
863{
864 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i8(&res[i], lhs[i], rhs[i], bits);
865}
866
867
868791static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) {
869792#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
870793 uint16_t full_res;
......@@ -879,13 +802,6 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
879802#endif
880803}
881804
882static inline void zig_vsubo_u16(uint8_t *ov, uint16_t *res, int n,
883 const uint16_t *lhs, const uint16_t *rhs, uint8_t bits)
884{
885 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u16(&res[i], lhs[i], rhs[i], bits);
886}
887
888
889805static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) {
890806#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
891807 int16_t full_res;
......@@ -900,12 +816,6 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
900816#endif
901817}
902818
903static inline void zig_vsubo_i16(uint8_t *ov, int16_t *res, int n,
904 const int16_t *lhs, const int16_t *rhs, uint8_t bits)
905{
906 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i16(&res[i], lhs[i], rhs[i], bits);
907}
908
909819static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
910820#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
911821 uint32_t full_res;
......@@ -918,12 +828,6 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8
918828#endif
919829}
920830
921static inline void zig_vmulo_u32(uint8_t *ov, uint32_t *res, int n,
922 const uint32_t *lhs, const uint32_t *rhs, uint8_t bits)
923{
924 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u32(&res[i], lhs[i], rhs[i], bits);
925}
926
927831zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
928832static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
929833#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
......@@ -938,12 +842,6 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t
938842 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
939843}
940844
941static inline void zig_vmulo_i32(uint8_t *ov, int32_t *res, int n,
942 const int32_t *lhs, const int32_t *rhs, uint8_t bits)
943{
944 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i32(&res[i], lhs[i], rhs[i], bits);
945}
946
947845static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
948846#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
949847 uint64_t full_res;
......@@ -956,12 +854,6 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8
956854#endif
957855}
958856
959static inline void zig_vmulo_u64(uint8_t *ov, uint64_t *res, int n,
960 const uint64_t *lhs, const uint64_t *rhs, uint8_t bits)
961{
962 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u64(&res[i], lhs[i], rhs[i], bits);
963}
964
965857zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
966858static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
967859#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
......@@ -976,12 +868,6 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t
976868 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
977869}
978870
979static inline void zig_vmulo_i64(uint8_t *ov, int64_t *res, int n,
980 const int64_t *lhs, const int64_t *rhs, uint8_t bits)
981{
982 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i64(&res[i], lhs[i], rhs[i], bits);
983}
984
985871static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
986872#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
987873 uint8_t full_res;
......@@ -996,12 +882,6 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b
996882#endif
997883}
998884
999static inline void zig_vmulo_u8(uint8_t *ov, uint8_t *res, int n,
1000 const uint8_t *lhs, const uint8_t *rhs, uint8_t bits)
1001{
1002 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u8(&res[i], lhs[i], rhs[i], bits);
1003}
1004
1005885static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) {
1006886#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
1007887 int8_t full_res;
......@@ -1016,12 +896,6 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits
1016896#endif
1017897}
1018898
1019static inline void zig_vmulo_i8(uint8_t *ov, int8_t *res, int n,
1020 const int8_t *lhs, const int8_t *rhs, uint8_t bits)
1021{
1022 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i8(&res[i], lhs[i], rhs[i], bits);
1023}
1024
1025899static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) {
1026900#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
1027901 uint16_t full_res;
......@@ -1036,12 +910,6 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8
1036910#endif
1037911}
1038912
1039static inline void zig_vmulo_u16(uint8_t *ov, uint16_t *res, int n,
1040 const uint16_t *lhs, const uint16_t *rhs, uint8_t bits)
1041{
1042 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u16(&res[i], lhs[i], rhs[i], bits);
1043}
1044
1045913static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) {
1046914#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
1047915 int16_t full_res;
......@@ -1056,12 +924,6 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t
1056924#endif
1057925}
1058926
1059static inline void zig_vmulo_i16(uint8_t *ov, int16_t *res, int n,
1060 const int16_t *lhs, const int16_t *rhs, uint8_t bits)
1061{
1062 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i16(&res[i], lhs[i], rhs[i], bits);
1063}
1064
1065927#define zig_int_builtins(w) \
1066928 static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
1067929 *res = zig_shlw_u##w(lhs, rhs, bits); \
......@@ -1360,8 +1222,8 @@ typedef signed __int128 zig_i128;
13601222
13611223#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
13621224#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1363#define zig_make_constant_u128(hi, lo) zig_make_u128(hi, lo)
1364#define zig_make_constant_i128(hi, lo) zig_make_i128(hi, lo)
1225#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
1226#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
13651227#define zig_hi_u128(val) ((uint64_t)((val) >> 64))
13661228#define zig_lo_u128(val) ((uint64_t)((val) >> 0))
13671229#define zig_hi_i128(val) (( int64_t)((val) >> 64))
......@@ -1379,7 +1241,7 @@ typedef signed __int128 zig_i128;
13791241
13801242#else /* zig_has_int128 */
13811243
1382#if __LITTLE_ENDIAN__ || _MSC_VER
1244#if zig_little_endian
13831245typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128;
13841246typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128;
13851247#else
......@@ -1391,11 +1253,11 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
13911253#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
13921254
13931255#if _MSC_VER /* MSVC doesn't allow struct literals in constant expressions */
1394#define zig_make_constant_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1395#define zig_make_constant_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1256#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1257#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
13961258#else /* But non-MSVC doesn't like the unprotected commas */
1397#define zig_make_constant_u128(hi, lo) zig_make_u128(hi, lo)
1398#define zig_make_constant_i128(hi, lo) zig_make_i128(hi, lo)
1259#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
1260#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
13991261#endif
14001262#define zig_hi_u128(val) ((val).hi)
14011263#define zig_lo_u128(val) ((val).lo)
......@@ -1638,7 +1500,9 @@ static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) {
16381500}
16391501
16401502static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) {
1641 return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val));
1503 if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val));
1504 int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits);
1505 return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo);
16421506}
16431507
16441508static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) {
......@@ -1909,6 +1773,972 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
19091773 return zig_bitcast_i128(zig_bit_reverse_u128(zig_bitcast_u128(val), bits));
19101774}
19111775
1776/* ========================== Big Integer Support =========================== */
1777
1778static inline uint16_t zig_int_bytes(uint16_t bits) {
1779 uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT;
1780 uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT;
1781 while (alignment / 2 >= bytes) alignment /= 2;
1782 return (bytes + alignment - 1) / alignment * alignment;
1783}
1784
1785static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
1786 const uint8_t *lhs_bytes = lhs;
1787 const uint8_t *rhs_bytes = rhs;
1788 uint16_t byte_offset = 0;
1789 bool do_signed = is_signed;
1790 uint16_t remaining_bytes = zig_int_bytes(bits);
1791
1792#if zig_little_endian
1793 byte_offset = remaining_bytes;
1794#endif
1795
1796 while (remaining_bytes >= 128 / CHAR_BIT) {
1797 int32_t limb_cmp;
1798
1799#if zig_little_endian
1800 byte_offset -= 128 / CHAR_BIT;
1801#endif
1802
1803 if (do_signed) {
1804 zig_i128 lhs_limb;
1805 zig_i128 rhs_limb;
1806
1807 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1808 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1809 limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);
1810 do_signed = false;
1811 } else {
1812 zig_u128 lhs_limb;
1813 zig_u128 rhs_limb;
1814
1815 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1816 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1817 limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);
1818 }
1819
1820 if (limb_cmp != 0) return limb_cmp;
1821 remaining_bytes -= 128 / CHAR_BIT;
1822
1823#if zig_big_endian
1824 byte_offset += 128 / CHAR_BIT;
1825#endif
1826 }
1827
1828 while (remaining_bytes >= 64 / CHAR_BIT) {
1829#if zig_little_endian
1830 byte_offset -= 64 / CHAR_BIT;
1831#endif
1832
1833 if (do_signed) {
1834 int64_t lhs_limb;
1835 int64_t rhs_limb;
1836
1837 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1838 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1839 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
1840 do_signed = false;
1841 } else {
1842 uint64_t lhs_limb;
1843 uint64_t rhs_limb;
1844
1845 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1846 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1847 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
1848 }
1849
1850 remaining_bytes -= 64 / CHAR_BIT;
1851
1852#if zig_big_endian
1853 byte_offset += 64 / CHAR_BIT;
1854#endif
1855 }
1856
1857 while (remaining_bytes >= 32 / CHAR_BIT) {
1858#if zig_little_endian
1859 byte_offset -= 32 / CHAR_BIT;
1860#endif
1861
1862 if (do_signed) {
1863 int32_t lhs_limb;
1864 int32_t rhs_limb;
1865
1866 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1867 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1868 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
1869 do_signed = false;
1870 } else {
1871 uint32_t lhs_limb;
1872 uint32_t rhs_limb;
1873
1874 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1875 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1876 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
1877 }
1878
1879 remaining_bytes -= 32 / CHAR_BIT;
1880
1881#if zig_big_endian
1882 byte_offset += 32 / CHAR_BIT;
1883#endif
1884 }
1885
1886 while (remaining_bytes >= 16 / CHAR_BIT) {
1887#if zig_little_endian
1888 byte_offset -= 16 / CHAR_BIT;
1889#endif
1890
1891 if (do_signed) {
1892 int16_t lhs_limb;
1893 int16_t rhs_limb;
1894
1895 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1896 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1897 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
1898 do_signed = false;
1899 } else {
1900 uint16_t lhs_limb;
1901 uint16_t rhs_limb;
1902
1903 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1904 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1905 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
1906 }
1907
1908 remaining_bytes -= 16 / CHAR_BIT;
1909
1910#if zig_big_endian
1911 byte_offset += 16 / CHAR_BIT;
1912#endif
1913 }
1914
1915 while (remaining_bytes >= 8 / CHAR_BIT) {
1916#if zig_little_endian
1917 byte_offset -= 8 / CHAR_BIT;
1918#endif
1919
1920 if (do_signed) {
1921 int8_t lhs_limb;
1922 int8_t rhs_limb;
1923
1924 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1925 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1926 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
1927 do_signed = false;
1928 } else {
1929 uint8_t lhs_limb;
1930 uint8_t rhs_limb;
1931
1932 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1933 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1934 if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
1935 }
1936
1937 remaining_bytes -= 8 / CHAR_BIT;
1938
1939#if zig_big_endian
1940 byte_offset += 8 / CHAR_BIT;
1941#endif
1942 }
1943
1944 return 0;
1945}
1946
1947static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
1948 uint8_t *res_bytes = res;
1949 const uint8_t *lhs_bytes = lhs;
1950 const uint8_t *rhs_bytes = rhs;
1951 uint16_t byte_offset = 0;
1952 uint16_t remaining_bytes = zig_int_bytes(bits);
1953 uint16_t top_bits = remaining_bytes * 8 - bits;
1954 bool overflow = false;
1955
1956#if zig_big_endian
1957 byte_offset = remaining_bytes;
1958#endif
1959
1960 while (remaining_bytes >= 128 / CHAR_BIT) {
1961 uint16_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
1962
1963#if zig_big_endian
1964 byte_offset -= 128 / CHAR_BIT;
1965#endif
1966
1967 if (remaining_bytes == 128 / CHAR_BIT && is_signed) {
1968 zig_i128 res_limb;
1969 zig_i128 tmp_limb;
1970 zig_i128 lhs_limb;
1971 zig_i128 rhs_limb;
1972 bool limb_overflow;
1973
1974 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1975 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1976 limb_overflow = zig_addo_i128(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
1977 overflow = limb_overflow ^ zig_addo_i128(&res_limb, tmp_limb, zig_make_i128(INT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
1978 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
1979 } else {
1980 zig_u128 res_limb;
1981 zig_u128 tmp_limb;
1982 zig_u128 lhs_limb;
1983 zig_u128 rhs_limb;
1984 bool limb_overflow;
1985
1986 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
1987 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
1988 limb_overflow = zig_addo_u128(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
1989 overflow = limb_overflow ^ zig_addo_u128(&res_limb, tmp_limb, zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
1990 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
1991 }
1992
1993 remaining_bytes -= 128 / CHAR_BIT;
1994
1995#if zig_little_endian
1996 byte_offset += 128 / CHAR_BIT;
1997#endif
1998 }
1999
2000 while (remaining_bytes >= 64 / CHAR_BIT) {
2001 uint16_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
2002
2003#if zig_big_endian
2004 byte_offset -= 64 / CHAR_BIT;
2005#endif
2006
2007 if (remaining_bytes == 64 / CHAR_BIT && is_signed) {
2008 int64_t res_limb;
2009 int64_t tmp_limb;
2010 int64_t lhs_limb;
2011 int64_t rhs_limb;
2012 bool limb_overflow;
2013
2014 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2015 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2016 limb_overflow = zig_addo_i64(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2017 overflow = limb_overflow ^ zig_addo_i64(&res_limb, tmp_limb, overflow ? INT64_C(1) : INT64_C(0), limb_bits);
2018 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2019 } else {
2020 uint64_t res_limb;
2021 uint64_t tmp_limb;
2022 uint64_t lhs_limb;
2023 uint64_t rhs_limb;
2024 bool limb_overflow;
2025
2026 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2027 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2028 limb_overflow = zig_addo_u64(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2029 overflow = limb_overflow ^ zig_addo_u64(&res_limb, tmp_limb, overflow ? UINT64_C(1) : UINT64_C(0), limb_bits);
2030 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2031 }
2032
2033 remaining_bytes -= 64 / CHAR_BIT;
2034
2035#if zig_little_endian
2036 byte_offset += 64 / CHAR_BIT;
2037#endif
2038 }
2039
2040 while (remaining_bytes >= 32 / CHAR_BIT) {
2041 uint16_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
2042
2043#if zig_big_endian
2044 byte_offset -= 32 / CHAR_BIT;
2045#endif
2046
2047 if (remaining_bytes == 32 / CHAR_BIT && is_signed) {
2048 int32_t res_limb;
2049 int32_t tmp_limb;
2050 int32_t lhs_limb;
2051 int32_t rhs_limb;
2052 bool limb_overflow;
2053
2054 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2055 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2056 limb_overflow = zig_addo_i32(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2057 overflow = limb_overflow ^ zig_addo_i32(&res_limb, tmp_limb, overflow ? INT32_C(1) : INT32_C(0), limb_bits);
2058 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2059 } else {
2060 uint32_t res_limb;
2061 uint32_t tmp_limb;
2062 uint32_t lhs_limb;
2063 uint32_t rhs_limb;
2064 bool limb_overflow;
2065
2066 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2067 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2068 limb_overflow = zig_addo_u32(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2069 overflow = limb_overflow ^ zig_addo_u32(&res_limb, tmp_limb, overflow ? UINT32_C(1) : UINT32_C(0), limb_bits);
2070 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2071 }
2072
2073 remaining_bytes -= 32 / CHAR_BIT;
2074
2075#if zig_little_endian
2076 byte_offset += 32 / CHAR_BIT;
2077#endif
2078 }
2079
2080 while (remaining_bytes >= 16 / CHAR_BIT) {
2081 uint16_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
2082
2083#if zig_big_endian
2084 byte_offset -= 16 / CHAR_BIT;
2085#endif
2086
2087 if (remaining_bytes == 16 / CHAR_BIT && is_signed) {
2088 int16_t res_limb;
2089 int16_t tmp_limb;
2090 int16_t lhs_limb;
2091 int16_t rhs_limb;
2092 bool limb_overflow;
2093
2094 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2095 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2096 limb_overflow = zig_addo_i16(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2097 overflow = limb_overflow ^ zig_addo_i16(&res_limb, tmp_limb, overflow ? INT16_C(1) : INT16_C(0), limb_bits);
2098 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2099 } else {
2100 uint16_t res_limb;
2101 uint16_t tmp_limb;
2102 uint16_t lhs_limb;
2103 uint16_t rhs_limb;
2104 bool limb_overflow;
2105
2106 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2107 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2108 limb_overflow = zig_addo_u16(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2109 overflow = limb_overflow ^ zig_addo_u16(&res_limb, tmp_limb, overflow ? UINT16_C(1) : UINT16_C(0), limb_bits);
2110 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2111 }
2112
2113 remaining_bytes -= 16 / CHAR_BIT;
2114
2115#if zig_little_endian
2116 byte_offset += 16 / CHAR_BIT;
2117#endif
2118 }
2119
2120 while (remaining_bytes >= 8 / CHAR_BIT) {
2121 uint16_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
2122
2123#if zig_big_endian
2124 byte_offset -= 8 / CHAR_BIT;
2125#endif
2126
2127 if (remaining_bytes == 8 / CHAR_BIT && is_signed) {
2128 int8_t res_limb;
2129 int8_t tmp_limb;
2130 int8_t lhs_limb;
2131 int8_t rhs_limb;
2132 bool limb_overflow;
2133
2134 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2135 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2136 limb_overflow = zig_addo_i8(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2137 overflow = limb_overflow ^ zig_addo_i8(&res_limb, tmp_limb, overflow ? INT8_C(1) : INT8_C(0), limb_bits);
2138 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2139 } else {
2140 uint8_t res_limb;
2141 uint8_t tmp_limb;
2142 uint8_t lhs_limb;
2143 uint8_t rhs_limb;
2144 bool limb_overflow;
2145
2146 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2147 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2148 limb_overflow = zig_addo_u8(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2149 overflow = limb_overflow ^ zig_addo_u8(&res_limb, tmp_limb, overflow ? UINT8_C(1) : UINT8_C(0), limb_bits);
2150 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2151 }
2152
2153 remaining_bytes -= 8 / CHAR_BIT;
2154
2155#if zig_little_endian
2156 byte_offset += 8 / CHAR_BIT;
2157#endif
2158 }
2159
2160 return overflow;
2161}
2162
2163static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2164 uint8_t *res_bytes = res;
2165 const uint8_t *lhs_bytes = lhs;
2166 const uint8_t *rhs_bytes = rhs;
2167 uint16_t byte_offset = 0;
2168 uint16_t remaining_bytes = zig_int_bytes(bits);
2169 uint16_t top_bits = remaining_bytes * 8 - bits;
2170 bool overflow = false;
2171
2172#if zig_big_endian
2173 byte_offset = remaining_bytes;
2174#endif
2175
2176 while (remaining_bytes >= 128 / CHAR_BIT) {
2177 uint16_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
2178
2179#if zig_big_endian
2180 byte_offset -= 128 / CHAR_BIT;
2181#endif
2182
2183 if (remaining_bytes == 128 / CHAR_BIT && is_signed) {
2184 zig_i128 res_limb;
2185 zig_i128 tmp_limb;
2186 zig_i128 lhs_limb;
2187 zig_i128 rhs_limb;
2188 bool limb_overflow;
2189
2190 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2191 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2192 limb_overflow = zig_subo_i128(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2193 overflow = limb_overflow ^ zig_subo_i128(&res_limb, tmp_limb, zig_make_i128(INT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
2194 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2195 } else {
2196 zig_u128 res_limb;
2197 zig_u128 tmp_limb;
2198 zig_u128 lhs_limb;
2199 zig_u128 rhs_limb;
2200 bool limb_overflow;
2201
2202 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2203 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2204 limb_overflow = zig_subo_u128(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2205 overflow = limb_overflow ^ zig_subo_u128(&res_limb, tmp_limb, zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
2206 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2207 }
2208
2209 remaining_bytes -= 128 / CHAR_BIT;
2210
2211#if zig_little_endian
2212 byte_offset += 128 / CHAR_BIT;
2213#endif
2214 }
2215
2216 while (remaining_bytes >= 64 / CHAR_BIT) {
2217 uint16_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
2218
2219#if zig_big_endian
2220 byte_offset -= 64 / CHAR_BIT;
2221#endif
2222
2223 if (remaining_bytes == 64 / CHAR_BIT && is_signed) {
2224 int64_t res_limb;
2225 int64_t tmp_limb;
2226 int64_t lhs_limb;
2227 int64_t rhs_limb;
2228 bool limb_overflow;
2229
2230 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2231 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2232 limb_overflow = zig_subo_i64(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2233 overflow = limb_overflow ^ zig_subo_i64(&res_limb, tmp_limb, overflow ? INT64_C(1) : INT64_C(0), limb_bits);
2234 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2235 } else {
2236 uint64_t res_limb;
2237 uint64_t tmp_limb;
2238 uint64_t lhs_limb;
2239 uint64_t rhs_limb;
2240 bool limb_overflow;
2241
2242 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2243 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2244 limb_overflow = zig_subo_u64(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2245 overflow = limb_overflow ^ zig_subo_u64(&res_limb, tmp_limb, overflow ? UINT64_C(1) : UINT64_C(0), limb_bits);
2246 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2247 }
2248
2249 remaining_bytes -= 64 / CHAR_BIT;
2250
2251#if zig_little_endian
2252 byte_offset += 64 / CHAR_BIT;
2253#endif
2254 }
2255
2256 while (remaining_bytes >= 32 / CHAR_BIT) {
2257 uint16_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
2258
2259#if zig_big_endian
2260 byte_offset -= 32 / CHAR_BIT;
2261#endif
2262
2263 if (remaining_bytes == 32 / CHAR_BIT && is_signed) {
2264 int32_t res_limb;
2265 int32_t tmp_limb;
2266 int32_t lhs_limb;
2267 int32_t rhs_limb;
2268 bool limb_overflow;
2269
2270 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2271 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2272 limb_overflow = zig_subo_i32(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2273 overflow = limb_overflow ^ zig_subo_i32(&res_limb, tmp_limb, overflow ? INT32_C(1) : INT32_C(0), limb_bits);
2274 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2275 } else {
2276 uint32_t res_limb;
2277 uint32_t tmp_limb;
2278 uint32_t lhs_limb;
2279 uint32_t rhs_limb;
2280 bool limb_overflow;
2281
2282 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2283 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2284 limb_overflow = zig_subo_u32(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2285 overflow = limb_overflow ^ zig_subo_u32(&res_limb, tmp_limb, overflow ? UINT32_C(1) : UINT32_C(0), limb_bits);
2286 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2287 }
2288
2289 remaining_bytes -= 32 / CHAR_BIT;
2290
2291#if zig_little_endian
2292 byte_offset += 32 / CHAR_BIT;
2293#endif
2294 }
2295
2296 while (remaining_bytes >= 16 / CHAR_BIT) {
2297 uint16_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
2298
2299#if zig_big_endian
2300 byte_offset -= 16 / CHAR_BIT;
2301#endif
2302
2303 if (remaining_bytes == 16 / CHAR_BIT && is_signed) {
2304 int16_t res_limb;
2305 int16_t tmp_limb;
2306 int16_t lhs_limb;
2307 int16_t rhs_limb;
2308 bool limb_overflow;
2309
2310 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2311 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2312 limb_overflow = zig_subo_i16(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2313 overflow = limb_overflow ^ zig_subo_i16(&res_limb, tmp_limb, overflow ? INT16_C(1) : INT16_C(0), limb_bits);
2314 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2315 } else {
2316 uint16_t res_limb;
2317 uint16_t tmp_limb;
2318 uint16_t lhs_limb;
2319 uint16_t rhs_limb;
2320 bool limb_overflow;
2321
2322 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2323 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2324 limb_overflow = zig_subo_u16(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2325 overflow = limb_overflow ^ zig_subo_u16(&res_limb, tmp_limb, overflow ? UINT16_C(1) : UINT16_C(0), limb_bits);
2326 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2327 }
2328
2329 remaining_bytes -= 16 / CHAR_BIT;
2330
2331#if zig_little_endian
2332 byte_offset += 16 / CHAR_BIT;
2333#endif
2334 }
2335
2336 while (remaining_bytes >= 8 / CHAR_BIT) {
2337 uint16_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
2338
2339#if zig_big_endian
2340 byte_offset -= 8 / CHAR_BIT;
2341#endif
2342
2343 if (remaining_bytes == 8 / CHAR_BIT && is_signed) {
2344 int8_t res_limb;
2345 int8_t tmp_limb;
2346 int8_t lhs_limb;
2347 int8_t rhs_limb;
2348 bool limb_overflow;
2349
2350 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2351 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2352 limb_overflow = zig_subo_i8(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2353 overflow = limb_overflow ^ zig_subo_i8(&res_limb, tmp_limb, overflow ? INT8_C(1) : INT8_C(0), limb_bits);
2354 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2355 } else {
2356 uint8_t res_limb;
2357 uint8_t tmp_limb;
2358 uint8_t lhs_limb;
2359 uint8_t rhs_limb;
2360 bool limb_overflow;
2361
2362 memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
2363 memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
2364 limb_overflow = zig_subo_u8(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
2365 overflow = limb_overflow ^ zig_subo_u8(&res_limb, tmp_limb, overflow ? UINT8_C(1) : UINT8_C(0), limb_bits);
2366 memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
2367 }
2368
2369 remaining_bytes -= 8 / CHAR_BIT;
2370
2371#if zig_little_endian
2372 byte_offset += 8 / CHAR_BIT;
2373#endif
2374 }
2375
2376 return overflow;
2377}
2378
2379static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2380 (void)zig_addo_big(res, lhs, rhs, is_signed, bits);
2381}
2382
2383static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2384 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
2385}
2386
2387static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) {
2388 const uint8_t *val_bytes = val;
2389 uint16_t byte_offset = 0;
2390 uint16_t remaining_bytes = zig_int_bytes(bits);
2391 uint16_t skip_bits = remaining_bytes * 8 - bits;
2392 uint16_t total_lz = 0;
2393 uint16_t limb_lz;
2394 (void)is_signed;
2395
2396#if zig_little_endian
2397 byte_offset = remaining_bytes;
2398#endif
2399
2400 while (remaining_bytes >= 128 / CHAR_BIT) {
2401#if zig_little_endian
2402 byte_offset -= 128 / CHAR_BIT;
2403#endif
2404
2405 {
2406 zig_u128 val_limb;
2407
2408 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2409 limb_lz = zig_clz_u128(val_limb, 128 - skip_bits);
2410 }
2411
2412 total_lz += limb_lz;
2413 if (limb_lz < 128 - skip_bits) return total_lz;
2414 skip_bits = 0;
2415 remaining_bytes -= 128 / CHAR_BIT;
2416
2417#if zig_big_endian
2418 byte_offset += 128 / CHAR_BIT;
2419#endif
2420 }
2421
2422 while (remaining_bytes >= 64 / CHAR_BIT) {
2423#if zig_little_endian
2424 byte_offset -= 64 / CHAR_BIT;
2425#endif
2426
2427 {
2428 uint64_t val_limb;
2429
2430 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2431 limb_lz = zig_clz_u64(val_limb, 64 - skip_bits);
2432 }
2433
2434 total_lz += limb_lz;
2435 if (limb_lz < 64 - skip_bits) return total_lz;
2436 skip_bits = 0;
2437 remaining_bytes -= 64 / CHAR_BIT;
2438
2439#if zig_big_endian
2440 byte_offset += 64 / CHAR_BIT;
2441#endif
2442 }
2443
2444 while (remaining_bytes >= 32 / CHAR_BIT) {
2445#if zig_little_endian
2446 byte_offset -= 32 / CHAR_BIT;
2447#endif
2448
2449 {
2450 uint32_t val_limb;
2451
2452 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2453 limb_lz = zig_clz_u32(val_limb, 32 - skip_bits);
2454 }
2455
2456 total_lz += limb_lz;
2457 if (limb_lz < 32 - skip_bits) return total_lz;
2458 skip_bits = 0;
2459 remaining_bytes -= 32 / CHAR_BIT;
2460
2461#if zig_big_endian
2462 byte_offset += 32 / CHAR_BIT;
2463#endif
2464 }
2465
2466 while (remaining_bytes >= 16 / CHAR_BIT) {
2467#if zig_little_endian
2468 byte_offset -= 16 / CHAR_BIT;
2469#endif
2470
2471 {
2472 uint16_t val_limb;
2473
2474 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2475 limb_lz = zig_clz_u16(val_limb, 16 - skip_bits);
2476 }
2477
2478 total_lz += limb_lz;
2479 if (limb_lz < 16 - skip_bits) return total_lz;
2480 skip_bits = 0;
2481 remaining_bytes -= 16 / CHAR_BIT;
2482
2483#if zig_big_endian
2484 byte_offset += 16 / CHAR_BIT;
2485#endif
2486 }
2487
2488 while (remaining_bytes >= 8 / CHAR_BIT) {
2489#if zig_little_endian
2490 byte_offset -= 8 / CHAR_BIT;
2491#endif
2492
2493 {
2494 uint8_t val_limb;
2495
2496 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2497 limb_lz = zig_clz_u8(val_limb, 8 - skip_bits);
2498 }
2499
2500 total_lz += limb_lz;
2501 if (limb_lz < 8 - skip_bits) return total_lz;
2502 skip_bits = 0;
2503 remaining_bytes -= 8 / CHAR_BIT;
2504
2505#if zig_big_endian
2506 byte_offset += 8 / CHAR_BIT;
2507#endif
2508 }
2509
2510 return total_lz;
2511}
2512
2513static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) {
2514 const uint8_t *val_bytes = val;
2515 uint16_t byte_offset = 0;
2516 uint16_t remaining_bytes = zig_int_bytes(bits);
2517 uint16_t total_tz = 0;
2518 uint16_t limb_tz;
2519 (void)is_signed;
2520
2521#if zig_big_endian
2522 byte_offset = remaining_bytes;
2523#endif
2524
2525 while (remaining_bytes >= 128 / CHAR_BIT) {
2526#if zig_big_endian
2527 byte_offset -= 128 / CHAR_BIT;
2528#endif
2529
2530 {
2531 zig_u128 val_limb;
2532
2533 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2534 limb_tz = zig_ctz_u128(val_limb, 128);
2535 }
2536
2537 total_tz += limb_tz;
2538 if (limb_tz < 128) return total_tz;
2539 remaining_bytes -= 128 / CHAR_BIT;
2540
2541#if zig_little_endian
2542 byte_offset += 128 / CHAR_BIT;
2543#endif
2544 }
2545
2546 while (remaining_bytes >= 64 / CHAR_BIT) {
2547#if zig_big_endian
2548 byte_offset -= 64 / CHAR_BIT;
2549#endif
2550
2551 {
2552 uint64_t val_limb;
2553
2554 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2555 limb_tz = zig_ctz_u64(val_limb, 64);
2556 }
2557
2558 total_tz += limb_tz;
2559 if (limb_tz < 64) return total_tz;
2560 remaining_bytes -= 64 / CHAR_BIT;
2561
2562#if zig_little_endian
2563 byte_offset += 64 / CHAR_BIT;
2564#endif
2565 }
2566
2567 while (remaining_bytes >= 32 / CHAR_BIT) {
2568#if zig_big_endian
2569 byte_offset -= 32 / CHAR_BIT;
2570#endif
2571
2572 {
2573 uint32_t val_limb;
2574
2575 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2576 limb_tz = zig_ctz_u32(val_limb, 32);
2577 }
2578
2579 total_tz += limb_tz;
2580 if (limb_tz < 32) return total_tz;
2581 remaining_bytes -= 32 / CHAR_BIT;
2582
2583#if zig_little_endian
2584 byte_offset += 32 / CHAR_BIT;
2585#endif
2586 }
2587
2588 while (remaining_bytes >= 16 / CHAR_BIT) {
2589#if zig_big_endian
2590 byte_offset -= 16 / CHAR_BIT;
2591#endif
2592
2593 {
2594 uint16_t val_limb;
2595
2596 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2597 limb_tz = zig_ctz_u16(val_limb, 16);
2598 }
2599
2600 total_tz += limb_tz;
2601 if (limb_tz < 16) return total_tz;
2602 remaining_bytes -= 16 / CHAR_BIT;
2603
2604#if zig_little_endian
2605 byte_offset += 16 / CHAR_BIT;
2606#endif
2607 }
2608
2609 while (remaining_bytes >= 8 / CHAR_BIT) {
2610#if zig_big_endian
2611 byte_offset -= 8 / CHAR_BIT;
2612#endif
2613
2614 {
2615 uint8_t val_limb;
2616
2617 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2618 limb_tz = zig_ctz_u8(val_limb, 8);
2619 }
2620
2621 total_tz += limb_tz;
2622 if (limb_tz < 8) return total_tz;
2623 remaining_bytes -= 8 / CHAR_BIT;
2624
2625#if zig_little_endian
2626 byte_offset += 8 / CHAR_BIT;
2627#endif
2628 }
2629
2630 return total_tz;
2631}
2632
2633static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) {
2634 const uint8_t *val_bytes = val;
2635 uint16_t byte_offset = 0;
2636 uint16_t remaining_bytes = zig_int_bytes(bits);
2637 uint16_t total_pc = 0;
2638 (void)is_signed;
2639
2640#if zig_big_endian
2641 byte_offset = remaining_bytes;
2642#endif
2643
2644 while (remaining_bytes >= 128 / CHAR_BIT) {
2645#if zig_big_endian
2646 byte_offset -= 128 / CHAR_BIT;
2647#endif
2648
2649 {
2650 zig_u128 val_limb;
2651
2652 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2653 total_pc += zig_popcount_u128(val_limb, 128);
2654 }
2655
2656 remaining_bytes -= 128 / CHAR_BIT;
2657
2658#if zig_little_endian
2659 byte_offset += 128 / CHAR_BIT;
2660#endif
2661 }
2662
2663 while (remaining_bytes >= 64 / CHAR_BIT) {
2664#if zig_big_endian
2665 byte_offset -= 64 / CHAR_BIT;
2666#endif
2667
2668 {
2669 uint64_t val_limb;
2670
2671 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2672 total_pc += zig_popcount_u64(val_limb, 64);
2673 }
2674
2675 remaining_bytes -= 64 / CHAR_BIT;
2676
2677#if zig_little_endian
2678 byte_offset += 64 / CHAR_BIT;
2679#endif
2680 }
2681
2682 while (remaining_bytes >= 32 / CHAR_BIT) {
2683#if zig_big_endian
2684 byte_offset -= 32 / CHAR_BIT;
2685#endif
2686
2687 {
2688 uint32_t val_limb;
2689
2690 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2691 total_pc += zig_popcount_u32(val_limb, 32);
2692 }
2693
2694 remaining_bytes -= 32 / CHAR_BIT;
2695
2696#if zig_little_endian
2697 byte_offset += 32 / CHAR_BIT;
2698#endif
2699 }
2700
2701 while (remaining_bytes >= 16 / CHAR_BIT) {
2702#if zig_big_endian
2703 byte_offset -= 16 / CHAR_BIT;
2704#endif
2705
2706 {
2707 uint16_t val_limb;
2708
2709 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2710 total_pc = zig_popcount_u16(val_limb, 16);
2711 }
2712
2713 remaining_bytes -= 16 / CHAR_BIT;
2714
2715#if zig_little_endian
2716 byte_offset += 16 / CHAR_BIT;
2717#endif
2718 }
2719
2720 while (remaining_bytes >= 8 / CHAR_BIT) {
2721#if zig_big_endian
2722 byte_offset -= 8 / CHAR_BIT;
2723#endif
2724
2725 {
2726 uint8_t val_limb;
2727
2728 memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
2729 total_pc = zig_popcount_u8(val_limb, 8);
2730 }
2731
2732 remaining_bytes -= 8 / CHAR_BIT;
2733
2734#if zig_little_endian
2735 byte_offset += 8 / CHAR_BIT;
2736#endif
2737 }
2738
2739 return total_pc;
2740}
2741
19122742/* ========================= Floating Point Support ========================= */
19132743
19142744#if _MSC_VER
......@@ -1933,7 +2763,6 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
19332763#define zig_make_special_f64(sign, name, arg, repr) sign zig_make_f64(__builtin_##name, )(arg)
19342764#define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80(__builtin_##name, )(arg)
19352765#define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg)
1936#define zig_make_special_c_longdouble(sign, name, arg, repr) sign zig_make_c_longdouble(__builtin_##name, )(arg)
19372766#else
19382767#define zig_has_float_builtins 0
19392768#define zig_make_special_f16(sign, name, arg, repr) zig_float_from_repr_f16(repr)
......@@ -1941,13 +2770,13 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
19412770#define zig_make_special_f64(sign, name, arg, repr) zig_float_from_repr_f64(repr)
19422771#define zig_make_special_f80(sign, name, arg, repr) zig_float_from_repr_f80(repr)
19432772#define zig_make_special_f128(sign, name, arg, repr) zig_float_from_repr_f128(repr)
1944#define zig_make_special_c_longdouble(sign, name, arg, repr) zig_float_from_repr_c_longdouble(repr)
19452773#endif
19462774
19472775#define zig_has_f16 1
19482776#define zig_bitSizeOf_f16 16
2777typedef int16_t zig_repr_f16;
19492778#define zig_libc_name_f16(name) __##name##h
1950#define zig_make_special_constant_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr)
2779#define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr)
19512780#if FLT_MANT_DIG == 11
19522781typedef float zig_f16;
19532782#define zig_make_f16(fp, repr) fp##f
......@@ -1956,7 +2785,9 @@ typedef double zig_f16;
19562785#define zig_make_f16(fp, repr) fp
19572786#elif LDBL_MANT_DIG == 11
19582787#define zig_bitSizeOf_c_longdouble 16
1959typedef uint16_t zig_repr_c_longdouble;
2788#ifndef ZIG_TARGET_ABI_MSVC
2789typedef zig_repr_f16 zig_repr_c_longdouble;
2790#endif
19602791typedef long double zig_f16;
19612792#define zig_make_f16(fp, repr) fp##l
19622793#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gnuc))
......@@ -1973,17 +2804,18 @@ typedef int16_t zig_f16;
19732804#define zig_make_f16(fp, repr) repr
19742805#undef zig_make_special_f16
19752806#define zig_make_special_f16(sign, name, arg, repr) repr
1976#undef zig_make_special_constant_f16
1977#define zig_make_special_constant_f16(sign, name, arg, repr) repr
2807#undef zig_init_special_f16
2808#define zig_init_special_f16(sign, name, arg, repr) repr
19782809#endif
19792810
19802811#define zig_has_f32 1
19812812#define zig_bitSizeOf_f32 32
2813typedef int32_t zig_repr_f32;
19822814#define zig_libc_name_f32(name) name##f
19832815#if _MSC_VER
1984#define zig_make_special_constant_f32(sign, name, arg, repr) sign zig_make_f32(zig_msvc_flt_##name, )
2816#define zig_init_special_f32(sign, name, arg, repr) sign zig_make_f32(zig_msvc_flt_##name, )
19852817#else
1986#define zig_make_special_constant_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr)
2818#define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr)
19872819#endif
19882820#if FLT_MANT_DIG == 24
19892821typedef float zig_f32;
......@@ -1993,7 +2825,9 @@ typedef double zig_f32;
19932825#define zig_make_f32(fp, repr) fp
19942826#elif LDBL_MANT_DIG == 24
19952827#define zig_bitSizeOf_c_longdouble 32
1996typedef uint32_t zig_repr_c_longdouble;
2828#ifndef ZIG_TARGET_ABI_MSVC
2829typedef zig_repr_f32 zig_repr_c_longdouble;
2830#endif
19972831typedef long double zig_f32;
19982832#define zig_make_f32(fp, repr) fp##l
19992833#elif FLT32_MANT_DIG == 24
......@@ -2007,21 +2841,24 @@ typedef int32_t zig_f32;
20072841#define zig_make_f32(fp, repr) repr
20082842#undef zig_make_special_f32
20092843#define zig_make_special_f32(sign, name, arg, repr) repr
2010#undef zig_make_special_constant_f32
2011#define zig_make_special_constant_f32(sign, name, arg, repr) repr
2844#undef zig_init_special_f32
2845#define zig_init_special_f32(sign, name, arg, repr) repr
20122846#endif
20132847
20142848#define zig_has_f64 1
20152849#define zig_bitSizeOf_f64 64
2850typedef int64_t zig_repr_f64;
20162851#define zig_libc_name_f64(name) name
20172852#if _MSC_VER
20182853#ifdef ZIG_TARGET_ABI_MSVC
20192854#define zig_bitSizeOf_c_longdouble 64
2020typedef uint64_t zig_repr_c_longdouble;
2855#ifndef ZIG_TARGET_ABI_MSVC
2856typedef zig_repr_f64 zig_repr_c_longdouble;
2857#endif
20212858#endif
2022#define zig_make_special_constant_f64(sign, name, arg, repr) sign zig_make_f64(zig_msvc_flt_##name, )
2859#define zig_init_special_f64(sign, name, arg, repr) sign zig_make_f64(zig_msvc_flt_##name, )
20232860#else /* _MSC_VER */
2024#define zig_make_special_constant_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr)
2861#define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr)
20252862#endif /* _MSC_VER */
20262863#if FLT_MANT_DIG == 53
20272864typedef float zig_f64;
......@@ -2031,7 +2868,9 @@ typedef double zig_f64;
20312868#define zig_make_f64(fp, repr) fp
20322869#elif LDBL_MANT_DIG == 53
20332870#define zig_bitSizeOf_c_longdouble 64
2034typedef uint64_t zig_repr_c_longdouble;
2871#ifndef ZIG_TARGET_ABI_MSVC
2872typedef zig_repr_f64 zig_repr_c_longdouble;
2873#endif
20352874typedef long double zig_f64;
20362875#define zig_make_f64(fp, repr) fp##l
20372876#elif FLT64_MANT_DIG == 53
......@@ -2048,14 +2887,15 @@ typedef int64_t zig_f64;
20482887#define zig_make_f64(fp, repr) repr
20492888#undef zig_make_special_f64
20502889#define zig_make_special_f64(sign, name, arg, repr) repr
2051#undef zig_make_special_constant_f64
2052#define zig_make_special_constant_f64(sign, name, arg, repr) repr
2890#undef zig_init_special_f64
2891#define zig_init_special_f64(sign, name, arg, repr) repr
20532892#endif
20542893
20552894#define zig_has_f80 1
20562895#define zig_bitSizeOf_f80 80
2896typedef zig_i128 zig_repr_f80;
20572897#define zig_libc_name_f80(name) __##name##x
2058#define zig_make_special_constant_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr)
2898#define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr)
20592899#if FLT_MANT_DIG == 64
20602900typedef float zig_f80;
20612901#define zig_make_f80(fp, repr) fp##f
......@@ -2064,7 +2904,9 @@ typedef double zig_f80;
20642904#define zig_make_f80(fp, repr) fp
20652905#elif LDBL_MANT_DIG == 64
20662906#define zig_bitSizeOf_c_longdouble 80
2067typedef zig_u128 zig_repr_c_longdouble;
2907#ifndef ZIG_TARGET_ABI_MSVC
2908typedef zig_repr_f80 zig_repr_c_longdouble;
2909#endif
20682910typedef long double zig_f80;
20692911#define zig_make_f80(fp, repr) fp##l
20702912#elif FLT80_MANT_DIG == 64
......@@ -2084,14 +2926,15 @@ typedef zig_i128 zig_f80;
20842926#define zig_make_f80(fp, repr) repr
20852927#undef zig_make_special_f80
20862928#define zig_make_special_f80(sign, name, arg, repr) repr
2087#undef zig_make_special_constant_f80
2088#define zig_make_special_constant_f80(sign, name, arg, repr) repr
2929#undef zig_init_special_f80
2930#define zig_init_special_f80(sign, name, arg, repr) repr
20892931#endif
20902932
20912933#define zig_has_f128 1
20922934#define zig_bitSizeOf_f128 128
2935typedef zig_i128 zig_repr_f128;
20932936#define zig_libc_name_f128(name) name##q
2094#define zig_make_special_constant_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr)
2937#define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr)
20952938#if FLT_MANT_DIG == 113
20962939typedef float zig_f128;
20972940#define zig_make_f128(fp, repr) fp##f
......@@ -2100,7 +2943,9 @@ typedef double zig_f128;
21002943#define zig_make_f128(fp, repr) fp
21012944#elif LDBL_MANT_DIG == 113
21022945#define zig_bitSizeOf_c_longdouble 128
2103typedef zig_u128 zig_repr_c_longdouble;
2946#ifndef ZIG_TARGET_ABI_MSVC
2947typedef zig_repr_f128 zig_repr_c_longdouble;
2948#endif
21042949typedef long double zig_f128;
21052950#define zig_make_f128(fp, repr) fp##l
21062951#elif FLT128_MANT_DIG == 113
......@@ -2122,63 +2967,44 @@ typedef zig_i128 zig_f128;
21222967#define zig_make_f128(fp, repr) repr
21232968#undef zig_make_special_f128
21242969#define zig_make_special_f128(sign, name, arg, repr) repr
2125#undef zig_make_special_constant_f128
2126#define zig_make_special_constant_f128(sign, name, arg, repr) repr
2970#undef zig_init_special_f128
2971#define zig_init_special_f128(sign, name, arg, repr) repr
21272972#endif
21282973
2129#define zig_has_c_longdouble 1
2130
2131#ifdef ZIG_TARGET_ABI_MSVC
2132#define zig_libc_name_c_longdouble(name) name
2133#else
2134#define zig_libc_name_c_longdouble(name) name##l
2135#endif
2136
2137#define zig_make_special_constant_c_longdouble(sign, name, arg, repr) zig_make_special_c_longdouble(sign, name, arg, repr)
21382974#ifdef zig_bitSizeOf_c_longdouble
21392975
2976#define zig_has_c_longdouble 1
21402977#ifdef ZIG_TARGET_ABI_MSVC
21412978#undef zig_bitSizeOf_c_longdouble
21422979#define zig_bitSizeOf_c_longdouble 64
2143typedef uint64_t zig_repr_c_longdouble;
21442980typedef zig_f64 zig_c_longdouble;
2145#define zig_make_c_longdouble(fp, repr) fp
2981typedef zig_repr_f64 zig_repr_c_longdouble;
21462982#else
21472983typedef long double zig_c_longdouble;
2148#define zig_make_c_longdouble(fp, repr) fp##l
21492984#endif
21502985
21512986#else /* zig_bitSizeOf_c_longdouble */
21522987
2153#undef zig_has_c_longdouble
21542988#define zig_has_c_longdouble 0
2155#define zig_bitSizeOf_c_longdouble 80
2156typedef zig_u128 zig_repr_c_longdouble;
2157#define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f80
21582989#define zig_bitSizeOf_repr_c_longdouble 128
2159typedef zig_i128 zig_c_longdouble;
2160#define zig_make_c_longdouble(fp, repr) repr
2161#undef zig_make_special_c_longdouble
2162#define zig_make_special_c_longdouble(sign, name, arg, repr) repr
2163#undef zig_make_special_constant_c_longdouble
2164#define zig_make_special_constant_c_longdouble(sign, name, arg, repr) repr
2990typedef zig_f128 zig_c_longdouble;
2991typedef zig_repr_f128 zig_repr_c_longdouble;
21652992
21662993#endif /* zig_bitSizeOf_c_longdouble */
21672994
21682995#if !zig_has_float_builtins
2169#define zig_float_from_repr(Type, ReprType) \
2170 static inline zig_##Type zig_float_from_repr_##Type(ReprType repr) { \
2996#define zig_float_from_repr(Type) \
2997 static inline zig_##Type zig_float_from_repr_##Type(zig_repr_##Type repr) { \
21712998 zig_##Type result; \
21722999 memcpy(&result, &repr, sizeof(result)); \
21733000 return result; \
21743001 }
21753002
2176zig_float_from_repr(f16, uint16_t)
2177zig_float_from_repr(f32, uint32_t)
2178zig_float_from_repr(f64, uint64_t)
2179zig_float_from_repr(f80, zig_u128)
2180zig_float_from_repr(f128, zig_u128)
2181zig_float_from_repr(c_longdouble, zig_repr_c_longdouble)
3003zig_float_from_repr(f16)
3004zig_float_from_repr(f32)
3005zig_float_from_repr(f64)
3006zig_float_from_repr(f80)
3007zig_float_from_repr(f128)
21823008#endif
21833009
21843010#define zig_cast_f16 (zig_f16)
......@@ -2187,11 +3013,9 @@ zig_float_from_repr(c_longdouble, zig_repr_c_longdouble)
21873013
21883014#if _MSC_VER && !zig_has_f128
21893015#define zig_cast_f80
2190#define zig_cast_c_longdouble
21913016#define zig_cast_f128
21923017#else
21933018#define zig_cast_f80 (zig_f80)
2194#define zig_cast_c_longdouble (zig_c_longdouble)
21953019#define zig_cast_f128 (zig_f128)
21963020#endif
21973021
......@@ -2320,7 +3144,6 @@ zig_float_builtins(f32)
23203144zig_float_builtins(f64)
23213145zig_float_builtins(f80)
23223146zig_float_builtins(f128)
2323zig_float_builtins(c_longdouble)
23243147
23253148#if _MSC_VER && (_M_IX86 || _M_X64)
23263149
src/Sema.zig+19-21
......@@ -574,11 +574,13 @@ pub const Block = struct {
574574 });
575575 }
576576
577 fn addCmpVector(block: *Block, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref, cmp_op: std.math.CompareOperator, vector_ty: Air.Inst.Ref) !Air.Inst.Ref {
577 fn addCmpVector(block: *Block, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref, cmp_op: std.math.CompareOperator) !Air.Inst.Ref {
578578 return block.addInst(.{
579579 .tag = if (block.float_mode == .Optimized) .cmp_vector_optimized else .cmp_vector,
580580 .data = .{ .ty_pl = .{
581 .ty = vector_ty,
581 .ty = try block.sema.addType(
582 try Type.vector(block.sema.arena, block.sema.typeOf(lhs).vectorLen(), Type.bool),
583 ),
582584 .payload = try block.sema.addExtra(Air.VectorCmp{
583585 .lhs = lhs,
584586 .rhs = rhs,
......@@ -9412,7 +9414,7 @@ fn intCast(
94129414 const ok = if (is_vector) ok: {
94139415 const zeros = try Value.Tag.repeated.create(sema.arena, Value.zero);
94149416 const zero_inst = try sema.addConstant(sema.typeOf(operand), zeros);
9415 const is_in_range = try block.addCmpVector(operand, zero_inst, .eq, try sema.addType(operand_ty));
9417 const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);
94169418 const all_in_range = try block.addInst(.{
94179419 .tag = .reduce,
94189420 .data = .{ .reduce = .{ .operand = is_in_range, .operation = .And } },
......@@ -9466,7 +9468,7 @@ fn intCast(
94669468 const dest_range = try sema.addConstant(unsigned_operand_ty, dest_range_val);
94679469
94689470 const ok = if (is_vector) ok: {
9469 const is_in_range = try block.addCmpVector(diff_unsigned, dest_range, .lte, try sema.addType(operand_ty));
9471 const is_in_range = try block.addCmpVector(diff_unsigned, dest_range, .lte);
94709472 const all_in_range = try block.addInst(.{
94719473 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
94729474 .data = .{ .reduce = .{
......@@ -9483,7 +9485,7 @@ fn intCast(
94839485 try sema.addSafetyCheck(block, ok, .cast_truncated_data);
94849486 } else {
94859487 const ok = if (is_vector) ok: {
9486 const is_in_range = try block.addCmpVector(diff, dest_max, .lte, try sema.addType(operand_ty));
9488 const is_in_range = try block.addCmpVector(diff, dest_max, .lte);
94879489 const all_in_range = try block.addInst(.{
94889490 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
94899491 .data = .{ .reduce = .{
......@@ -9504,7 +9506,7 @@ fn intCast(
95049506 const ok = if (is_vector) ok: {
95059507 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
95069508 const zero_inst = try sema.addConstant(operand_ty, zero_val);
9507 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte, try sema.addType(operand_ty));
9509 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);
95089510 const all_in_range = try block.addInst(.{
95099511 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
95109512 .data = .{ .reduce = .{
......@@ -12016,7 +12018,7 @@ fn zirShl(
1201612018
1201712019 const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: {
1201812020 const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val));
12019 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt, try sema.addType(rhs_ty));
12021 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
1202012022 break :ok try block.addInst(.{
1202112023 .tag = .reduce,
1202212024 .data = .{ .reduce = .{
......@@ -12172,7 +12174,7 @@ fn zirShr(
1217212174
1217312175 const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: {
1217412176 const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val));
12175 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt, try sema.addType(rhs_ty));
12177 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
1217612178 break :ok try block.addInst(.{
1217712179 .tag = .reduce,
1217812180 .data = .{ .reduce = .{
......@@ -12191,7 +12193,7 @@ fn zirShr(
1219112193 const back = try block.addBinOp(.shl, result, rhs);
1219212194
1219312195 const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: {
12194 const eql = try block.addCmpVector(lhs, back, .eq, try sema.addType(rhs_ty));
12196 const eql = try block.addCmpVector(lhs, back, .eq);
1219512197 break :ok try block.addInst(.{
1219612198 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
1219712199 .data = .{ .reduce = .{
......@@ -13192,7 +13194,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1319213194 const floored = try block.addUnOp(.floor, result);
1319313195
1319413196 if (resolved_type.zigTypeTag() == .Vector) {
13195 const eql = try block.addCmpVector(result, floored, .eq, try sema.addType(resolved_type));
13197 const eql = try block.addCmpVector(result, floored, .eq);
1319613198 break :ok try block.addInst(.{
1319713199 .tag = switch (block.float_mode) {
1319813200 .Strict => .reduce,
......@@ -13216,7 +13218,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1321613218 if (resolved_type.zigTypeTag() == .Vector) {
1321713219 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
1321813220 const zero = try sema.addConstant(resolved_type, zero_val);
13219 const eql = try block.addCmpVector(remainder, zero, .eq, try sema.addType(resolved_type));
13221 const eql = try block.addCmpVector(remainder, zero, .eq);
1322013222 break :ok try block.addInst(.{
1322113223 .tag = .reduce,
1322213224 .data = .{ .reduce = .{
......@@ -13514,14 +13516,13 @@ fn addDivIntOverflowSafety(
1351413516
1351513517 var ok: Air.Inst.Ref = .none;
1351613518 if (resolved_type.zigTypeTag() == .Vector) {
13517 const vector_ty_ref = try sema.addType(resolved_type);
1351813519 if (maybe_lhs_val == null) {
1351913520 const min_int_ref = try sema.addConstant(resolved_type, min_int);
13520 ok = try block.addCmpVector(casted_lhs, min_int_ref, .neq, vector_ty_ref);
13521 ok = try block.addCmpVector(casted_lhs, min_int_ref, .neq);
1352113522 }
1352213523 if (maybe_rhs_val == null) {
1352313524 const neg_one_ref = try sema.addConstant(resolved_type, neg_one);
13524 const rhs_ok = try block.addCmpVector(casted_rhs, neg_one_ref, .neq, vector_ty_ref);
13525 const rhs_ok = try block.addCmpVector(casted_rhs, neg_one_ref, .neq);
1352513526 if (ok == .none) {
1352613527 ok = rhs_ok;
1352713528 } else {
......@@ -13573,7 +13574,7 @@ fn addDivByZeroSafety(
1357313574 const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
1357413575 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
1357513576 const zero = try sema.addConstant(resolved_type, zero_val);
13576 const ok = try block.addCmpVector(casted_rhs, zero, .neq, try sema.addType(resolved_type));
13577 const ok = try block.addCmpVector(casted_rhs, zero, .neq);
1357713578 break :ok try block.addInst(.{
1357813579 .tag = if (is_int) .reduce else .reduce_optimized,
1357913580 .data = .{ .reduce = .{
......@@ -15202,9 +15203,7 @@ fn cmpSelf(
1520215203 };
1520315204 try sema.requireRuntimeBlock(block, src, runtime_src);
1520415205 if (resolved_type.zigTypeTag() == .Vector) {
15205 const result_ty = try Type.vector(sema.arena, resolved_type.vectorLen(), Type.bool);
15206 const result_ty_ref = try sema.addType(result_ty);
15207 return block.addCmpVector(casted_lhs, casted_rhs, op, result_ty_ref);
15206 return block.addCmpVector(casted_lhs, casted_rhs, op);
1520815207 }
1520915208 const tag = Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized);
1521015209 return block.addBinOp(tag, casted_lhs, casted_rhs);
......@@ -23035,7 +23034,7 @@ fn panicSentinelMismatch(
2303523034
2303623035 const ok = if (sentinel_ty.zigTypeTag() == .Vector) ok: {
2303723036 const eql =
23038 try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq, try sema.addType(sentinel_ty));
23037 try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq);
2303923038 break :ok try parent_block.addInst(.{
2304023039 .tag = .reduce,
2304123040 .data = .{ .reduce = .{
......@@ -29368,8 +29367,7 @@ fn cmpVector(
2936829367 };
2936929368
2937029369 try sema.requireRuntimeBlock(block, src, runtime_src);
29371 const result_ty_inst = try sema.addType(result_ty);
29372 return block.addCmpVector(lhs, rhs, op, result_ty_inst);
29370 return block.addCmpVector(lhs, rhs, op);
2937329371}
2937429372
2937529373fn wrapOptional(
src/codegen/c.zig+895-511
......@@ -17,12 +17,6 @@ const LazySrcLoc = Module.LazySrcLoc;
1717const Air = @import("../Air.zig");
1818const Liveness = @import("../Liveness.zig");
1919
20const target_util = @import("../target.zig");
21const libcFloatPrefix = target_util.libcFloatPrefix;
22const libcFloatSuffix = target_util.libcFloatSuffix;
23const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev;
24const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;
25
2620const BigIntLimb = std.math.big.Limb;
2721const BigInt = std.math.big.int;
2822
......@@ -112,11 +106,7 @@ const ValueRenderLocation = enum {
112106 }
113107};
114108
115const BuiltinInfo = enum {
116 None,
117 Range,
118 Bits,
119};
109const BuiltinInfo = enum { none, bits };
120110
121111const reserved_idents = std.ComptimeStringMap(void, .{
122112 // C language
......@@ -440,16 +430,24 @@ pub const Function = struct {
440430 return f.object.dg.typeToCType(ty, kind);
441431 }
442432
433 fn byteSize(f: *Function, cty: CType) u64 {
434 return f.object.dg.byteSize(cty);
435 }
436
443437 fn renderType(f: *Function, w: anytype, t: Type) !void {
444438 return f.object.dg.renderType(w, t);
445439 }
446440
447 fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, src_ty: Type, location: ValueRenderLocation) !void {
448 return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src } }, src_ty, location);
441 fn renderCType(f: *Function, w: anytype, t: CType.Index) !void {
442 return f.object.dg.renderCType(w, t);
443 }
444
445 fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, v: Vectorizer, src_ty: Type, location: ValueRenderLocation) !void {
446 return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location);
449447 }
450448
451449 fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) {
452 return f.object.dg.fmtIntLiteral(ty, val);
450 return f.object.dg.fmtIntLiteral(ty, val, .Other);
453451 }
454452
455453 fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 {
......@@ -574,9 +572,9 @@ pub const DeclGen = struct {
574572 const len_val = Value.initPayload(&len_pl.base);
575573
576574 if (location == .StaticInitializer) {
577 return writer.print(", {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)});
575 return writer.print(", {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val, .Other)});
578576 } else {
579 return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)});
577 return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val, .Other)});
580578 }
581579 }
582580
......@@ -606,7 +604,7 @@ pub const DeclGen = struct {
606604 try writer.writeByte(')');
607605 }
608606 switch (ptr_val.tag()) {
609 .int_u64, .one => try writer.print("{x}", .{try dg.fmtIntLiteral(Type.usize, ptr_val)}),
607 .int_u64, .one => try writer.print("{x}", .{try dg.fmtIntLiteral(Type.usize, ptr_val, .Other)}),
610608 .decl_ref_mut, .decl_ref, .variable => {
611609 const decl_index = switch (ptr_val.tag()) {
612610 .decl_ref => ptr_val.castTag(.decl_ref).?.data,
......@@ -670,7 +668,9 @@ pub const DeclGen = struct {
670668 container_ptr_ty,
671669 location,
672670 );
673 try writer.print(" + {})", .{try dg.fmtIntLiteral(Type.usize, byte_offset_val)});
671 try writer.print(" + {})", .{
672 try dg.fmtIntLiteral(Type.usize, byte_offset_val, .Other),
673 });
674674 },
675675 .end => {
676676 try writer.writeAll("((");
......@@ -680,7 +680,9 @@ pub const DeclGen = struct {
680680 container_ptr_ty,
681681 location,
682682 );
683 try writer.print(") + {})", .{try dg.fmtIntLiteral(Type.usize, Value.one)});
683 try writer.print(") + {})", .{
684 try dg.fmtIntLiteral(Type.usize, Value.one, .Other),
685 });
684686 },
685687 }
686688 },
......@@ -746,7 +748,7 @@ pub const DeclGen = struct {
746748 return writer.writeAll("false");
747749 }
748750 },
749 .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteralLoc(ty, val, location)}),
751 .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val, location)}),
750752 .Float => {
751753 const bits = ty.floatBits(target);
752754 var int_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits };
......@@ -780,11 +782,11 @@ pub const DeclGen = struct {
780782 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
781783 const ptr_ty = ty.slicePtrFieldType(&buf);
782784 try dg.renderType(writer, ptr_ty);
783 return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val)});
785 return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
784786 } else {
785787 try writer.writeAll("((");
786788 try dg.renderType(writer, ty);
787 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)});
789 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
788790 },
789791 .Optional => {
790792 var opt_buf: Type.Payload.ElemType = undefined;
......@@ -831,7 +833,7 @@ pub const DeclGen = struct {
831833
832834 return writer.writeByte('}');
833835 },
834 .Packed => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef)}),
836 .Packed => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef, .Other)}),
835837 },
836838 .Union => {
837839 if (!location.isInitializer()) {
......@@ -854,7 +856,7 @@ pub const DeclGen = struct {
854856 if (!field.ty.hasRuntimeBits()) continue;
855857 try dg.renderValue(writer, field.ty, val, initializer_type);
856858 break;
857 } else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)});
859 } else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef, .Other)});
858860 if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
859861 return writer.writeByte('}');
860862 },
......@@ -868,7 +870,7 @@ pub const DeclGen = struct {
868870 try writer.writeAll("{ .payload = ");
869871 try dg.renderValue(writer, ty.errorUnionPayload(), val, initializer_type);
870872 return writer.print(", .error = {x} }}", .{
871 try dg.fmtIntLiteral(ty.errorUnionSet(), val),
873 try dg.fmtIntLiteral(ty.errorUnionSet(), val, .Other),
872874 });
873875 },
874876 .Array, .Vector => {
......@@ -927,7 +929,7 @@ pub const DeclGen = struct {
927929 .decl_ref_mut,
928930 .decl_ref,
929931 => try dg.renderParentPtr(writer, val, ty, location),
930 else => try writer.print("{}", .{try dg.fmtIntLiteralLoc(ty, val, location)}),
932 else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}),
931933 },
932934 .Float => {
933935 const bits = ty.floatBits(target);
......@@ -999,8 +1001,9 @@ pub const DeclGen = struct {
9991001 // return dg.fail("Only quiet nans are supported in global variable initializers", .{});
10001002 }
10011003
1002 try writer.writeAll("zig_make_special_");
1003 if (location == .StaticInitializer) try writer.writeAll("constant_");
1004 try writer.writeAll("zig_");
1005 try writer.writeAll(if (location == .StaticInitializer) "init" else "make");
1006 try writer.writeAll("_special_");
10041007 try dg.renderTypeForBuiltinFnName(writer, ty);
10051008 try writer.writeByte('(');
10061009 if (std.math.signbit(f128_val)) try writer.writeByte('-');
......@@ -1020,7 +1023,7 @@ pub const DeclGen = struct {
10201023 try writer.writeAll(", ");
10211024 empty = false;
10221025 }
1023 try writer.print("{x}", .{try dg.fmtIntLiteralLoc(int_ty, int_val, location)});
1026 try writer.print("{x}", .{try dg.fmtIntLiteral(int_ty, int_val, location)});
10241027 if (!empty) try writer.writeByte(')');
10251028 return;
10261029 },
......@@ -1069,7 +1072,7 @@ pub const DeclGen = struct {
10691072 .int_u64, .one => {
10701073 try writer.writeAll("((");
10711074 try dg.renderType(writer, ty);
1072 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)});
1075 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
10731076 },
10741077 .field_ptr,
10751078 .elem_ptr,
......@@ -1561,6 +1564,10 @@ pub const DeclGen = struct {
15611564 return dg.ctypes.typeToCType(dg.gpa, ty, dg.module, kind);
15621565 }
15631566
1567 fn byteSize(dg: *DeclGen, cty: CType) u64 {
1568 return cty.byteSize(dg.ctypes.set, dg.module.getTarget());
1569 }
1570
15641571 /// Renders a type as a single identifier, generating intermediate typedefs
15651572 /// if necessary.
15661573 ///
......@@ -1573,9 +1580,12 @@ pub const DeclGen = struct {
15731580 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
15741581 ///
15751582 fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void {
1583 try dg.renderCType(w, try dg.typeToIndex(t, .complete));
1584 }
1585
1586 fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void {
15761587 const store = &dg.ctypes.set;
15771588 const module = dg.module;
1578 const idx = try dg.typeToIndex(t, .complete);
15791589 _ = try renderTypePrefix(dg.decl_index, store.*, module, w, idx, .suffix, .{});
15801590 try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix, .{});
15811591 }
......@@ -1584,6 +1594,7 @@ pub const DeclGen = struct {
15841594 c_value: struct {
15851595 f: *Function,
15861596 value: CValue,
1597 v: Vectorizer,
15871598 },
15881599 value: struct {
15891600 value: Value,
......@@ -1593,6 +1604,7 @@ pub const DeclGen = struct {
15931604 switch (self.*) {
15941605 .c_value => |v| {
15951606 try v.f.writeCValue(w, v.value, location);
1607 try v.v.elem(v.f, w);
15961608 },
15971609 .value => |v| {
15981610 try dg.renderValue(w, value_ty, v.value, location);
......@@ -1829,79 +1841,67 @@ pub const DeclGen = struct {
18291841 dg.module.markDeclAlive(decl);
18301842
18311843 if (dg.module.decl_exports.get(decl_index)) |exports| {
1832 return writer.writeAll(exports.items[export_index].options.name);
1844 try writer.writeAll(exports.items[export_index].options.name);
18331845 } else if (decl.isExtern()) {
1834 return writer.writeAll(mem.sliceTo(decl.name, 0));
1835 } else if (dg.module.test_functions.get(decl_index)) |_| {
1836 const gpa = dg.gpa;
1837 const name = try decl.getFullyQualifiedName(dg.module);
1838 defer gpa.free(name);
1839 return writer.print("{}_{d}", .{ fmtIdent(name), @enumToInt(decl_index) });
1846 try writer.writeAll(mem.sliceTo(decl.name, 0));
18401847 } else {
1841 const gpa = dg.gpa;
1842 const name = try decl.getFullyQualifiedName(dg.module);
1843 defer gpa.free(name);
1844
1845 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), expand
1846 // to 3x the length of its input
1847 if (name.len > 1365) {
1848 var hash = ident_hasher_init;
1849 hash.update(name);
1850 const ident_hash = hash.finalInt();
1851 try writer.writeAll("zig_D_");
1852 return std.fmt.formatIntValue(ident_hash, "x", .{}, writer);
1853 } else {
1854 return writer.print("{}", .{fmtIdent(name)});
1855 }
1848 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
1849 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
1850 var name: [100]u8 = undefined;
1851 var name_stream = std.io.fixedBufferStream(&name);
1852 decl.renderFullyQualifiedName(dg.module, name_stream.writer()) catch |err| switch (err) {
1853 error.NoSpaceLeft => {},
1854 };
1855 try writer.print("{}__{d}", .{
1856 fmtIdent(name_stream.getWritten()),
1857 @enumToInt(decl_index),
1858 });
18561859 }
18571860 }
18581861
18591862 fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void {
1860 const target = dg.module.getTarget();
1861 if (ty.isAbiInt()) {
1862 const int_info = ty.intInfo(target);
1863 const c_bits = toCIntBits(int_info.bits) orelse
1864 return dg.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
1865 try writer.print("{c}{d}", .{ signAbbrev(int_info.signedness), c_bits });
1866 } else if (ty.isRuntimeFloat()) {
1867 try ty.print(writer, dg.module);
1868 } else if (ty.isPtrAtRuntime()) {
1869 try writer.print("p{d}", .{ty.bitSize(target)});
1870 } else if (ty.zigTypeTag() == .Bool) {
1871 try writer.print("u8", .{});
1872 } else return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{
1873 ty.fmt(dg.module),
1874 });
1863 try dg.renderCTypeForBuiltinFnName(writer, try dg.typeToCType(ty, .complete));
1864 }
1865
1866 fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, cty: CType) !void {
1867 switch (cty.tag()) {
1868 else => try writer.print("{c}{d}", .{
1869 if (cty.isBool())
1870 signAbbrev(.unsigned)
1871 else if (cty.isInteger())
1872 signAbbrev(cty.signedness() orelse .unsigned)
1873 else if (cty.isFloat())
1874 @as(u8, 'f')
1875 else if (cty.isPointer())
1876 @as(u8, 'p')
1877 else
1878 return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{
1879 cty.tag(),
1880 }),
1881 if (cty.isFloat()) cty.floatActiveBits(dg.module.getTarget()) else dg.byteSize(cty) * 8,
1882 }),
1883 .array => try writer.writeAll("big"),
1884 }
18751885 }
18761886
18771887 fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void {
1878 const target = dg.module.getTarget();
18791888 switch (info) {
1880 .None => {},
1881 .Range => {
1882 var arena = std.heap.ArenaAllocator.init(dg.gpa);
1883 defer arena.deinit();
1884
1885 const ExpectedContents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
1886 var stack align(@alignOf(ExpectedContents)) =
1887 std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
1888
1889 const int_info = ty.intInfo(target);
1890 if (int_info.signedness == .signed) {
1891 const min_val = try ty.minInt(stack.get(), target);
1892 try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, min_val)});
1893 }
1894
1895 const max_val = try ty.maxInt(stack.get(), target);
1896 try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, max_val)});
1897 },
1898 .Bits => {
1899 var bits_pl = Value.Payload.U64{
1900 .base = .{ .tag = .int_u64 },
1901 .data = ty.bitSize(target),
1889 .none => {},
1890 .bits => {
1891 const target = dg.module.getTarget();
1892 const int_info = if (ty.isAbiInt()) ty.intInfo(target) else std.builtin.Type.Int{
1893 .signedness = .unsigned,
1894 .bits = @intCast(u16, ty.bitSize(target)),
19021895 };
1903 const bits_val = Value.initPayload(&bits_pl.base);
1904 try writer.print(", {}", .{try dg.fmtIntLiteral(Type.u8, bits_val)});
1896
1897 const cty = try dg.typeToCType(ty, .complete);
1898 if (cty.tag() == .array) try writer.print(", {}", .{int_info.signedness == .signed});
1899
1900 var bits_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = int_info.bits };
1901 try writer.print(", {}", .{try dg.fmtIntLiteral(switch (cty.tag()) {
1902 else => Type.u8,
1903 .array => Type.u16,
1904 }, Value.initPayload(&bits_pl.base), .FunctionArgument)});
19051905 },
19061906 }
19071907 }
......@@ -1910,30 +1910,21 @@ pub const DeclGen = struct {
19101910 dg: *DeclGen,
19111911 ty: Type,
19121912 val: Value,
1913 loc: ValueRenderLocation,
19131914 ) !std.fmt.Formatter(formatIntLiteral) {
1914 const int_info = ty.intInfo(dg.module.getTarget());
1915 const c_bits = toCIntBits(int_info.bits);
1916 if (c_bits == null or c_bits.? > 128)
1917 return dg.fail("TODO implement integer constants larger than 128 bits", .{});
1915 const kind: CType.Kind = switch (loc) {
1916 .FunctionArgument => .parameter,
1917 .Initializer, .Other => .complete,
1918 .StaticInitializer => .global,
1919 };
19181920 return std.fmt.Formatter(formatIntLiteral){ .data = .{
1919 .ty = ty,
1921 .dg = dg,
1922 .int_info = ty.intInfo(dg.module.getTarget()),
1923 .kind = kind,
1924 .cty = try dg.typeToCType(ty, kind),
19201925 .val = val,
1921 .mod = dg.module,
19221926 } };
19231927 }
1924
1925 fn fmtIntLiteralLoc(
1926 dg: *DeclGen,
1927 ty: Type,
1928 val: Value,
1929 location: ValueRenderLocation, // TODO: Instead add this as optional arg to fmtIntLiteral
1930 ) !std.fmt.Formatter(formatIntLiteral) {
1931 const int_info = ty.intInfo(dg.module.getTarget());
1932 const c_bits = toCIntBits(int_info.bits);
1933 if (c_bits == null or c_bits.? > 128)
1934 return dg.fail("TODO implement integer constants larger than 128 bits", .{});
1935 return std.fmt.Formatter(formatIntLiteral){ .data = .{ .ty = ty, .val = val, .mod = dg.module, .location = location } };
1936 }
19371928};
19381929
19391930const CTypeFix = enum { prefix, suffix };
......@@ -2450,7 +2441,7 @@ pub fn genErrDecls(o: *Object) !void {
24502441 const len_val = Value.initPayload(&len_pl.base);
24512442
24522443 try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{
2453 fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val),
2444 fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val, .Other),
24542445 });
24552446 }
24562447 try writer.writeAll("};\n");
......@@ -2501,7 +2492,10 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
25012492 var int_pl: Value.Payload.U64 = undefined;
25022493 const int_val = tag_val.enumToInt(enum_ty, &int_pl);
25032494
2504 var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len };
2495 var name_ty_pl = Type.Payload.Len{
2496 .base = .{ .tag = .array_u8_sentinel_0 },
2497 .data = name.len,
2498 };
25052499 const name_ty = Type.initPayload(&name_ty_pl.base);
25062500
25072501 var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name };
......@@ -2510,14 +2504,16 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
25102504 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
25112505 const len_val = Value.initPayload(&len_pl.base);
25122506
2513 try w.print(" case {}: {{\n static ", .{try o.dg.fmtIntLiteral(enum_ty, int_val)});
2507 try w.print(" case {}: {{\n static ", .{
2508 try o.dg.fmtIntLiteral(enum_ty, int_val, .Other),
2509 });
25142510 try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, 0, .complete);
25152511 try w.writeAll(" = ");
25162512 try o.dg.renderValue(w, name_ty, name_val, .Initializer);
25172513 try w.writeAll(";\n return (");
25182514 try o.dg.renderType(w, name_slice_ty);
25192515 try w.print("){{{}, {}}};\n", .{
2520 fmtIdent("name"), try o.dg.fmtIntLiteral(Type.usize, len_val),
2516 fmtIdent("name"), try o.dg.fmtIntLiteral(Type.usize, len_val, .Other),
25212517 });
25222518
25232519 try w.writeAll(" }\n");
......@@ -2535,7 +2531,12 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
25352531
25362532 const fwd_decl_writer = o.dg.fwd_decl.writer();
25372533 try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)});
2538 try o.dg.renderFunctionSignature(fwd_decl_writer, fn_decl_index, .forward, .{ .string = fn_name });
2534 try o.dg.renderFunctionSignature(
2535 fwd_decl_writer,
2536 fn_decl_index,
2537 .forward,
2538 .{ .string = fn_name },
2539 );
25392540 try fwd_decl_writer.writeAll(";\n");
25402541
25412542 try w.print("static zig_{s} ", .{@tagName(key)});
......@@ -2753,35 +2754,35 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
27532754
27542755 // TODO use a different strategy for add, sub, mul, div
27552756 // that communicates to the optimizer that wrapping is UB.
2756 .add => try airBinOp(f, inst, "+", "add", .None),
2757 .sub => try airBinOp(f, inst, "-", "sub", .None),
2758 .mul => try airBinOp(f, inst, "*", "mul", .None),
2757 .add => try airBinOp(f, inst, "+", "add", .none),
2758 .sub => try airBinOp(f, inst, "-", "sub", .none),
2759 .mul => try airBinOp(f, inst, "*", "mul", .none),
27592760
27602761 .neg => try airFloatNeg(f, inst),
2761 .div_float => try airBinBuiltinCall(f, inst, "div", .None),
2762 .div_float => try airBinBuiltinCall(f, inst, "div", .none),
27622763
2763 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None),
2764 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none),
27642765 .rem => blk: {
27652766 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2766 const lhs_ty = f.air.typeOf(bin_op.lhs);
2767 const lhs_scalar_ty = f.air.typeOf(bin_op.lhs).scalarType();
27672768 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
27682769 // so we only check one.
2769 break :blk if (lhs_ty.isInt())
2770 try airBinOp(f, inst, "%", "rem", .None)
2770 break :blk if (lhs_scalar_ty.isInt())
2771 try airBinOp(f, inst, "%", "rem", .none)
27712772 else
27722773 try airBinFloatOp(f, inst, "fmod");
27732774 },
2774 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None),
2775 .mod => try airBinBuiltinCall(f, inst, "mod", .None),
2775 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none),
2776 .mod => try airBinBuiltinCall(f, inst, "mod", .none),
27762777
2777 .addwrap => try airBinBuiltinCall(f, inst, "addw", .Bits),
2778 .subwrap => try airBinBuiltinCall(f, inst, "subw", .Bits),
2779 .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .Bits),
2778 .addwrap => try airBinBuiltinCall(f, inst, "addw", .bits),
2779 .subwrap => try airBinBuiltinCall(f, inst, "subw", .bits),
2780 .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .bits),
27802781
2781 .add_sat => try airBinBuiltinCall(f, inst, "adds", .Bits),
2782 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .Bits),
2783 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits),
2784 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits),
2782 .add_sat => try airBinBuiltinCall(f, inst, "adds", .bits),
2783 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .bits),
2784 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .bits),
2785 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits),
27852786
27862787 .sqrt => try airUnFloatOp(f, inst, "sqrt"),
27872788 .sin => try airUnFloatOp(f, inst, "sin"),
......@@ -2800,34 +2801,38 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
28002801
28012802 .mul_add => try airMulAdd(f, inst),
28022803
2803 .add_with_overflow => try airOverflow(f, inst, "add", .Bits),
2804 .sub_with_overflow => try airOverflow(f, inst, "sub", .Bits),
2805 .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits),
2806 .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits),
2804 .add_with_overflow => try airOverflow(f, inst, "add", .bits),
2805 .sub_with_overflow => try airOverflow(f, inst, "sub", .bits),
2806 .mul_with_overflow => try airOverflow(f, inst, "mul", .bits),
2807 .shl_with_overflow => try airOverflow(f, inst, "shl", .bits),
28072808
28082809 .min => try airMinMax(f, inst, '<', "fmin"),
28092810 .max => try airMinMax(f, inst, '>', "fmax"),
28102811
28112812 .slice => try airSlice(f, inst),
28122813
2813 .cmp_gt => try airCmpOp(f, inst, ">", "gt"),
2814 .cmp_gte => try airCmpOp(f, inst, ">=", "ge"),
2815 .cmp_lt => try airCmpOp(f, inst, "<", "lt"),
2816 .cmp_lte => try airCmpOp(f, inst, "<=", "le"),
2814 .cmp_gt => try airCmpOp(f, inst, f.air.instructions.items(.data)[inst].bin_op, .gt),
2815 .cmp_gte => try airCmpOp(f, inst, f.air.instructions.items(.data)[inst].bin_op, .gte),
2816 .cmp_lt => try airCmpOp(f, inst, f.air.instructions.items(.data)[inst].bin_op, .lt),
2817 .cmp_lte => try airCmpOp(f, inst, f.air.instructions.items(.data)[inst].bin_op, .lte),
28172818
2818 .cmp_eq => try airEquality(f, inst, "((", "==", "eq"),
2819 .cmp_neq => try airEquality(f, inst, "!((", "!=", "ne"),
2819 .cmp_eq => try airEquality(f, inst, .eq),
2820 .cmp_neq => try airEquality(f, inst, .neq),
28202821
2821 .cmp_vector => return f.fail("TODO: C backend: implement cmp_vector", .{}),
2822 .cmp_vector => blk: {
2823 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
2824 const extra = f.air.extraData(Air.VectorCmp, ty_pl.payload).data;
2825 break :blk try airCmpOp(f, inst, extra, extra.compareOperator());
2826 },
28222827 .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst),
28232828
28242829 // bool_and and bool_or are non-short-circuit operations
2825 .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .None),
2826 .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .None),
2827 .xor => try airBinOp(f, inst, "^", "xor", .None),
2828 .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .None),
2829 .shl, => try airBinBuiltinCall(f, inst, "shlw", .Bits),
2830 .shl_exact => try airBinOp(f, inst, "<<", "shl", .None),
2830 .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .none),
2831 .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .none),
2832 .xor => try airBinOp(f, inst, "^", "xor", .none),
2833 .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .none),
2834 .shl, => try airBinBuiltinCall(f, inst, "shlw", .bits),
2835 .shl_exact => try airBinOp(f, inst, "<<", "shl", .none),
28312836 .not => try airNot (f, inst),
28322837
28332838 .optional_payload => try airOptionalPayload(f, inst),
......@@ -2872,11 +2877,11 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
28722877 .memcpy => try airMemcpy(f, inst),
28732878 .set_union_tag => try airSetUnionTag(f, inst),
28742879 .get_union_tag => try airGetUnionTag(f, inst),
2875 .clz => try airUnBuiltinCall(f, inst, "clz", .Bits),
2876 .ctz => try airUnBuiltinCall(f, inst, "ctz", .Bits),
2877 .popcount => try airUnBuiltinCall(f, inst, "popcount", .Bits),
2878 .byte_swap => try airUnBuiltinCall(f, inst, "byte_swap", .Bits),
2879 .bit_reverse => try airUnBuiltinCall(f, inst, "bit_reverse", .Bits),
2880 .clz => try airUnBuiltinCall(f, inst, "clz", .bits),
2881 .ctz => try airUnBuiltinCall(f, inst, "ctz", .bits),
2882 .popcount => try airUnBuiltinCall(f, inst, "popcount", .bits),
2883 .byte_swap => try airUnBuiltinCall(f, inst, "byte_swap", .bits),
2884 .bit_reverse => try airUnBuiltinCall(f, inst, "bit_reverse", .bits),
28802885 .tag_name => try airTagName(f, inst),
28812886 .error_name => try airErrorName(f, inst),
28822887 .splat => try airSplat(f, inst),
......@@ -3267,7 +3272,10 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
32673272
32683273fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
32693274 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3270 const ptr_info = f.air.typeOf(ty_op.operand).ptrInfo().data;
3275
3276 const ptr_ty = f.air.typeOf(ty_op.operand);
3277 const ptr_scalar_ty = ptr_ty.scalarType();
3278 const ptr_info = ptr_scalar_ty.ptrInfo().data;
32713279 const src_ty = ptr_info.pointee_type;
32723280
32733281 if (!src_ty.hasRuntimeBitsIgnoreComptime() or
......@@ -3285,20 +3293,23 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
32853293 const is_aligned = ptr_info.@"align" == 0 or ptr_info.@"align" >= src_ty.abiAlignment(target);
32863294 const is_array = lowersToArray(src_ty, target);
32873295 const need_memcpy = !is_aligned or is_array;
3288 const writer = f.object.writer();
32893296
3297 const writer = f.object.writer();
32903298 const local = try f.allocLocal(inst, src_ty);
3299 const v = try Vectorizer.start(f, inst, writer, ptr_ty);
32913300
32923301 if (need_memcpy) {
32933302 try writer.writeAll("memcpy(");
32943303 if (!is_array) try writer.writeByte('&');
3295 try f.writeCValue(writer, local, .FunctionArgument);
3304 try f.writeCValue(writer, local, .Other);
3305 try v.elem(f, writer);
32963306 try writer.writeAll(", (const char *)");
32973307 try f.writeCValue(writer, operand, .Other);
3308 try v.elem(f, writer);
32983309 try writer.writeAll(", sizeof(");
32993310 try f.renderType(writer, src_ty);
33003311 try writer.writeAll("))");
3301 } else if (ptr_info.host_size != 0) {
3312 } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) {
33023313 var host_pl = Type.Payload.Bits{
33033314 .base = .{ .tag = .int_unsigned },
33043315 .data = ptr_info.host_size * 8,
......@@ -3324,6 +3335,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
33243335 const field_ty = Type.initPayload(&field_pl.base);
33253336
33263337 try f.writeCValue(writer, local, .Other);
3338 try v.elem(f, writer);
33273339 try writer.writeAll(" = (");
33283340 try f.renderType(writer, src_ty);
33293341 try writer.writeAll(")zig_wrap_");
......@@ -3342,16 +3354,21 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
33423354 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
33433355 try writer.writeByte('(');
33443356 try f.writeCValueDeref(writer, operand);
3357 try v.elem(f, writer);
33453358 try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)});
33463359 if (cant_cast) try writer.writeByte(')');
3347 try f.object.dg.renderBuiltinInfo(writer, field_ty, .Bits);
3360 try f.object.dg.renderBuiltinInfo(writer, field_ty, .bits);
33483361 try writer.writeByte(')');
33493362 } else {
33503363 try f.writeCValue(writer, local, .Other);
3364 try v.elem(f, writer);
33513365 try writer.writeAll(" = ");
33523366 try f.writeCValueDeref(writer, operand);
3367 try v.elem(f, writer);
33533368 }
33543369 try writer.writeAll(";\n");
3370 try v.end(f, inst, writer);
3371
33553372 return local;
33563373}
33573374
......@@ -3417,15 +3434,22 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
34173434
34183435 const operand = try f.resolveInst(ty_op.operand);
34193436 try reap(f, inst, &.{ty_op.operand});
3420 const writer = f.object.writer();
3437
34213438 const inst_ty = f.air.typeOfIndex(inst);
3422 const local = try f.allocLocal(inst, inst_ty);
3439 const inst_scalar_ty = inst_ty.scalarType();
34233440 const operand_ty = f.air.typeOf(ty_op.operand);
3441 const scalar_ty = operand_ty.scalarType();
34243442
3443 const writer = f.object.writer();
3444 const local = try f.allocLocal(inst, inst_ty);
3445 const v = try Vectorizer.start(f, inst, writer, operand_ty);
34253446 try f.writeCValue(writer, local, .Other);
3447 try v.elem(f, writer);
34263448 try writer.writeAll(" = ");
3427 try f.renderIntCast(writer, inst_ty, operand, operand_ty, .Other);
3449 try f.renderIntCast(writer, inst_scalar_ty, operand, v, scalar_ty, .Other);
34283450 try writer.writeAll(";\n");
3451 try v.end(f, inst, writer);
3452
34293453 return local;
34303454}
34313455
......@@ -3439,34 +3463,40 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
34393463 const operand = try f.resolveInst(ty_op.operand);
34403464 try reap(f, inst, &.{ty_op.operand});
34413465 const inst_ty = f.air.typeOfIndex(inst);
3442 const writer = f.object.writer();
3443 const local = try f.allocLocal(inst, inst_ty);
3466 const inst_scalar_ty = inst_ty.scalarType();
34443467 const target = f.object.dg.module.getTarget();
3445 const dest_int_info = inst_ty.intInfo(target);
3468 const dest_int_info = inst_scalar_ty.intInfo(target);
34463469 const dest_bits = dest_int_info.bits;
34473470 const dest_c_bits = toCIntBits(dest_int_info.bits) orelse
34483471 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
34493472 const operand_ty = f.air.typeOf(ty_op.operand);
3450 const operand_int_info = operand_ty.intInfo(target);
3473 const scalar_ty = operand_ty.scalarType();
3474 const scalar_int_info = scalar_ty.intInfo(target);
3475
3476 const writer = f.object.writer();
3477 const local = try f.allocLocal(inst, inst_ty);
3478 const v = try Vectorizer.start(f, inst, writer, operand_ty);
34513479
34523480 try f.writeCValue(writer, local, .Other);
3481 try v.elem(f, writer);
34533482 try writer.writeAll(" = ");
34543483
34553484 if (dest_c_bits < 64) {
34563485 try writer.writeByte('(');
3457 try f.renderType(writer, inst_ty);
3486 try f.renderType(writer, inst_scalar_ty);
34583487 try writer.writeByte(')');
34593488 }
34603489
3461 const needs_lo = operand_int_info.bits > 64 and dest_bits <= 64;
3490 const needs_lo = scalar_int_info.bits > 64 and dest_bits <= 64;
34623491 if (needs_lo) {
34633492 try writer.writeAll("zig_lo_");
3464 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
3493 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
34653494 try writer.writeByte('(');
34663495 }
34673496
34683497 if (dest_bits >= 8 and std.math.isPowerOfTwo(dest_bits)) {
34693498 try f.writeCValue(writer, operand, .Other);
3499 try v.elem(f, writer);
34703500 } else switch (dest_int_info.signedness) {
34713501 .unsigned => {
34723502 var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa);
......@@ -3476,15 +3506,16 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
34763506 var stack align(@alignOf(ExpectedContents)) =
34773507 std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
34783508
3479 const mask_val = try inst_ty.maxInt(stack.get(), target);
3509 const mask_val = try inst_scalar_ty.maxInt(stack.get(), target);
34803510 try writer.writeAll("zig_and_");
3481 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
3511 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
34823512 try writer.writeByte('(');
34833513 try f.writeCValue(writer, operand, .FunctionArgument);
3484 try writer.print(", {x})", .{try f.fmtIntLiteral(operand_ty, mask_val)});
3514 try v.elem(f, writer);
3515 try writer.print(", {x})", .{try f.fmtIntLiteral(scalar_ty, mask_val)});
34853516 },
34863517 .signed => {
3487 const c_bits = toCIntBits(operand_int_info.bits) orelse
3518 const c_bits = toCIntBits(scalar_int_info.bits) orelse
34883519 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
34893520 var shift_pl = Value.Payload.U64{
34903521 .base = .{ .tag = .int_u64 },
......@@ -3493,7 +3524,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
34933524 const shift_val = Value.initPayload(&shift_pl.base);
34943525
34953526 try writer.writeAll("zig_shr_");
3496 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
3527 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
34973528 if (c_bits == 128) {
34983529 try writer.print("(zig_bitcast_i{d}(", .{c_bits});
34993530 } else {
......@@ -3506,6 +3537,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
35063537 try writer.print("(uint{d}_t)", .{c_bits});
35073538 }
35083539 try f.writeCValue(writer, operand, .FunctionArgument);
3540 try v.elem(f, writer);
35093541 if (c_bits == 128) try writer.writeByte(')');
35103542 try writer.print(", {})", .{try f.fmtIntLiteral(Type.u8, shift_val)});
35113543 if (c_bits == 128) try writer.writeByte(')');
......@@ -3515,6 +3547,8 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
35153547
35163548 if (needs_lo) try writer.writeByte(')');
35173549 try writer.writeAll(";\n");
3550 try v.end(f, inst, writer);
3551
35183552 return local;
35193553}
35203554
......@@ -3551,7 +3585,10 @@ fn storeUndefined(f: *Function, lhs_child_ty: Type, dest_ptr: CValue) !CValue {
35513585fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
35523586 // *a = b;
35533587 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3554 const ptr_info = f.air.typeOf(bin_op.lhs).ptrInfo().data;
3588
3589 const ptr_ty = f.air.typeOf(bin_op.lhs);
3590 const ptr_scalar_ty = ptr_ty.scalarType();
3591 const ptr_info = ptr_scalar_ty.ptrInfo().data;
35553592 if (!ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime()) {
35563593 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
35573594 return .none;
......@@ -3574,11 +3611,13 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
35743611 ptr_info.@"align" >= ptr_info.pointee_type.abiAlignment(target);
35753612 const is_array = lowersToArray(ptr_info.pointee_type, target);
35763613 const need_memcpy = !is_aligned or is_array;
3577 const writer = f.object.writer();
35783614
35793615 const src_val = try f.resolveInst(bin_op.rhs);
35803616 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
35813617
3618 const writer = f.object.writer();
3619 const v = try Vectorizer.start(f, inst, writer, ptr_ty);
3620
35823621 if (need_memcpy) {
35833622 // For this memcpy to safely work we need the rhs to have the same
35843623 // underlying type as the lhs (i.e. they must both be arrays of the same underlying type).
......@@ -3599,16 +3638,18 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
35993638
36003639 try writer.writeAll("memcpy((char *)");
36013640 try f.writeCValue(writer, ptr_val, .FunctionArgument);
3641 try v.elem(f, writer);
36023642 try writer.writeAll(", ");
36033643 if (!is_array) try writer.writeByte('&');
36043644 try f.writeCValue(writer, array_src, .FunctionArgument);
3645 try v.elem(f, writer);
36053646 try writer.writeAll(", sizeof(");
36063647 try f.renderType(writer, src_ty);
36073648 try writer.writeAll("))");
36083649 if (src_val == .constant) {
36093650 try freeLocal(f, inst, array_src.new_local, 0);
36103651 }
3611 } else if (ptr_info.host_size != 0) {
3652 } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) {
36123653 const host_bits = ptr_info.host_size * 8;
36133654 var host_pl = Type.Payload.Bits{ .base = .{ .tag = .int_unsigned }, .data = host_bits };
36143655 const host_ty = Type.initPayload(&host_pl.base);
......@@ -3645,12 +3686,14 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
36453686 const mask_val = Value.initPayload(&mask_pl.base);
36463687
36473688 try f.writeCValueDeref(writer, ptr_val);
3689 try v.elem(f, writer);
36483690 try writer.writeAll(" = zig_or_");
36493691 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
36503692 try writer.writeAll("(zig_and_");
36513693 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
36523694 try writer.writeByte('(');
36533695 try f.writeCValueDeref(writer, ptr_val);
3696 try v.elem(f, writer);
36543697 try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(host_ty, mask_val)});
36553698 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
36563699 try writer.writeByte('(');
......@@ -3672,14 +3715,19 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
36723715 try writer.writeByte(')');
36733716 }
36743717 try f.writeCValue(writer, src_val, .Other);
3718 try v.elem(f, writer);
36753719 if (cant_cast) try writer.writeByte(')');
36763720 try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)});
36773721 } else {
36783722 try f.writeCValueDeref(writer, ptr_val);
3723 try v.elem(f, writer);
36793724 try writer.writeAll(" = ");
36803725 try f.writeCValue(writer, src_val, .Other);
3726 try v.elem(f, writer);
36813727 }
36823728 try writer.writeAll(";\n");
3729 try v.end(f, inst, writer);
3730
36833731 return .none;
36843732}
36853733
......@@ -3697,51 +3745,39 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
36973745 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
36983746
36993747 const inst_ty = f.air.typeOfIndex(inst);
3700 const vector_ty = f.air.typeOf(bin_op.lhs);
3701 const scalar_ty = vector_ty.scalarType();
3702 const w = f.object.writer();
3748 const operand_ty = f.air.typeOf(bin_op.lhs);
3749 const scalar_ty = operand_ty.scalarType();
37033750
3751 const w = f.object.writer();
37043752 const local = try f.allocLocal(inst, inst_ty);
3705
3706 switch (vector_ty.zigTypeTag()) {
3707 .Vector => {
3708 try w.writeAll("zig_v");
3709 try w.writeAll(operation);
3710 try w.writeAll("o_");
3711 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3712 try w.writeAll("(");
3713 try f.writeCValueMember(w, local, .{ .field = 1 });
3714 try w.writeAll(", ");
3715 try f.writeCValueMember(w, local, .{ .field = 0 });
3716 try w.print(", {d}, ", .{vector_ty.vectorLen()});
3717 },
3718 else => {
3719 try f.writeCValueMember(w, local, .{ .field = 1 });
3720 try w.writeAll(" = zig_");
3721 try w.writeAll(operation);
3722 try w.writeAll("o_");
3723 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3724 try w.writeAll("(&");
3725 try f.writeCValueMember(w, local, .{ .field = 0 });
3726 try w.writeAll(", ");
3727 },
3728 }
3729
3753 const v = try Vectorizer.start(f, inst, w, operand_ty);
3754 try f.writeCValueMember(w, local, .{ .field = 1 });
3755 try v.elem(f, w);
3756 try w.writeAll(" = zig_");
3757 try w.writeAll(operation);
3758 try w.writeAll("o_");
3759 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3760 try w.writeAll("(&");
3761 try f.writeCValueMember(w, local, .{ .field = 0 });
3762 try v.elem(f, w);
3763 try w.writeAll(", ");
37303764 try f.writeCValue(w, lhs, .FunctionArgument);
3765 try v.elem(f, w);
37313766 try w.writeAll(", ");
37323767 try f.writeCValue(w, rhs, .FunctionArgument);
3768 try v.elem(f, w);
37333769 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
37343770 try w.writeAll(");\n");
3771 try v.end(f, inst, w);
37353772
37363773 return local;
37373774}
37383775
37393776fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
3740 const inst_ty = f.air.typeOfIndex(inst);
3741 if (inst_ty.tag() != .bool)
3742 return try airUnBuiltinCall(f, inst, "not", .Bits);
3743
37443777 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3778 const operand_ty = f.air.typeOf(ty_op.operand);
3779 const scalar_ty = operand_ty.scalarType();
3780 if (scalar_ty.tag() != .bool) return try airUnBuiltinCall(f, inst, "not", .bits);
37453781
37463782 if (f.liveness.isUnused(inst)) {
37473783 try reap(f, inst, &.{ty_op.operand});
......@@ -3751,14 +3787,20 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
37513787 const op = try f.resolveInst(ty_op.operand);
37523788 try reap(f, inst, &.{ty_op.operand});
37533789
3790 const inst_ty = f.air.typeOfIndex(inst);
3791
37543792 const writer = f.object.writer();
37553793 const local = try f.allocLocal(inst, inst_ty);
3756
3794 const v = try Vectorizer.start(f, inst, writer, operand_ty);
37573795 try f.writeCValue(writer, local, .Other);
3796 try v.elem(f, writer);
37583797 try writer.writeAll(" = ");
37593798 try writer.writeByte('!');
37603799 try f.writeCValue(writer, op, .Other);
3800 try v.elem(f, writer);
37613801 try writer.writeAll(";\n");
3802 try v.end(f, inst, writer);
3803
37623804 return local;
37633805}
37643806
......@@ -3771,63 +3813,89 @@ fn airBinOp(
37713813) !CValue {
37723814 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
37733815 const operand_ty = f.air.typeOf(bin_op.lhs);
3816 const scalar_ty = operand_ty.scalarType();
37743817 const target = f.object.dg.module.getTarget();
3775 if ((operand_ty.isInt() and operand_ty.bitSize(target) > 64) or operand_ty.isRuntimeFloat())
3818 if ((scalar_ty.isInt() and scalar_ty.bitSize(target) > 64) or scalar_ty.isRuntimeFloat())
37763819 return try airBinBuiltinCall(f, inst, operation, info);
37773820
3821 if (f.liveness.isUnused(inst)) {
3822 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3823 return .none;
3824 }
3825
37783826 const lhs = try f.resolveInst(bin_op.lhs);
37793827 const rhs = try f.resolveInst(bin_op.rhs);
3780
37813828 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37823829
3783 if (f.liveness.isUnused(inst)) return .none;
3784
37853830 const inst_ty = f.air.typeOfIndex(inst);
37863831
37873832 const writer = f.object.writer();
37883833 const local = try f.allocLocal(inst, inst_ty);
3834 const v = try Vectorizer.start(f, inst, writer, operand_ty);
37893835 try f.writeCValue(writer, local, .Other);
3836 try v.elem(f, writer);
37903837 try writer.writeAll(" = ");
37913838 try f.writeCValue(writer, lhs, .Other);
3839 try v.elem(f, writer);
37923840 try writer.writeByte(' ');
37933841 try writer.writeAll(operator);
37943842 try writer.writeByte(' ');
37953843 try f.writeCValue(writer, rhs, .Other);
3844 try v.elem(f, writer);
37963845 try writer.writeAll(";\n");
3846 try v.end(f, inst, writer);
37973847
37983848 return local;
37993849}
38003850
3801fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: []const u8) !CValue {
3802 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3803
3851fn airCmpOp(
3852 f: *Function,
3853 inst: Air.Inst.Index,
3854 data: anytype,
3855 operator: std.math.CompareOperator,
3856) !CValue {
38043857 if (f.liveness.isUnused(inst)) {
3805 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3858 try reap(f, inst, &.{ data.lhs, data.rhs });
38063859 return .none;
38073860 }
38083861
3809 const operand_ty = f.air.typeOf(bin_op.lhs);
3862 const operand_ty = f.air.typeOf(data.lhs);
3863 const scalar_ty = operand_ty.scalarType();
3864
38103865 const target = f.object.dg.module.getTarget();
3811 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)
3812 return try cmpBuiltinCall(f, inst, operator, "cmp");
3813 if (operand_ty.isRuntimeFloat())
3814 return try cmpBuiltinCall(f, inst, operator, operation);
3866 const scalar_bits = scalar_ty.bitSize(target);
3867 if (scalar_ty.isInt() and scalar_bits > 64)
3868 return airCmpBuiltinCall(
3869 f,
3870 inst,
3871 data,
3872 operator,
3873 .cmp,
3874 if (scalar_bits > 128) .bits else .none,
3875 );
3876 if (scalar_ty.isRuntimeFloat())
3877 return airCmpBuiltinCall(f, inst, data, operator, .operator, .none);
38153878
38163879 const inst_ty = f.air.typeOfIndex(inst);
3817 const lhs = try f.resolveInst(bin_op.lhs);
3818 const rhs = try f.resolveInst(bin_op.rhs);
3819 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
3880 const lhs = try f.resolveInst(data.lhs);
3881 const rhs = try f.resolveInst(data.rhs);
3882 try reap(f, inst, &.{ data.lhs, data.rhs });
38203883
38213884 const writer = f.object.writer();
38223885 const local = try f.allocLocal(inst, inst_ty);
3886 const v = try Vectorizer.start(f, inst, writer, operand_ty);
38233887 try f.writeCValue(writer, local, .Other);
3888 try v.elem(f, writer);
38243889 try writer.writeAll(" = ");
38253890 try f.writeCValue(writer, lhs, .Other);
3891 try v.elem(f, writer);
38263892 try writer.writeByte(' ');
3827 try writer.writeAll(operator);
3893 try writer.writeAll(compareOperatorC(operator));
38283894 try writer.writeByte(' ');
38293895 try f.writeCValue(writer, rhs, .Other);
3896 try v.elem(f, writer);
38303897 try writer.writeAll(";\n");
3898 try v.end(f, inst, writer);
38313899
38323900 return local;
38333901}
......@@ -3835,9 +3903,7 @@ fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation:
38353903fn airEquality(
38363904 f: *Function,
38373905 inst: Air.Inst.Index,
3838 negate_prefix: []const u8,
3839 operator: []const u8,
3840 operation: []const u8,
3906 operator: std.math.CompareOperator,
38413907) !CValue {
38423908 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
38433909
......@@ -3848,10 +3914,18 @@ fn airEquality(
38483914
38493915 const operand_ty = f.air.typeOf(bin_op.lhs);
38503916 const target = f.object.dg.module.getTarget();
3851 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)
3852 return try cmpBuiltinCall(f, inst, operator, "cmp");
3917 const operand_bits = operand_ty.bitSize(target);
3918 if (operand_ty.isInt() and operand_bits > 64)
3919 return airCmpBuiltinCall(
3920 f,
3921 inst,
3922 bin_op,
3923 operator,
3924 .cmp,
3925 if (operand_bits > 128) .bits else .none,
3926 );
38533927 if (operand_ty.isRuntimeFloat())
3854 return try cmpBuiltinCall(f, inst, operator, operation);
3928 return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none);
38553929
38563930 const lhs = try f.resolveInst(bin_op.lhs);
38573931 const rhs = try f.resolveInst(bin_op.rhs);
......@@ -3867,7 +3941,12 @@ fn airEquality(
38673941 // (A && B) || (C && (A == B))
38683942 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload
38693943
3870 try writer.writeAll(negate_prefix);
3944 switch (operator) {
3945 .eq => {},
3946 .neq => try writer.writeByte('!'),
3947 else => unreachable,
3948 }
3949 try writer.writeAll("((");
38713950 try f.writeCValue(writer, lhs, .Other);
38723951 try writer.writeAll(".is_null && ");
38733952 try f.writeCValue(writer, rhs, .Other);
......@@ -3886,7 +3965,7 @@ fn airEquality(
38863965
38873966 try f.writeCValue(writer, lhs, .Other);
38883967 try writer.writeByte(' ');
3889 try writer.writeAll(operator);
3968 try writer.writeAll(compareOperatorC(operator));
38903969 try writer.writeByte(' ');
38913970 try f.writeCValue(writer, rhs, .Other);
38923971 try writer.writeAll(";\n");
......@@ -3928,11 +4007,14 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
39284007 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
39294008
39304009 const inst_ty = f.air.typeOfIndex(inst);
3931 const elem_ty = inst_ty.elemType2();
4010 const inst_scalar_ty = inst_ty.scalarType();
4011 const elem_ty = inst_scalar_ty.elemType2();
39324012
39334013 const local = try f.allocLocal(inst, inst_ty);
39344014 const writer = f.object.writer();
4015 const v = try Vectorizer.start(f, inst, writer, inst_ty);
39354016 try f.writeCValue(writer, local, .Other);
4017 try v.elem(f, writer);
39364018 try writer.writeAll(" = ");
39374019
39384020 if (elem_ty.hasRuntimeBitsIgnoreComptime()) {
......@@ -3940,19 +4022,26 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
39404022 // results in a NULL pointer, or if LHS is NULL. The operation is only UB
39414023 // if the result is NULL and then dereferenced.
39424024 try writer.writeByte('(');
3943 try f.renderType(writer, inst_ty);
4025 try f.renderType(writer, inst_scalar_ty);
39444026 try writer.writeAll(")(((uintptr_t)");
39454027 try f.writeCValue(writer, lhs, .Other);
4028 try v.elem(f, writer);
39464029 try writer.writeAll(") ");
39474030 try writer.writeByte(operator);
39484031 try writer.writeAll(" (");
39494032 try f.writeCValue(writer, rhs, .Other);
4033 try v.elem(f, writer);
39504034 try writer.writeAll("*sizeof(");
39514035 try f.renderType(writer, elem_ty);
39524036 try writer.writeAll(")))");
3953 } else try f.writeCValue(writer, lhs, .Initializer);
4037 } else {
4038 try f.writeCValue(writer, lhs, .Other);
4039 try v.elem(f, writer);
4040 }
39544041
39554042 try writer.writeAll(";\n");
4043 try v.end(f, inst, writer);
4044
39564045 return local;
39574046}
39584047
......@@ -3965,10 +4054,12 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
39654054 }
39664055
39674056 const inst_ty = f.air.typeOfIndex(inst);
4057 const inst_scalar_ty = inst_ty.scalarType();
4058
39684059 const target = f.object.dg.module.getTarget();
3969 if (inst_ty.isInt() and inst_ty.bitSize(target) > 64)
3970 return try airBinBuiltinCall(f, inst, operation[1..], .None);
3971 if (inst_ty.isRuntimeFloat())
4060 if (inst_scalar_ty.isInt() and inst_scalar_ty.bitSize(target) > 64)
4061 return try airBinBuiltinCall(f, inst, operation[1..], .none);
4062 if (inst_scalar_ty.isRuntimeFloat())
39724063 return try airBinFloatOp(f, inst, operation);
39734064
39744065 const lhs = try f.resolveInst(bin_op.lhs);
......@@ -3977,19 +4068,26 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
39774068
39784069 const writer = f.object.writer();
39794070 const local = try f.allocLocal(inst, inst_ty);
4071 const v = try Vectorizer.start(f, inst, writer, inst_ty);
39804072 try f.writeCValue(writer, local, .Other);
4073 try v.elem(f, writer);
39814074 // (lhs <> rhs) ? lhs : rhs
39824075 try writer.writeAll(" = (");
39834076 try f.writeCValue(writer, lhs, .Other);
4077 try v.elem(f, writer);
39844078 try writer.writeByte(' ');
39854079 try writer.writeByte(operator);
39864080 try writer.writeByte(' ');
39874081 try f.writeCValue(writer, rhs, .Other);
4082 try v.elem(f, writer);
39884083 try writer.writeAll(") ? ");
39894084 try f.writeCValue(writer, lhs, .Other);
4085 try v.elem(f, writer);
39904086 try writer.writeAll(" : ");
39914087 try f.writeCValue(writer, rhs, .Other);
4088 try v.elem(f, writer);
39924089 try writer.writeAll(";\n");
4090 try v.end(f, inst, writer);
39934091
39944092 return local;
39954093}
......@@ -4413,12 +4511,56 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
44134511
44144512 // Ensure padding bits have the expected value.
44154513 if (dest_ty.isAbiInt()) {
4514 const dest_cty = try f.typeToCType(dest_ty, .complete);
4515 const dest_info = dest_ty.intInfo(target);
4516 var info_ty_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dest_info.signedness) {
4517 .unsigned => .int_unsigned,
4518 .signed => .int_signed,
4519 } }, .data = dest_info.bits };
4520 var wrap_cty: ?CType = null;
4521 var need_bitcasts = false;
4522
44164523 try f.writeCValue(writer, local, .Other);
4417 try writer.writeAll(" = zig_wrap_");
4418 try f.object.dg.renderTypeForBuiltinFnName(writer, dest_ty);
4524 if (dest_cty.castTag(.array)) |pl| {
4525 try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) {
4526 .Little => pl.data.len - 1,
4527 .Big => 0,
4528 }});
4529 const elem_cty = f.indexToCType(pl.data.elem_type);
4530 wrap_cty = elem_cty.toSignedness(dest_info.signedness);
4531 need_bitcasts = wrap_cty.?.tag() == .zig_i128;
4532 info_ty_pl.data -= 1;
4533 info_ty_pl.data %= @intCast(u16, f.byteSize(elem_cty) * 8);
4534 info_ty_pl.data += 1;
4535 }
4536 try writer.writeAll(" = ");
4537 if (need_bitcasts) {
4538 try writer.writeAll("zig_bitcast_");
4539 try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_cty.?.toUnsigned());
4540 try writer.writeByte('(');
4541 }
4542 try writer.writeAll("zig_wrap_");
4543 const info_ty = Type.initPayload(&info_ty_pl.base);
4544 if (wrap_cty) |cty|
4545 try f.object.dg.renderCTypeForBuiltinFnName(writer, cty)
4546 else
4547 try f.object.dg.renderTypeForBuiltinFnName(writer, info_ty);
44194548 try writer.writeByte('(');
4549 if (need_bitcasts) {
4550 try writer.writeAll("zig_bitcast_");
4551 try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_cty.?);
4552 try writer.writeByte('(');
4553 }
44204554 try f.writeCValue(writer, local, .Other);
4421 try f.object.dg.renderBuiltinInfo(writer, dest_ty, .Bits);
4555 if (dest_cty.castTag(.array)) |pl| {
4556 try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) {
4557 .Little => pl.data.len - 1,
4558 .Big => 0,
4559 }});
4560 }
4561 if (need_bitcasts) try writer.writeByte(')');
4562 try f.object.dg.renderBuiltinInfo(writer, info_ty, .bits);
4563 if (need_bitcasts) try writer.writeByte(')');
44224564 try writer.writeAll(");\n");
44234565 }
44244566
......@@ -5433,7 +5575,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
54335575 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
54345576 try writer.writeByte(')');
54355577 if (cant_cast) try writer.writeByte(')');
5436 try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .Bits);
5578 try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits);
54375579 try writer.writeAll(");\n");
54385580 if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local;
54395581
......@@ -5866,7 +6008,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
58666008 try f.writeCValue(writer, operand, .FunctionArgument);
58676009 try writer.writeByte(')');
58686010 if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) {
5869 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits);
6011 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits);
58706012 try writer.writeByte(')');
58716013 }
58726014 try writer.writeAll(";\n");
......@@ -5912,19 +6054,35 @@ fn airUnBuiltinCall(
59126054 const operand = try f.resolveInst(ty_op.operand);
59136055 try reap(f, inst, &.{ty_op.operand});
59146056 const inst_ty = f.air.typeOfIndex(inst);
6057 const inst_scalar_ty = inst_ty.scalarType();
59156058 const operand_ty = f.air.typeOf(ty_op.operand);
6059 const scalar_ty = operand_ty.scalarType();
6060
6061 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
6062 const ref_ret = inst_scalar_cty.tag() == .array;
59166063
59176064 const writer = f.object.writer();
59186065 const local = try f.allocLocal(inst, inst_ty);
5919 try f.writeCValue(writer, local, .Other);
5920 try writer.writeAll(" = zig_");
5921 try writer.writeAll(operation);
5922 try writer.writeByte('_');
5923 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
6066 const v = try Vectorizer.start(f, inst, writer, operand_ty);
6067 if (!ref_ret) {
6068 try f.writeCValue(writer, local, .Other);
6069 try v.elem(f, writer);
6070 try writer.writeAll(" = ");
6071 }
6072 try writer.print("zig_{s}_", .{operation});
6073 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
59246074 try writer.writeByte('(');
6075 if (ref_ret) {
6076 try f.writeCValue(writer, local, .FunctionArgument);
6077 try v.elem(f, writer);
6078 try writer.writeAll(", ");
6079 }
59256080 try f.writeCValue(writer, operand, .FunctionArgument);
5926 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);
6081 try v.elem(f, writer);
6082 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);
59276083 try writer.writeAll(");\n");
6084 try v.end(f, inst, writer);
6085
59286086 return local;
59296087}
59306088
......@@ -5946,50 +6104,99 @@ fn airBinBuiltinCall(
59466104 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
59476105
59486106 const inst_ty = f.air.typeOfIndex(inst);
6107 const inst_scalar_ty = inst_ty.scalarType();
59496108 const operand_ty = f.air.typeOf(bin_op.lhs);
6109 const scalar_ty = operand_ty.scalarType();
6110
6111 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
6112 const ref_ret = inst_scalar_cty.tag() == .array;
59506113
59516114 const writer = f.object.writer();
59526115 const local = try f.allocLocal(inst, inst_ty);
5953 try f.writeCValue(writer, local, .Other);
5954 try writer.writeAll(" = zig_");
5955 try writer.writeAll(operation);
5956 try writer.writeByte('_');
5957 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
6116 const v = try Vectorizer.start(f, inst, writer, operand_ty);
6117 if (!ref_ret) {
6118 try f.writeCValue(writer, local, .Other);
6119 try v.elem(f, writer);
6120 try writer.writeAll(" = ");
6121 }
6122 try writer.print("zig_{s}_", .{operation});
6123 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
59586124 try writer.writeByte('(');
6125 if (ref_ret) {
6126 try f.writeCValue(writer, local, .FunctionArgument);
6127 try v.elem(f, writer);
6128 try writer.writeAll(", ");
6129 }
59596130 try f.writeCValue(writer, lhs, .FunctionArgument);
6131 try v.elem(f, writer);
59606132 try writer.writeAll(", ");
59616133 try f.writeCValue(writer, rhs, .FunctionArgument);
5962 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);
6134 try v.elem(f, writer);
6135 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);
59636136 try writer.writeAll(");\n");
6137 try v.end(f, inst, writer);
6138
59646139 return local;
59656140}
59666141
5967fn cmpBuiltinCall(
6142fn airCmpBuiltinCall(
59686143 f: *Function,
59696144 inst: Air.Inst.Index,
5970 operator: []const u8,
5971 operation: []const u8,
6145 data: anytype,
6146 operator: std.math.CompareOperator,
6147 operation: enum { cmp, operator },
6148 info: BuiltinInfo,
59726149) !CValue {
6150 if (f.liveness.isUnused(inst)) {
6151 try reap(f, inst, &.{ data.lhs, data.rhs });
6152 return .none;
6153 }
6154
6155 const lhs = try f.resolveInst(data.lhs);
6156 const rhs = try f.resolveInst(data.rhs);
6157 try reap(f, inst, &.{ data.lhs, data.rhs });
6158
59736159 const inst_ty = f.air.typeOfIndex(inst);
5974 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
5975 const operand_ty = f.air.typeOf(bin_op.lhs);
6160 const inst_scalar_ty = inst_ty.scalarType();
6161 const operand_ty = f.air.typeOf(data.lhs);
6162 const scalar_ty = operand_ty.scalarType();
59766163
5977 const lhs = try f.resolveInst(bin_op.lhs);
5978 const rhs = try f.resolveInst(bin_op.rhs);
5979 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
6164 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
6165 const ref_ret = inst_scalar_cty.tag() == .array;
59806166
59816167 const writer = f.object.writer();
59826168 const local = try f.allocLocal(inst, inst_ty);
5983 try f.writeCValue(writer, local, .Other);
5984 try writer.writeAll(" = zig_");
5985 try writer.writeAll(operation);
5986 try writer.writeByte('_');
5987 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
6169 const v = try Vectorizer.start(f, inst, writer, operand_ty);
6170 if (!ref_ret) {
6171 try f.writeCValue(writer, local, .Other);
6172 try v.elem(f, writer);
6173 try writer.writeAll(" = ");
6174 }
6175 try writer.print("zig_{s}_", .{switch (operation) {
6176 else => @tagName(operation),
6177 .operator => compareOperatorAbbrev(operator),
6178 }});
6179 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
59886180 try writer.writeByte('(');
6181 if (ref_ret) {
6182 try f.writeCValue(writer, local, .FunctionArgument);
6183 try v.elem(f, writer);
6184 try writer.writeAll(", ");
6185 }
59896186 try f.writeCValue(writer, lhs, .FunctionArgument);
6187 try v.elem(f, writer);
59906188 try writer.writeAll(", ");
59916189 try f.writeCValue(writer, rhs, .FunctionArgument);
5992 try writer.print(") {s} {};\n", .{ operator, try f.fmtIntLiteral(Type.initTag(.i32), Value.zero) });
6190 try v.elem(f, writer);
6191 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);
6192 try writer.writeByte(')');
6193 if (!ref_ret) try writer.print(" {s} {}", .{
6194 compareOperatorC(operator),
6195 try f.fmtIntLiteral(Type.initTag(.i32), Value.zero),
6196 });
6197 try writer.writeAll(";\n");
6198 try v.end(f, inst, writer);
6199
59936200 return local;
59946201}
59956202
......@@ -6334,33 +6541,120 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
63346541
63356542fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
63366543 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
6544
63376545 if (f.liveness.isUnused(inst)) {
63386546 try reap(f, inst, &.{ty_op.operand});
63396547 return .none;
63406548 }
63416549
6342 const inst_ty = f.air.typeOfIndex(inst);
63436550 const operand = try f.resolveInst(ty_op.operand);
63446551 try reap(f, inst, &.{ty_op.operand});
6552
6553 const inst_ty = f.air.typeOfIndex(inst);
6554 const inst_scalar_ty = inst_ty.scalarType();
6555 const inst_scalar_cty = try f.typeToIndex(inst_scalar_ty, .complete);
6556 const need_memcpy = f.indexToCType(inst_scalar_cty).tag() == .array;
6557
63456558 const writer = f.object.writer();
63466559 const local = try f.allocLocal(inst, inst_ty);
6560 const v = try Vectorizer.start(f, inst, writer, inst_ty);
6561 if (need_memcpy) try writer.writeAll("memcpy(&");
63476562 try f.writeCValue(writer, local, .Other);
6348 try writer.writeAll(" = ");
6563 try v.elem(f, writer);
6564 try writer.writeAll(if (need_memcpy) ", &" else " = ");
6565 try f.writeCValue(writer, operand, .Other);
6566 if (need_memcpy) {
6567 try writer.writeAll(", sizeof(");
6568 try f.renderCType(writer, inst_scalar_cty);
6569 try writer.writeAll("))");
6570 }
6571 try writer.writeAll(";\n");
6572 try v.end(f, inst, writer);
63496573
6350 _ = operand;
6351 return f.fail("TODO: C backend: implement airSplat", .{});
6574 return local;
63526575}
63536576
63546577fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
6355 if (f.liveness.isUnused(inst)) return .none;
6578 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
6579 const extra = f.air.extraData(Air.Bin, pl_op.payload).data;
63566580
6357 return f.fail("TODO: C backend: implement airSelect", .{});
6581 if (f.liveness.isUnused(inst)) {
6582 try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs });
6583 return .none;
6584 }
6585
6586 const pred = try f.resolveInst(pl_op.operand);
6587 const lhs = try f.resolveInst(extra.lhs);
6588 const rhs = try f.resolveInst(extra.rhs);
6589 try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs });
6590
6591 const inst_ty = f.air.typeOfIndex(inst);
6592
6593 const writer = f.object.writer();
6594 const local = try f.allocLocal(inst, inst_ty);
6595 const v = try Vectorizer.start(f, inst, writer, inst_ty);
6596 try f.writeCValue(writer, local, .Other);
6597 try v.elem(f, writer);
6598 try writer.writeAll(" = ");
6599 try f.writeCValue(writer, pred, .Other);
6600 try v.elem(f, writer);
6601 try writer.writeAll(" ? ");
6602 try f.writeCValue(writer, lhs, .Other);
6603 try v.elem(f, writer);
6604 try writer.writeAll(" : ");
6605 try f.writeCValue(writer, rhs, .Other);
6606 try v.elem(f, writer);
6607 try writer.writeAll(";\n");
6608 try v.end(f, inst, writer);
6609
6610 return local;
63586611}
63596612
63606613fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
6361 if (f.liveness.isUnused(inst)) return .none;
6614 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
6615 const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data;
6616
6617 if (f.liveness.isUnused(inst)) {
6618 try reap(f, inst, &.{ extra.a, extra.b });
6619 return .none;
6620 }
63626621
6363 return f.fail("TODO: C backend: implement airShuffle", .{});
6622 const mask = f.air.values[extra.mask];
6623 const lhs = try f.resolveInst(extra.a);
6624 const rhs = try f.resolveInst(extra.b);
6625
6626 const module = f.object.dg.module;
6627 const target = module.getTarget();
6628 const inst_ty = f.air.typeOfIndex(inst);
6629
6630 const writer = f.object.writer();
6631 const local = try f.allocLocal(inst, inst_ty);
6632 try reap(f, inst, &.{ extra.a, extra.b }); // local cannot alias operands
6633 for (0..extra.mask_len) |index| {
6634 var dst_pl = Value.Payload.U64{
6635 .base = .{ .tag = .int_u64 },
6636 .data = @intCast(u64, index),
6637 };
6638
6639 try f.writeCValue(writer, local, .Other);
6640 try writer.writeByte('[');
6641 try f.object.dg.renderValue(writer, Type.usize, Value.initPayload(&dst_pl.base), .Other);
6642 try writer.writeAll("] = ");
6643
6644 var buf: Value.ElemValueBuffer = undefined;
6645 const mask_elem = mask.elemValueBuffer(module, index, &buf).toSignedInt(target);
6646 var src_pl = Value.Payload.U64{
6647 .base = .{ .tag = .int_u64 },
6648 .data = @intCast(u64, mask_elem ^ mask_elem >> 63),
6649 };
6650
6651 try f.writeCValue(writer, if (mask_elem >= 0) lhs else rhs, .Other);
6652 try writer.writeByte('[');
6653 try f.object.dg.renderValue(writer, Type.usize, Value.initPayload(&src_pl.base), .Other);
6654 try writer.writeAll("];\n");
6655 }
6656
6657 return local;
63646658}
63656659
63666660fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -6376,65 +6670,45 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
63766670 const operand = try f.resolveInst(reduce.operand);
63776671 try reap(f, inst, &.{reduce.operand});
63786672 const operand_ty = f.air.typeOf(reduce.operand);
6379 const vector_len = operand_ty.vectorLen();
63806673 const writer = f.object.writer();
63816674
6382 const Op = union(enum) {
6383 call_fn: []const u8,
6675 const use_operator = scalar_ty.bitSize(target) <= 64;
6676 const op: union(enum) {
6677 const Func = struct { operation: []const u8, info: BuiltinInfo = .none };
6678 float_op: Func,
6679 builtin: Func,
63846680 infix: []const u8,
63856681 ternary: []const u8,
6386 };
6387 var fn_name_buf: [64]u8 = undefined;
6388 const op: Op = switch (reduce.operation) {
6389 .And => .{ .infix = " &= " },
6390 .Or => .{ .infix = " |= " },
6391 .Xor => .{ .infix = " ^= " },
6682 } = switch (reduce.operation) {
6683 .And => if (use_operator) .{ .infix = " &= " } else .{ .builtin = .{ .operation = "and" } },
6684 .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } },
6685 .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } },
63926686 .Min => switch (scalar_ty.zigTypeTag()) {
6393 .Int => Op{ .ternary = " < " },
6394 .Float => op: {
6395 const float_bits = scalar_ty.floatBits(target);
6396 break :op Op{
6397 .call_fn = std.fmt.bufPrintZ(&fn_name_buf, "{s}fmin{s}", .{
6398 libcFloatPrefix(float_bits), libcFloatSuffix(float_bits),
6399 }) catch unreachable,
6400 };
6687 .Int => if (use_operator) .{ .ternary = " < " } else .{
6688 .builtin = .{ .operation = "min" },
64016689 },
6690 .Float => .{ .float_op = .{ .operation = "fmin" } },
64026691 else => unreachable,
64036692 },
64046693 .Max => switch (scalar_ty.zigTypeTag()) {
6405 .Int => Op{ .ternary = " > " },
6406 .Float => op: {
6407 const float_bits = scalar_ty.floatBits(target);
6408 break :op Op{
6409 .call_fn = std.fmt.bufPrintZ(&fn_name_buf, "{s}fmax{s}", .{
6410 libcFloatPrefix(float_bits), libcFloatSuffix(float_bits),
6411 }) catch unreachable,
6412 };
6694 .Int => if (use_operator) .{ .ternary = " > " } else .{
6695 .builtin = .{ .operation = "max" },
64136696 },
6697 .Float => .{ .float_op = .{ .operation = "fmax" } },
64146698 else => unreachable,
64156699 },
64166700 .Add => switch (scalar_ty.zigTypeTag()) {
6417 .Int => Op{ .infix = " += " },
6418 .Float => op: {
6419 const float_bits = scalar_ty.floatBits(target);
6420 break :op Op{
6421 .call_fn = std.fmt.bufPrintZ(&fn_name_buf, "__add{s}f3", .{
6422 compilerRtFloatAbbrev(float_bits),
6423 }) catch unreachable,
6424 };
6701 .Int => if (use_operator) .{ .infix = " += " } else .{
6702 .builtin = .{ .operation = "addw", .info = .bits },
64256703 },
6704 .Float => .{ .builtin = .{ .operation = "add" } },
64266705 else => unreachable,
64276706 },
64286707 .Mul => switch (scalar_ty.zigTypeTag()) {
6429 .Int => Op{ .infix = " *= " },
6430 .Float => op: {
6431 const float_bits = scalar_ty.floatBits(target);
6432 break :op Op{
6433 .call_fn = std.fmt.bufPrintZ(&fn_name_buf, "__mul{s}f3", .{
6434 compilerRtFloatAbbrev(float_bits),
6435 }) catch unreachable,
6436 };
6708 .Int => if (use_operator) .{ .infix = " *= " } else .{
6709 .builtin = .{ .operation = "mulw", .info = .bits },
64376710 },
6711 .Float => .{ .builtin = .{ .operation = "mul" } },
64386712 else => unreachable,
64396713 },
64406714 };
......@@ -6450,75 +6724,96 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
64506724 // }
64516725 // break :reduce accum;
64526726 // }
6453 const it = try f.allocLocal(inst, Type.usize);
6454 try f.writeCValue(writer, it, .Other);
6455 try writer.writeAll(" = 0;\n");
64566727
64576728 const accum = try f.allocLocal(inst, scalar_ty);
64586729 try f.writeCValue(writer, accum, .Other);
64596730 try writer.writeAll(" = ");
64606731
6461 const init_val = switch (reduce.operation) {
6462 .And, .Or, .Xor, .Add => "0",
6732 var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa);
6733 defer arena.deinit();
6734
6735 const ExpectedContents = union {
6736 u: Value.Payload.U64,
6737 i: Value.Payload.I64,
6738 f16: Value.Payload.Float_16,
6739 f32: Value.Payload.Float_32,
6740 f64: Value.Payload.Float_64,
6741 f80: Value.Payload.Float_80,
6742 f128: Value.Payload.Float_128,
6743 };
6744 var stack align(@alignOf(ExpectedContents)) =
6745 std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
6746
6747 try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) {
6748 .Or, .Xor, .Add => Value.zero,
6749 .And => switch (scalar_ty.zigTypeTag()) {
6750 .Bool => Value.one,
6751 else => switch (scalar_ty.intInfo(target).signedness) {
6752 .unsigned => try scalar_ty.maxInt(stack.get(), target),
6753 .signed => Value.negative_one,
6754 },
6755 },
64636756 .Min => switch (scalar_ty.zigTypeTag()) {
6464 .Int => "TODO_intmax",
6465 .Float => "TODO_nan",
6757 .Bool => Value.one,
6758 .Int => try scalar_ty.maxInt(stack.get(), target),
6759 .Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target),
64666760 else => unreachable,
64676761 },
64686762 .Max => switch (scalar_ty.zigTypeTag()) {
6469 .Int => "TODO_intmin",
6470 .Float => "TODO_nan",
6763 .Bool => Value.zero,
6764 .Int => try scalar_ty.minInt(stack.get(), target),
6765 .Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target),
64716766 else => unreachable,
64726767 },
6473 .Mul => "1",
6474 };
6475 try writer.writeAll(init_val);
6476 try writer.writeAll(";");
6477 try f.object.indent_writer.insertNewline();
6478 try writer.writeAll("for (;");
6479 try f.writeCValue(writer, it, .Other);
6480 try writer.print("<{d};++", .{vector_len});
6481 try f.writeCValue(writer, it, .Other);
6482 try writer.writeAll(") ");
6483 try f.writeCValue(writer, accum, .Other);
6768 .Mul => Value.one,
6769 }, .Initializer);
6770 try writer.writeAll(";\n");
64846771
6772 const v = try Vectorizer.start(f, inst, writer, operand_ty);
6773 try f.writeCValue(writer, accum, .Other);
64856774 switch (op) {
6486 .call_fn => |fn_name| {
6487 try writer.print(" = {s}(", .{fn_name});
6775 .float_op => |func| {
6776 try writer.writeAll(" = zig_libc_name_");
6777 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
6778 try writer.print("({s})(", .{func.operation});
6779 try f.writeCValue(writer, accum, .FunctionArgument);
6780 try writer.writeAll(", ");
6781 try f.writeCValue(writer, operand, .Other);
6782 try v.elem(f, writer);
6783 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, func.info);
6784 try writer.writeByte(')');
6785 },
6786 .builtin => |func| {
6787 try writer.print(" = zig_{s}_", .{func.operation});
6788 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
6789 try writer.writeByte('(');
64886790 try f.writeCValue(writer, accum, .FunctionArgument);
64896791 try writer.writeAll(", ");
64906792 try f.writeCValue(writer, operand, .Other);
6491 try writer.writeAll("[");
6492 try f.writeCValue(writer, it, .Other);
6493 try writer.writeAll("])");
6793 try v.elem(f, writer);
6794 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, func.info);
6795 try writer.writeByte(')');
64946796 },
64956797 .infix => |ass| {
64966798 try writer.writeAll(ass);
64976799 try f.writeCValue(writer, operand, .Other);
6498 try writer.writeAll("[");
6499 try f.writeCValue(writer, it, .Other);
6500 try writer.writeAll("]");
6800 try v.elem(f, writer);
65016801 },
65026802 .ternary => |cmp| {
65036803 try writer.writeAll(" = ");
65046804 try f.writeCValue(writer, accum, .Other);
65056805 try writer.writeAll(cmp);
65066806 try f.writeCValue(writer, operand, .Other);
6507 try writer.writeAll("[");
6508 try f.writeCValue(writer, it, .Other);
6509 try writer.writeAll("] ? ");
6807 try v.elem(f, writer);
6808 try writer.writeAll(" ? ");
65106809 try f.writeCValue(writer, accum, .Other);
65116810 try writer.writeAll(" : ");
65126811 try f.writeCValue(writer, operand, .Other);
6513 try writer.writeAll("[");
6514 try f.writeCValue(writer, it, .Other);
6515 try writer.writeAll("]");
6812 try v.elem(f, writer);
65166813 },
65176814 }
6518
65196815 try writer.writeAll(";\n");
6520
6521 try freeLocal(f, inst, it.new_local, 0);
6816 try v.end(f, inst, writer);
65226817
65236818 return accum;
65246819}
......@@ -6652,7 +6947,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
66526947 try writer.writeByte('(');
66536948
66546949 if (inst_ty.isAbiInt() and (field_ty.isAbiInt() or field_ty.isPtrAtRuntime())) {
6655 try f.renderIntCast(writer, inst_ty, element, field_ty, .FunctionArgument);
6950 try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument);
66566951 } else {
66576952 try writer.writeByte('(');
66586953 try f.renderType(writer, inst_ty);
......@@ -6670,7 +6965,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
66706965
66716966 try writer.writeAll(", ");
66726967 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
6673 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits);
6968 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits);
66746969 try writer.writeByte(')');
66756970 if (!empty) try writer.writeByte(')');
66766971
......@@ -6794,7 +7089,6 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
67947089}
67957090
67967091fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
6797 const inst_ty = f.air.typeOfIndex(inst);
67987092 const un_op = f.air.instructions.items(.data)[inst].un_op;
67997093 if (f.liveness.isUnused(inst)) {
68007094 try reap(f, inst, &.{un_op});
......@@ -6803,16 +7097,23 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
68037097
68047098 const operand = try f.resolveInst(un_op);
68057099 try reap(f, inst, &.{un_op});
7100
68067101 const operand_ty = f.air.typeOf(un_op);
7102 const scalar_ty = operand_ty.scalarType();
68077103
68087104 const writer = f.object.writer();
6809 const local = try f.allocLocal(inst, inst_ty);
7105 const local = try f.allocLocal(inst, operand_ty);
7106 const v = try Vectorizer.start(f, inst, writer, operand_ty);
68107107 try f.writeCValue(writer, local, .Other);
7108 try v.elem(f, writer);
68117109 try writer.writeAll(" = zig_neg_");
6812 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
7110 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
68137111 try writer.writeByte('(');
68147112 try f.writeCValue(writer, operand, .FunctionArgument);
7113 try v.elem(f, writer);
68157114 try writer.writeAll(");\n");
7115 try v.end(f, inst, writer);
7116
68167117 return local;
68177118}
68187119
......@@ -6822,19 +7123,28 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
68227123 try reap(f, inst, &.{un_op});
68237124 return .none;
68247125 }
7126
68257127 const operand = try f.resolveInst(un_op);
68267128 try reap(f, inst, &.{un_op});
6827 const writer = f.object.writer();
7129
68287130 const inst_ty = f.air.typeOfIndex(inst);
7131 const inst_scalar_ty = inst_ty.scalarType();
7132
7133 const writer = f.object.writer();
68297134 const local = try f.allocLocal(inst, inst_ty);
7135 const v = try Vectorizer.start(f, inst, writer, inst_ty);
68307136 try f.writeCValue(writer, local, .Other);
7137 try v.elem(f, writer);
68317138 try writer.writeAll(" = zig_libc_name_");
6832 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
7139 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);
68337140 try writer.writeByte('(');
68347141 try writer.writeAll(operation);
68357142 try writer.writeAll(")(");
68367143 try f.writeCValue(writer, operand, .FunctionArgument);
7144 try v.elem(f, writer);
68377145 try writer.writeAll(");\n");
7146 try v.end(f, inst, writer);
7147
68387148 return local;
68397149}
68407150
......@@ -6844,23 +7154,32 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
68447154 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
68457155 return .none;
68467156 }
7157
68477158 const lhs = try f.resolveInst(bin_op.lhs);
68487159 const rhs = try f.resolveInst(bin_op.rhs);
68497160 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
68507161
6851 const writer = f.object.writer();
68527162 const inst_ty = f.air.typeOfIndex(inst);
7163 const inst_scalar_ty = inst_ty.scalarType();
7164
7165 const writer = f.object.writer();
68537166 const local = try f.allocLocal(inst, inst_ty);
7167 const v = try Vectorizer.start(f, inst, writer, inst_ty);
68547168 try f.writeCValue(writer, local, .Other);
7169 try v.elem(f, writer);
68557170 try writer.writeAll(" = zig_libc_name_");
6856 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
7171 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);
68577172 try writer.writeByte('(');
68587173 try writer.writeAll(operation);
68597174 try writer.writeAll(")(");
68607175 try f.writeCValue(writer, lhs, .FunctionArgument);
7176 try v.elem(f, writer);
68617177 try writer.writeAll(", ");
68627178 try f.writeCValue(writer, rhs, .FunctionArgument);
7179 try v.elem(f, writer);
68637180 try writer.writeAll(");\n");
7181 try v.end(f, inst, writer);
7182
68647183 return local;
68657184}
68667185
......@@ -6871,23 +7190,34 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
68717190 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });
68727191 return .none;
68737192 }
6874 const inst_ty = f.air.typeOfIndex(inst);
7193
68757194 const mulend1 = try f.resolveInst(bin_op.lhs);
68767195 const mulend2 = try f.resolveInst(bin_op.rhs);
68777196 const addend = try f.resolveInst(pl_op.operand);
68787197 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });
7198
7199 const inst_ty = f.air.typeOfIndex(inst);
7200 const inst_scalar_ty = inst_ty.scalarType();
7201
68797202 const writer = f.object.writer();
68807203 const local = try f.allocLocal(inst, inst_ty);
7204 const v = try Vectorizer.start(f, inst, writer, inst_ty);
68817205 try f.writeCValue(writer, local, .Other);
7206 try v.elem(f, writer);
68827207 try writer.writeAll(" = zig_libc_name_");
6883 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
7208 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);
68847209 try writer.writeAll("(fma)(");
68857210 try f.writeCValue(writer, mulend1, .FunctionArgument);
7211 try v.elem(f, writer);
68867212 try writer.writeAll(", ");
68877213 try f.writeCValue(writer, mulend2, .FunctionArgument);
7214 try v.elem(f, writer);
68887215 try writer.writeAll(", ");
68897216 try f.writeCValue(writer, addend, .FunctionArgument);
7217 try v.elem(f, writer);
68907218 try writer.writeAll(");\n");
7219 try v.end(f, inst, writer);
7220
68917221 return local;
68927222}
68937223
......@@ -7089,6 +7419,28 @@ fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 {
70897419 } else unreachable;
70907420}
70917421
7422fn compareOperatorAbbrev(operator: std.math.CompareOperator) []const u8 {
7423 return switch (operator) {
7424 .lt => "lt",
7425 .lte => "le",
7426 .eq => "eq",
7427 .gte => "ge",
7428 .gt => "gt",
7429 .neq => "ne",
7430 };
7431}
7432
7433fn compareOperatorC(operator: std.math.CompareOperator) []const u8 {
7434 return switch (operator) {
7435 .lt => "<",
7436 .lte => "<=",
7437 .eq => "==",
7438 .gte => ">=",
7439 .gt => ">",
7440 .neq => "!=",
7441 };
7442}
7443
70927444fn StringLiteral(comptime WriterType: type) type {
70937445 // MSVC has a length limit of 16380 per string literal (before concatenation)
70947446 const max_char_len = 4;
......@@ -7177,30 +7529,33 @@ fn undefPattern(comptime IntType: type) IntType {
71777529 return @bitCast(IntType, @as(UnsignedType, (1 << (int_info.bits | 1)) / 3));
71787530}
71797531
7180const FormatIntLiteralContext = struct { ty: Type, val: Value, mod: *Module, location: ?ValueRenderLocation = null };
7532const FormatIntLiteralContext = struct {
7533 dg: *DeclGen,
7534 int_info: std.builtin.Type.Int,
7535 kind: CType.Kind,
7536 cty: CType,
7537 val: Value,
7538};
71817539fn formatIntLiteral(
71827540 data: FormatIntLiteralContext,
71837541 comptime fmt: []const u8,
71847542 options: std.fmt.FormatOptions,
71857543 writer: anytype,
71867544) @TypeOf(writer).Error!void {
7187 const target = data.mod.getTarget();
7188 const int_info = data.ty.intInfo(target);
7545 const target = data.dg.module.getTarget();
71897546
71907547 const ExpectedContents = struct {
71917548 const base = 10;
7192 const limbs_count_128 = BigInt.calcTwosCompLimbCount(128);
7193 const expected_needed_limbs_count = BigInt.calcToStringLimbsBufferLen(limbs_count_128, base);
7194 const worst_case_int = BigInt.Const{
7195 .limbs = &([1]BigIntLimb{std.math.maxInt(BigIntLimb)} ** expected_needed_limbs_count),
7196 .positive = false,
7197 };
7549 const bits = 128;
7550 const limbs_count = BigInt.calcTwosCompLimbCount(bits);
71987551
7199 undef_limbs: [limbs_count_128]BigIntLimb,
7200 wrap_limbs: [limbs_count_128]BigIntLimb,
7552 undef_limbs: [limbs_count]BigIntLimb,
7553 wrap_limbs: [limbs_count]BigIntLimb,
7554 to_string_buf: [bits]u8,
7555 to_string_limbs: [BigInt.calcToStringLimbsBufferLen(limbs_count, base)]BigIntLimb,
72017556 };
72027557 var stack align(@alignOf(ExpectedContents)) =
7203 std.heap.stackFallback(@sizeOf(ExpectedContents), data.mod.gpa);
7558 std.heap.stackFallback(@sizeOf(ExpectedContents), data.dg.gpa);
72047559 const allocator = stack.get();
72057560
72067561 var undef_limbs: []BigIntLimb = &.{};
......@@ -7208,7 +7563,7 @@ fn formatIntLiteral(
72087563
72097564 var int_buf: Value.BigIntSpace = undefined;
72107565 const int = if (data.val.isUndefDeep()) blk: {
7211 undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(int_info.bits));
7566 undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits));
72127567 std.mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb));
72137568
72147569 var undef_int = BigInt.Mutable{
......@@ -7216,164 +7571,193 @@ fn formatIntLiteral(
72167571 .len = undef_limbs.len,
72177572 .positive = true,
72187573 };
7219 undef_int.truncate(undef_int.toConst(), int_info.signedness, int_info.bits);
7574 undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits);
72207575 break :blk undef_int.toConst();
72217576 } else data.val.toBigInt(&int_buf, target);
7222 assert(int.fitsInTwosComp(int_info.signedness, int_info.bits));
7577 assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits));
72237578
7224 const c_bits = toCIntBits(int_info.bits) orelse unreachable;
7579 const c_bits = @intCast(usize, data.cty.byteSize(data.dg.ctypes.set, target) * 8);
72257580 var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined;
72267581 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
72277582
7228 const wrap_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits));
7229 defer allocator.free(wrap_limbs);
7230 var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined };
7231 if (wrap.addWrap(int, one, int_info.signedness, c_bits) or
7232 int_info.signedness == .signed and wrap.subWrap(int, one, int_info.signedness, c_bits))
7233 {
7234 const abbrev = switch (data.ty.tag()) {
7235 .c_short, .c_ushort => "SHRT",
7236 .c_int, .c_uint => "INT",
7237 .c_long, .c_ulong => "LONG",
7238 .c_longlong, .c_ulonglong => "LLONG",
7239 .isize, .usize => "INTPTR",
7240 else => return writer.print("zig_{s}Int_{c}{d}", .{
7241 if (int.positive) "max" else "min", signAbbrev(int_info.signedness), c_bits,
7242 }),
7243 };
7244 if (int_info.signedness == .unsigned) try writer.writeByte('U');
7245 return writer.print("{s}_{s}", .{ abbrev, if (int.positive) "MAX" else "MIN" });
7246 }
7247
7248 var use_twos_comp = false;
7249 if (!int.positive) {
7250 if (c_bits > 64) {
7251 // TODO: Can this be done for decimal literals as well?
7252 if (fmt.len == 1 and fmt[0] != 'd') {
7253 use_twos_comp = true;
7254 } else {
7255 // TODO: Use fmtIntLiteral for 0?
7256 try writer.print("zig_sub_{c}{d}(zig_make_{c}{d}(0, 0), ", .{ signAbbrev(int_info.signedness), c_bits, signAbbrev(int_info.signedness), c_bits });
7257 }
7258 } else {
7259 try writer.writeByte('-');
7260 }
7261 }
7262
7263 switch (data.ty.tag()) {
7264 .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {},
7265 else => {
7266 if (int_info.bits <= 64) {
7267 try writer.print("{s}INT{d}_C(", .{ switch (int_info.signedness) {
7268 .signed => "",
7269 .unsigned => "U",
7270 }, c_bits });
7271 } else if (data.location != null and data.location.? == .StaticInitializer) {
7272 // MSVC treats casting the struct initializer as not constant (C2099), so an alternate form is used in global initializers
7273 try writer.print("zig_make_constant_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits });
7274 } else {
7275 try writer.print("zig_make_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits });
7276 }
7583 var wrap = BigInt.Mutable{
7584 .limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)),
7585 .len = undefined,
7586 .positive = undefined,
7587 };
7588 defer allocator.free(wrap.limbs);
7589
7590 const c_limb_info: struct {
7591 cty: CType,
7592 count: usize,
7593 endian: std.builtin.Endian,
7594 homogeneous: bool,
7595 } = switch (data.cty.tag()) {
7596 else => .{
7597 .cty = CType.initTag(.void),
7598 .count = 1,
7599 .endian = .Little,
7600 .homogeneous = true,
72777601 },
7278 }
7602 .zig_u128, .zig_i128 => .{
7603 .cty = CType.initTag(.uint64_t),
7604 .count = 2,
7605 .endian = .Big,
7606 .homogeneous = false,
7607 },
7608 .array => info: {
7609 const array_data = data.cty.castTag(.array).?.data;
7610 break :info .{
7611 .cty = data.dg.indexToCType(array_data.elem_type),
7612 .count = @intCast(usize, array_data.len),
7613 .endian = target.cpu.arch.endian(),
7614 .homogeneous = true,
7615 };
7616 },
7617 };
7618 if (c_limb_info.count == 1) {
7619 if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or
7620 data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits))
7621 return writer.print("{s}_{s}", .{
7622 data.cty.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{
7623 if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits,
7624 }),
7625 if (int.positive) "MAX" else "MIN",
7626 });
72797627
7280 const limbs_count_64 = @divExact(64, @bitSizeOf(BigIntLimb));
7281 if (c_bits <= 64) {
7282 var base: u8 = undefined;
7283 var case: std.fmt.Case = undefined;
7284 switch (fmt.len) {
7285 0 => base = 10,
7628 if (!int.positive) try writer.writeByte('-');
7629 try data.cty.renderLiteralPrefix(writer, data.kind);
7630
7631 const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) {
7632 0 => .{ .base = 10 },
72867633 1 => switch (fmt[0]) {
7287 'b' => {
7288 base = 2;
7634 'b' => style: {
72897635 try writer.writeAll("0b");
7636 break :style .{ .base = 2 };
72907637 },
7291 'o' => {
7292 base = 8;
7638 'o' => style: {
72937639 try writer.writeByte('0');
7640 break :style .{ .base = 8 };
72947641 },
7295 'd' => base = 10,
7296 'x' => {
7297 base = 16;
7298 case = .lower;
7299 try writer.writeAll("0x");
7300 },
7301 'X' => {
7302 base = 16;
7303 case = .upper;
7642 'd' => .{ .base = 10 },
7643 'x', 'X' => |base| style: {
73047644 try writer.writeAll("0x");
7645 break :style .{ .base = 16, .case = switch (base) {
7646 'x' => .lower,
7647 'X' => .upper,
7648 else => unreachable,
7649 } };
73057650 },
73067651 else => @compileError("Invalid fmt: " ++ fmt),
73077652 },
73087653 else => @compileError("Invalid fmt: " ++ fmt),
7309 }
7654 };
73107655
7311 var str: [64]u8 = undefined;
7312 var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]BigIntLimb = undefined;
7313 try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]);
7656 const string = try int.abs().toStringAlloc(allocator, style.base, style.case);
7657 defer allocator.free(string);
7658 try writer.writeAll(string);
73147659 } else {
7315 assert(c_bits == 128);
7316 const split = std.math.min(int.limbs.len, limbs_count_64);
7317 var twos_comp_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;
7318
7319 // Adding a negation in the C code before the doesn't work in all cases:
7320 // - struct versions would require an extra zig_sub_ call to negate, which wouldn't work in constant expressions
7321 // - negating the f80 int representation (i128) doesn't make sense
7322 // Instead we write out the literal as a negative number in twos complement
7323 var limbs = int.limbs;
7324
7325 if (use_twos_comp) {
7326 var twos_comp = BigInt.Mutable{
7327 .limbs = &twos_comp_limbs,
7328 .positive = undefined,
7660 try data.cty.renderLiteralPrefix(writer, data.kind);
7661 wrap.convertToTwosComplement(int, data.int_info.signedness, c_bits);
7662 std.mem.set(BigIntLimb, wrap.limbs[wrap.len..], 0);
7663 wrap.len = wrap.limbs.len;
7664 const limbs_per_c_limb = @divExact(wrap.len, c_limb_info.count);
7665
7666 var c_limb_int_info = std.builtin.Type.Int{
7667 .signedness = undefined,
7668 .bits = @intCast(u16, @divExact(c_bits, c_limb_info.count)),
7669 };
7670 var c_limb_cty: CType = undefined;
7671
7672 var limb_offset: usize = 0;
7673 const most_significant_limb_i = wrap.len - limbs_per_c_limb;
7674 while (limb_offset < wrap.len) : (limb_offset += limbs_per_c_limb) {
7675 const limb_i = switch (c_limb_info.endian) {
7676 .Little => limb_offset,
7677 .Big => most_significant_limb_i - limb_offset,
7678 };
7679 var c_limb_mut = BigInt.Mutable{
7680 .limbs = wrap.limbs[limb_i..][0..limbs_per_c_limb],
73297681 .len = undefined,
7682 .positive = true,
73307683 };
7684 c_limb_mut.normalize(limbs_per_c_limb);
73317685
7332 twos_comp.convertToTwosComplement(int, .signed, int_info.bits);
7333 limbs = twos_comp.limbs;
7686 if (limb_i == most_significant_limb_i and
7687 !c_limb_info.homogeneous and data.int_info.signedness == .signed)
7688 {
7689 // most significant limb is actually signed
7690 c_limb_int_info.signedness = .signed;
7691 c_limb_cty = c_limb_info.cty.toSigned();
7692
7693 c_limb_mut.positive = wrap.positive;
7694 c_limb_mut.truncate(
7695 c_limb_mut.toConst(),
7696 .signed,
7697 data.int_info.bits - limb_i * @bitSizeOf(BigIntLimb),
7698 );
7699 } else {
7700 c_limb_int_info.signedness = .unsigned;
7701 c_limb_cty = c_limb_info.cty;
7702 }
7703 var c_limb_val_pl = Value.Payload.BigInt{
7704 .base = .{ .tag = if (c_limb_mut.positive) .int_big_positive else .int_big_negative },
7705 .data = c_limb_mut.limbs[0..c_limb_mut.len],
7706 };
7707
7708 if (limb_offset > 0) try writer.writeAll(", ");
7709 try formatIntLiteral(.{
7710 .dg = data.dg,
7711 .int_info = c_limb_int_info,
7712 .kind = data.kind,
7713 .cty = c_limb_cty,
7714 .val = Value.initPayload(&c_limb_val_pl.base),
7715 }, fmt, options, writer);
73347716 }
7717 }
7718 try data.cty.renderLiteralSuffix(writer);
7719}
73357720
7336 var upper_pl = Value.Payload.BigInt{
7337 .base = .{ .tag = .int_big_positive },
7338 .data = limbs[split..],
7339 };
7340 const upper_val = Value.initPayload(&upper_pl.base);
7341 try formatIntLiteral(.{
7342 .ty = switch (int_info.signedness) {
7343 .unsigned => Type.u64,
7344 .signed => if (use_twos_comp) Type.u64 else Type.i64,
7345 },
7346 .val = upper_val,
7347 .mod = data.mod,
7348 }, fmt, options, writer);
7721const Vectorizer = struct {
7722 index: CValue = .none,
73497723
7350 try writer.writeAll(", ");
7724 pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorizer {
7725 return if (ty.zigTypeTag() == .Vector) index: {
7726 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = ty.vectorLen() };
73517727
7352 var lower_pl = Value.Payload.BigInt{
7353 .base = .{ .tag = .int_big_positive },
7354 .data = limbs[0..split],
7355 };
7356 const lower_val = Value.initPayload(&lower_pl.base);
7357 try formatIntLiteral(.{
7358 .ty = Type.u64,
7359 .val = lower_val,
7360 .mod = data.mod,
7361 }, fmt, options, writer);
7728 const local = try f.allocLocal(inst, Type.usize);
73627729
7363 if (!int.positive and c_bits > 64 and !use_twos_comp) try writer.writeByte(')');
7364 return writer.writeByte(')');
7730 try writer.writeAll("for (");
7731 try f.writeCValue(writer, local, .Other);
7732 try writer.print(" = {d}; ", .{try f.fmtIntLiteral(Type.usize, Value.zero)});
7733 try f.writeCValue(writer, local, .Other);
7734 try writer.print(" < {d}; ", .{
7735 try f.fmtIntLiteral(Type.usize, Value.initPayload(&len_pl.base)),
7736 });
7737 try f.writeCValue(writer, local, .Other);
7738 try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(Type.usize, Value.one)});
7739 f.object.indent_writer.pushIndent();
7740
7741 break :index .{ .index = local };
7742 } else .{};
7743 }
7744
7745 pub fn elem(self: Vectorizer, f: *Function, writer: anytype) !void {
7746 if (self.index != .none) {
7747 try writer.writeByte('[');
7748 try f.writeCValue(writer, self.index, .Other);
7749 try writer.writeByte(']');
7750 }
73657751 }
73667752
7367 switch (data.ty.tag()) {
7368 .c_short, .c_ushort, .c_int => {},
7369 .c_uint => try writer.writeAll("u"),
7370 .c_long => try writer.writeAll("l"),
7371 .c_ulong => try writer.writeAll("ul"),
7372 .c_longlong => try writer.writeAll("ll"),
7373 .c_ulonglong => try writer.writeAll("ull"),
7374 else => try writer.writeByte(')'),
7753 pub fn end(self: Vectorizer, f: *Function, inst: Air.Inst.Index, writer: anytype) !void {
7754 if (self.index != .none) {
7755 f.object.indent_writer.popIndent();
7756 try writer.writeAll("}\n");
7757 try freeLocal(f, inst, self.index.new_local, 0);
7758 }
73757759 }
7376}
7760};
73777761
73787762fn isByRef(ty: Type) bool {
73797763 _ = ty;
src/codegen/c/type.zig+449-32
......@@ -496,6 +496,427 @@ pub const CType = extern union {
496496 }
497497 };
498498
499 pub fn isBool(self: CType) bool {
500 return switch (self.tag()) {
501 ._Bool,
502 .bool,
503 => true,
504 else => false,
505 };
506 }
507
508 pub fn isInteger(self: CType) bool {
509 return switch (self.tag()) {
510 .char,
511 .@"signed char",
512 .short,
513 .int,
514 .long,
515 .@"long long",
516 .@"unsigned char",
517 .@"unsigned short",
518 .@"unsigned int",
519 .@"unsigned long",
520 .@"unsigned long long",
521 .size_t,
522 .ptrdiff_t,
523 .uint8_t,
524 .int8_t,
525 .uint16_t,
526 .int16_t,
527 .uint32_t,
528 .int32_t,
529 .uint64_t,
530 .int64_t,
531 .uintptr_t,
532 .intptr_t,
533 .zig_u128,
534 .zig_i128,
535 => true,
536 else => false,
537 };
538 }
539
540 pub fn signedness(self: CType) ?std.builtin.Signedness {
541 return switch (self.tag()) {
542 .char => null, // unknown signedness
543 .@"signed char",
544 .short,
545 .int,
546 .long,
547 .@"long long",
548 .ptrdiff_t,
549 .int8_t,
550 .int16_t,
551 .int32_t,
552 .int64_t,
553 .intptr_t,
554 .zig_i128,
555 => .signed,
556 .@"unsigned char",
557 .@"unsigned short",
558 .@"unsigned int",
559 .@"unsigned long",
560 .@"unsigned long long",
561 .size_t,
562 .uint8_t,
563 .uint16_t,
564 .uint32_t,
565 .uint64_t,
566 .uintptr_t,
567 .zig_u128,
568 => .unsigned,
569 else => unreachable,
570 };
571 }
572
573 pub fn isFloat(self: CType) bool {
574 return switch (self.tag()) {
575 .float,
576 .double,
577 .@"long double",
578 .zig_f16,
579 .zig_f32,
580 .zig_f64,
581 .zig_f80,
582 .zig_f128,
583 .zig_c_longdouble,
584 => true,
585 else => false,
586 };
587 }
588
589 pub fn isPointer(self: CType) bool {
590 return switch (self.tag()) {
591 .pointer,
592 .pointer_const,
593 .pointer_volatile,
594 .pointer_const_volatile,
595 => true,
596 else => false,
597 };
598 }
599
600 pub fn isFunction(self: CType) bool {
601 return switch (self.tag()) {
602 .function,
603 .varargs_function,
604 => true,
605 else => false,
606 };
607 }
608
609 pub fn toSigned(self: CType) CType {
610 return CType.initTag(switch (self.tag()) {
611 .char, .@"signed char", .@"unsigned char" => .@"signed char",
612 .short, .@"unsigned short" => .short,
613 .int, .@"unsigned int" => .int,
614 .long, .@"unsigned long" => .long,
615 .@"long long", .@"unsigned long long" => .@"long long",
616 .size_t, .ptrdiff_t => .ptrdiff_t,
617 .uint8_t, .int8_t => .int8_t,
618 .uint16_t, .int16_t => .int16_t,
619 .uint32_t, .int32_t => .int32_t,
620 .uint64_t, .int64_t => .int64_t,
621 .uintptr_t, .intptr_t => .intptr_t,
622 .zig_u128, .zig_i128 => .zig_i128,
623 .float,
624 .double,
625 .@"long double",
626 .zig_f16,
627 .zig_f32,
628 .zig_f80,
629 .zig_f128,
630 .zig_c_longdouble,
631 => |t| t,
632 else => unreachable,
633 });
634 }
635
636 pub fn toUnsigned(self: CType) CType {
637 return CType.initTag(switch (self.tag()) {
638 .char, .@"signed char", .@"unsigned char" => .@"unsigned char",
639 .short, .@"unsigned short" => .@"unsigned short",
640 .int, .@"unsigned int" => .@"unsigned int",
641 .long, .@"unsigned long" => .@"unsigned long",
642 .@"long long", .@"unsigned long long" => .@"unsigned long long",
643 .size_t, .ptrdiff_t => .size_t,
644 .uint8_t, .int8_t => .uint8_t,
645 .uint16_t, .int16_t => .uint16_t,
646 .uint32_t, .int32_t => .uint32_t,
647 .uint64_t, .int64_t => .uint64_t,
648 .uintptr_t, .intptr_t => .uintptr_t,
649 .zig_u128, .zig_i128 => .zig_u128,
650 else => unreachable,
651 });
652 }
653
654 pub fn toSignedness(self: CType, s: std.builtin.Signedness) CType {
655 return switch (s) {
656 .unsigned => self.toUnsigned(),
657 .signed => self.toSigned(),
658 };
659 }
660
661 pub fn getStandardDefineAbbrev(self: CType) ?[]const u8 {
662 return switch (self.tag()) {
663 .char => "CHAR",
664 .@"signed char" => "SCHAR",
665 .short => "SHRT",
666 .int => "INT",
667 .long => "LONG",
668 .@"long long" => "LLONG",
669 .@"unsigned char" => "UCHAR",
670 .@"unsigned short" => "USHRT",
671 .@"unsigned int" => "UINT",
672 .@"unsigned long" => "ULONG",
673 .@"unsigned long long" => "ULLONG",
674 .float => "FLT",
675 .double => "DBL",
676 .@"long double" => "LDBL",
677 .size_t => "SIZE",
678 .ptrdiff_t => "PTRDIFF",
679 .uint8_t => "UINT8",
680 .int8_t => "INT8",
681 .uint16_t => "UINT16",
682 .int16_t => "INT16",
683 .uint32_t => "UINT32",
684 .int32_t => "INT32",
685 .uint64_t => "UINT64",
686 .int64_t => "INT64",
687 .uintptr_t => "UINTPTR",
688 .intptr_t => "INTPTR",
689 else => null,
690 };
691 }
692
693 pub fn renderLiteralPrefix(self: CType, writer: anytype, kind: Kind) @TypeOf(writer).Error!void {
694 switch (self.tag()) {
695 .void => unreachable,
696 ._Bool,
697 .char,
698 .@"signed char",
699 .short,
700 .@"unsigned short",
701 .bool,
702 .size_t,
703 .ptrdiff_t,
704 .uintptr_t,
705 .intptr_t,
706 => |t| switch (kind) {
707 else => try writer.print("({s})", .{@tagName(t)}),
708 .global => {},
709 },
710 .int,
711 .long,
712 .@"long long",
713 .@"unsigned char",
714 .@"unsigned int",
715 .@"unsigned long",
716 .@"unsigned long long",
717 .float,
718 .double,
719 .@"long double",
720 => {},
721 .uint8_t,
722 .int8_t,
723 .uint16_t,
724 .int16_t,
725 .uint32_t,
726 .int32_t,
727 .uint64_t,
728 .int64_t,
729 => try writer.print("{s}_C(", .{self.getStandardDefineAbbrev().?}),
730 .zig_u128,
731 .zig_i128,
732 .zig_f16,
733 .zig_f32,
734 .zig_f64,
735 .zig_f80,
736 .zig_f128,
737 .zig_c_longdouble,
738 => |t| try writer.print("zig_{s}_{s}(", .{
739 switch (kind) {
740 else => "make",
741 .global => "init",
742 },
743 @tagName(t)["zig_".len..],
744 }),
745 .pointer,
746 .pointer_const,
747 .pointer_volatile,
748 .pointer_const_volatile,
749 => unreachable,
750 .array,
751 .vector,
752 => try writer.writeByte('{'),
753 .fwd_anon_struct,
754 .fwd_anon_union,
755 .fwd_struct,
756 .fwd_union,
757 .unnamed_struct,
758 .unnamed_union,
759 .packed_unnamed_struct,
760 .packed_unnamed_union,
761 .anon_struct,
762 .anon_union,
763 .@"struct",
764 .@"union",
765 .packed_struct,
766 .packed_union,
767 .function,
768 .varargs_function,
769 => unreachable,
770 }
771 }
772
773 pub fn renderLiteralSuffix(self: CType, writer: anytype) @TypeOf(writer).Error!void {
774 switch (self.tag()) {
775 .void => unreachable,
776 ._Bool => {},
777 .char,
778 .@"signed char",
779 .short,
780 .int,
781 => {},
782 .long => try writer.writeByte('l'),
783 .@"long long" => try writer.writeAll("ll"),
784 .@"unsigned char",
785 .@"unsigned short",
786 .@"unsigned int",
787 => try writer.writeByte('u'),
788 .@"unsigned long",
789 .size_t,
790 .uintptr_t,
791 => try writer.writeAll("ul"),
792 .@"unsigned long long" => try writer.writeAll("ull"),
793 .float => try writer.writeByte('f'),
794 .double => {},
795 .@"long double" => try writer.writeByte('l'),
796 .bool,
797 .ptrdiff_t,
798 .intptr_t,
799 => {},
800 .uint8_t,
801 .int8_t,
802 .uint16_t,
803 .int16_t,
804 .uint32_t,
805 .int32_t,
806 .uint64_t,
807 .int64_t,
808 .zig_u128,
809 .zig_i128,
810 .zig_f16,
811 .zig_f32,
812 .zig_f64,
813 .zig_f80,
814 .zig_f128,
815 .zig_c_longdouble,
816 => try writer.writeByte(')'),
817 .pointer,
818 .pointer_const,
819 .pointer_volatile,
820 .pointer_const_volatile,
821 => unreachable,
822 .array,
823 .vector,
824 => try writer.writeByte('}'),
825 .fwd_anon_struct,
826 .fwd_anon_union,
827 .fwd_struct,
828 .fwd_union,
829 .unnamed_struct,
830 .unnamed_union,
831 .packed_unnamed_struct,
832 .packed_unnamed_union,
833 .anon_struct,
834 .anon_union,
835 .@"struct",
836 .@"union",
837 .packed_struct,
838 .packed_union,
839 .function,
840 .varargs_function,
841 => unreachable,
842 }
843 }
844
845 pub fn floatActiveBits(self: CType, target: Target) u16 {
846 return switch (self.tag()) {
847 .float => target.c_type_bit_size(.float),
848 .double => target.c_type_bit_size(.double),
849 .@"long double", .zig_c_longdouble => target.c_type_bit_size(.longdouble),
850 .zig_f16 => 16,
851 .zig_f32 => 32,
852 .zig_f64 => 64,
853 .zig_f80 => 80,
854 .zig_f128 => 128,
855 else => unreachable,
856 };
857 }
858
859 pub fn byteSize(self: CType, store: Store.Set, target: Target) u64 {
860 return switch (self.tag()) {
861 .void => 0,
862 .char, .@"signed char", ._Bool, .@"unsigned char", .bool, .uint8_t, .int8_t => 1,
863 .short => target.c_type_byte_size(.short),
864 .int => target.c_type_byte_size(.int),
865 .long => target.c_type_byte_size(.long),
866 .@"long long" => target.c_type_byte_size(.longlong),
867 .@"unsigned short" => target.c_type_byte_size(.ushort),
868 .@"unsigned int" => target.c_type_byte_size(.uint),
869 .@"unsigned long" => target.c_type_byte_size(.ulong),
870 .@"unsigned long long" => target.c_type_byte_size(.ulonglong),
871 .float => target.c_type_byte_size(.float),
872 .double => target.c_type_byte_size(.double),
873 .@"long double" => target.c_type_byte_size(.longdouble),
874 .size_t,
875 .ptrdiff_t,
876 .uintptr_t,
877 .intptr_t,
878 .pointer,
879 .pointer_const,
880 .pointer_volatile,
881 .pointer_const_volatile,
882 => @divExact(target.cpu.arch.ptrBitWidth(), 8),
883 .uint16_t, .int16_t, .zig_f16 => 2,
884 .uint32_t, .int32_t, .zig_f32 => 4,
885 .uint64_t, .int64_t, .zig_f64 => 8,
886 .zig_u128, .zig_i128, .zig_f128 => 16,
887 .zig_f80 => if (target.c_type_bit_size(.longdouble) == 80)
888 target.c_type_byte_size(.longdouble)
889 else
890 16,
891 .zig_c_longdouble => target.c_type_byte_size(.longdouble),
892
893 .array,
894 .vector,
895 => {
896 const data = self.cast(Payload.Sequence).?.data;
897 return data.len * store.indexToCType(data.elem_type).byteSize(store, target);
898 },
899
900 .fwd_anon_struct,
901 .fwd_anon_union,
902 .fwd_struct,
903 .fwd_union,
904 .unnamed_struct,
905 .unnamed_union,
906 .packed_unnamed_struct,
907 .packed_unnamed_union,
908 .anon_struct,
909 .anon_union,
910 .@"struct",
911 .@"union",
912 .packed_struct,
913 .packed_union,
914 .function,
915 .varargs_function,
916 => unreachable,
917 };
918 }
919
499920 pub fn isPacked(self: CType) bool {
500921 return switch (self.tag()) {
501922 else => false,
......@@ -787,26 +1208,26 @@ pub const CType = extern union {
7871208 };
7881209 }
7891210
790 fn tagFromIntInfo(signedness: std.builtin.Signedness, bits: u16) Tag {
791 return switch (bits) {
1211 fn tagFromIntInfo(int_info: std.builtin.Type.Int) Tag {
1212 return switch (int_info.bits) {
7921213 0 => .void,
793 1...8 => switch (signedness) {
1214 1...8 => switch (int_info.signedness) {
7941215 .unsigned => .uint8_t,
7951216 .signed => .int8_t,
7961217 },
797 9...16 => switch (signedness) {
1218 9...16 => switch (int_info.signedness) {
7981219 .unsigned => .uint16_t,
7991220 .signed => .int16_t,
8001221 },
801 17...32 => switch (signedness) {
1222 17...32 => switch (int_info.signedness) {
8021223 .unsigned => .uint32_t,
8031224 .signed => .int32_t,
8041225 },
805 33...64 => switch (signedness) {
1226 33...64 => switch (int_info.signedness) {
8061227 .unsigned => .uint64_t,
8071228 .signed => .int64_t,
8081229 },
809 65...128 => switch (signedness) {
1230 65...128 => switch (int_info.signedness) {
8101231 .unsigned => .zig_u128,
8111232 .signed => .zig_i128,
8121233 },
......@@ -945,31 +1366,27 @@ pub const CType = extern union {
9451366 .c_ulong => self.init(.@"unsigned long"),
9461367 .c_longlong => self.init(.@"long long"),
9471368 .c_ulonglong => self.init(.@"unsigned long long"),
948 else => {
949 const info = ty.intInfo(target);
950 const t = tagFromIntInfo(info.signedness, info.bits);
951 switch (t) {
952 .void => unreachable,
953 else => self.init(t),
954 .array => switch (kind) {
955 .forward, .complete, .global => {
956 const abi_size = ty.abiSize(target);
957 const abi_align = ty.abiAlignment(target);
958 self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{
959 .len = @divExact(abi_size, abi_align),
960 .elem_type = tagFromIntInfo(
961 .unsigned,
962 @intCast(u16, abi_align * 8),
963 ).toIndex(),
964 } } };
965 self.value = .{ .cty = initPayload(&self.storage.seq) };
966 },
967 .forward_parameter,
968 .parameter,
969 => try self.initArrayParameter(ty, kind, lookup),
970 .payload => unreachable,
1369 else => switch (tagFromIntInfo(ty.intInfo(target))) {
1370 .void => unreachable,
1371 else => |t| self.init(t),
1372 .array => switch (kind) {
1373 .forward, .complete, .global => {
1374 const abi_size = ty.abiSize(target);
1375 const abi_align = ty.abiAlignment(target);
1376 self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{
1377 .len = @divExact(abi_size, abi_align),
1378 .elem_type = tagFromIntInfo(.{
1379 .signedness = .unsigned,
1380 .bits = @intCast(u16, abi_align * 8),
1381 }).toIndex(),
1382 } } };
1383 self.value = .{ .cty = initPayload(&self.storage.seq) };
9711384 },
972 }
1385 .forward_parameter,
1386 .parameter,
1387 => try self.initArrayParameter(ty, kind, lookup),
1388 .payload => unreachable,
1389 },
9731390 },
9741391 } else switch (ty.zigTypeTag()) {
9751392 .Frame => unreachable,
......@@ -1048,7 +1465,7 @@ pub const CType = extern union {
10481465 .base = .{ .tag = .int_unsigned },
10491466 .data = info.host_size * 8,
10501467 };
1051 const pointee_ty = if (info.host_size > 0)
1468 const pointee_ty = if (info.host_size > 0 and info.vector_index == .none)
10521469 Type.initPayload(&host_int_pl.base)
10531470 else
10541471 info.pointee_type;
src/link/C.zig+14-8
......@@ -221,14 +221,19 @@ pub fn flush(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void
221221 return self.flushModule(comp, prog_node);
222222}
223223
224fn abiDefine(comp: *Compilation) ?[]const u8 {
225 return switch (comp.getTarget().abi) {
226 .msvc => "#define ZIG_TARGET_ABI_MSVC\n",
227 else => null,
228 };
224fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
225 var defines = std.ArrayList(u8).init(self.base.allocator);
226 errdefer defines.deinit();
227 const writer = defines.writer();
228 switch (target.abi) {
229 .msvc => try writer.writeAll("#define ZIG_TARGET_ABI_MSVC\n"),
230 else => {},
231 }
232 try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{target.maxIntAlignment()});
233 return defines;
229234}
230235
231pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void {
236pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !void {
232237 const tracy = trace(@src());
233238 defer tracy.end();
234239
......@@ -245,12 +250,13 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
245250 var f: Flush = .{};
246251 defer f.deinit(gpa);
247252
248 const abi_define = abiDefine(comp);
253 const abi_defines = try self.abiDefines(module.getTarget());
254 defer abi_defines.deinit();
249255
250256 // Covers defines, zig.h, ctypes, asm, lazy fwd.
251257 try f.all_buffers.ensureUnusedCapacity(gpa, 5);
252258
253 if (abi_define) |buf| f.appendBufAssumeCapacity(buf);
259 f.appendBufAssumeCapacity(abi_defines.items);
254260 f.appendBufAssumeCapacity(zig_h);
255261
256262 const ctypes_index = f.all_buffers.items.len;
src/value.zig+1-1
......@@ -3319,7 +3319,7 @@ pub const Value = extern union {
33193319 }
33203320 }
33213321
3322 fn floatToValue(float: f128, arena: Allocator, dest_ty: Type, target: Target) !Value {
3322 pub fn floatToValue(float: f128, arena: Allocator, dest_ty: Type, target: Target) !Value {
33233323 switch (dest_ty.floatBits(target)) {
33243324 16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)),
33253325 32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)),
test/behavior/bitcast.zig-3
......@@ -34,7 +34,6 @@ test "@bitCast iX -> uX (8, 16, 128)" {
3434
3535test "@bitCast iX -> uX exotic integers" {
3636 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
37 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
3837 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
3938 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
4039 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -81,7 +80,6 @@ fn conv_uN(comptime N: usize, x: std.meta.Int(.unsigned, N)) std.meta.Int(.signe
8180
8281test "bitcast uX to bytes" {
8382 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
84 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
8583 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8684 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
8785 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -368,7 +366,6 @@ test "comptime @bitCast packed struct to int and back" {
368366}
369367
370368test "comptime bitcast with fields following f80" {
371 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
372369 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
373370 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
374371 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
test/behavior/bitreverse.zig-3
......@@ -96,7 +96,6 @@ fn vector8() !void {
9696
9797test "bitReverse vectors u8" {
9898 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
99 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
10099 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
101100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
102101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -115,7 +114,6 @@ fn vector16() !void {
115114
116115test "bitReverse vectors u16" {
117116 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
118 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
119117 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
120118 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
121119 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -134,7 +132,6 @@ fn vector24() !void {
134132
135133test "bitReverse vectors u24" {
136134 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
137 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
138135 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
139136 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
140137 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
test/behavior/bugs/10147.zig-1
......@@ -6,7 +6,6 @@ test "test calling @clz on both vector and scalar inputs" {
66 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1110
1211 var x: u32 = 0x1;
test/behavior/byteswap.zig-3
......@@ -62,7 +62,6 @@ fn vector8() !void {
6262
6363test "@byteSwap vectors u8" {
6464 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
65 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
6665 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
6766 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
6867 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -81,7 +80,6 @@ fn vector16() !void {
8180
8281test "@byteSwap vectors u16" {
8382 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
84 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
8583 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8684 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8785 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -100,7 +98,6 @@ fn vector24() !void {
10098
10199test "@byteSwap vectors u24" {
102100 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
103 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
104101 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
105102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
106103 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
test/behavior/cast.zig-1
......@@ -598,7 +598,6 @@ test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
598598
599599test "vector casts" {
600600 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
601 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
602601 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
603602 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
604603 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/floatop.zig-12
......@@ -141,7 +141,6 @@ fn testSqrt() !void {
141141
142142test "@sqrt with vectors" {
143143 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
144 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
145144 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
146145 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
147146 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -234,7 +233,6 @@ fn testSin() !void {
234233
235234test "@sin with vectors" {
236235 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
237 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
238236 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
239237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
240238 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -275,7 +273,6 @@ fn testCos() !void {
275273
276274test "@cos with vectors" {
277275 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
278 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
279276 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
280277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
281278 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -315,7 +312,6 @@ fn testExp() !void {
315312
316313test "@exp with vectors" {
317314 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
318 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
319315 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
320316 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
321317 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -355,7 +351,6 @@ fn testExp2() !void {
355351
356352test "@exp2" {
357353 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
358 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
359354 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
360355 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
361356 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -409,7 +404,6 @@ test "@log with @vectors" {
409404 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
410405 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
411406 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
412 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
413407 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
414408
415409 {
......@@ -447,7 +441,6 @@ test "@log2 with vectors" {
447441 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
448442 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
449443 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
450 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
451444 // https://github.com/ziglang/zig/issues/13681
452445 if (builtin.zig_backend == .stage2_llvm and
453446 builtin.cpu.arch == .aarch64 and
......@@ -491,7 +484,6 @@ test "@log10 with vectors" {
491484 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
492485 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
493486 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
494 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
495487
496488 comptime try testLog10WithVectors();
497489 try testLog10WithVectors();
......@@ -537,7 +529,6 @@ fn testFabs() !void {
537529
538530test "@fabs with vectors" {
539531 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
540 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
541532 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
542533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
543534 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -660,7 +651,6 @@ fn testFloor() !void {
660651
661652test "@floor with vectors" {
662653 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
663 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
664654 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
665655 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
666656 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -754,7 +744,6 @@ fn testCeil() !void {
754744
755745test "@ceil with vectors" {
756746 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
757 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
758747 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
759748 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
760749 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -848,7 +837,6 @@ fn testTrunc() !void {
848837
849838test "@trunc with vectors" {
850839 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
851 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
852840 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
853841 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
854842 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/math.zig+6-3
......@@ -100,7 +100,6 @@ test "@clz vectors" {
100100 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
101101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
102102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
103 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
104103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
105104
106105 try testClzVectors();
......@@ -163,7 +162,6 @@ test "@ctz vectors" {
163162 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
164163 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
165164 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
166 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
167165 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
168166
169167 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
......@@ -1526,7 +1524,6 @@ fn testNanEqNan(comptime F: type) !void {
15261524}
15271525
15281526test "vector comparison" {
1529 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15301527 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
15311528 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15321529 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -1563,6 +1560,12 @@ test "signed zeros are represented properly" {
15631560 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
15641561 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15651562
1563 if (builtin.os.tag == .windows and builtin.cpu.arch == .aarch64 and
1564 builtin.zig_backend == .stage2_c)
1565 {
1566 return error.SkipZigTest;
1567 }
1568
15661569 const S = struct {
15671570 fn doTheTest() !void {
15681571 try testOne(f16);
test/behavior/maximum_minimum.zig-2
......@@ -25,7 +25,6 @@ test "@max" {
2525test "@max on vectors" {
2626 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2727 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
28 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2928 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
3029 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
3130 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -75,7 +74,6 @@ test "@min for vectors" {
7574 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
7675 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7776 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7977 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8078
8179 const S = struct {
test/behavior/muladd.zig+7-5
......@@ -100,7 +100,6 @@ fn vector16() !void {
100100}
101101
102102test "vector f16" {
103 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
104103 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
105104 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
106105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -124,7 +123,6 @@ fn vector32() !void {
124123}
125124
126125test "vector f32" {
127 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
128126 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
129127 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
130128 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -148,7 +146,6 @@ fn vector64() !void {
148146}
149147
150148test "vector f64" {
151 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
152149 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
153150 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
154151 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -171,7 +168,6 @@ fn vector80() !void {
171168}
172169
173170test "vector f80" {
174 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
175171 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
176172 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
177173 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -195,13 +191,19 @@ fn vector128() !void {
195191}
196192
197193test "vector f128" {
198 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
199194 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
200195 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
201196 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
202197 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
203198 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
204199
200 if (builtin.os.tag == .windows and builtin.cpu.arch == .aarch64 and
201 builtin.zig_backend == .stage2_c)
202 {
203 // https://github.com/ziglang/zig/issues/13876
204 return error.SkipZigTest;
205 }
206
205207 comptime try vector128();
206208 try vector128();
207209}
test/behavior/popcount.zig-1
......@@ -67,7 +67,6 @@ fn testPopCountIntegers() !void {
6767}
6868
6969test "@popCount vectors" {
70 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7170 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
7271 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
7372 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/select.zig-2
......@@ -4,7 +4,6 @@ const mem = std.mem;
44const expect = std.testing.expect;
55
66test "@select vectors" {
7 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
87 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
98 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -33,7 +32,6 @@ fn selectVectors() !void {
3332}
3433
3534test "@select arrays" {
36 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
3735 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
3836 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3937 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/shuffle.zig+1-4
......@@ -8,7 +8,6 @@ test "@shuffle int" {
88 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1010 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1211 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1312
1413 const S = struct {
......@@ -50,7 +49,6 @@ test "@shuffle bool 1" {
5049 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
5150 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5251 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
53 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5452 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5553
5654 const S = struct {
......@@ -71,7 +69,6 @@ test "@shuffle bool 2" {
7169 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
7270 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7371 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
74 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7572 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7673
7774 if (builtin.zig_backend == .stage2_llvm) {
......@@ -83,7 +80,7 @@ test "@shuffle bool 2" {
8380 fn doTheTest() !void {
8481 var x: @Vector(3, bool) = [3]bool{ false, true, false };
8582 var v: @Vector(2, bool) = [2]bool{ true, false };
86 const mask: @Vector(4, i32) = [4]i32{ 0, ~@as(i32, 1), 1, 2 };
83 const mask = [4]i32{ 0, ~@as(i32, 1), 1, 2 };
8784 var res = @shuffle(bool, x, v, mask);
8885 try expect(mem.eql(bool, &@as([4]bool, res), &[4]bool{ false, false, true, false }));
8986 }
test/behavior/truncate.zig-1
......@@ -60,7 +60,6 @@ test "truncate on comptime integer" {
6060}
6161
6262test "truncate on vectors" {
63 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
6463 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
6564 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
6665 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
test/behavior/vector.zig+17-31
......@@ -25,7 +25,6 @@ test "implicit cast vector to array - bool" {
2525
2626test "vector wrap operators" {
2727 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
28 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2928 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3029 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
3130 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -48,7 +47,6 @@ test "vector wrap operators" {
4847
4948test "vector bin compares with mem.eql" {
5049 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
51 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5250 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
5351 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5452 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -93,12 +91,18 @@ test "vector int operators" {
9391
9492test "vector float operators" {
9593 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
96 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
9794 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
9895 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
9996 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10097 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10198
99 if (builtin.os.tag == .windows and builtin.cpu.arch == .aarch64 and
100 builtin.zig_backend == .stage2_c)
101 {
102 // https://github.com/ziglang/zig/issues/13876
103 return error.SkipZigTest;
104 }
105
102106 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
103107 const S = struct {
104108 fn doTheTest() !void {
......@@ -117,7 +121,6 @@ test "vector float operators" {
117121
118122test "vector bit operators" {
119123 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
120 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
121124 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
122125 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
123126 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -237,7 +240,6 @@ test "vector casts of sizes not divisible by 8" {
237240}
238241
239242test "vector @splat" {
240 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
241243 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
242244 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
243245 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -403,7 +405,6 @@ test "initialize vector which is a struct field" {
403405
404406test "vector comparison operators" {
405407 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
406 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
407408 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
408409 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
409410 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -444,7 +445,6 @@ test "vector comparison operators" {
444445
445446test "vector division operators" {
446447 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
447 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
448448 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
449449 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
450450 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -527,7 +527,6 @@ test "vector division operators" {
527527
528528test "vector bitwise not operator" {
529529 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
530 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
531530 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
532531 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
533532 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -559,7 +558,6 @@ test "vector bitwise not operator" {
559558
560559test "vector shift operators" {
561560 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
562 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
563561 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
564562 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
565563 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -653,7 +651,6 @@ test "vector shift operators" {
653651
654652test "vector reduce operation" {
655653 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
656 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
657654 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
658655 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
659656 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -709,7 +706,7 @@ test "vector reduce operation" {
709706
710707 // LLVM 11 ERROR: Cannot select type
711708 // https://github.com/ziglang/zig/issues/7138
712 if (builtin.target.cpu.arch != .aarch64) {
709 if (builtin.zig_backend != .stage2_llvm or builtin.target.cpu.arch != .aarch64) {
713710 try testReduce(.Min, [4]i64{ 1234567, -386, 0, 3 }, @as(i64, -386));
714711 try testReduce(.Min, [4]u64{ 99, 9999, 9, 99999 }, @as(u64, 9));
715712 }
......@@ -727,7 +724,7 @@ test "vector reduce operation" {
727724
728725 // LLVM 11 ERROR: Cannot select type
729726 // https://github.com/ziglang/zig/issues/7138
730 if (builtin.target.cpu.arch != .aarch64) {
727 if (builtin.zig_backend != .stage2_llvm or builtin.target.cpu.arch != .aarch64) {
731728 try testReduce(.Max, [4]i64{ 1234567, -386, 0, 3 }, @as(i64, 1234567));
732729 try testReduce(.Max, [4]u64{ 99, 9999, 9, 99999 }, @as(u64, 99999));
733730 }
......@@ -775,14 +772,14 @@ test "vector reduce operation" {
775772
776773 // LLVM 11 ERROR: Cannot select type
777774 // https://github.com/ziglang/zig/issues/7138
778 if (false) {
779 try testReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
780 try testReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
781 try testReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
782
783 try testReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
784 try testReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan);
785 try testReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan);
775 if (builtin.zig_backend != .stage2_llvm) {
776 try testReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, -1.9));
777 try testReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, -1.9));
778 try testReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, -1.9));
779
780 try testReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, 100.0));
781 try testReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, 100.0));
782 try testReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, 100.0));
786783 }
787784
788785 try testReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan);
......@@ -813,7 +810,6 @@ test "vector @reduce comptime" {
813810
814811test "mask parameter of @shuffle is comptime scope" {
815812 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
816 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
817813 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
818814 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
819815 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -833,7 +829,6 @@ test "mask parameter of @shuffle is comptime scope" {
833829
834830test "saturating add" {
835831 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
836 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
837832 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
838833 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
839834 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -865,7 +860,6 @@ test "saturating add" {
865860
866861test "saturating subtraction" {
867862 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
868 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
869863 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
870864 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
871865 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -888,7 +882,6 @@ test "saturating subtraction" {
888882
889883test "saturating multiplication" {
890884 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
891 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
892885 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
893886 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
894887 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -915,7 +908,6 @@ test "saturating multiplication" {
915908
916909test "saturating shift-left" {
917910 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
918 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
919911 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
920912 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
921913 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1049,7 +1041,6 @@ test "@mulWithOverflow" {
10491041}
10501042
10511043test "@shlWithOverflow" {
1052 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10531044 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10541045 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10551046 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -1131,7 +1122,6 @@ test "byte vector initialized in inline function" {
11311122}
11321123
11331124test "byte vector initialized in inline function" {
1134 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11351125 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
11361126 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11371127 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -1204,7 +1194,6 @@ test "zero multiplicand" {
12041194
12051195test "@intCast to u0" {
12061196 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1207 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12081197 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12091198 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12101199 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1228,7 +1217,6 @@ test "modRem with zero divisor" {
12281217
12291218test "array operands to shuffle are coerced to vectors" {
12301219 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1231 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12321220 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12331221 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12341222 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1247,7 +1235,6 @@ test "load packed vector element" {
12471235 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12481236 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
12491237 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1250 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12511238
12521239 var x: @Vector(2, u15) = .{ 1, 4 };
12531240 try expect((&x[0]).* == 1);
......@@ -1260,7 +1247,6 @@ test "store packed vector element" {
12601247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12611248 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
12621249 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1263 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12641250
12651251 var v = @Vector(4, u1){ 1, 1, 1, 1 };
12661252 try expectEqual(@Vector(4, u1){ 1, 1, 1, 1 }, v);