[MSP430] Align the _Complex ABI with current msp430-gcc
authorAnatoly Trosinenko <atrosinenko@accesssoftek.com>
Thu, 9 Jul 2020 14:25:32 +0000 (17:25 +0300)
committerAnatoly Trosinenko <atrosinenko@accesssoftek.com>
Thu, 9 Jul 2020 15:28:48 +0000 (18:28 +0300)
Assembler output is checked against msp430-gcc 9.2.0.50 from TI.

Reviewed By: asl

Differential Revision: https://reviews.llvm.org/D82646

clang/lib/CodeGen/TargetInfo.cpp
clang/test/CodeGen/msp430-abi-complex.c [new file with mode: 0644]

index 801adc2..b83267d 100644 (file)
@@ -7475,10 +7475,49 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
 
 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->isAnyComplexType())
+      return complexArgInfo();
+
+    return DefaultABIInfo::classifyReturnType(RetTy);
+  }
+
+  ABIArgInfo classifyArgumentType(QualType RetTy) const {
+    if (RetTy->isAnyComplexType())
+      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<DefaultABIInfo>(CGT)) {}
+      : TargetCodeGenInfo(std::make_unique<MSP430ABIInfo>(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 (file)
index 0000000..faafcd2
--- /dev/null
@@ -0,0 +1,226 @@
+// REQUIRES: msp430-registered-target
+// RUN: %clang -target msp430 -Os -S -o- %s | FileCheck %s
+
+volatile int N;
+volatile int i16_1, i16_2;
+volatile long i32_1, i32_2;
+volatile long long i64_1, i64_2;
+volatile float f1, f2;
+volatile double d1, d2;
+
+_Static_assert(sizeof(int) == 2, "Assumption failed");
+_Static_assert(sizeof(long) == 4, "Assumption failed");
+_Static_assert(sizeof(long long) == 8, "Assumption failed");
+
+void complex_i16_arg_first(int _Complex x, int n) {
+// CHECK-LABEL: @complex_i16_arg_first
+  i16_1 = __real__ x;
+// CHECK-DAG: mov r12, &i16_1
+  i16_2 = __imag__ x;
+// CHECK-DAG: mov r13, &i16_2
+  N = n;
+// CHECK-DAG: mov r14, &N
+// CHECK:     ret
+}
+
+void complex_i16_arg_second(int n, int _Complex x) {
+// CHECK-LABEL: @complex_i16_arg_second
+  N = n;
+// CHECK-DAG: mov r12, &N
+  i16_1 = __real__ x;
+// CHECK-DAG: mov r13, &i16_1
+  i16_2 = __imag__ x;
+// CHECK-DAG: mov r14, &i16_2
+// CHECK:     ret
+}
+
+void complex_i32_arg_first(long _Complex x, int n) {
+// CHECK-LABEL: @complex_i32_arg_first
+  i32_1 = __real__ x;
+// CHECK-DAG: mov r12, &i32_1
+// CHECK-DAG: mov r13, &i32_1+2
+  i32_2 = __imag__ x;
+// CHECK-DAG: mov r14, &i32_2
+// CHECK-DAG: mov r15, &i32_2+2
+  N = n;
+// CHECK-DAG: mov 2(r1), &N
+// CHECK:     ret
+}
+
+void complex_i32_arg_second(int n, long _Complex x) {
+// CHECK-LABEL: @complex_i32_arg_second
+  N = n;
+// CHECK-DAG: mov r12, &N
+  i32_1 = __real__ x;
+// CHECK-DAG: mov 2(r1), &i32_1
+// CHECK-DAG: mov 4(r1), &i32_1+2
+  i32_2 = __imag__ x;
+// CHECK-DAG: mov 6(r1), &i32_2
+// CHECK-DAG: mov 8(r1), &i32_2+2
+// CHECK:     ret
+}
+
+void complex_i64_arg_first(long long _Complex x, int n) {
+// CHECK-LABEL: @complex_i64_arg_first
+  i64_1 = __real__ x;
+// CHECK-DAG: mov 2(r1), &i64_1
+// CHECK-DAG: mov 4(r1), &i64_1+2
+// CHECK-DAG: mov 6(r1), &i64_1+4
+// CHECK-DAG: mov 8(r1), &i64_1+6
+  i64_2 = __imag__ x;
+// CHECK-DAG: mov 10(r1), &i64_2
+// CHECK-DAG: mov 12(r1), &i64_2+2
+// CHECK-DAG: mov 14(r1), &i64_2+4
+// CHECK-DAG: mov 16(r1), &i64_2+6
+  N = n;
+// CHECK-DAG: mov r12, &N
+// CHECK:     ret
+}
+
+void complex_i64_arg_second(int n, long long _Complex x) {
+// CHECK-LABEL: @complex_i64_arg_second
+  N = n;
+// CHECK-DAG: mov r12, &N
+  i64_1 = __real__ x;
+// CHECK-DAG: mov 2(r1), &i64_1
+// CHECK-DAG: mov 4(r1), &i64_1+2
+// CHECK-DAG: mov 6(r1), &i64_1+4
+// CHECK-DAG: mov 8(r1), &i64_1+6
+  i64_2 = __imag__ x;
+// CHECK-DAG: mov 10(r1), &i64_2
+// CHECK-DAG: mov 12(r1), &i64_2+2
+// CHECK-DAG: mov 14(r1), &i64_2+4
+// CHECK-DAG: mov 16(r1), &i64_2+6
+// CHECK:     ret
+}
+
+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
+  f2 = __imag__ x;
+// CHECK-DAG: mov 6(r1), &f2
+// CHECK-DAG: mov 8(r1), &f2+2
+// 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
+}
+
+int _Complex complex_i16_res(void) {
+// CHECK-LABEL: @complex_i16_res
+  int _Complex res;
+  __real__ res = 0x1122;
+// CHECK-DAG: mov #4386, r12
+  __imag__ res = 0x3344;
+// CHECK-DAG: mov #13124, r13
+  return res;
+// CHECK:     ret
+}
+
+long _Complex complex_i32_res(void) {
+// CHECK-LABEL: @complex_i32_res
+  long _Complex res;
+  __real__ res = 0x11223344;
+// CHECK-DAG: mov #13124, r12
+// CHECK-DAG: mov #4386,  r13
+  __imag__ res = 0x55667788;
+// CHECK-DAG: mov #30600, r14
+// CHECK-DAG: mov #21862, r15
+  return res;
+// CHECK:     ret
+}
+
+long long _Complex complex_i64_res(void) {
+// CHECK-LABEL: @complex_i64_res
+  long long _Complex res;
+  __real__ res = 0x1122334455667788;
+// CHECK-DAG: mov #30600,  0(r12)
+// CHECK-DAG: mov #21862,  2(r12)
+// CHECK-DAG: mov #13124,  4(r12)
+// CHECK-DAG: mov #4386,   6(r12)
+  __imag__ res = 0x99aabbccddeeff00;
+// CHECK-DAG: mov #-256,   8(r12)
+// CHECK-DAG: mov #-8722,  10(r12)
+// CHECK-DAG: mov #-17460, 12(r12)
+// CHECK-DAG: mov #-26198, 14(r12)
+  return res;
+// 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
+}