1 // REQUIRES: aarch64-registered-target 2 3 // RUN: %clang_cc1 -triple aarch64 -target-feature +fp-armv8 -S -o /dev/null -target-abi aapcs -verify=fp-hard %s 4 // RUN: %clang_cc1 -triple aarch64 -target-feature -fp-armv8 -S -o /dev/null -target-abi aapcs-soft -verify=nofp-soft %s 5 // RUN: %clang_cc1 -triple aarch64 -target-feature -fp-armv8 -S -o /dev/null -target-abi aapcs -verify=nofp-hard %s 6 // RUN: %clang_cc1 -triple aarch64 -target-feature -fp-armv8 -o /dev/null -target-abi aapcs -O1 -verify=nofp-hard,nofp-hard-opt -emit-llvm %s 7 // No run line needed for soft-float ABI with an FPU because that is rejected by the driver 8 9 // With the hard-float ABI and a target with an FPU, FP arguments are passed in 10 // FP registers, no diagnostics needed. 11 // fp-hard-no-diagnostics 12 13 // With the soft-float ABI, FP arguments are passed in integer registers, no 14 // diagnostics needed. 15 // nofp-soft-no-diagnostics 16 17 // With the hard-float ABI but no FPU, FP arguments cannot be passed in an 18 // ABI-compatible way, so we report errors for these cases: 19 20 struct HFA { 21 float x, y; 22 }; 23 24 struct non_HFA { 25 float x; 26 int y; 27 }; 28 29 // Floating-point arguments are returns are rejected 30 void test_fp16_arg(__fp16 a) {} 31 // nofp-hard-error@-1 {{'a' requires '__fp16' type support, but ABI 'aapcs' does not support it}} 32 __fp16 test_fp16_ret(void) { return 3.141; } 33 // nofp-hard-error@-1 {{'test_fp16_ret' requires '__fp16' type support, but ABI 'aapcs' does not support it}} 34 void test_float_arg(float a) {} 35 // nofp-hard-error@-1 {{'a' requires 'float' type support, but ABI 'aapcs' does not support it}} 36 float test_float_ret(void) { return 3.141f; } 37 // nofp-hard-error@-1 {{'test_float_ret' requires 'float' type support, but ABI 'aapcs' does not support it}} 38 void test_double_arg(double a) {} 39 // nofp-hard-error@-1 {{'a' requires 'double' type support, but ABI 'aapcs' does not support it}} 40 double test_double_ret(void) { return 3.141; } 41 // nofp-hard-error@-1 {{'test_double_ret' requires 'double' type support, but ABI 'aapcs' does not support it}} 42 void test_long_double_arg(long double a) {} 43 // nofp-hard-error@-1 {{'a' requires 'long double' type support, but ABI 'aapcs' does not support it}} 44 long double test_long_double_ret(void) { return 3.141L; } 45 // nofp-hard-error@-1 {{'test_long_double_ret' requires 'long double' type support, but ABI 'aapcs' does not support it}} 46 47 // HFAs would be passed in floating-point registers, so are rejected. 48 void test_hfa_arg(struct HFA a) {} 49 // nofp-hard-error@-1 {{'a' requires 'struct HFA' type support, but ABI 'aapcs' does not support it}} 50 struct HFA test_hfa_ret(void) { return (struct HFA){}; } 51 // nofp-hard-error@-1 {{'test_hfa_ret' requires 'struct HFA' type support, but ABI 'aapcs' does not support it}} 52 53 // Note: vector types cannot be created at all for targets without an FPU, so 54 // it is not possible to create a function which passes/returns them when using 55 // either the default or soft-float ABI. This is tested elsewhere. 56 57 // This struct contains a floating-point type, but is not an HFA, so can be 58 // passed/returned without affecting the ABI. 59 struct non_HFA test_non_hfa_ret(void) { return (struct non_HFA){}; } 60 void test_non_hfa_arg(struct non_HFA a) {} 61 62 // This inline function does not get code-generated because there is no use of 63 // it in this file, so we we don't emit an error for it, matching GCC's 64 // behaviour. 65 inline void test_float_arg_inline(float a) {} 66 67 // This inline function is used, so we emit the error if we generate code for 68 // it. The code isn't generated at -O0, so no error is emitted there. 69 inline void test_float_arg_inline_used(float a) {} 70 // nofp-hard-opt-error@-1 {{'a' requires 'float' type support, but ABI 'aapcs' does not support it}} 71 void use_inline() { test_float_arg_inline_used(1.0f); } 72 // nofp-hard-error@-1 {{'test_float_arg_inline_used' requires 'float' type support, but ABI 'aapcs' does not support it}} 73 74 // The always_inline attribute causes an inline function to always be 75 // code-genned, even at -O0, so we always emit the error. 76 __attribute((always_inline)) 77 inline void test_float_arg_always_inline_used(float a) {} 78 // nofp-hard-error@-1 {{'a' requires 'float' type support, but ABI 'aapcs' does not support it}} 79 void use_always_inline() { test_float_arg_always_inline_used(1.0f); } 80 // nofp-hard-error@-1 {{'test_float_arg_always_inline_used' requires 'float' type support, but ABI 'aapcs' does not support it}} 81 82 // Floating-point expressions, global variables and local variables do not 83 // affect the ABI, so are allowed. GCC does reject some uses of floating point 84 // types like this, but it does so after optimisation, which we can't 85 // accurately match in clang. 86 int test_expr_float(int a) { return a + 1.0f; } 87 int test_expr_double(int a) { return a + 1.0; } 88 89 float global_float = 2.0f * 3.5f; 90 float global_double = 2.0 * 3.5; 91 92 int test_var_float(int a) { 93 float f = a; 94 f *= 6.0; 95 return (int)f; 96 } 97 int test_var_double(int a) { 98 double d = a; 99 d *= 6.0; 100 return (int)d; 101 } 102 103 extern void extern_float_arg(float); 104 extern float extern_float_ret(void); 105 void call_extern_float_arg() { extern_float_arg(1.0f); } 106 // nofp-hard-error@-1 {{'extern_float_arg' requires 'float' type support, but ABI 'aapcs' does not support it}} 107 void call_extern_float_ret() { extern_float_ret(); } 108 // nofp-hard-error@-1 {{'extern_float_ret' requires 'float' type support, but ABI 'aapcs' does not support it}} 109 110 // Definitions of variadic functions, and calls to them which only use integer 111 // argument registers, are both fine. 112 void variadic(int, ...); 113 void call_variadic_int() { variadic(0, 1); } 114 115 // Calls to variadic functions with floating-point arguments are an error, 116 // since this would require floating-point registers. 117 void call_variadic_double() { variadic(0, 1.0); } 118 // nofp-hard-error@-1 {{'variadic' requires 'double' type support, but ABI 'aapcs' does not support it}} 119 120 // Calls through function pointers are also diagnosed. 121 void (*fptr)(float); 122 void call_indirect() { fptr(1.0f); } 123 // nofp-hard-error@-1 {{'call_indirect' requires 'float' type support, but ABI 'aapcs' does not support it}} 124