diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index f57469b6e23..f40f6432fd4 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -21661,6 +21661,68 @@ aarch64_stack_protect_guard (void) return NULL_TREE; } +/* Return the diagnostic message string if conversion from FROMTYPE to + TOTYPE is not allowed, NULL otherwise. */ + +static const char * +aarch64_invalid_conversion (const_tree fromtype, const_tree totype) +{ + static char templ[100]; + if ((GET_MODE_INNER (TYPE_MODE (fromtype)) == BFmode + || GET_MODE_INNER (TYPE_MODE (totype)) == BFmode) + && TYPE_MODE (fromtype) != TYPE_MODE (totype)) + { + snprintf (templ, sizeof (templ), \ + "incompatible types when assigning to type '%s' from type '%s'", + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (totype))), + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (fromtype)))); + return N_(templ); + } + /* Conversion allowed. */ + return NULL; +} + +/* Return the diagnostic message string if the unary operation OP is + not permitted on TYPE, NULL otherwise. */ + +static const char * +aarch64_invalid_unary_op (int op, const_tree type) +{ + static char templ[100]; + /* Reject all single-operand operations on BFmode except for &. */ + if (GET_MODE_INNER (TYPE_MODE (type)) == BFmode && op != ADDR_EXPR) + { + snprintf (templ, sizeof (templ), + "operation not permitted on type '%s'", + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); + return N_(templ); + } + /* Operation allowed. */ + return NULL; +} + +/* Return the diagnostic message string if the binary operation OP is + not permitted on TYPE1 and TYPE2, NULL otherwise. */ + +static const char * +aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, + const_tree type2) +{ + static char templ[100]; + /* Reject all 2-operand operations on BFmode. */ + if (GET_MODE_INNER (TYPE_MODE (type1)) == BFmode + || GET_MODE_INNER (TYPE_MODE (type2)) == BFmode) + { + snprintf (templ, sizeof (templ), \ + "operation not permitted on types '%s', '%s'", + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type1))), + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)))); + return N_(templ); + } + /* Operation allowed. */ + return NULL; +} + /* Implement TARGET_ASM_FILE_END for AArch64. This adds the AArch64 GNU NOTE section at the end if needed. */ #define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 @@ -21911,6 +21973,15 @@ aarch64_libgcc_floating_mode_supported_p #undef TARGET_MANGLE_TYPE #define TARGET_MANGLE_TYPE aarch64_mangle_type +#undef TARGET_INVALID_CONVERSION +#define TARGET_INVALID_CONVERSION aarch64_invalid_conversion + +#undef TARGET_INVALID_UNARY_OP +#define TARGET_INVALID_UNARY_OP aarch64_invalid_unary_op + +#undef TARGET_INVALID_BINARY_OP +#define TARGET_INVALID_BINARY_OP aarch64_invalid_binary_op + #undef TARGET_VERIFY_TYPE_CONTEXT #define TARGET_VERIFY_TYPE_CONTEXT aarch64_verify_type_context diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c new file mode 100644 index 00000000000..6f6a6af9587 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c @@ -0,0 +1,83 @@ +/* { dg-do compile { target { aarch64*-*-* } } } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=armv8.2-a+i8mm" } */ + +#include + +bfloat16_t glob; +float is_a_float; +int n; + +bfloat16_t footest (bfloat16_t scalar0) +{ + + /* Initialisation */ + + bfloat16_t scalar1 = 0.1; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'double'" "" {target *-*-*} } */ + bfloat16_t scalar2 = 0; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'int'" "" {target *-*-*} } */ + bfloat16_t scalar3 = {}; /* { dg-error "empty scalar initializer" "" {target *-*-*} } */ + + float16_t initi_a = scalar1; /* { dg-error "incompatible types when assigning to type 'float16_t' from type 'bfloat16_t'" "" {target *-*-*} } */ + float16_t initi_b = { scalar1 }; /* { dg-error "incompatible types when assigning to type 'float16_t' from type 'bfloat16_t'" "" {target *-*-*} } */ + + /* Compound literals. */ + + (bfloat16_t) {}; /* { dg-error "empty scalar initializer" "" {target *-*-*} } */ + (bfloat16_t) { scalar1 }; + + (int) { scalar1 }; /* { dg-error "incompatible types when assigning to type 'int' from type 'bfloat16_t'" "" {target *-*-*} } */ + + /* Casting. */ + + (void) scalar1; + (bfloat16_t) scalar1; + + /* Arrays and Structs. */ + + typedef bfloat16_t array_type[2]; + extern bfloat16_t extern_array[]; + + bfloat16_t array[2]; + bfloat16_t zero_length_array[0]; + bfloat16_t empty_init_array[] = {}; + typedef bfloat16_t vla_type[n]; + + struct struct1 { + bfloat16_t a; + }; + + union union1 { + bfloat16_t a; + }; + + /* Assignments. */ + + n = scalar1; /* { dg-error "incompatible types when assigning to type 'int' from type 'bfloat16_t'" "" {target *-*-*} } */ + is_a_float = scalar1; /* { dg-error "incompatible types when assigning to type 'float' from type 'bfloat16_t'" "" {target *-*-*} } */ + scalar1 = 0; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'int'" "" {target *-*-*} } */ + scalar1 = 0.1; /* { dg-error "incompatible types when assigning to type 'bfloat16_t' from type 'double'" "" {target *-*-*} } */ + scalar1 = scalar2; + + /* Addressing and dereferencing. */ + + bfloat16_t *bfloat_ptr = &scalar1; + scalar1 = *bfloat_ptr; + + /* Pointer assignment. */ + + bfloat16_t *bfloat_ptr2 = bfloat_ptr; + + /* Single-operand operation. */ + + scalar1 = !glob; /* { dg-error "operation not permitted on type 'bfloat16_t'" "" {target *-*-*} } */ + + /* Double-operand operations. */ + + scalar1 = glob + *bfloat_ptr; /* { dg-error "operation not permitted on types 'bfloat16_t', 'bfloat16_t'" "" {target *-*-*} } */ + scalar1 = glob + 0.1; /* { dg-error "operation not permitted on types 'bfloat16_t', 'double'" "" {target *-*-*} } */ + scalar1 = glob + 0; /* { dg-error "operation not permitted on types 'bfloat16_t', 'int'" "" {target *-*-*} } */ + scalar1 = glob + is_a_float; /* { dg-error "operation not permitted on types 'bfloat16_t', 'float'" "" {target *-*-*} } */ + + return scalar0; +} + diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck1.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck1.c new file mode 100644 index 00000000000..06786d9daa9 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck1.c @@ -0,0 +1,85 @@ +/* { dg-do compile { target { aarch64*-*-* } } } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=armv8.2-a+i8mm" } */ + +#include + +bfloat16x4_t glob; +float is_a_float; +float16x4_t is_a_floatx4; +int16x4_t intvec; +int n; +short n2; +bfloat16_t scalar0, scalar1, scalar2, scalar3; + +bfloat16x4_t footest (bfloat16x4_t vector0) +{ + /* Initialisation */ + + bfloat16x4_t vector1 = { 0.0, n, n2, is_a_float }; + /* { dg-error "incompatible types when assigning to type '__bf16' from type 'double'" "" {target *-*-*} 19 } */ + /* { dg-error "incompatible types when assigning to type '__bf16' from type 'int'" "" {target *-*-*} 19 } */ + /* { dg-error "incompatible types when assigning to type '__bf16' from type 'short int'" "" {target *-*-*} 19 } */ + /* { dg-error "incompatible types when assigning to type '__bf16' from type 'float'" "" {target *-*-*} 19 } */ + + bfloat16x4_t vector2 = {}; + + (bfloat16x4_t) {}; + + bfloat16x4_t vector4 = { scalar0, scalar1, scalar2, scalar3 }; + + float16x4_t initi_a = vector1; /* { dg-error "incompatible types when initializing type 'float16x4_t' using type 'bfloat16x4_t'" "" {target *-*-*} } */ + + /* Casting. */ + + (void) vector1; + (bfloat16x4_t) vector1; + + /* Arrays and Structs. */ + + typedef bfloat16x4_t array_type[2]; + extern bfloat16x4_t extern_array[]; + + bfloat16x4_t array[2]; + bfloat16x4_t zero_length_array[0]; + bfloat16x4_t empty_init_array[] = {}; + typedef bfloat16x4_t some_other_type[n]; + + struct struct1 { + bfloat16x4_t a; + }; + + union union1 { + bfloat16x4_t a; + }; + + /* Assignments. */ + + intvec = vector1; /* { dg-error "incompatible types when assigning to type 'int16x4_t' from type 'bfloat16x4_t'" "" {target *-*-*} } */ + is_a_floatx4 = vector1; /* { dg-error "incompatible types when assigning to type 'float16x4_t' from type 'bfloat16x4_t'" "" {target *-*-*} } */ + vector1 = 0; /* { dg-error "incompatible types when assigning to type 'bfloat16x4_t' from type 'int'" "" {target *-*-*} } */ + vector1 = 0.1; /* { dg-error "incompatible types when assigning to type 'bfloat16x4_t' from type 'double'" "" {target *-*-*} } */ + vector1 = vector2; + + /* Addressing and dereferencing. */ + + bfloat16x4_t *bfloat_ptr = &vector1; + vector1 = *bfloat_ptr; + + /* Pointer assignment. */ + + bfloat16x4_t *bfloat_ptr2 = bfloat_ptr; + + /* Single-operand operation. */ + + vector1 = !glob; /* { dg-error "operation not permitted on type 'bfloat16x4_t'" "" {target *-*-*} } */ + + /* Double-operand operations. */ + + vector1 = glob + *bfloat_ptr; /* { dg-error "operation not permitted on types 'bfloat16x4_t', 'bfloat16x4_t'" "" {target *-*-*} } */ + vector1 = glob + 0.1; /* { dg-error "operation not permitted on types 'bfloat16x4_t', 'double'" "" {target *-*-*} } */ + vector1 = glob + 0; /* { dg-error "operation not permitted on types 'bfloat16x4_t', 'int'" "" {target *-*-*} } */ + vector1 = glob + is_a_floatx4; /* { dg-error "operation not permitted on types 'bfloat16x4_t', 'float16x4_t'" "" {target *-*-*} } */ + + return vector0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck2.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck2.c new file mode 100644 index 00000000000..3be3e0551b2 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck2.c @@ -0,0 +1,95 @@ +/* { dg-do compile { target { aarch64*-*-* } } } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=armv8.2-a+i8mm" } */ + +#include + +bfloat16_t scalar0, scalar1, scalar2, scalar3; +bfloat16x8_t glob; + +float16_t is_a_half_float; +float16x8_t is_a_floatx8; +int16x8_t intvec; + +float is_a_float; +int is_an_int; +unsigned int is_a_uint; +short is_a_short_int; +long is_long; +long double is_long_double; + +bfloat16x8_t footest (bfloat16x8_t vector0) +{ + /* Initialisation */ + + bfloat16x8_t vector1 = { 0.0, is_an_int, is_a_short_int, is_a_float, is_a_half_float, is_long, is_a_uint, is_long_double }; + /* { dg-error "incompatible types when assigning to type '__bf16' from type 'double'" "" {target *-*-*} 25 } */ + /* { dg-error "incompatible types when assigning to type '__bf16' from type 'int'" "" {target *-*-*} 25 } */ + /* { dg-error "incompatible types when assigning to type '__bf16' from type 'short int'" "" {target *-*-*} 25 } */ + /* { dg-error "incompatible types when assigning to type '__bf16' from type 'float'" "" {target *-*-*} 25 } */ + /* { dg-error "incompatible types when assigning to type '__bf16' from type 'float16_t'" "" {target *-*-*} 25 } */ + /* { dg-error "incompatible types when assigning to type '__bf16' from type 'long int'" "" {target *-*-*} 25 } */ + /* { dg-error "incompatible types when assigning to type '__bf16' from type 'unsigned int'" "" {target *-*-*} 25 } */ + /* { dg-error "incompatible types when assigning to type '__bf16' from type 'long double'" "" {target *-*-*} 25 } */ + + bfloat16x8_t vector2 = {}; + + (bfloat16x8_t) {}; + + bfloat16x8_t vector4 = { scalar0, scalar1, scalar2, scalar3, scalar0, scalar1, scalar2, scalar3 }; + + float16x8_t initi_a = vector1; /* { dg-error "incompatible types when initializing type 'float16x8_t' using type 'bfloat16x8_t'" "" {target *-*-*} } */ + + /* Casting. */ + + (void) vector1; + (bfloat16x8_t) vector1; + + /* Arrays and Structs. */ + + typedef bfloat16x8_t array_type[2]; + extern bfloat16x8_t extern_array[]; + + bfloat16x8_t array[2]; + bfloat16x8_t zero_length_array[0]; + bfloat16x8_t empty_init_array[] = {}; + typedef bfloat16x8_t some_other_type[is_an_int]; + + struct struct1 { + bfloat16x8_t a; + }; + + union union1 { + bfloat16x8_t a; + }; + + /* Assignments. */ + + intvec = vector1; /* { dg-error "incompatible types when assigning to type 'int16x8_t' from type 'bfloat16x8_t'" "" {target *-*-*} } */ + is_a_floatx8 = vector1; /* { dg-error "incompatible types when assigning to type 'float16x8_t' from type 'bfloat16x8_t'" "" {target *-*-*} } */ + vector1 = 0; /* { dg-error "incompatible types when assigning to type 'bfloat16x8_t' from type 'int'" "" {target *-*-*} } */ + vector1 = 0.1; /* { dg-error "incompatible types when assigning to type 'bfloat16x8_t' from type 'double'" "" {target *-*-*} } */ + vector1 = vector2; + + /* Addressing and dereferencing. */ + + bfloat16x8_t *bfloat_ptr = &vector1; + vector1 = *bfloat_ptr; + + /* Pointer assignment. */ + + bfloat16x8_t *bfloat_ptr2 = bfloat_ptr; + + /* Single-operand operation. */ + + vector1 = !glob; /* { dg-error "operation not permitted on type 'bfloat16x8_t'" "" {target *-*-*} } */ + + /* Double-operand operations. */ + + vector1 = glob + *bfloat_ptr; /* { dg-error "operation not permitted on types 'bfloat16x8_t', 'bfloat16x8_t'" "" {target *-*-*} } */ + vector1 = glob + 0.1; /* { dg-error "operation not permitted on types 'bfloat16x8_t', 'double'" "" {target *-*-*} } */ + vector1 = glob + 0; /* { dg-error "operation not permitted on types 'bfloat16x8_t', 'int'" "" {target *-*-*} } */ + vector1 = glob + is_a_floatx8; /* { dg-error "operation not permitted on types 'bfloat16x8_t', 'float16x8_t'" "" {target *-*-*} } */ + + return vector0; +}