summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/TargetInfo.cpp
diff options
context:
space:
mode:
authorUlrich Weigand <ulrich.weigand@de.ibm.com>2014-07-10 16:39:01 +0000
committerUlrich Weigand <ulrich.weigand@de.ibm.com>2014-07-10 16:39:01 +0000
commitf4eba98853dbb8fa1adbd29a2e697f94818c5a7a (patch)
tree463af82fe09042f06572cacb03e97f312c18c710 /clang/lib/CodeGen/TargetInfo.cpp
parent57417d0d972f41c99173663a0131f1e85ee991f5 (diff)
downloadbcm5719-llvm-f4eba98853dbb8fa1adbd29a2e697f94818c5a7a.tar.gz
bcm5719-llvm-f4eba98853dbb8fa1adbd29a2e697f94818c5a7a.zip
[PowerPC] ABI support for non-Altivec vector types
This patch adds support for passing arguments of non-Altivec vector type (i.e. defined via attribute ((vector_size (...)))) on powerpc64-linux. While such types are not mentioned in the formal ABI document, this patch implements a calling convention compatible with GCC: - Vectors of size < 16 bytes are passed in a GPR - Vectors of size > 16 bytes are passed via reference Note that vector types with a number of elements that is not a power of 2 are not supported by GCC, so there is no pre-existing ABI to follow. We choose to pass those (of size < 16) as if widened to the next power of two, so they might end up in a vector register or in a GPR. (Sizes > 16 are always passed via reference as well.) Reviewed by Hal Finkel. llvm-svn: 212734
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp27
1 files changed, 26 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index be2d5b38c61..f4a1a5fd04c 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -2923,7 +2923,8 @@ public:
const Type *T = isSingleElementStruct(I.type, getContext());
if (T) {
const BuiltinType *BT = T->getAs<BuiltinType>();
- if (T->isVectorType() || (BT && BT->isFloatingPoint())) {
+ if ((T->isVectorType() && getContext().getTypeSize(T) == 128) ||
+ (BT && BT->isFloatingPoint())) {
QualType QT(T, 0);
I.info = ABIArgInfo::getDirectInReg(CGT.ConvertType(QT));
continue;
@@ -2997,6 +2998,18 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
if (Ty->isAnyComplexType())
return ABIArgInfo::getDirect();
+ // Non-Altivec vector types are passed in GPRs (smaller than 16 bytes)
+ // or via reference (larger than 16 bytes).
+ if (Ty->isVectorType()) {
+ uint64_t Size = getContext().getTypeSize(Ty);
+ if (Size > 128)
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ else if (Size < 128) {
+ llvm::Type *CoerceTy = llvm::IntegerType::get(getVMContext(), Size);
+ return ABIArgInfo::getDirect(CoerceTy);
+ }
+ }
+
if (isAggregateTypeForABI(Ty)) {
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
@@ -3016,6 +3029,18 @@ PPC64_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const {
if (RetTy->isAnyComplexType())
return ABIArgInfo::getDirect();
+ // Non-Altivec vector types are returned in GPRs (smaller than 16 bytes)
+ // or via reference (larger than 16 bytes).
+ if (RetTy->isVectorType()) {
+ uint64_t Size = getContext().getTypeSize(RetTy);
+ if (Size > 128)
+ return ABIArgInfo::getIndirect(0);
+ else if (Size < 128) {
+ llvm::Type *CoerceTy = llvm::IntegerType::get(getVMContext(), Size);
+ return ABIArgInfo::getDirect(CoerceTy);
+ }
+ }
+
if (isAggregateTypeForABI(RetTy))
return ABIArgInfo::getIndirect(0);
OpenPOWER on IntegriCloud