authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-11-23 22:49:13-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-09 14:40:44-07:00
log05afb3f358e6c9fc8ae3ba9f3b135dc93f5d9aad
treec99747d2ab8c127995f65d321d41f31f4ad35051
parent703552e253757db994b20533526f2a5d0826a193

Merge pull request #13632 from ziglang/cbe


5 files changed, 377 insertions(+), 84 deletions(-)

lib/zig.h+148-4
......@@ -344,6 +344,12 @@ static inline zig_bool zig_addo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_
344344#endif
345345}
346346
347static inline void zig_vaddo_u32(zig_u8 *ov, zig_u32 *res, int n,
348 const zig_u32 *lhs, const zig_u32 *rhs, zig_u8 bits)
349{
350 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u32(&res[i], lhs[i], rhs[i], bits);
351}
352
347353zig_extern zig_i32 __addosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
348354static inline zig_bool zig_addo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
349355#if zig_has_builtin(add_overflow)
......@@ -358,6 +364,12 @@ static inline zig_bool zig_addo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_
358364 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
359365}
360366
367static inline void zig_vaddo_i32(zig_u8 *ov, zig_i32 *res, int n,
368 const zig_i32 *lhs, const zig_i32 *rhs, zig_u8 bits)
369{
370 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i32(&res[i], lhs[i], rhs[i], bits);
371}
372
361373static inline zig_bool zig_addo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
362374#if zig_has_builtin(add_overflow)
363375 zig_u64 full_res;
......@@ -370,6 +382,12 @@ static inline zig_bool zig_addo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_
370382#endif
371383}
372384
385static inline void zig_vaddo_u64(zig_u8 *ov, zig_u64 *res, int n,
386 const zig_u64 *lhs, const zig_u64 *rhs, zig_u8 bits)
387{
388 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u64(&res[i], lhs[i], rhs[i], bits);
389}
390
373391zig_extern zig_i64 __addodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
374392static inline zig_bool zig_addo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
375393#if zig_has_builtin(add_overflow)
......@@ -384,6 +402,12 @@ static inline zig_bool zig_addo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_
384402 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
385403}
386404
405static inline void zig_vaddo_i64(zig_u8 *ov, zig_i64 *res, int n,
406 const zig_i64 *lhs, const zig_i64 *rhs, zig_u8 bits)
407{
408 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i64(&res[i], lhs[i], rhs[i], bits);
409}
410
387411static inline zig_bool zig_addo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
388412#if zig_has_builtin(add_overflow)
389413 zig_u8 full_res;
......@@ -395,6 +419,12 @@ static inline zig_bool zig_addo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 b
395419#endif
396420}
397421
422static inline void zig_vaddo_u8(zig_u8 *ov, zig_u8 *res, int n,
423 const zig_u8 *lhs, const zig_u8 *rhs, zig_u8 bits)
424{
425 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u8(&res[i], lhs[i], rhs[i], bits);
426}
427
398428static inline zig_bool zig_addo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
399429#if zig_has_builtin(add_overflow)
400430 zig_i8 full_res;
......@@ -406,6 +436,12 @@ static inline zig_bool zig_addo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 b
406436#endif
407437}
408438
439static inline void zig_vaddo_i8(zig_u8 *ov, zig_i8 *res, int n,
440 const zig_i8 *lhs, const zig_i8 *rhs, zig_u8 bits)
441{
442 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i8(&res[i], lhs[i], rhs[i], bits);
443}
444
409445static inline zig_bool zig_addo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
410446#if zig_has_builtin(add_overflow)
411447 zig_u16 full_res;
......@@ -417,6 +453,12 @@ static inline zig_bool zig_addo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_
417453#endif
418454}
419455
456static inline void zig_vaddo_u16(zig_u8 *ov, zig_u16 *res, int n,
457 const zig_u16 *lhs, const zig_u16 *rhs, zig_u8 bits)
458{
459 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u16(&res[i], lhs[i], rhs[i], bits);
460}
461
420462static inline zig_bool zig_addo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
421463#if zig_has_builtin(add_overflow)
422464 zig_i16 full_res;
......@@ -428,6 +470,12 @@ static inline zig_bool zig_addo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_
428470#endif
429471}
430472
473static inline void zig_vaddo_i16(zig_u8 *ov, zig_i16 *res, int n,
474 const zig_i16 *lhs, const zig_i16 *rhs, zig_u8 bits)
475{
476 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i16(&res[i], lhs[i], rhs[i], bits);
477}
478
431479static inline zig_bool zig_subo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
432480#if zig_has_builtin(sub_overflow)
433481 zig_u32 full_res;
......@@ -440,6 +488,12 @@ static inline zig_bool zig_subo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_
440488#endif
441489}
442490
491static inline void zig_vsubo_u32(zig_u8 *ov, zig_u32 *res, int n,
492 const zig_u32 *lhs, const zig_u32 *rhs, zig_u8 bits)
493{
494 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u32(&res[i], lhs[i], rhs[i], bits);
495}
496
443497zig_extern zig_i32 __subosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
444498static inline zig_bool zig_subo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
445499#if zig_has_builtin(sub_overflow)
......@@ -454,6 +508,12 @@ static inline zig_bool zig_subo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_
454508 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
455509}
456510
511static inline void zig_vsubo_i32(zig_u8 *ov, zig_i32 *res, int n,
512 const zig_i32 *lhs, const zig_i32 *rhs, zig_u8 bits)
513{
514 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i32(&res[i], lhs[i], rhs[i], bits);
515}
516
457517static inline zig_bool zig_subo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
458518#if zig_has_builtin(sub_overflow)
459519 zig_u64 full_res;
......@@ -466,6 +526,12 @@ static inline zig_bool zig_subo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_
466526#endif
467527}
468528
529static inline void zig_vsubo_u64(zig_u8 *ov, zig_u64 *res, int n,
530 const zig_u64 *lhs, const zig_u64 *rhs, zig_u8 bits)
531{
532 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u64(&res[i], lhs[i], rhs[i], bits);
533}
534
469535zig_extern zig_i64 __subodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
470536static inline zig_bool zig_subo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
471537#if zig_has_builtin(sub_overflow)
......@@ -480,6 +546,12 @@ static inline zig_bool zig_subo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_
480546 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
481547}
482548
549static inline void zig_vsubo_i64(zig_u8 *ov, zig_i64 *res, int n,
550 const zig_i64 *lhs, const zig_i64 *rhs, zig_u8 bits)
551{
552 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i64(&res[i], lhs[i], rhs[i], bits);
553}
554
483555static inline zig_bool zig_subo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
484556#if zig_has_builtin(sub_overflow)
485557 zig_u8 full_res;
......@@ -491,6 +563,12 @@ static inline zig_bool zig_subo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 b
491563#endif
492564}
493565
566static inline void zig_vsubo_u8(zig_u8 *ov, zig_u8 *res, int n,
567 const zig_u8 *lhs, const zig_u8 *rhs, zig_u8 bits)
568{
569 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u8(&res[i], lhs[i], rhs[i], bits);
570}
571
494572static inline zig_bool zig_subo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
495573#if zig_has_builtin(sub_overflow)
496574 zig_i8 full_res;
......@@ -502,6 +580,13 @@ static inline zig_bool zig_subo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 b
502580#endif
503581}
504582
583static inline void zig_vsubo_i8(zig_u8 *ov, zig_i8 *res, int n,
584 const zig_i8 *lhs, const zig_i8 *rhs, zig_u8 bits)
585{
586 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i8(&res[i], lhs[i], rhs[i], bits);
587}
588
589
505590static inline zig_bool zig_subo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
506591#if zig_has_builtin(sub_overflow)
507592 zig_u16 full_res;
......@@ -513,6 +598,13 @@ static inline zig_bool zig_subo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_
513598#endif
514599}
515600
601static inline void zig_vsubo_u16(zig_u8 *ov, zig_u16 *res, int n,
602 const zig_u16 *lhs, const zig_u16 *rhs, zig_u8 bits)
603{
604 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u16(&res[i], lhs[i], rhs[i], bits);
605}
606
607
516608static inline zig_bool zig_subo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
517609#if zig_has_builtin(sub_overflow)
518610 zig_i16 full_res;
......@@ -524,6 +616,12 @@ static inline zig_bool zig_subo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_
524616#endif
525617}
526618
619static inline void zig_vsubo_i16(zig_u8 *ov, zig_i16 *res, int n,
620 const zig_i16 *lhs, const zig_i16 *rhs, zig_u8 bits)
621{
622 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i16(&res[i], lhs[i], rhs[i], bits);
623}
624
527625static inline zig_bool zig_mulo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
528626#if zig_has_builtin(mul_overflow)
529627 zig_u32 full_res;
......@@ -536,6 +634,12 @@ static inline zig_bool zig_mulo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_
536634#endif
537635}
538636
637static inline void zig_vmulo_u32(zig_u8 *ov, zig_u32 *res, int n,
638 const zig_u32 *lhs, const zig_u32 *rhs, zig_u8 bits)
639{
640 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u32(&res[i], lhs[i], rhs[i], bits);
641}
642
539643zig_extern zig_i32 __mulosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
540644static inline zig_bool zig_mulo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
541645#if zig_has_builtin(mul_overflow)
......@@ -550,6 +654,12 @@ static inline zig_bool zig_mulo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_
550654 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
551655}
552656
657static inline void zig_vmulo_i32(zig_u8 *ov, zig_i32 *res, int n,
658 const zig_i32 *lhs, const zig_i32 *rhs, zig_u8 bits)
659{
660 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i32(&res[i], lhs[i], rhs[i], bits);
661}
662
553663static inline zig_bool zig_mulo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
554664#if zig_has_builtin(mul_overflow)
555665 zig_u64 full_res;
......@@ -562,6 +672,12 @@ static inline zig_bool zig_mulo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_
562672#endif
563673}
564674
675static inline void zig_vmulo_u64(zig_u8 *ov, zig_u64 *res, int n,
676 const zig_u64 *lhs, const zig_u64 *rhs, zig_u8 bits)
677{
678 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u64(&res[i], lhs[i], rhs[i], bits);
679}
680
565681zig_extern zig_i64 __mulodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
566682static inline zig_bool zig_mulo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
567683#if zig_has_builtin(mul_overflow)
......@@ -576,6 +692,12 @@ static inline zig_bool zig_mulo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_
576692 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
577693}
578694
695static inline void zig_vmulo_i64(zig_u8 *ov, zig_i64 *res, int n,
696 const zig_i64 *lhs, const zig_i64 *rhs, zig_u8 bits)
697{
698 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i64(&res[i], lhs[i], rhs[i], bits);
699}
700
579701static inline zig_bool zig_mulo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
580702#if zig_has_builtin(mul_overflow)
581703 zig_u8 full_res;
......@@ -587,6 +709,12 @@ static inline zig_bool zig_mulo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 b
587709#endif
588710}
589711
712static inline void zig_vmulo_u8(zig_u8 *ov, zig_u8 *res, int n,
713 const zig_u8 *lhs, const zig_u8 *rhs, zig_u8 bits)
714{
715 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u8(&res[i], lhs[i], rhs[i], bits);
716}
717
590718static inline zig_bool zig_mulo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
591719#if zig_has_builtin(mul_overflow)
592720 zig_i8 full_res;
......@@ -598,6 +726,12 @@ static inline zig_bool zig_mulo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 b
598726#endif
599727}
600728
729static inline void zig_vmulo_i8(zig_u8 *ov, zig_i8 *res, int n,
730 const zig_i8 *lhs, const zig_i8 *rhs, zig_u8 bits)
731{
732 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i8(&res[i], lhs[i], rhs[i], bits);
733}
734
601735static inline zig_bool zig_mulo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
602736#if zig_has_builtin(mul_overflow)
603737 zig_u16 full_res;
......@@ -609,6 +743,12 @@ static inline zig_bool zig_mulo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_
609743#endif
610744}
611745
746static inline void zig_vmulo_u16(zig_u8 *ov, zig_u16 *res, int n,
747 const zig_u16 *lhs, const zig_u16 *rhs, zig_u8 bits)
748{
749 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u16(&res[i], lhs[i], rhs[i], bits);
750}
751
612752static inline zig_bool zig_mulo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
613753#if zig_has_builtin(mul_overflow)
614754 zig_i16 full_res;
......@@ -620,6 +760,12 @@ static inline zig_bool zig_mulo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_
620760#endif
621761}
622762
763static inline void zig_vmulo_i16(zig_u8 *ov, zig_i16 *res, int n,
764 const zig_i16 *lhs, const zig_i16 *rhs, zig_u8 bits)
765{
766 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i16(&res[i], lhs[i], rhs[i], bits);
767}
768
623769#define zig_int_builtins(w) \
624770 static inline zig_u##w zig_shlw_u##w(zig_u##w lhs, zig_u8 rhs, zig_u8 bits) { \
625771 return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \
......@@ -846,10 +992,8 @@ static inline zig_u8 zig_bit_reverse_u8(zig_u8 val, zig_u8 bits) {
846992 full_res = __builtin_bitreverse8(val);
847993#else
848994 static zig_u8 const lut[0x10] = {
849 0b0000, 0b1000, 0b0100, 0b1100,
850 0b0010, 0b1010, 0b0110, 0b1110,
851 0b0001, 0b1001, 0b0101, 0b1101,
852 0b0011, 0b1011, 0b0111, 0b1111,
995 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
996 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
853997 };
854998 full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0;
855999#endif
src/codegen/c.zig+182-24
......@@ -18,6 +18,12 @@ const Air = @import("../Air.zig");
1818const Liveness = @import("../Liveness.zig");
1919const CType = @import("../type.zig").CType;
2020
21const target_util = @import("../target.zig");
22const libcFloatPrefix = target_util.libcFloatPrefix;
23const libcFloatSuffix = target_util.libcFloatSuffix;
24const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev;
25const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;
26
2127const Mutability = enum { Const, ConstArgument, Mut };
2228const BigIntLimb = std.math.big.Limb;
2329const BigInt = std.math.big.int;
......@@ -733,7 +739,7 @@ pub const DeclGen = struct {
733739 try dg.fmtIntLiteral(ty.errorUnionSet(), val),
734740 });
735741 },
736 .Array => {
742 .Array, .Vector => {
737743 if (location != .Initializer) {
738744 try writer.writeByte('(');
739745 try dg.renderTypecast(writer, ty);
......@@ -770,10 +776,10 @@ pub const DeclGen = struct {
770776 .BoundFn,
771777 .Opaque,
772778 => unreachable,
779
773780 .Fn,
774781 .Frame,
775782 .AnyFrame,
776 .Vector,
777783 => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{
778784 @tagName(tag),
779785 }),
......@@ -922,7 +928,7 @@ pub const DeclGen = struct {
922928 => try dg.renderParentPtr(writer, val, ty),
923929 else => unreachable,
924930 },
925 .Array => {
931 .Array, .Vector => {
926932 if (location == .FunctionArgument) {
927933 try writer.writeByte('(');
928934 try dg.renderTypecast(writer, ty);
......@@ -1200,7 +1206,6 @@ pub const DeclGen = struct {
12001206
12011207 .Frame,
12021208 .AnyFrame,
1203 .Vector,
12041209 => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{
12051210 @tagName(tag),
12061211 }),
......@@ -1746,7 +1751,7 @@ pub const DeclGen = struct {
17461751 if (t.isVolatilePtr()) try w.writeAll(" volatile");
17471752 return w.writeAll(" *");
17481753 },
1749 .Array => {
1754 .Array, .Vector => {
17501755 var array_pl = Type.Payload.Array{ .base = .{ .tag = .array }, .data = .{
17511756 .len = t.arrayLenIncludingSentinel(),
17521757 .elem_type = t.childType(),
......@@ -1859,7 +1864,6 @@ pub const DeclGen = struct {
18591864
18601865 .Frame,
18611866 .AnyFrame,
1862 .Vector,
18631867 => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{
18641868 @tagName(tag),
18651869 }),
......@@ -3180,25 +3184,43 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
31803184 const rhs = try f.resolveInst(bin_op.rhs);
31813185
31823186 const inst_ty = f.air.typeOfIndex(inst);
3183 const scalar_ty = f.air.typeOf(bin_op.lhs).scalarType();
3187 const vector_ty = f.air.typeOf(bin_op.lhs);
3188 const scalar_ty = vector_ty.scalarType();
31843189 const w = f.object.writer();
31853190
31863191 const local = try f.allocLocal(inst_ty, .Mut);
31873192 try w.writeAll(";\n");
31883193
3189 try f.writeCValueMember(w, local, .{ .field = 1 });
3190 try w.writeAll(" = zig_");
3191 try w.writeAll(operation);
3192 try w.writeAll("o_");
3193 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3194 try w.writeAll("(&");
3195 try f.writeCValueMember(w, local, .{ .field = 0 });
3196 try w.writeAll(", ");
3194 switch (vector_ty.zigTypeTag()) {
3195 .Vector => {
3196 try w.writeAll("zig_v");
3197 try w.writeAll(operation);
3198 try w.writeAll("o_");
3199 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3200 try w.writeAll("(");
3201 try f.writeCValueMember(w, local, .{ .field = 1 });
3202 try w.writeAll(", ");
3203 try f.writeCValueMember(w, local, .{ .field = 0 });
3204 try w.print(", {d}, ", .{vector_ty.vectorLen()});
3205 },
3206 else => {
3207 try f.writeCValueMember(w, local, .{ .field = 1 });
3208 try w.writeAll(" = zig_");
3209 try w.writeAll(operation);
3210 try w.writeAll("o_");
3211 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3212 try w.writeAll("(&");
3213 try f.writeCValueMember(w, local, .{ .field = 0 });
3214 try w.writeAll(", ");
3215 },
3216 }
3217
31973218 try f.writeCValue(w, lhs, .FunctionArgument);
31983219 try w.writeAll(", ");
31993220 try f.writeCValue(w, rhs, .FunctionArgument);
32003221 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
32013222 try w.writeAll(");\n");
3223
32023224 return local;
32033225}
32043226
......@@ -5206,16 +5228,153 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
52065228fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
52075229 if (f.liveness.isUnused(inst)) return CValue.none;
52085230
5209 const inst_ty = f.air.typeOfIndex(inst);
5231 const target = f.object.dg.module.getTarget();
5232 const scalar_ty = f.air.typeOfIndex(inst);
52105233 const reduce = f.air.instructions.items(.data)[inst].reduce;
52115234 const operand = try f.resolveInst(reduce.operand);
5235 const operand_ty = f.air.typeOf(reduce.operand);
5236 const vector_len = operand_ty.vectorLen();
52125237 const writer = f.object.writer();
5213 const local = try f.allocLocal(inst_ty, .Const);
5238
5239 const Op = union(enum) {
5240 call_fn: []const u8,
5241 infix: []const u8,
5242 ternary: []const u8,
5243 };
5244 var fn_name_buf: [64]u8 = undefined;
5245 const op: Op = switch (reduce.operation) {
5246 .And => .{ .infix = " &= " },
5247 .Or => .{ .infix = " |= " },
5248 .Xor => .{ .infix = " ^= " },
5249 .Min => switch (scalar_ty.zigTypeTag()) {
5250 .Int => Op{ .ternary = " < " },
5251 .Float => op: {
5252 const float_bits = scalar_ty.floatBits(target);
5253 break :op Op{
5254 .call_fn = std.fmt.bufPrintZ(&fn_name_buf, "{s}fmin{s}", .{
5255 libcFloatPrefix(float_bits), libcFloatSuffix(float_bits),
5256 }) catch unreachable,
5257 };
5258 },
5259 else => unreachable,
5260 },
5261 .Max => switch (scalar_ty.zigTypeTag()) {
5262 .Int => Op{ .ternary = " > " },
5263 .Float => op: {
5264 const float_bits = scalar_ty.floatBits(target);
5265 break :op Op{
5266 .call_fn = std.fmt.bufPrintZ(&fn_name_buf, "{s}fmax{s}", .{
5267 libcFloatPrefix(float_bits), libcFloatSuffix(float_bits),
5268 }) catch unreachable,
5269 };
5270 },
5271 else => unreachable,
5272 },
5273 .Add => switch (scalar_ty.zigTypeTag()) {
5274 .Int => Op{ .infix = " += " },
5275 .Float => op: {
5276 const float_bits = scalar_ty.floatBits(target);
5277 break :op Op{
5278 .call_fn = std.fmt.bufPrintZ(&fn_name_buf, "__add{s}f3", .{
5279 compilerRtFloatAbbrev(float_bits),
5280 }) catch unreachable,
5281 };
5282 },
5283 else => unreachable,
5284 },
5285 .Mul => switch (scalar_ty.zigTypeTag()) {
5286 .Int => Op{ .infix = " *= " },
5287 .Float => op: {
5288 const float_bits = scalar_ty.floatBits(target);
5289 break :op Op{
5290 .call_fn = std.fmt.bufPrintZ(&fn_name_buf, "__mul{s}f3", .{
5291 compilerRtFloatAbbrev(float_bits),
5292 }) catch unreachable,
5293 };
5294 },
5295 else => unreachable,
5296 },
5297 };
5298
5299 // Reduce a vector by repeatedly applying a function to produce an
5300 // accumulated result.
5301 //
5302 // Equivalent to:
5303 // reduce: {
5304 // var i: usize = 0;
5305 // var accum: T = init;
5306 // while (i < vec.len) : (i += 1) {
5307 // accum = func(accum, vec[i]);
5308 // }
5309 // break :reduce accum;
5310 // }
5311 const it = try f.allocLocal(Type.usize, .Mut);
5312 try writer.writeAll(" = 0;\n");
5313
5314 const accum = try f.allocLocal(scalar_ty, .Mut);
52145315 try writer.writeAll(" = ");
52155316
5216 _ = operand;
5217 _ = local;
5218 return f.fail("TODO: C backend: implement airReduce", .{});
5317 const init_val = switch (reduce.operation) {
5318 .And, .Or, .Xor, .Add => "0",
5319 .Min => switch (scalar_ty.zigTypeTag()) {
5320 .Int => "TODO_intmax",
5321 .Float => "TODO_nan",
5322 else => unreachable,
5323 },
5324 .Max => switch (scalar_ty.zigTypeTag()) {
5325 .Int => "TODO_intmin",
5326 .Float => "TODO_nan",
5327 else => unreachable,
5328 },
5329 .Mul => "1",
5330 };
5331 try writer.writeAll(init_val);
5332 try writer.writeAll(";");
5333 try f.object.indent_writer.insertNewline();
5334 try writer.writeAll("for(;");
5335 try f.writeCValue(writer, it, .Other);
5336 try writer.print("<{d};++", .{vector_len});
5337 try f.writeCValue(writer, it, .Other);
5338 try writer.writeAll(") ");
5339 try f.writeCValue(writer, accum, .Other);
5340
5341 switch (op) {
5342 .call_fn => |fn_name| {
5343 try writer.print(" = {s}(", .{fn_name});
5344 try f.writeCValue(writer, accum, .FunctionArgument);
5345 try writer.writeAll(", ");
5346 try f.writeCValue(writer, operand, .Other);
5347 try writer.writeAll("[");
5348 try f.writeCValue(writer, it, .Other);
5349 try writer.writeAll("])");
5350 },
5351 .infix => |ass| {
5352 try writer.writeAll(ass);
5353 try f.writeCValue(writer, operand, .Other);
5354 try writer.writeAll("[");
5355 try f.writeCValue(writer, it, .Other);
5356 try writer.writeAll("]");
5357 },
5358 .ternary => |cmp| {
5359 try writer.writeAll(" = ");
5360 try f.writeCValue(writer, accum, .Other);
5361 try writer.writeAll(cmp);
5362 try f.writeCValue(writer, operand, .Other);
5363 try writer.writeAll("[");
5364 try f.writeCValue(writer, it, .Other);
5365 try writer.writeAll("] ? ");
5366 try f.writeCValue(writer, accum, .Other);
5367 try writer.writeAll(" : ");
5368 try f.writeCValue(writer, operand, .Other);
5369 try writer.writeAll("[");
5370 try f.writeCValue(writer, it, .Other);
5371 try writer.writeAll("]");
5372 },
5373 }
5374
5375 try writer.writeAll(";\n");
5376
5377 return accum;
52195378}
52205379
52215380fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -5234,7 +5393,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
52345393 const local = try f.allocLocal(inst_ty, mutability);
52355394 try writer.writeAll(" = ");
52365395 switch (inst_ty.zigTypeTag()) {
5237 .Array => {
5396 .Array, .Vector => {
52385397 const elem_ty = inst_ty.childType();
52395398 try writer.writeByte('{');
52405399 var empty = true;
......@@ -5354,7 +5513,6 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
53545513 try writer.writeAll(";\n");
53555514 },
53565515 },
5357 .Vector => return f.fail("TODO: C backend: implement airAggregateInit for vectors", .{}),
53585516 else => unreachable,
53595517 }
53605518
......@@ -5868,7 +6026,7 @@ fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) T
58686026
58696027fn lowersToArray(ty: Type, target: std.Target) bool {
58706028 return switch (ty.zigTypeTag()) {
5871 .Array => return true,
6029 .Array, .Vector => return true,
58726030 else => return ty.isAbiInt() and toCIntBits(@intCast(u32, ty.bitSize(target))) == null,
58736031 };
58746032}
......@@ -5877,7 +6035,7 @@ fn loweredArrayInfo(ty: Type, target: std.Target) ?Type.ArrayInfo {
58776035 if (!lowersToArray(ty, target)) return null;
58786036
58796037 switch (ty.zigTypeTag()) {
5880 .Array => return ty.arrayInfo(),
6038 .Array, .Vector => return ty.arrayInfo(),
58816039 else => {
58826040 const abi_size = ty.abiSize(target);
58836041 const abi_align = ty.abiAlignment(target);
src/codegen/llvm.zig+7-44
......@@ -16,7 +16,6 @@ const Package = @import("../Package.zig");
1616const TypedValue = @import("../TypedValue.zig");
1717const Air = @import("../Air.zig");
1818const Liveness = @import("../Liveness.zig");
19const target_util = @import("../target.zig");
2019const Value = @import("../value.zig").Value;
2120const Type = @import("../type.zig").Type;
2221const LazySrcLoc = Module.LazySrcLoc;
......@@ -27,6 +26,12 @@ const aarch64_c_abi = @import("../arch/aarch64/abi.zig");
2726const arm_c_abi = @import("../arch/arm/abi.zig");
2827const riscv_c_abi = @import("../arch/riscv64/abi.zig");
2928
29const target_util = @import("../target.zig");
30const libcFloatPrefix = target_util.libcFloatPrefix;
31const libcFloatSuffix = target_util.libcFloatSuffix;
32const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev;
33const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;
34
3035const Error = error{ OutOfMemory, CodegenFail };
3136
3237pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 {
......@@ -7328,46 +7333,6 @@ pub const FuncGen = struct {
73287333 };
73297334 }
73307335
7331 fn libcFloatPrefix(float_bits: u16) []const u8 {
7332 return switch (float_bits) {
7333 16, 80 => "__",
7334 32, 64, 128 => "",
7335 else => unreachable,
7336 };
7337 }
7338
7339 fn libcFloatSuffix(float_bits: u16) []const u8 {
7340 return switch (float_bits) {
7341 16 => "h", // Non-standard
7342 32 => "f",
7343 64 => "",
7344 80 => "x", // Non-standard
7345 128 => "q", // Non-standard (mimics convention in GCC libquadmath)
7346 else => unreachable,
7347 };
7348 }
7349
7350 fn compilerRtFloatAbbrev(float_bits: u16) []const u8 {
7351 return switch (float_bits) {
7352 16 => "h",
7353 32 => "s",
7354 64 => "d",
7355 80 => "x",
7356 128 => "t",
7357 else => unreachable,
7358 };
7359 }
7360
7361 fn compilerRtIntAbbrev(bits: u16) []const u8 {
7362 return switch (bits) {
7363 16 => "h",
7364 32 => "s",
7365 64 => "d",
7366 128 => "t",
7367 else => "o", // Non-standard
7368 };
7369 }
7370
73717336 /// Creates a floating point comparison by lowering to the appropriate
73727337 /// hardware instruction or softfloat routine for the target
73737338 fn buildFloatCmp(
......@@ -9034,12 +8999,10 @@ pub const FuncGen = struct {
90348999 const target = self.dg.module.getTarget();
90359000
90369001 const reduce = self.air.instructions.items(.data)[inst].reduce;
9037 var operand = try self.resolveInst(reduce.operand);
9002 const operand = try self.resolveInst(reduce.operand);
90389003 const operand_ty = self.air.typeOf(reduce.operand);
90399004 const scalar_ty = self.air.typeOfIndex(inst);
90409005
9041 // TODO handle the fast math setting
9042
90439006 switch (reduce.operation) {
90449007 .And => return self.builder.buildAndReduce(operand),
90459008 .Or => return self.builder.buildOrReduce(operand),
src/target.zig+40
......@@ -724,3 +724,43 @@ pub fn supportsTailCall(target: std.Target, backend: std.builtin.CompilerBackend
724724 else => return false,
725725 }
726726}
727
728pub fn libcFloatPrefix(float_bits: u16) []const u8 {
729 return switch (float_bits) {
730 16, 80 => "__",
731 32, 64, 128 => "",
732 else => unreachable,
733 };
734}
735
736pub fn libcFloatSuffix(float_bits: u16) []const u8 {
737 return switch (float_bits) {
738 16 => "h", // Non-standard
739 32 => "f",
740 64 => "",
741 80 => "x", // Non-standard
742 128 => "q", // Non-standard (mimics convention in GCC libquadmath)
743 else => unreachable,
744 };
745}
746
747pub fn compilerRtFloatAbbrev(float_bits: u16) []const u8 {
748 return switch (float_bits) {
749 16 => "h",
750 32 => "s",
751 64 => "d",
752 80 => "x",
753 128 => "t",
754 else => unreachable,
755 };
756}
757
758pub fn compilerRtIntAbbrev(bits: u16) []const u8 {
759 return switch (bits) {
760 16 => "h",
761 32 => "s",
762 64 => "d",
763 128 => "t",
764 else => "o", // Non-standard
765 };
766}
test/behavior/vector.zig-12
......@@ -13,7 +13,6 @@ test "implicit cast vector to array - bool" {
1313 }
1414
1515 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1716 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1817 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1918 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -294,7 +293,6 @@ test "vector @splat" {
294293
295294test "load vector elements via comptime index" {
296295 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
297 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
298296 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
299297 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
300298 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -317,7 +315,6 @@ test "load vector elements via comptime index" {
317315
318316test "store vector elements via comptime index" {
319317 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
320 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
321318 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
322319 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
323320 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -346,7 +343,6 @@ test "store vector elements via comptime index" {
346343
347344test "load vector elements via runtime index" {
348345 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
349 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
350346 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
351347 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
352348 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -369,7 +365,6 @@ test "load vector elements via runtime index" {
369365
370366test "store vector elements via runtime index" {
371367 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
372 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
373368 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
374369 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
375370 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -393,7 +388,6 @@ test "store vector elements via runtime index" {
393388
394389test "initialize vector which is a struct field" {
395390 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
396 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
397391 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
398392 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
399393 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -975,7 +969,6 @@ test "@addWithOverflow" {
975969 return error.SkipZigTest;
976970 }
977971 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
978 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
979972 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
980973 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
981974 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1018,7 +1011,6 @@ test "@subWithOverflow" {
10181011 return error.SkipZigTest;
10191012 }
10201013 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1021 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10221014 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10231015 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10241016 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1049,7 +1041,6 @@ test "@mulWithOverflow" {
10491041 return error.SkipZigTest;
10501042 }
10511043 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1052 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10531044 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10541045 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10551046 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1072,7 +1063,6 @@ test "@shlWithOverflow" {
10721063 return error.SkipZigTest;
10731064 }
10741065 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1075 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10761066 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10771067 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10781068 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1098,7 +1088,6 @@ test "alignment of vectors" {
10981088
10991089test "loading the second vector from a slice of vectors" {
11001090 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1101 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11021091 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11031092 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11041093 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1115,7 +1104,6 @@ test "loading the second vector from a slice of vectors" {
11151104
11161105test "array of vectors is copied" {
11171106 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1118 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11191107 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11201108 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11211109 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO