mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-07 00:23:43 +00:00
[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
This commit is contained in:
parent
57417d0d97
commit
f4eba98853
@ -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);
|
||||
|
||||
|
52
clang/test/CodeGen/ppc64-vector.c
Normal file
52
clang/test/CodeGen/ppc64-vector.c
Normal file
@ -0,0 +1,52 @@
|
||||
// RUN: %clang_cc1 -faltivec -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
typedef short v2i16 __attribute__((vector_size (4)));
|
||||
typedef short v3i16 __attribute__((vector_size (6)));
|
||||
typedef short v4i16 __attribute__((vector_size (8)));
|
||||
typedef short v6i16 __attribute__((vector_size (12)));
|
||||
typedef short v8i16 __attribute__((vector_size (16)));
|
||||
typedef short v16i16 __attribute__((vector_size (32)));
|
||||
|
||||
struct v16i16 { v16i16 x; };
|
||||
|
||||
// CHECK: define i32 @test_v2i16(i32 %x.coerce)
|
||||
v2i16 test_v2i16(v2i16 x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
// CHECK: define i64 @test_v3i16(i64 %x.coerce)
|
||||
v3i16 test_v3i16(v3i16 x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
// CHECK: define i64 @test_v4i16(i64 %x.coerce)
|
||||
v4i16 test_v4i16(v4i16 x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
// CHECK: define <6 x i16> @test_v6i16(<6 x i16> %x)
|
||||
v6i16 test_v6i16(v6i16 x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
// CHECK: define <8 x i16> @test_v8i16(<8 x i16> %x)
|
||||
v8i16 test_v8i16(v8i16 x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
// CHECK: define void @test_v16i16(<16 x i16>* noalias sret %agg.result, <16 x i16>*)
|
||||
v16i16 test_v16i16(v16i16 x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
// CHECK: define void @test_struct_v16i16(%struct.v16i16* noalias sret %agg.result, %struct.v16i16* byval %x)
|
||||
struct v16i16 test_struct_v16i16(struct v16i16 x)
|
||||
{
|
||||
return x;
|
||||
}
|
Loading…
Reference in New Issue
Block a user