[PATCH] D35259: Complex Long Double classification In RegCall calling convention

Elizabeth Andrews via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 11 08:39:09 PDT 2017


eandrews created this revision.

This change is part of the RegCall calling convention support for LLVM. Existing RegCall implementation was extended to include correct handling of Complex Long Double type. Complex long double types should be returned/passed in memory and not register stack. This patch implements this behavior.


https://reviews.llvm.org/D35259

Files:
  lib/CodeGen/ABIInfo.h
  lib/CodeGen/TargetInfo.cpp
  test/CodeGenCXX/regcall.cpp


Index: test/CodeGenCXX/regcall.cpp
===================================================================
--- test/CodeGenCXX/regcall.cpp
+++ test/CodeGenCXX/regcall.cpp
@@ -95,3 +95,11 @@
   freeTempFunc(1);
   t3.do_thing();
 }
+
+long double _Complex __regcall foo(long double _Complex f) {
+  return f;
+}
+// CHECK-LIN64-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 16 %f)
+// CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* inreg noalias sret %agg.result, { x86_fp80, x86_fp80 }* byval align 4 %f)
+// CHECK-WIN64-DAG: define x86_regcallcc { double, double } @"\01?foo@@YwU?$_Complex at O@__clang@@U12@@Z"(double %f.0, double %f.1)
+// CHECK-WIN32-DAG: define x86_regcallcc { double, double } @"\01?foo@@YwU?$_Complex at O@__clang@@U12@@Z"(double %f.0, double %f.1)
Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -1289,9 +1289,11 @@
 
   const Type *Base = nullptr;
   uint64_t NumElts = 0;
-  if ((State.CC == llvm::CallingConv::X86_VectorCall ||
-       State.CC == llvm::CallingConv::X86_RegCall) &&
-      isHomogeneousAggregate(RetTy, Base, NumElts)) {
+  if ((State.CC == llvm::CallingConv::X86_VectorCall &&
+       isHomogeneousAggregate(RetTy, Base, NumElts)) ||
+      (State.CC == llvm::CallingConv::X86_RegCall &&
+       isRegcallReturnableHomogeneousAggregate(RetTy, Base, NumElts,
+                                               IsWin32StructABI))) {
     // The LLVM struct type for such an aggregate should lower properly.
     return ABIArgInfo::getDirect();
   }
@@ -1558,8 +1560,8 @@
   const Type *Base = nullptr;
   uint64_t NumElts = 0;
   if (State.CC == llvm::CallingConv::X86_RegCall &&
-      isHomogeneousAggregate(Ty, Base, NumElts)) {
-
+      isRegcallReturnableHomogeneousAggregate(Ty, Base, NumElts,
+                                              IsWin32StructABI)) {
     if (State.FreeSSERegs >= NumElts) {
       State.FreeSSERegs -= NumElts;
       if (Ty->isBuiltinType() || Ty->isVectorType())
@@ -3495,6 +3497,11 @@
     } else {
       FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
     }
+  } else if (IsRegCall && FI.getReturnType()->getAs<ComplexType>()) {
+    const ComplexType *CT = FI.getReturnType()->getAs<ComplexType>();
+    if (getContext().getCanonicalType(CT->getElementType()) ==
+        getContext().LongDoubleTy)
+      FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
   } else if (!getCXXABI().classifyReturnType(FI))
     FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
 
@@ -4385,6 +4392,24 @@
   return CharUnits::fromQuantity(8);
 }
 
+/// isRegcallReturnableHomogeneousAggregate - Return true if a type is an ELFv2
+/// homogeneous aggregate that can be returned in stack for regcall.
+bool ABIInfo::isRegcallReturnableHomogeneousAggregate(
+    QualType Ty, const Type *&Base, uint64_t &Members,
+    bool IsWin32StructABI) const {
+  if (isHomogeneousAggregate(Ty, Base, Members)) {
+    if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
+      if (!IsWin32StructABI) {
+        QualType ET = getContext().getCanonicalType(CT->getElementType());
+        if (ET == getContext().LongDoubleTy)
+          return false;
+      }
+    }
+    return true;
+  }
+  return false;
+}
+
 /// isHomogeneousAggregate - Return true if a type is an ELFv2 homogeneous
 /// aggregate.  Base is set to the base element type, and Members is set
 /// to the number of base elements.
Index: lib/CodeGen/ABIInfo.h
===================================================================
--- lib/CodeGen/ABIInfo.h
+++ lib/CodeGen/ABIInfo.h
@@ -111,6 +111,10 @@
     bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
                                 uint64_t &Members) const;
 
+    bool isRegcallReturnableHomogeneousAggregate(QualType Ty, const Type *&Base,
+                                                 uint64_t &Members,
+                                                 bool IsWin32StructABI) const;
+
     /// A convenience method to return an indirect ABIArgInfo with an
     /// expected alignment equal to the ABI alignment of the given type.
     CodeGen::ABIArgInfo


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D35259.106031.patch
Type: text/x-patch
Size: 4342 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170711/7e6bad8a/attachment.bin>


More information about the cfe-commits mailing list