peter.smith updated this revision to Diff 108092.
peter.smith added a comment.
Herald added a subscriber: javed.absar.

I've added a clang test that will check that none of the floating point helper 
functions defined in the Runtime ABI for the ARM Architecture are directly 
called by clang. Given that the calling convention decisions for these helpers 
are made in llvm I think the best place for a test that the correct calling 
convention is in llvm. I'll start working on that and post in a separate 
review. Please let me know if I'm not on the right lines.


https://reviews.llvm.org/D35538

Files:
  lib/CodeGen/TargetInfo.cpp
  test/CodeGen/arm-float-helpers.c
  test/CodeGen/complex-math.c

Index: test/CodeGen/complex-math.c
===================================================================
--- test/CodeGen/complex-math.c
+++ test/CodeGen/complex-math.c
@@ -2,7 +2,8 @@
 // RUN: %clang_cc1 %s -O1 -emit-llvm -triple x86_64-pc-win64 -o - | FileCheck %s --check-prefix=X86
 // RUN: %clang_cc1 %s -O1 -emit-llvm -triple i686-unknown-unknown -o - | FileCheck %s --check-prefix=X86
 // RUN: %clang_cc1 %s -O1 -emit-llvm -triple powerpc-unknown-unknown -o - | FileCheck %s --check-prefix=PPC
-// RUN: %clang_cc1 %s -O1 -emit-llvm -triple armv7-none-linux-gnueabihf -o - | FileCheck %s --check-prefix=ARM
+// RUN %clang_cc1 %s -O1 -emit-llvm -triple armv7-none-linux-gnueabi -o - | FileCheck %s --check-prefix=ARM
+// RUN: %clang_cc1 %s -O1 -emit-llvm -triple armv7-none-linux-gnueabihf -o - | FileCheck %s --check-prefix=ARMHF
 // RUN: %clang_cc1 %s -O1 -emit-llvm -triple thumbv7k-apple-watchos2.0 -o - -target-abi aapcs16 | FileCheck %s --check-prefix=ARM7K
 
 float _Complex add_float_rr(float a, float b) {
@@ -476,8 +477,15 @@
 
 // Check that the libcall will obtain proper calling convention on ARM
 _Complex double foo(_Complex double a, _Complex double b) {
+  // These functions are not defined as floating point helper functions in
+  // Run-time ABI for the ARM architecture document so they must not always
+  // use the base AAPCS
+
   // ARM-LABEL: @foo(
-  // ARM: call arm_aapcscc { double, double } @__muldc3
+  // ARM: call void { double, double } @__muldc3
+
+  // ARMHF-LABEL: @foo(
+  // ARMHF: call { double, double } @__muldc3
 
   // ARM7K-LABEL: @foo(
   // ARM7K: call { double, double } @__muldc3
Index: test/CodeGen/arm-float-helpers.c
===================================================================
--- /dev/null
+++ test/CodeGen/arm-float-helpers.c
@@ -0,0 +1,195 @@
+// REQUIRES: arm-registered-target
+// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabihf %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -target-feature "+soft-float" -target-feature "+soft-float-abi" %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -target-feature "+soft-float" %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi -meabi gnu %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi -target-feature "+soft-float" -target-feature "+soft-float-abi" -meabi gnu %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi -target-feature "+soft-float" -meabi gnu %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabihf %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabihf -meabi gnu %s | FileCheck %s
+
+// The Runtime ABI for the ARM Architecture IHI0043 section 4.1.2 The
+// floating-point helper functions to always use the base AAPCS (soft-float)
+// calling convention.
+//
+// These helper functions such as __aeabi_fadd are not explicitly called by
+// clang, instead they are generated by the ARMISelLowering when they are
+// needed; clang relies on llvm to use the base AAPCS.
+//
+// In this test we check that clang is not directly calling the __aeabi_
+// functions. We rely on llvm to test that the base AAPCS is used for any
+// __aeabi_ function from 4.1.2 that is used.
+//
+// When compiled to an object file with -mfloat-abi=soft each function F
+// below should result in a call to __aeabi_F. If clang is changed to call any
+// of these functions directly the test will need to be altered to check that
+// arm_aapcscc is used.
+//
+// Note that it is only the functions in 4.1.2 that must use the base AAPCS,
+// other runtime functions such as the _Complex helper routines are not covered
+
+float fadd(float a, float b) { return a + b; }
+// CHECK: @fadd
+// CHECK-NOT: __aeabi_fadd
+
+float fdiv(float a, float b) { return a / b; }
+// CHECK: @fdiv
+// CHECK-NOT: __aeabi_fdiv
+
+float fmul(float a, float b) { return a * b; }
+// CHECK: @fmul
+// CHECK-NOT: __aeabi_fmul
+
+float fsub(float a, float b) { return a - b; }
+// CHECK: @fsub
+// CHECK-NOT: __aeabi_fsub
+
+int fcmpeq(float a, float b) { return a == b; }
+// CHECK: @fcmpeq
+// CHECK-NOT: __aeabi_fcmpeq
+
+int fcmplt(float a, float b) { return a < b; }
+// CHECK: @fcmplt
+// CHECK-NOT: __aeabi_fcmplt
+
+int fcmple(float a, float b) { return a <= b; }
+// CHECK: @fcmple
+// CHECK-NOT: __aeabi_fcmple
+
+int fcmpge(float a, float b) { return a >= b; }
+// CHECK: @fcmpge
+// CHECK-NOT: __aeabi_fcmpge
+
+int fcmpgt(float a, float b) { return a > b; }
+// CHECK: @fcmpgt
+// CHECK-NOT: __aeabi_fcmpgt
+
+int fcmpun(float a, float b) { return __builtin_isunordered(a, b); }
+// CHECK: @fcmpun
+// CHECK-NOT: __aeabi_fcmpun
+
+double dadd(double a, double b) { return a + b; }
+// CHECK: @dadd
+// CHECK-NOT: __aeabi_dadd
+
+double ddiv(double a, double b) { return a / b; }
+// CHECK: @ddiv
+// CHECK-NOT: __aeabi_ddiv
+
+double dmul(double a, double b) { return a * b; }
+// CHECK: @dmul
+// CHECK-NOT: __aeabi_dmul
+
+double dsub(double a, double b) { return a - b; }
+// CHECK: @dsub
+// CHECK-NOT: __aeabi_dsub
+
+int dcmpeq(double a, double b) { return a == b; }
+// CHECK: @dcmpeq
+// CHECK-NOT: __aeabi_dcmpeq
+
+int dcmplt(double a, double b) { return a < b; }
+// CHECK: @dcmplt
+// CHECK-NOT: __aeabi_dcmplt
+
+int dcmple(double a, double b) { return a <= b; }
+// CHECK: @dcmple
+// CHECK-NOT: __aeabi_dcmple
+
+int dcmpge(double a, double b) { return a >= b; }
+// CHECK: @dcmpge
+// CHECK-NOT: __aeabi_dcmpge
+
+int dcmpgt(double a, double b) { return a > b; }
+// CHECK: @dcmpgt
+// CHECK-NOT: __aeabi_dcmpgt
+
+int dcmpun(double a, double b) { return __builtin_isunordered(a, b); }
+// CHECK: @dcmpun
+// CHECK-NOT: __aeabi_dcmpun
+
+int d2iz(double a) { return (int)a; }
+// CHECK: @d2iz
+// CHECK-NOT: __aeabi_d2iz
+
+unsigned int d2uiz(double a) { return (unsigned int)a; }
+// CHECK: @d2uiz
+// CHECK-NOT: __aeabi_d2uiz
+
+long long d2lz(double a) { return (long long)a; }
+// CHECK: @d2lz
+// CHECK-NOT: __aeabi_d2lz
+
+unsigned long long d2ulz(double a) { return (unsigned long long)a; }
+// CHECK: @d2ulz
+// CHECK-NOT: __aeabi_d2ulz
+
+int f2iz(float a) { return (int)a; }
+// CHECK: @f2iz
+// CHECK-NOT: __aeabi_f2iz
+
+unsigned int f2uiz(float a) { return (unsigned int)a; }
+// CHECK: @f2uiz
+// CHECK-NOT: __aeabi_f2uiz
+
+long long f2lz(float a) { return (long long)a; }
+// CHECK: @f2lz
+// CHECK-NOT: __aeabi_f2lz
+
+unsigned long long f2ulz(float a) { return (unsigned long long)a; }
+// CHECK: @f2ulz
+// CHECK-NOT: __aeabi_f2ulz
+
+float d2f(double a) { return (float)a; }
+// CHECK: @d2f
+// CHECK-NOT: __aeabi_d2f
+
+double f2d(float a) { return (double)a; }
+// CHECK: @f2d
+// CHECK-NOT: __aeabi_f2d
+
+double i2d(int a) { return (double)a; }
+// CHECK: @i2d
+// CHECK-NOT: __aeabi_i2d
+
+double ui2d(unsigned int a) { return (double)a; }
+// CHECK: @ui2d
+// CHECK-NOT: __aeabi_ui2d
+
+double l2d(long long a) { return (double)a; }
+// CHECK: @l2d
+// CHECK-NOT: __aeabi_l2d
+
+double ul2d(unsigned long long a) { return (unsigned long long)a; }
+// CHECK: @ul2d
+// CHECK-NOT: __aeabi_ul2d
+
+float i2f(int a) { return (int)a; }
+// CHECK: @i2f
+// CHECK-NOT: __aeabi_i2f
+
+float ui2f(unsigned int a) { return (unsigned int)a; }
+// CHECK: @ui2f
+// CHECK-NOT: __aeabi_ui2f
+
+float l2f(long long a) { return (long long)a; }
+// CHECK: @l2f
+// CHECK-NOT: __aeabi_l2f
+
+float ul2f(unsigned long long a) { return (unsigned long long)a; }
+// CHECK: @ul2f
+// CHECK-NOT: __aeabi_ul2f
+
+// Functions in section 4.1.2 not used by llvm and don't easily map directly to
+// C source code.
+// cfcmpeq
+// cfcmple
+// cfrcmple
+// cdcmpeq
+// cdcmple
+// cdrcmple
+// frsub
+// drsub
Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -5620,17 +5620,14 @@
   // AAPCS apparently requires runtime support functions to be soft-float, but
   // that's almost certainly for historic reasons (Thumb1 not supporting VFP
   // most likely). It's more convenient for AAPCS16_VFP to be hard-float.
-  switch (getABIKind()) {
-  case APCS:
-  case AAPCS16_VFP:
-    if (abiCC != getLLVMDefaultCC())
+
+  // The Run-time ABI for the ARM Architecture section 4.1.2 requires
+  // AEABI-complying FP helper functions to use the base AAPCS
+  // These AEABI functions are expanded in the ARM llvm backend, all the builtin
+  // support functions emitted by clang such as the _Complex helpers follow the
+  // abiCC.
+  if (abiCC != getLLVMDefaultCC())
       BuiltinCC = abiCC;
-    break;
-  case AAPCS:
-  case AAPCS_VFP:
-    BuiltinCC = llvm::CallingConv::ARM_AAPCS;
-    break;
-  }
 }
 
 ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to