[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