Skip to content

Commit 74ef6a1

Browse files
author
Erich Keane
committed
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.
1 parent 350dada commit 74ef6a1

File tree

2 files changed

+26
-10
lines changed

2 files changed

+26
-10
lines changed

clang/lib/CodeGen/TargetInfo.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3745,14 +3745,15 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
37453745
} else {
37463746
FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
37473747
}
3748-
} else if (IsRegCall && FI.getReturnType()->getAs<ComplexType>()) {
3748+
} else if (IsRegCall && FI.getReturnType()->getAs<ComplexType>() &&
3749+
getContext().getCanonicalType(FI.getReturnType()
3750+
->getAs<ComplexType>()
3751+
->getElementType()) ==
3752+
getContext().LongDoubleTy)
37493753
// Complex Long Double Type is passed in Memory when Regcall
37503754
// calling convention is used.
3751-
const ComplexType *CT = FI.getReturnType()->getAs<ComplexType>();
3752-
if (getContext().getCanonicalType(CT->getElementType()) ==
3753-
getContext().LongDoubleTy)
3754-
FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
3755-
} else
3755+
FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
3756+
else
37563757
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
37573758
}
37583759

clang/test/CodeGenCXX/regcall.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class test_class {
3131
int a;
3232
public:
3333
#ifndef WIN_TEST
34-
__regcall
34+
__regcall
3535
#endif
3636
test_class(){++x;}
3737
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classC1Ev
@@ -41,15 +41,15 @@ class test_class {
4141
// CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc %class.test_class* @"??0test_class@@QAE@XZ"
4242

4343
#ifndef WIN_TEST
44-
__regcall
44+
__regcall
4545
#endif
4646
~test_class(){--x;}
4747
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD2Ev
4848
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD1Ev
4949
// Windows ignores calling convention on constructor/destructors.
5050
// CHECK-WIN64-DAG: define linkonce_odr dso_local void @"??1test_class@@QEAA@XZ"
5151
// CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"??1test_class@@QAE@XZ"
52-
52+
5353
test_class& __regcall operator+=(const test_class&){
5454
return *this;
5555
}
@@ -60,7 +60,7 @@ class test_class {
6060
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_class20__regcall3__do_thingEv
6161
// CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc void @"?do_thing@test_class@@QEAwXXZ"
6262
// CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc void @"?do_thing@test_class@@QAwXXZ"
63-
63+
6464
template<typename T>
6565
void __regcall tempFunc(T i){}
6666
// 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) {
103103
// 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)
104104
// CHECK-WIN64-DAG: define dso_local x86_regcallcc { double, double } @"?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
105105
// CHECK-WIN32-DAG: define dso_local x86_regcallcc { double, double } @"?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
106+
107+
// The following caused us to dereference uninitialized memory. The long name
108+
// seems necessary, as does the return types.
109+
float _Complex __regcall callee(float _Complex f);
110+
// CHECK-LIN64-DAG: declare x86_regcallcc <2 x float> @_Z18__regcall3__calleeCf(<2 x float>)
111+
// CHECK-LIN32-DAG: declare x86_regcallcc { float, float } @_Z18__regcall3__calleeCf(float, float)
112+
// CHECK-WIN64-DAG: declare dso_local x86_regcallcc { float, float } @"?callee@@YwU?$_Complex@M@__clang@@U12@@Z"(float, float)
113+
// CHECK-WIN32-DAG: declare dso_local x86_regcallcc { float, float } @"?callee@@YwU?$_Complex@M@__clang@@U12@@Z"(float, float)
114+
115+
__regcall int
116+
some_really_long_name_that_manages_to_hit_the_right_spot_of_mem(int a) {
117+
float _Complex x[2];
118+
x[0] = callee(x[0]);
119+
return a;
120+
}

0 commit comments

Comments
 (0)