> On 19 Sep 2024, at 15:39, Claudio Bantaloukas <claudio.bantalou...@arm.com> > wrote: > > External email: Use caution opening links or attachments > > > On 9/19/2024 2:18 PM, Kyrylo Tkachov wrote: >> Hi Claudio, >> >>> On 19 Sep 2024, at 15:09, Claudio Bantaloukas <claudio.bantalou...@arm.com> >>> wrote: >>> >>> External email: Use caution opening links or attachments >>> >>> >>> The ACLE defines a new scalar type, __mfp8. This is an opaque 8bit types >>> that >>> can only be used by fp8 intrinsics. Additionally, the mfloat8_t type is made >>> available in arm_neon.h and arm_sve.h as an alias of the same. >>> >>> This implementation uses an unsigned INTEGER_TYPE, with precision 8 to >>> represent __mfp8. Conversions to int and other types are disabled via the >>> TARGET_INVALID_CONVERSION hook. >>> Additionally, operations that are typically available to integer types are >>> disabled via TARGET_INVALID_UNARY_OP and TARGET_INVALID_BINARY_OP hooks. >>> >>> gcc/ChangeLog: >>> >>> * config/aarch64/aarch64-builtins.cc (aarch64_mfp8_type_node): Add >>> node >>> for __mfp8 type. >>> (aarch64_mfp8_ptr_type_node): Add node for __mfp8 pointer type. >>> (aarch64_init_fp8_types): New function to initialise fp8 types and >>> register with language backends. >>> * config/aarch64/aarch64.cc (aarch64_mangle_type): Add ABI mangling >>> for >>> new type. >>> (aarch64_invalid_conversion): Add function implementing >>> TARGET_INVALID_CONVERSION hook that blocks conversion to and from the >>> __mfp8 type. >>> (aarch64_invalid_unary_op): Add function implementing TARGET_UNARY_OP >>> hook that blocks operations on __mfp8 other than &. >>> (aarch64_invalid_binary_op): Extend TARGET_BINARY_OP hook to disallow >>> operations on __mfp8 type. >>> (TARGET_INVALID_CONVERSION): Add define. >>> (TARGET_INVALID_UNARY_OP): Likewise. >>> * config/aarch64/aarch64.h (aarch64_mfp8_type_node): Add node for >>> __mfp8 >>> type. >>> (aarch64_mfp8_ptr_type_node): Add node for __mfp8 pointer type. >>> * config/aarch64/arm_neon.h (mfloat8_t): Add typedef. >>> * config/aarch64/arm_sve.h (mfloat8_t): Likewise. >> >> Looks like this typedef is a good candidate to go into arm_private_fp8.h so >> that arm_neon.h, arm_sve.h and arm_sme.h inherit it. > > Hi Kyrill, > thanks for the quick review. The thought of using arm_private_fp8.h > crossed my mind but I thought that ultimately it made more sense to > follow existing practice and place the typedef near existing ones for > bfloat types. > If you feel strongly about this, I'll make the suggested change, but I'd > rather keep it as is. As you can see, the rest of the patch borrows > heavily in style from the bfloat implementation and my hope is that the > closeness in code will aid in maintainability.
I see. It’s not an unreasonable argument. But the bfloat16 implementation does exactly that :) The "typedef __bf16 bfloat16_t” is defined in arm_bf16.h and that is in turn included in arm_neon.h, arm_sve.h (and therefore arm_sme.h) so arm_bfp16.h performs the same role as arm_private_fp8.h so it seems consistent to define the fp8 typedefs in arm_private_fp8.h The rest of the patch looks reasonable to me but I think Richard should give the final okay as he’s done the initial review. Thanks, Kyrill > > Let me know :) > > Cheers, > Claudio > >> >> Thanks, >> Kyrill >> >> >>> >>> gcc/testsuite/ChangeLog: >>> >>> * g++.target/aarch64/fp8_mangling.C: New tests exercising mangling. >>> * g++.target/aarch64/fp8_scalar_typecheck_2.C: New tests in C++. >>> * gcc.target/aarch64/fp8_scalar_1.c: New tests in C. >>> * gcc.target/aarch64/fp8_scalar_typecheck_1.c: Likewise. >>> --- >>> Hi, >>> Is this ok for master? I do not have commit rights yet, if ok, can someone >>> commit it on my behalf? >>> >>> Regression tested with aarch64-unknown-linux-gnu. >>> >>> Compared to V1 of the patch, in version 2: >>> - mangling for the __mfp8 type was added along with tests >>> - unneeded comments were removed >>> - simplified type checks in hooks >>> - simplified initialization of aarch64_mfp8_type_node >>> - separated mfloat8_t define from other fp types in arm_sve.h >>> - C++ tests were moved to g++.target/aarch64 >>> - added more tests around binary operations, function declaration, >>> type traits >>> - added tests exercising loads and stores from floating point registers >>> >>> >>> Thanks, >>> Claudio Bantaloukas >>> >>> gcc/config/aarch64/aarch64-builtins.cc | 20 + >>> gcc/config/aarch64/aarch64.cc | 54 ++- >>> gcc/config/aarch64/aarch64.h | 5 + >>> gcc/config/aarch64/arm_neon.h | 2 + >>> gcc/config/aarch64/arm_sve.h | 2 + >>> .../g++.target/aarch64/fp8_mangling.C | 44 ++ >>> .../aarch64/fp8_scalar_typecheck_2.C | 381 ++++++++++++++++++ >>> .../gcc.target/aarch64/fp8_scalar_1.c | 134 ++++++ >>> .../aarch64/fp8_scalar_typecheck_1.c | 356 ++++++++++++++++ >>> 9 files changed, 996 insertions(+), 2 deletions(-) >>> create mode 100644 gcc/testsuite/g++.target/aarch64/fp8_mangling.C >>> create mode 100644 gcc/testsuite/g++.target/aarch64/fp8_scalar_typecheck_2.C >>> create mode 100644 gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c >>> create mode 100644 gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c >>> >>> diff --git a/gcc/config/aarch64/aarch64-builtins.cc >>> b/gcc/config/aarch64/aarch64-builtins.cc >>> index eb878b933fe..7d17df05a0f 100644 >>> --- a/gcc/config/aarch64/aarch64-builtins.cc >>> +++ b/gcc/config/aarch64/aarch64-builtins.cc >>> @@ -961,6 +961,11 @@ static GTY(()) tree aarch64_simd_intOI_type_node = >>> NULL_TREE; >>> static GTY(()) tree aarch64_simd_intCI_type_node = NULL_TREE; >>> static GTY(()) tree aarch64_simd_intXI_type_node = NULL_TREE; >>> >>> +/* The user-visible __mfp8 type, and a pointer to that type. Used >>> + across the back-end. */ >>> +tree aarch64_mfp8_type_node = NULL_TREE; >>> +tree aarch64_mfp8_ptr_type_node = NULL_TREE; >>> + >>> /* The user-visible __fp16 type, and a pointer to that type. Used >>> across the back-end. */ >>> tree aarch64_fp16_type_node = NULL_TREE; >>> @@ -1721,6 +1726,19 @@ aarch64_init_builtin_rsqrt (void) >>> } >>> } >>> >>> +/* Initialize the backend type that supports the user-visible __mfp8 >>> + type and its relative pointer type. */ >>> + >>> +static void >>> +aarch64_init_fp8_types (void) >>> +{ >>> + aarch64_mfp8_type_node = make_unsigned_type (8); >>> + SET_TYPE_MODE (aarch64_mfp8_type_node, QImode); >>> + >>> + lang_hooks.types.register_builtin_type (aarch64_mfp8_type_node, >>> "__mfp8"); >>> + aarch64_mfp8_ptr_type_node = build_pointer_type (aarch64_mfp8_type_node); >>> +} >>> + >>> /* Initialize the backend types that support the user-visible __fp16 >>> type, also initialize a pointer to that type, to be used when >>> forming HFAs. */ >>> @@ -2125,6 +2143,8 @@ aarch64_general_init_builtins (void) >>> { >>> aarch64_init_fpsr_fpcr_builtins (); >>> >>> + aarch64_init_fp8_types (); >>> + >>> aarch64_init_fp16_types (); >>> >>> aarch64_init_bf16_types (); >>> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc >>> index 92763d403c7..0ac00027502 100644 >>> --- a/gcc/config/aarch64/aarch64.cc >>> +++ b/gcc/config/aarch64/aarch64.cc >>> @@ -22467,6 +22467,10 @@ aarch64_mangle_type (const_tree type) >>> return "Dh"; >>> } >>> >>> + /* Modal 8 bit floating point types. */ >>> + if (TYPE_MAIN_VARIANT (type) == aarch64_mfp8_type_node) >>> + return "u6__mfp8"; >>> + >>> /* Mangle AArch64-specific internal types. TYPE_NAME is non-NULL_TREE for >>> builtin types. */ >>> if (TYPE_NAME (type) != NULL) >>> @@ -22481,6 +22485,29 @@ aarch64_mangle_type (const_tree type) >>> return NULL; >>> } >>> >>> +/* Implement TARGET_INVALID_CONVERSION. */ >>> + >>> +static const char * >>> +aarch64_invalid_conversion (const_tree fromtype, const_tree totype) >>> +{ >>> + /* Do not allow conversions to/from FP8. But do allow conversions between >>> + volatile and const variants of __mfp8. */ >>> + bool fromtype_is_fp8 >>> + = (TYPE_MAIN_VARIANT (fromtype) == aarch64_mfp8_type_node); >>> + bool totype_is_fp8 = (TYPE_MAIN_VARIANT (totype) == >>> aarch64_mfp8_type_node); >>> + >>> + if (fromtype_is_fp8 && totype_is_fp8) >>> + return NULL; >>> + >>> + if (fromtype_is_fp8) >>> + return N_ ("invalid conversion from type %<mfloat8_t%>"); >>> + if (totype_is_fp8) >>> + return N_ ("invalid conversion to type %<mfloat8_t%>"); >>> + >>> + /* Conversion allowed. */ >>> + return NULL; >>> +} >>> + >>> /* Implement TARGET_VERIFY_TYPE_CONTEXT. */ >>> >>> static bool >>> @@ -29031,8 +29058,20 @@ aarch64_stack_protect_guard (void) >>> return NULL_TREE; >>> } >>> >>> -/* Return the diagnostic message string if the binary operation OP is >>> - not permitted on TYPE1 and TYPE2, NULL otherwise. */ >>> +/* Implement TARGET_INVALID_UNARY_OP. */ >>> + >>> +static const char * >>> +aarch64_invalid_unary_op (int op, const_tree type) >>> +{ >>> + /* Reject all single-operand operations on __mfp8 except for &. */ >>> + if (TYPE_MAIN_VARIANT (type) == aarch64_mfp8_type_node && op != >>> ADDR_EXPR) >>> + return N_ ("operation not permitted on type %<mfloat8_t%>"); >>> + >>> + /* Operation allowed. */ >>> + return NULL; >>> +} >>> + >>> +/* Implement TARGET_INVALID_BINARY_OP. */ >>> >>> static const char * >>> aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, >>> @@ -29046,6 +29085,11 @@ aarch64_invalid_binary_op (int op >>> ATTRIBUTE_UNUSED, const_tree type1, >>> != aarch64_sve::builtin_type_p (type2))) >>> return N_("cannot combine GNU and SVE vectors in a binary operation"); >>> >>> + /* Reject all 2-operand operations on __mfp8. */ >>> + if (TYPE_MAIN_VARIANT (type1) == aarch64_mfp8_type_node >>> + || TYPE_MAIN_VARIANT (type2) == aarch64_mfp8_type_node) >>> + return N_ ("operation not permitted on type %<mfloat8_t%>"); >>> + >>> /* Operation allowed. */ >>> return NULL; >>> } >>> @@ -30763,6 +30807,12 @@ 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 >>> >>> diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h >>> index 2dfb999bea5..7ef82ce3587 100644 >>> --- a/gcc/config/aarch64/aarch64.h >>> +++ b/gcc/config/aarch64/aarch64.h >>> @@ -1447,6 +1447,11 @@ extern const char *aarch64_rewrite_mcpu (int argc, >>> const char **argv); >>> >>> #define ASM_OUTPUT_POOL_EPILOGUE aarch64_asm_output_pool_epilogue >>> >>> +/* This type is the user-visible __mfp8, and a pointer to that type. We >>> + need it in many places in the backend. Defined in aarch64-builtins.cc. >>> */ >>> +extern GTY(()) tree aarch64_mfp8_type_node; >>> +extern GTY(()) tree aarch64_mfp8_ptr_type_node; >>> + >>> /* This type is the user-visible __fp16, and a pointer to that type. We >>> need it in many places in the backend. Defined in aarch64-builtins.cc. >>> */ >>> extern GTY(()) tree aarch64_fp16_type_node; >>> diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h >>> index e376685489d..0092314cf75 100644 >>> --- a/gcc/config/aarch64/arm_neon.h >>> +++ b/gcc/config/aarch64/arm_neon.h >>> @@ -72,6 +72,8 @@ typedef __Poly16_t poly16_t; >>> typedef __Poly64_t poly64_t; >>> typedef __Poly128_t poly128_t; >>> >>> +typedef __mfp8 mfloat8_t; >>> + >>> typedef __fp16 float16_t; >>> typedef float float32_t; >>> typedef double float64_t; >>> diff --git a/gcc/config/aarch64/arm_sve.h b/gcc/config/aarch64/arm_sve.h >>> index aa0bd9909f9..dbc61650df2 100644 >>> --- a/gcc/config/aarch64/arm_sve.h >>> +++ b/gcc/config/aarch64/arm_sve.h >>> @@ -29,6 +29,8 @@ >>> #include <arm_private_fp8.h> >>> #include <arm_bf16.h> >>> >>> +typedef __mfp8 mfloat8_t; >>> + >>> typedef __fp16 float16_t; >>> typedef float float32_t; >>> typedef double float64_t; >>> diff --git a/gcc/testsuite/g++.target/aarch64/fp8_mangling.C >>> b/gcc/testsuite/g++.target/aarch64/fp8_mangling.C >>> new file mode 100644 >>> index 00000000000..1dfcaa71f15 >>> --- /dev/null >>> +++ b/gcc/testsuite/g++.target/aarch64/fp8_mangling.C >>> @@ -0,0 +1,44 @@ >>> +/* Test that mfloat8_t mangles differently from uint8_t */ >>> +/* { dg-options "-O1 -march=armv9.4-a+fp8" } */ >>> + >>> +int >>> +foo (__mfp8) >>> +{ >>> + return 1; >>> +} >>> + >>> +int >>> +foo (unsigned char) >>> +{ >>> + return 2; >>> +} >>> + >>> +int >>> +bar (__mfp8 x) >>> +{ >>> + return foo (x); >>> +} >>> +/* { dg-final { scan-assembler-times "\n_Z3fooh:\n" 1 } } */ >>> +/* { dg-final { scan-assembler-times "\n_Z3foou6__mfp8:\n" 1 } } */ >>> + >>> +constexpr __mfp8 cfp8{}; >>> + >>> +constexpr int >>> +fooc (unsigned char) >>> +{ >>> + return 3; >>> +} >>> + >>> +constexpr int >>> +fooc (__mfp8) >>> +{ >>> + return 4; >>> +} >>> + >>> +constexpr int >>> +barc (__mfp8 x) >>> +{ >>> + return fooc (x); >>> +} >>> + >>> +static_assert (barc (cfp8) == 4, "constexpr selects incorrect overload"); >>> diff --git a/gcc/testsuite/g++.target/aarch64/fp8_scalar_typecheck_2.C >>> b/gcc/testsuite/g++.target/aarch64/fp8_scalar_typecheck_2.C >>> new file mode 100644 >>> index 00000000000..61557c95663 >>> --- /dev/null >>> +++ b/gcc/testsuite/g++.target/aarch64/fp8_scalar_typecheck_2.C >>> @@ -0,0 +1,381 @@ >>> +/* Test that mfloat8_t is only usable with intrinsics, thus not >>> convertible. */ >>> +/* { dg-do assemble } */ >>> +/* { dg-options "-O1 -march=armv9.4-a+fp8 -Wno-narrowing" } */ >>> + >>> +#include <arm_neon.h> >>> +#include <stdint.h> >>> +#include <type_traits> >>> + >>> +mfloat8_t glob_fp8; >>> + >>> +int is_an_int; >>> +uint8_t is_a_uint8; >>> +int8_t is_an_int8; >>> +short is_a_short_int; >>> +float is_a_float; >>> +double is_a_double; >>> + >>> +uint8_t *uint8_ptr; >>> + >>> +mfloat8_t >>> +invalid_from_fp8 (uint16_t __a) >>> +{ >>> + mfloat8_t b = __a; /* { dg-error "invalid conversion to type >>> 'mfloat8_t'" } */ >>> + return b; >>> +} >>> + >>> +uint16_t >>> +invalid_to_fp8 (mfloat8_t __a) >>> +{ >>> + uint16_t b = __a; /*{ dg-error "invalid conversion from type >>> 'mfloat8_t'" } */ >>> + return b; >>> +} >>> + >>> +mfloat8_t >>> +foo1 (void) >>> +{ >>> + return (mfloat8_t)0x1234; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> +} >>> + >>> +mfloat8_t >>> +foo2 (void) >>> +{ >>> + return (mfloat8_t)(short)0x1234; /* { dg-error {invalid conversion to >>> type 'mfloat8_t'} } */ >>> +} >>> + >>> +mfloat8_t >>> +footest (mfloat8_t scalar0) >>> +{ >>> + >>> + /* Initialisation */ >>> + >>> + mfloat8_t scalar1_1; >>> + mfloat8_t scalar1_2 = glob_fp8; >>> + mfloat8_t scalar1_3 >>> + = 0; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + mfloat8_t scalar1_4 >>> + = 0.1; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + mfloat8_t scalar1_5 >>> + = is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + mfloat8_t scalar1_6 >>> + = is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + mfloat8_t scalar1_8 >>> + = is_a_double; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + mfloat8_t scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion >>> to type 'mfloat8_t'} } */ >>> + mfloat8_t scalar1_10 >>> + = is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + mfloat8_t scalar1_11 >>> + = is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + >>> + int initi_1_1 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + float initi_1_2 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + short initi_1_4 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + double initi_1_5 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + uint8_t initi_1_6 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + int8_t initi_1_7 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + >>> + mfloat8_t scalar2_1 = {}; >>> + mfloat8_t scalar2_2 = { glob_fp8 }; >>> + mfloat8_t scalar2_3 >>> + = { 0 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + mfloat8_t scalar2_4 >>> + = { 0.1 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } >>> */ >>> + mfloat8_t scalar2_5 = { >>> + is_a_float /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + }; >>> + mfloat8_t scalar2_6 = { >>> + is_an_int /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + }; >>> + mfloat8_t scalar2_8 = { >>> + is_a_double /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + }; >>> + mfloat8_t scalar2_9 = { >>> + is_a_short_int /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + }; >>> + mfloat8_t scalar2_10 = { >>> + is_a_uint8 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + }; >>> + mfloat8_t scalar2_11 = { >>> + is_an_int8 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + }; >>> + >>> + int initi_2_1 = { >>> + glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + }; >>> + float initi_2_2 = { >>> + glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + }; >>> + short initi_2_4 = { >>> + glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + }; >>> + double initi_2_5 = { >>> + glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + }; >>> + uint8_t initi_2_6 = { >>> + glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + }; >>> + int8_t initi_2_7 = { >>> + glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + }; >>> + >>> + /* Assignments. */ >>> + >>> + glob_fp8 = glob_fp8; >>> + glob_fp8 = 0; /* { dg-error {invalid conversion to type 'mfloat8_t'} } >>> */ >>> + glob_fp8 = 0.1; /* { dg-error {invalid conversion to type 'mfloat8_t'} } >>> */ >>> + glob_fp8 >>> + = is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + glob_fp8 >>> + = is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + glob_fp8 >>> + = is_a_double; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + glob_fp8 = is_a_short_int; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + glob_fp8 >>> + = is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + glob_fp8 >>> + = is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + >>> + is_an_int >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + is_a_float >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + is_a_double >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + is_a_short_int >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + is_a_uint8 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + is_an_int8 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + >>> + /* Casting. */ >>> + >>> + (void)glob_fp8; >>> + (mfloat8_t) glob_fp8; >>> + >>> + (int)glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + (float)glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + (double) >>> + glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + (short)glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + (uint8_t) >>> + glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } >>> */ >>> + (int8_t) >>> + glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } >>> */ >>> + >>> + (mfloat8_t) >>> + is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } >>> */ >>> + (mfloat8_t) >>> + is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} } >>> */ >>> + (mfloat8_t) >>> + is_a_double; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + (mfloat8_t) is_a_short_int; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + (mfloat8_t) >>> + is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } >>> */ >>> + (mfloat8_t) >>> + is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } >>> */ >>> + >>> + /* Compound literals. */ >>> + >>> + (mfloat8_t){}; >>> + (mfloat8_t){ glob_fp8 }; >>> + (mfloat8_t){ 0 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + (mfloat8_t){ >>> + 0.1 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + }; >>> + (mfloat8_t){ >>> + is_a_float /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + }; >>> + (mfloat8_t){ >>> + is_an_int /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + }; >>> + (mfloat8_t){ >>> + is_a_double /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + }; >>> + (mfloat8_t){ >>> + is_a_short_int /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + }; >>> + (mfloat8_t){ >>> + is_a_uint8 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + }; >>> + (mfloat8_t){ >>> + is_an_int8 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + }; >>> + >>> + (int){ >>> + glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + }; >>> + (float){ >>> + glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + }; >>> + (double){ >>> + glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + }; >>> + (short){ >>> + glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + }; >>> + (uint8_t){ >>> + glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + }; >>> + (int8_t){ >>> + glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + }; >>> + >>> + /* Arrays and Structs. */ >>> + >>> + typedef mfloat8_t array_type[2]; >>> + extern mfloat8_t extern_array[]; >>> + >>> + mfloat8_t array[2]; >>> + mfloat8_t zero_length_array[0]; >>> + mfloat8_t empty_init_array[] = {}; >>> + typedef mfloat8_t some_other_type[is_an_int]; >>> + >>> + struct struct1 >>> + { >>> + mfloat8_t a; >>> + }; >>> + >>> + union union1 >>> + { >>> + mfloat8_t a; >>> + }; >>> + >>> + /* Addressing and dereferencing. */ >>> + >>> + mfloat8_t *fp8_ptr = &scalar0; >>> + scalar0 = *fp8_ptr; >>> + >>> + /* Pointer assignment. */ >>> + >>> + mfloat8_t *fp8_ptr2 = fp8_ptr; >>> + mfloat8_t *fp8_ptr3 = array; >>> + >>> + /* Pointer arithmetic. */ >>> + >>> + ++fp8_ptr; >>> + --fp8_ptr; >>> + fp8_ptr++; >>> + fp8_ptr--; >>> + fp8_ptr += 1; >>> + fp8_ptr -= 1; >>> + fp8_ptr - fp8_ptr2; >>> + fp8_ptr = &fp8_ptr3[0]; >>> + fp8_ptr = &fp8_ptr3[1]; >>> + >>> + /* Simple comparison. */ >>> + scalar0 >>> + > glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + glob_fp8 >>> + == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + scalar0 > is_a_float; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + is_a_float >>> + == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + scalar0 > 0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } >>> */ >>> + 0 == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + scalar0 > 0.1; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + 0.1 == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + scalar0 >>> + > is_an_int; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + is_an_int >>> + == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + >>> + /* Pointer comparison. */ >>> + >>> + fp8_ptr == &scalar0; >>> + fp8_ptr != &scalar0; >>> + fp8_ptr < &scalar0; >>> + fp8_ptr <= &scalar0; >>> + fp8_ptr > &scalar0; >>> + fp8_ptr >= &scalar0; >>> + fp8_ptr == fp8_ptr2; >>> + fp8_ptr != fp8_ptr2; >>> + fp8_ptr < fp8_ptr2; >>> + fp8_ptr <= fp8_ptr2; >>> + fp8_ptr > fp8_ptr2; >>> + fp8_ptr >= fp8_ptr2; >>> + >>> + /* Conditional expressions. */ >>> + >>> + 0 ? scalar0 : scalar0; >>> + 0 ? scalar0 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + : is_a_float; >>> + 0 ? is_a_float >>> + : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + 0 ? scalar0 : 0; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + 0 ? 0 : scalar0; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + 0 ? 0.1 >>> + : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } >>> */ >>> + 0 ? scalar0 /* { dg-error {invalid conversion from type 'mfloat8_t'} } >>> */ >>> + : 0.1; >>> + 0 ? fp8_ptr : fp8_ptr2; >>> + 0 ? fp8_ptr : uint8_ptr; /* { dg-error {conditional expression between >>> distinct pointer types} } */ >>> + 0 ? uint8_ptr : fp8_ptr; /* { dg-error {conditional expression between >>> distinct pointer types} } */ >>> + >>> + scalar0 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + ? scalar0 >>> + : scalar0; >>> + scalar0 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + ? is_a_float >>> + : scalar0; >>> + scalar0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion >>> from type 'mfloat8_t'} } */ >>> + scalar0 ? is_a_float : is_a_float; /* { dg-error {invalid conversion >>> from type 'mfloat8_t'} } */ >>> + >>> + /* Unary operators. */ >>> + >>> + +scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } >>> */ >>> + -scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } >>> */ >>> + ~scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } >>> */ >>> + !scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } >>> */ >>> + *scalar0; /* { dg-error {invalid type argument of unary} } */ >>> + __real scalar0; /* { dg-error {operation not permitted on type >>> 'mfloat8_t'} } */ >>> + __imag scalar0; /* { dg-error {operation not permitted on type >>> 'mfloat8_t'} } */ >>> + ++scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } >>> */ >>> + --scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } >>> */ >>> + scalar0++; /* { dg-error {operation not permitted on type 'mfloat8_t'} } >>> */ >>> + scalar0--; /* { dg-error {operation not permitted on type 'mfloat8_t'} } >>> */ >>> + >>> + /* Binary arithmetic operations. */ >>> + >>> + scalar0 = glob_fp8 + scalar1_2; /* { dg-error {invalid conversion from >>> type 'mfloat8_t'} } */ >>> + scalar0 = glob_fp8 + *fp8_ptr; /* { dg-error {invalid conversion from >>> type 'mfloat8_t'} } */ >>> + scalar0 = glob_fp8 >>> + + 0.1; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + scalar0 = glob_fp8 >>> + + 0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + scalar0 = glob_fp8 + is_a_float; /* { dg-error {invalid conversion from >>> type 'mfloat8_t'} } */ >>> + >>> + glob_fp8 + glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + glob_fp8 - glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + glob_fp8 * glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + glob_fp8 / glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + glob_fp8 && glob_fp8; /* { dg-error {operation not permitted on type >>> 'mfloat8_t'} } */ >>> + glob_fp8 || glob_fp8; /* { dg-error {operation not permitted on type >>> 'mfloat8_t'} } */ >>> + >>> + return scalar0; >>> +} >>> + >>> +/* Check that function decls for mfloat8_t and unsigned char differ */ >>> + >>> +mfloat8_t extern_fn1(void); >>> +unsigned char extern_fn1(void); /* { dg-error {ambiguating new declaration >>> of 'unsigned char extern_fn1\(\)'} } */ >>> + >>> +mfloat8_t extern_fn2(void); >>> +uint8_t extern_fn2(void); /* { dg-error {ambiguating new declaration of >>> 'uint8_t extern_fn2\(\)} } */ >>> + >>> +unsigned char extern_fn3(void); >>> +mfloat8_t extern_fn3(void); /* { dg-error {ambiguating new declaration of >>> 'mfloat8_t extern_fn3\(\)} } */ >>> + >>> +uint8_t extern_fn4(void); >>> +mfloat8_t extern_fn4(void); /* { dg-error {ambiguating new declaration of >>> 'mfloat8_t extern_fn4\(\)} } */ >>> + >>> +/* Check that the type conforms to the contract */ >>> +static_assert(!std::is_integral<__mfp8>(), "not integral"); >>> +static_assert(!std::is_signed<__mfp8>(), "not signed"); >>> +static_assert(!std::is_unsigned<__mfp8>(), "not unsigned"); >>> diff --git a/gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c >>> b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c >>> new file mode 100644 >>> index 00000000000..1bc2ac26b2a >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c >>> @@ -0,0 +1,134 @@ >>> +/* Test the fp8 ACLE intrinsics family. */ >>> +/* { dg-do compile } */ >>> +/* { dg-options "-O2 -march=armv9.4-a+fp8" } */ >>> +/* { dg-final { check-function-bodies "**" "" "" } } */ >>> + >>> +#include <arm_neon.h> >>> + >>> +/* >>> +**stacktest1: >>> +** sub sp, sp, #16 >>> +** and w0, w0, 255 >>> +** strb w0, \[sp, 15\] >>> +** ldrb w0, \[sp, 15\] >>> +** add sp, sp, 16 >>> +** ret >>> +*/ >>> +mfloat8_t >>> +stacktest1 (mfloat8_t __a) >>> +{ >>> + volatile mfloat8_t b = __a; >>> + return b; >>> +} >>> + >>> +/* >>> +**fp8_mov_ww: >>> +** dup b1, v2.b\[0\] >>> +** ret >>> +*/ >>> +void >>> +fp8_mov_ww (void) >>> +{ >>> + register mfloat8_t x asm ("h2"); >>> + register mfloat8_t y asm ("h1"); >>> + asm volatile ("" : "=w"(x)); >>> + y = x; >>> + asm volatile ("" ::"w"(y)); >>> +} >>> + >>> +/* >>> +**fp8_mov_rw: >>> +** dup v1.8b, w1 >>> +** ret >>> +*/ >>> +void >>> +fp8_mov_rw (void) >>> +{ >>> + register mfloat8_t x asm ("w1"); >>> + register mfloat8_t y asm ("h1"); >>> + asm volatile ("" : "=r"(x)); >>> + y = x; >>> + asm volatile ("" ::"w"(y)); >>> +} >>> + >>> +/* >>> +**fp8_mov_wr: >>> +** umov w1, v1.b\[0\] >>> +** ret >>> +*/ >>> +void >>> +fp8_mov_wr (void) >>> +{ >>> + register mfloat8_t x asm ("h1"); >>> + register mfloat8_t y asm ("w1"); >>> + asm volatile ("" : "=w"(x)); >>> + y = x; >>> + asm volatile ("" ::"r"(y)); >>> +} >>> + >>> +/* >>> +**fp8_mov_rr: >>> +** mov w1, w2 >>> +** ret >>> +*/ >>> +void >>> +fp8_mov_rr (void) >>> +{ >>> + register mfloat8_t x asm ("w2"); >>> + register mfloat8_t y asm ("w1"); >>> + asm volatile ("" : "=r"(x)); >>> + y = x; >>> + asm volatile ("" ::"r"(y)); >>> +} >>> + >>> +/* >>> +**fp8_mov_rm: >>> +** strb w2, \[x0\] >>> +** ret >>> +*/ >>> +void >>> +fp8_mov_rm (mfloat8_t *ptr) >>> +{ >>> + register mfloat8_t x asm ("w2"); >>> + asm volatile ("" : "=r"(x)); >>> + *ptr = x; >>> +} >>> + >>> +/* >>> +**fp8_mov_mr: >>> +** ldrb w2, \[x0\] >>> +** ret >>> +*/ >>> +void >>> +fp8_mov_mr (mfloat8_t *ptr) >>> +{ >>> + register mfloat8_t y asm ("w2"); >>> + y = *ptr; >>> + asm volatile ("" ::"r"(y)); >>> +} >>> + >>> +/* >>> +**fp8_str_r: >>> +** str b2, \[x0\] >>> +** ret >>> +*/ >>> +void >>> +fp8_str_r (mfloat8_t *ptr) >>> +{ >>> + register mfloat8_t x asm ("v2"); >>> + asm volatile ("" : "=w"(x)); >>> + *ptr = x; >>> +} >>> + >>> +/* >>> +**fp8_ldr_r: >>> +** ldr b2, \[x0\] >>> +** ret >>> +*/ >>> +void >>> +fp8_ldr_r (mfloat8_t *ptr) >>> +{ >>> + register mfloat8_t y asm ("v2"); >>> + y = *ptr; >>> + asm volatile ("" ::"w"(y)); >>> +} >>> diff --git a/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c >>> b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c >>> new file mode 100644 >>> index 00000000000..9169f40c4b7 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c >>> @@ -0,0 +1,356 @@ >>> +/* Test that there is no conversion between ints and mfloat8_t. */ >>> +/* { dg-do assemble } */ >>> +/* { dg-options "-O1 -march=armv9.4-a+fp8" } */ >>> + >>> +#include <arm_neon.h> >>> +#include <stdint.h> >>> + >>> +mfloat8_t glob_fp8; >>> + >>> +int is_an_int; >>> +uint8_t is_a_uint8; >>> +int8_t is_an_int8; >>> +short is_a_short_int; >>> +float is_a_float; >>> +double is_a_double; >>> + >>> +uint8_t *uint8_ptr; >>> + >>> +mfloat8_t >>> +invalid_from_fp8 (uint16_t __a) >>> +{ >>> + mfloat8_t b = __a; // { dg-error "invalid conversion to type >>> 'mfloat8_t'" } >>> + return b; >>> +} >>> + >>> +uint16_t >>> +invalid_to_fp8 (mfloat8_t __a) >>> +{ >>> + uint16_t b = __a; // { dg-error "invalid conversion from type >>> 'mfloat8_t'" } >>> + return b; >>> +} >>> + >>> +mfloat8_t >>> +foo1 (void) >>> +{ >>> + return (mfloat8_t)0x1234; // { dg-error {invalid conversion to type >>> 'mfloat8_t'} } >>> +} >>> +mfloat8_t >>> +foo2 (void) >>> +{ >>> + return (mfloat8_t)(short)0x1234; // { dg-error {invalid conversion to >>> type 'mfloat8_t'} } >>> +} >>> + >>> +mfloat8_t >>> +footest (mfloat8_t scalar0) >>> +{ >>> + >>> + /* Initialisation */ >>> + >>> + mfloat8_t scalar1_1; >>> + mfloat8_t scalar1_2 = glob_fp8; >>> + mfloat8_t scalar1_3 = 0; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + mfloat8_t scalar1_4 >>> + = 0.1; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + mfloat8_t scalar1_5 >>> + = is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + mfloat8_t scalar1_6 >>> + = is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + mfloat8_t scalar1_8 >>> + = is_a_double; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + mfloat8_t scalar1_9 >>> + = is_a_short_int; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + mfloat8_t scalar1_10 >>> + = is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + mfloat8_t scalar1_11 >>> + = is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + >>> + int initi_1_1 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + float initi_1_2 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + short initi_1_4 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + double initi_1_5 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + uint8_t initi_1_6 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + int8_t initi_1_7 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + >>> + mfloat8_t scalar2_1 = {}; >>> + mfloat8_t scalar2_2 = { glob_fp8 }; >>> + mfloat8_t scalar2_3 >>> + = { 0 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + mfloat8_t scalar2_4 >>> + = { 0.1 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } >>> */ >>> + mfloat8_t scalar2_5 >>> + = { is_a_float }; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + mfloat8_t scalar2_6 >>> + = { is_an_int }; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + mfloat8_t scalar2_8 = { >>> + is_a_double >>> + }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + mfloat8_t scalar2_9 = { >>> + is_a_short_int >>> + }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + mfloat8_t scalar2_10 >>> + = { is_a_uint8 }; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + mfloat8_t scalar2_11 >>> + = { is_an_int8 }; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + >>> + int initi_2_1 >>> + = { glob_fp8 }; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + float initi_2_2 >>> + = { glob_fp8 }; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + short initi_2_4 >>> + = { glob_fp8 }; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + double initi_2_5 >>> + = { glob_fp8 }; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + uint8_t initi_2_6 >>> + = { glob_fp8 }; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + int8_t initi_2_7 >>> + = { glob_fp8 }; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + >>> + /* Assignments. */ >>> + >>> + glob_fp8 = glob_fp8; >>> + glob_fp8 = 0; /* { dg-error {invalid conversion to type 'mfloat8_t'} } >>> */ >>> + glob_fp8 = 0.1; /* { dg-error {invalid conversion to type 'mfloat8_t'} } >>> */ >>> + glob_fp8 >>> + = is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + glob_fp8 = is_an_int; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + glob_fp8 >>> + = is_a_double; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + glob_fp8 >>> + = is_a_short_int; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + glob_fp8 >>> + = is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + glob_fp8 >>> + = is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} >>> } */ >>> + >>> + is_an_int >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + is_a_float >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + is_a_double >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + is_a_short_int >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + is_a_uint8 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + is_an_int8 >>> + = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + >>> + /* Casting. */ >>> + >>> + (void)glob_fp8; >>> + (mfloat8_t) glob_fp8; >>> + >>> + (int)glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + (float)glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + (double)glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + (short)glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + (uint8_t)glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + (int8_t)glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + >>> + (mfloat8_t) is_an_int; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + (mfloat8_t) is_a_float; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + (mfloat8_t) is_a_double; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + (mfloat8_t) >>> + is_a_short_int; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + (mfloat8_t) is_a_uint8; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + (mfloat8_t) is_an_int8; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + >>> + /* Compound literals. */ >>> + >>> + (mfloat8_t){}; >>> + (mfloat8_t){ glob_fp8 }; >>> + (mfloat8_t){ 0 }; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + (mfloat8_t){ 0.1 }; /* { dg-error {invalid conversion to type >>> 'mfloat8_t'} } */ >>> + (mfloat8_t){ >>> + is_a_float >>> + }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + (mfloat8_t){ >>> + is_an_int >>> + }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + (mfloat8_t){ >>> + is_a_double >>> + }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + (mfloat8_t){ >>> + is_a_short_int >>> + }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + (mfloat8_t){ >>> + is_a_uint8 >>> + }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + (mfloat8_t){ >>> + is_an_int8 >>> + }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */ >>> + >>> + (int){ glob_fp8 }; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + (float){ >>> + glob_fp8 >>> + }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + (double){ >>> + glob_fp8 >>> + }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + (short){ >>> + glob_fp8 >>> + }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + (uint8_t){ >>> + glob_fp8 >>> + }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + (int8_t){ >>> + glob_fp8 >>> + }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + >>> + /* Arrays and Structs. */ >>> + >>> + typedef mfloat8_t array_type[2]; >>> + extern mfloat8_t extern_array[]; >>> + >>> + mfloat8_t array[2]; >>> + mfloat8_t zero_length_array[0]; >>> + mfloat8_t empty_init_array[] = {}; >>> + typedef mfloat8_t some_other_type[is_an_int]; >>> + >>> + struct struct1 >>> + { >>> + mfloat8_t a; >>> + }; >>> + >>> + union union1 >>> + { >>> + mfloat8_t a; >>> + }; >>> + >>> + /* Addressing and dereferencing. */ >>> + >>> + mfloat8_t *fp8_ptr = &scalar0; >>> + scalar0 = *fp8_ptr; >>> + >>> + /* Pointer assignment. */ >>> + >>> + mfloat8_t *fp8_ptr2 = fp8_ptr; >>> + mfloat8_t *fp8_ptr3 = array; >>> + >>> + /* Pointer arithmetic. */ >>> + >>> + ++fp8_ptr; >>> + --fp8_ptr; >>> + fp8_ptr++; >>> + fp8_ptr--; >>> + fp8_ptr += 1; >>> + fp8_ptr -= 1; >>> + fp8_ptr - fp8_ptr2; >>> + fp8_ptr = &fp8_ptr3[0]; >>> + fp8_ptr = &fp8_ptr3[1]; >>> + >>> + /* Simple comparison. */ >>> + scalar0 > glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + glob_fp8 >>> + == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + scalar0 > is_a_float; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + is_a_float >>> + == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + scalar0 > 0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } >>> */ >>> + 0 == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + scalar0 > 0.1; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + 0.1 == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + scalar0 >>> + > is_an_int; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + is_an_int >>> + == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + >>> + /* Pointer comparison. */ >>> + >>> + fp8_ptr == &scalar0; >>> + fp8_ptr != &scalar0; >>> + fp8_ptr < &scalar0; >>> + fp8_ptr <= &scalar0; >>> + fp8_ptr > &scalar0; >>> + fp8_ptr >= &scalar0; >>> + fp8_ptr == fp8_ptr2; >>> + fp8_ptr != fp8_ptr2; >>> + fp8_ptr < fp8_ptr2; >>> + fp8_ptr <= fp8_ptr2; >>> + fp8_ptr > fp8_ptr2; >>> + fp8_ptr >= fp8_ptr2; >>> + >>> + /* Conditional expressions. */ >>> + >>> + 0 ? scalar0 : scalar0; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + 0 ? scalar0 >>> + : is_a_float; /* { dg-error {invalid conversion from type 'mfloat8_t'} >>> } */ >>> + 0 ? is_a_float >>> + : scalar0; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + 0 ? scalar0 : 0; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + 0 ? 0 : scalar0; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + 0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + 0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + 0 ? fp8_ptr : fp8_ptr2; >>> + 0 ? fp8_ptr : uint8_ptr; /* { dg-error {pointer type mismatch in >>> conditional expression} } */ >>> + 0 ? uint8_ptr : fp8_ptr; /* { dg-error {pointer type mismatch in >>> conditional expression} } */ >>> + >>> + scalar0 ? scalar0 /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + scalar0 ? is_a_float /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + scalar0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from >>> type 'mfloat8_t'} } */ >>> + scalar0 ? is_a_float : is_a_float; /* { dg-error {invalid conversion >>> from type 'mfloat8_t'} } */ >>> + >>> + /* Unary operators. */ >>> + >>> + +scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } >>> */ >>> + -scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } >>> */ >>> + ~scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } >>> */ >>> + !scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } >>> */ >>> + *scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + __real scalar0; /* { dg-error {operation not permitted on type >>> 'mfloat8_t'} } */ >>> + __imag scalar0; /* { dg-error {operation not permitted on type >>> 'mfloat8_t'} } */ >>> + ++scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} >>> } */ >>> + --scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} >>> } */ >>> + scalar0++; /* { dg-error {operation not permitted on type 'mfloat8_t'} >>> } */ >>> + scalar0--; /* { dg-error {operation not permitted on type 'mfloat8_t'} >>> } */ >>> + >>> + /* Binary arithmetic operations. */ >>> + >>> + scalar0 = glob_fp8 + scalar1_2; /* { dg-error {invalid conversion from >>> type 'mfloat8_t'} } */ >>> + scalar0 = glob_fp8 + *fp8_ptr; /* { dg-error {invalid conversion from >>> type 'mfloat8_t'} } */ >>> + scalar0 = glob_fp8 >>> + + 0.1; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */ >>> + scalar0 >>> + = glob_fp8 + 0; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + scalar0 >>> + = glob_fp8 >>> + + is_a_float; /* { dg-error {invalid conversion from type 'mfloat8_t'} } >>> */ >>> + >>> + glob_fp8 + glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + glob_fp8 - glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + glob_fp8 * glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + glob_fp8 / glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + glob_fp8 && glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + glob_fp8 || glob_fp8; /* { dg-error {invalid conversion from type >>> 'mfloat8_t'} } */ >>> + >>> + return scalar0; >>> +} >>> + >>> +/* Check that function decls for mfloat8_t and unsigned char differ */ >>> + >>> +mfloat8_t extern_fn1(void); >>> +unsigned char extern_fn1(void); /* { dg-error {conflicting types for >>> 'extern_fn1'; have 'unsigned char\(void\)'} } */ >>> + >>> +mfloat8_t extern_fn2(void); >>> +uint8_t extern_fn2(void); /* { dg-error {conflicting types for >>> 'extern_fn2'; have 'uint8_t\(void\)'} } */ >>> + >>> +unsigned char extern_fn3(void); >>> +mfloat8_t extern_fn3(void); /* { dg-error {conflicting types for >>> 'extern_fn3'; have 'mfloat8_t\(void\)'} } */ >>> + >>> +uint8_t extern_fn4(void); >>> +mfloat8_t extern_fn4(void); /* { dg-error {conflicting types for >>> 'extern_fn4'; have 'mfloat8_t\(void\)'} } */ >>> + >>> +void extern_fn5(mfloat8_t); >>> +void extern_fn5(unsigned char); /* { dg-error {conflicting types for >>> 'extern_fn5'; have 'void\(unsigned char\)'} } */ >>> + >>> +void extern_fn6(mfloat8_t); >>> +void extern_fn6(uint8_t); /* { dg-error {conflicting types for >>> 'extern_fn6'; have 'void\(uint8_t\)'} } */ >> > > -- > Claudio Bantaloukas >