diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -7370,10 +7370,49 @@ namespace { +class MSP430ABIInfo : public DefaultABIInfo { + static ABIArgInfo complexArgInfo() { + ABIArgInfo Info = ABIArgInfo::getDirect(); + Info.setCanBeFlattened(false); + return Info; + } + +public: + MSP430ABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} + + ABIArgInfo classifyReturnType(QualType RetTy) const { + if (RetTy->isComplexType()) + return complexArgInfo(); + + return DefaultABIInfo::classifyReturnType(RetTy); + } + + ABIArgInfo classifyArgumentType(QualType RetTy) const { + if (RetTy->isComplexType()) + return complexArgInfo(); + + return DefaultABIInfo::classifyArgumentType(RetTy); + } + + // Just copy the original implementations because + // DefaultABIInfo::classify{Return,Argument}Type() are not virtual + void computeInfo(CGFunctionInfo &FI) const override { + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + for (auto &I : FI.arguments()) + I.info = classifyArgumentType(I.type); + } + + Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, + QualType Ty) const override { + return EmitVAArgInstr(CGF, VAListAddr, Ty, classifyArgumentType(Ty)); + } +}; + class MSP430TargetCodeGenInfo : public TargetCodeGenInfo { public: MSP430TargetCodeGenInfo(CodeGenTypes &CGT) - : TargetCodeGenInfo(std::make_unique(CGT)) {} + : TargetCodeGenInfo(std::make_unique(CGT)) {} void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const override; }; diff --git a/clang/test/CodeGen/msp430-abi-complex.c b/clang/test/CodeGen/msp430-abi-complex.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/msp430-abi-complex.c @@ -0,0 +1,96 @@ +// REQUIRES: msp430-registered-target +// RUN: %clang -target msp430 -Os -S -o- %s | FileCheck %s + +volatile int N; +volatile float f1, f2; +volatile double d1, d2; + +void complex_float_arg_first(float _Complex x, int n) { +// CHECK-LABEL: @complex_float_arg_first + f1 = __real__ x; +// CHECK-DAG: mov r12, &f1 +// CHECK-DAG: mov r13, &f1+2 + f2 = __imag__ x; +// CHECK-DAG: mov r14, &f2 +// CHECK-DAG: mov r15, &f2+2 + N = n; +// CHECK-DAG: mov 2(r1), &N +// CHECK: ret +} + +void complex_float_arg_second(int n, float _Complex x) { +// CHECK-LABEL: @complex_float_arg_second + N = n; +// CHECK-DAG: mov r12, &N + f1 = __real__ x; +// CHECK-DAG: mov 2(r1), &f1 +// CHECK-DAG: mov 4(r1), &f1+2 +// CHECK-DAG: mov 6(r1), &f2 +// CHECK-DAG: mov 8(r1), &f2+2 + f2 = __imag__ x; +// CHECK: ret +} + +void complex_double_arg_first(double _Complex x, int n) { +// CHECK-LABEL: @complex_double_arg_first + d1 = __real__ x; +// CHECK-DAG: mov 2(r1), &d1 +// CHECK-DAG: mov 4(r1), &d1+2 +// CHECK-DAG: mov 6(r1), &d1+4 +// CHECK-DAG: mov 8(r1), &d1+6 + d2 = __imag__ x; +// CHECK-DAG: mov 10(r1), &d2 +// CHECK-DAG: mov 12(r1), &d2+2 +// CHECK-DAG: mov 14(r1), &d2+4 +// CHECK-DAG: mov 16(r1), &d2+6 + N = n; +// CHECK-DAG: mov r12, &N +// CHECK: ret +} + +void complex_double_arg_second(int n, double _Complex x) { +// CHECK-LABEL: @complex_double_arg_second + d1 = __real__ x; +// CHECK-DAG: mov 2(r1), &d1 +// CHECK-DAG: mov 4(r1), &d1+2 +// CHECK-DAG: mov 6(r1), &d1+4 +// CHECK-DAG: mov 8(r1), &d1+6 + d2 = __imag__ x; +// CHECK-DAG: mov 10(r1), &d2 +// CHECK-DAG: mov 12(r1), &d2+2 +// CHECK-DAG: mov 14(r1), &d2+4 +// CHECK-DAG: mov 16(r1), &d2+6 + N = n; +// CHECK-DAG: mov r12, &N +// CHECK: ret +} + +float _Complex complex_float_res(void) { +// CHECK-LABEL: @complex_float_res + float _Complex res; + __real__ res = 1; +// CHECK-DAG: clr r12 +// CHECK-DAG: mov #16256, r13 + __imag__ res = -1; +// CHECK-DAG: clr r14 +// CHECK-DAG: mov #-16512, r15 + return res; +// CHECK: ret +} + +double _Complex complex_double_res(void) { +// CHECK-LABEL: @complex_double_res + double _Complex res; + __real__ res = 1; +// CHECK-DAG: clr 0(r12) +// CHECK-DAG: clr 2(r12) +// CHECK-DAG: clr 4(r12) +// CHECK-DAG: mov #16368, 6(r12) + __imag__ res = -1; +// CHECK-DAG: clr 8(r12) +// CHECK-DAG: clr 10(r12) +// CHECK-DAG: clr 12(r12) +// CHECK-DAG: mov #-16400, 14(r12) + return res; +// CHECK: ret +}