[clang] 74ef6a1 - Fix X86_64 complex-returns for regcall.

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Tue May 19 13:21:34 PDT 2020


Author: Erich Keane
Date: 2020-05-19T13:21:15-07:00
New Revision: 74ef6a11478abe5f0f3f817640508f0cf5d8de0c

URL: https://github.com/llvm/llvm-project/commit/74ef6a11478abe5f0f3f817640508f0cf5d8de0c
DIFF: https://github.com/llvm/llvm-project/commit/74ef6a11478abe5f0f3f817640508f0cf5d8de0c.diff

LOG: Fix X86_64 complex-returns for regcall.

D35259 introduced a case where complex types of non-long-double would
result in FI.getReturnInfo() to not be initialized properly.  This
resulted in a crash under some very specific circumstances when
dereferencing the LLVMContext.

This patch makes sure that these types have the intended getReturnInfo
initialization.

Added: 
    

Modified: 
    clang/lib/CodeGen/TargetInfo.cpp
    clang/test/CodeGenCXX/regcall.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index e1fe1330695c..2f564f3e860b 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -3745,14 +3745,15 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
       } else {
         FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
       }
-    } else if (IsRegCall && FI.getReturnType()->getAs<ComplexType>()) {
+    } else if (IsRegCall && FI.getReturnType()->getAs<ComplexType>() &&
+               getContext().getCanonicalType(FI.getReturnType()
+                                                 ->getAs<ComplexType>()
+                                                 ->getElementType()) ==
+                   getContext().LongDoubleTy)
       // Complex Long Double Type is passed in Memory when Regcall
       // calling convention is used.
-      const ComplexType *CT = FI.getReturnType()->getAs<ComplexType>();
-      if (getContext().getCanonicalType(CT->getElementType()) ==
-          getContext().LongDoubleTy)
-        FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
-    } else
+      FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
+    else
       FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
   }
 

diff  --git a/clang/test/CodeGenCXX/regcall.cpp b/clang/test/CodeGenCXX/regcall.cpp
index 9eca868fc31d..5bc9d462877b 100644
--- a/clang/test/CodeGenCXX/regcall.cpp
+++ b/clang/test/CodeGenCXX/regcall.cpp
@@ -31,7 +31,7 @@ class test_class {
   int a;
 public:
 #ifndef WIN_TEST
-  __regcall 
+  __regcall
 #endif
     test_class(){++x;}
   // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classC1Ev
@@ -41,7 +41,7 @@ class test_class {
   // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc %class.test_class* @"??0test_class@@QAE at XZ"
 
 #ifndef WIN_TEST
-  __regcall 
+  __regcall
 #endif
   ~test_class(){--x;}
   // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD2Ev
@@ -49,7 +49,7 @@ class test_class {
   // Windows ignores calling convention on constructor/destructors.
   // CHECK-WIN64-DAG: define linkonce_odr dso_local void @"??1test_class@@QEAA at XZ"
   // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"??1test_class@@QAE at XZ"
-  
+
   test_class& __regcall operator+=(const test_class&){
     return *this;
   }
@@ -60,7 +60,7 @@ class test_class {
   // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_class20__regcall3__do_thingEv
   // CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc void @"?do_thing at test_class@@QEAwXXZ"
   // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc void @"?do_thing at test_class@@QAwXXZ"
-  
+
   template<typename T>
   void __regcall tempFunc(T i){}
   // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_class20__regcall3__tempFuncIiEEvT_
@@ -103,3 +103,18 @@ long double _Complex __regcall foo(long double _Complex f) {
 // CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* inreg noalias sret align 4 %agg.result, { x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 4 %f)
 // CHECK-WIN64-DAG: define dso_local x86_regcallcc { double, double } @"?foo@@YwU?$_Complex at O@__clang@@U12@@Z"(double %f.0, double %f.1)
 // CHECK-WIN32-DAG: define dso_local x86_regcallcc { double, double } @"?foo@@YwU?$_Complex at O@__clang@@U12@@Z"(double %f.0, double %f.1)
+
+// The following caused us to dereference uninitialized memory. The long name
+// seems necessary, as does the return types.
+float _Complex __regcall callee(float _Complex f);
+// CHECK-LIN64-DAG: declare x86_regcallcc <2 x float> @_Z18__regcall3__calleeCf(<2 x float>)
+// CHECK-LIN32-DAG: declare x86_regcallcc { float, float } @_Z18__regcall3__calleeCf(float, float)
+// CHECK-WIN64-DAG: declare dso_local x86_regcallcc { float, float } @"?callee@@YwU?$_Complex at M@__clang@@U12@@Z"(float, float)
+// CHECK-WIN32-DAG: declare dso_local x86_regcallcc { float, float } @"?callee@@YwU?$_Complex at M@__clang@@U12@@Z"(float, float)
+
+__regcall int
+some_really_long_name_that_manages_to_hit_the_right_spot_of_mem(int a) {
+  float _Complex x[2];
+  x[0] = callee(x[0]);
+  return a;
+}


        


More information about the cfe-commits mailing list