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@O@__clang@@U12@@Z"(double %f.0, double %f.1) +// CHECK-WIN32-DAG: define x86_regcallcc { double, double } @"\01?foo@@YwU?$_Complex@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
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@O@__clang@@U12@@Z"(double %f.0, double %f.1) +// CHECK-WIN32-DAG: define x86_regcallcc { double, double } @"\01?foo@@YwU?$_Complex@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
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits