ARMEB: Fix function result return for composite types
authorChristian Pirker <cpirker@a-bix.com>
Thu, 3 Jul 2014 09:28:12 +0000 (09:28 +0000)
committerChristian Pirker <cpirker@a-bix.com>
Thu, 3 Jul 2014 09:28:12 +0000 (09:28 +0000)
Reviewed at http://reviews.llvm.org/D4364

llvm-svn: 212261

clang/lib/CodeGen/TargetInfo.cpp
clang/test/CodeGen/arm-be-result-return.c [new file with mode: 0644]

index 16dee57..ae3caf7 100644 (file)
@@ -4379,6 +4379,10 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
   // are returned indirectly.
   uint64_t Size = getContext().getTypeSize(RetTy);
   if (Size <= 32) {
+    if (getDataLayout().isBigEndian())
+      // Return in 32 bit integer integer type (as if loaded by LDR, AAPCS 5.4)
+      return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
+
     // Return in the smallest viable integer type.
     if (Size <= 8)
       return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
diff --git a/clang/test/CodeGen/arm-be-result-return.c b/clang/test/CodeGen/arm-be-result-return.c
new file mode 100644 (file)
index 0000000..aadc4e1
--- /dev/null
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -triple armebv7-arm-none-eabi -emit-llvm -w -o - %s | FileCheck %s
+
+// this tests for AAPCS section 5.4:
+// A Composite Type not larger than 4 bytes is returned in r0.
+// The format is as if the result had been stored in memory at a
+// word-aligned address and then loaded into r0 with an LDR instruction
+
+extern union Us { short s; } us;
+union Us callee_us() { return us; }
+// CHECK-LABEL: callee_us()
+// CHECK: zext i16
+// CHECK: shl 
+// CHECK: ret i32
+
+void caller_us() {
+  us = callee_us();
+// CHECK-LABEL: caller_us()
+// CHECK: call i32
+// CHECK: lshr i32
+// CHECK: trunc i32
+}
+
+extern struct Ss { short s; } ss;
+struct Ss callee_ss() { return ss; }
+// CHECK-LABEL: callee_ss()
+// CHECK: zext i16
+// CHECK: shl 
+// CHECK: ret i32
+
+void caller_ss() {
+  ss = callee_ss();
+// CHECK-LABEL: caller_ss()
+// CHECK: call i32
+// CHECK: lshr i32
+// CHECK: trunc i32
+}
+