Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -4379,12 +4379,16 @@ // are returned indirectly. uint64_t Size = getContext().getTypeSize(RetTy); if (Size <= 32) { - // Return in the smallest viable integer type. - if (Size <= 8) - return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); - if (Size <= 16) - return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); - return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); + if (getDataLayout().isLittleEndian()) { + // Return in the smallest viable integer type. + if (Size <= 8) + return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); + if (Size <= 16) + return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); + return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); + } else + // Return in 32 bit integer integer type (as if loaded by LDR, AAPCS 5.4) + return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); } markAllocatedGPRs(1, 1); Index: test/CodeGen/arm-be-result-return.c =================================================================== --- test/CodeGen/arm-be-result-return.c +++ test/CodeGen/arm-be-result-return.c @@ -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 +} +