From f330d9f163f644b968c6aa5884dc1be5efda20a1 Mon Sep 17 00:00:00 2001 From: Chris Bowler Date: Fri, 25 Sep 2020 07:36:49 -0400 Subject: [PATCH] [PPC] [AIX] Implement calling convention IR for C99 complex types on AIX Add AIX calling convention logic to Clang for C99 complex types on AIX Differential Revision: https://reviews.llvm.org/D88130 --- clang/lib/CodeGen/TargetInfo.cpp | 9 +++-- clang/test/CodeGen/aix-complex.c | 10 ----- clang/test/CodeGen/powerpc-c99complex.c | 51 ++++++++++++++----------- 3 files changed, 33 insertions(+), 37 deletions(-) delete mode 100644 clang/test/CodeGen/aix-complex.c diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 2f3f4c281079f1..6e15cac7359e09 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -4504,7 +4504,7 @@ bool AIXABIInfo::isPromotableTypeForABI(QualType Ty) const { ABIArgInfo AIXABIInfo::classifyReturnType(QualType RetTy) const { if (RetTy->isAnyComplexType()) - llvm::report_fatal_error("complex type is not supported on AIX yet"); + return ABIArgInfo::getDirect(); if (RetTy->isVectorType()) llvm::report_fatal_error("vector type is not supported on AIX yet"); @@ -4525,7 +4525,7 @@ ABIArgInfo AIXABIInfo::classifyArgumentType(QualType Ty) const { Ty = useFirstFieldIfTransparentUnion(Ty); if (Ty->isAnyComplexType()) - llvm::report_fatal_error("complex type is not supported on AIX yet"); + return ABIArgInfo::getDirect(); if (Ty->isVectorType()) llvm::report_fatal_error("vector type is not supported on AIX yet"); @@ -4550,8 +4550,9 @@ ABIArgInfo AIXABIInfo::classifyArgumentType(QualType Ty) const { } CharUnits AIXABIInfo::getParamTypeAlignment(QualType Ty) const { - if (Ty->isAnyComplexType()) - llvm::report_fatal_error("complex type is not supported on AIX yet"); + // Complex types are passed just like their elements. + if (const ComplexType *CTy = Ty->getAs()) + Ty = CTy->getElementType(); if (Ty->isVectorType()) llvm::report_fatal_error("vector type is not supported on AIX yet"); diff --git a/clang/test/CodeGen/aix-complex.c b/clang/test/CodeGen/aix-complex.c deleted file mode 100644 index 62ab481a915650..00000000000000 --- a/clang/test/CodeGen/aix-complex.c +++ /dev/null @@ -1,10 +0,0 @@ -// REQUIRES: powerpc-registered-target -// RUN: not %clang_cc1 -triple powerpc-unknown-aix \ -// RUN: -emit-llvm -o - %s 2>&1 | FileCheck %s -// RUN: not %clang_cc1 -triple powerpc64-unknown-aix \ -// RUN: -emit-llvm -o - %s 2>&1 | FileCheck %s - -// CHECK: fatal error: error in backend: complex type is not supported on AIX yet -_Complex float foo_float(_Complex float x) { - return x; -} diff --git a/clang/test/CodeGen/powerpc-c99complex.c b/clang/test/CodeGen/powerpc-c99complex.c index 95c71ee4ec8146..a59cdb683c0eaf 100644 --- a/clang/test/CodeGen/powerpc-c99complex.c +++ b/clang/test/CodeGen/powerpc-c99complex.c @@ -1,39 +1,44 @@ -// RUN: %clang_cc1 -triple powerpc64-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefixes=PPC64LNX -// RUN: %clang_cc1 -triple ppc64le-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefixes=PPC64LNX +// RUN: %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOLDBL128 +// RUN: %clang_cc1 -triple powerpc-unknown-aix -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOLDBL128 +// RUN: %clang_cc1 -triple powerpc64-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-LDBL128 +// RUN: %clang_cc1 -triple ppc64le-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-LDBL128 // RUN: %clang_cc1 -triple powerpc-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefix=PPC32LNX _Complex float foo1(_Complex float x) { return x; -// PPC64LNX-LABEL: define { float, float } @foo1(float %x.{{.*}}, float %x.{{.*}}) #0 { -// PPC64LNX: ret { float, float } +// CHECK-LABEL: define { float, float } @foo1(float %x.{{.*}}, float %x.{{.*}}) #0 { +// CHECK: ret { float, float } -// PPC32LNX-LABEL: define void @foo1({ float, float }* noalias sret align 4 %agg.result, { float, float }* byval({ float, float }) align 4 %x) #0 { -// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { float, float }, { float, float }* %agg.result, i32 0, i32 0 -// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { float, float }, { float, float }* %agg.result, i32 0, i32 1 -// PPC32LNX-NEXT: store float %{{.*}}, float* [[RETREAL]], align 4 -// PPC32LNX-NEXT: store float %{{.*}}, float* [[RETIMAG]], align 4 +// PPC32LNX-LABEL: define void @foo1({ float, float }* noalias sret align 4 %agg.result, { float, float }* byval({ float, float }) align 4 %x) #0 { +// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { float, float }, { float, float }* %agg.result, i32 0, i32 0 +// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { float, float }, { float, float }* %agg.result, i32 0, i32 1 +// PPC32LNX-NEXT: store float %{{.*}}, float* [[RETREAL]], align 4 +// PPC32LNX-NEXT: store float %{{.*}}, float* [[RETIMAG]], align 4 } _Complex double foo2(_Complex double x) { return x; -// PPC64LNX-LABEL: define { double, double } @foo2(double %x.{{.*}}, double %x.{{.*}}) #0 { -// PPC64LNX: ret { double, double } +// CHECK-LABEL: define { double, double } @foo2(double %x.{{.*}}, double %x.{{.*}}) #0 { +// CHECK: ret { double, double } -// PPC32LNX-LABEL: define void @foo2({ double, double }* noalias sret align 8 %agg.result, { double, double }* byval({ double, double }) align 8 %x) #0 { -// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { double, double }, { double, double }* %agg.result, i32 0, i32 0 -// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { double, double }, { double, double }* %agg.result, i32 0, i32 1 -// PPC32LNX-NEXT: store double %{{.*}}, double* [[RETREAL]], align 8 -// PPC32LNX-NEXT: store double %{{.*}}, double* [[RETIMAG]], align 8 +// PPC32LNX-LABEL: define void @foo2({ double, double }* noalias sret align 8 %agg.result, { double, double }* byval({ double, double }) align 8 %x) #0 { +// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { double, double }, { double, double }* %agg.result, i32 0, i32 0 +// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { double, double }, { double, double }* %agg.result, i32 0, i32 1 +// PPC32LNX-NEXT: store double %{{.*}}, double* [[RETREAL]], align 8 +// PPC32LNX-NEXT: store double %{{.*}}, double* [[RETIMAG]], align 8 } _Complex long double foo3(_Complex long double x) { return x; -// PPC64LNX-LABEL: define { ppc_fp128, ppc_fp128 } @foo3(ppc_fp128 %x.{{.*}}, ppc_fp128 %x.{{.*}}) #0 { -// PPC64LNX: ret { ppc_fp128, ppc_fp128 } +// CHECK-NOLDBL128-LABEL: define { double, double } @foo3(double %x.{{.*}}, double %x.{{.*}}) #0 { +// CHECK-NOLDBL128: ret { double, double } -// PPC32LNX-LABEL: define void @foo3({ ppc_fp128, ppc_fp128 }* noalias sret align 16 %agg.result, { ppc_fp128, ppc_fp128 }* byval({ ppc_fp128, ppc_fp128 }) align 16 %x) #0 { -// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, { ppc_fp128, ppc_fp128 }* %agg.result, i32 0, i32 0 -// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, { ppc_fp128, ppc_fp128 }* %agg.result, i32 0, i32 1 -// PPC32LNX-NEXT: store ppc_fp128 %{{.*}}, ppc_fp128* [[RETREAL]], align 16 -// PPC32LNX-NEXT: store ppc_fp128 %{{.*}}, ppc_fp128* [[RETIMAG]], align 16 +// CHECK-LDBL128-LABEL: define { ppc_fp128, ppc_fp128 } @foo3(ppc_fp128 %x.{{.*}}, ppc_fp128 %x.{{.*}}) #0 { +// CHECK-LDBL128: ret { ppc_fp128, ppc_fp128 } + +// PPC32LNX-LABEL: define void @foo3({ ppc_fp128, ppc_fp128 }* noalias sret align 16 %agg.result, { ppc_fp128, ppc_fp128 }* byval({ ppc_fp128, ppc_fp128 }) align 16 %x) #0 { +// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, { ppc_fp128, ppc_fp128 }* %agg.result, i32 0, i32 0 +// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, { ppc_fp128, ppc_fp128 }* %agg.result, i32 0, i32 1 +// PPC32LNX-NEXT: store ppc_fp128 %{{.*}}, ppc_fp128* [[RETREAL]], align 16 +// PPC32LNX-NEXT: store ppc_fp128 %{{.*}}, ppc_fp128* [[RETIMAG]], align 16 }