Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -1010,8 +1010,9 @@ uint64_t Size = Context.getTypeSize(Ty); // For i386, type must be register sized. - // For the MCU ABI, it only needs to be <= 8-byte - if ((IsMCUABI && Size > 64) || (!IsMCUABI && !isRegisterSize(Size))) + // For the MCU ABI, it only needs to be positive <= 8-byte. + if ((IsMCUABI && (Size == 0 || Size > 64)) || + (!IsMCUABI && !isRegisterSize(Size))) return false; if (Ty->isVectorType()) { Index: test/CodeGen/mcu-struct-return.c =================================================================== --- test/CodeGen/mcu-struct-return.c +++ test/CodeGen/mcu-struct-return.c @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -triple i386-pc-elfiamcu -emit-llvm %s -o - | FileCheck %s + +// Structure that is more than 8 byte. +struct Big { + double a[10]; +}; + +// Empty union with zero size must be returned via memory. +union U1 { +} u1; + +// Too large union (80 bytes) must be returned via memory. +union U2 { + struct Big b; +} u2; + +// Aggregate union, must be returned in register. +union U3 { + int x; +} u3; + +// Empty struct with zero size, must be returned via memory. +struct S1 { +} s1; + +// Aggregate struct, must be returend in register. +struct S2 { + int x; +} s2; + +// CHECK: [[UNION1_TYPE:%.+]] = type {} +// CHECK: [[UNION2_TYPE:%.+]] = type { [[STRUCT_TYPE:%.+]] } +// CHECK: [[STRUCT_TYPE]] = type { [10 x double] } +// CHECK: [[UNION3_TYPE:%.+]] = type { i32 } +// CHECK: [[STRUCT1_TYPE:%.+]] = type {} +// CHECK: [[STRUCT2_TYPE:%.+]] = type { i32 } + +union U1 foo1() { return u1; } +union U2 foo2() { return u2; } +union U3 foo3() { return u3; } +struct S1 bar1() { return s1; } +struct S2 bar2() { return s2; } +// CHECK: define void @foo1([[UNION1_TYPE]]* noalias sret %{{.+}}) +// CHECK: define void @foo2([[UNION2_TYPE]]* noalias sret %{{.+}}) +// CHECK: define i32 @foo3() +// CHECK: define void @bar1([[STRUCT1_TYPE]]* noalias sret %{{.+}}) +// CHECK: define i32 @bar2() + +void run() { + union U1 x1 = foo1(); + union U2 x2 = foo2(); + union U3 x3 = foo3(); + struct S1 y1 = bar1(); + struct S2 y2 = bar2(); + + // CHECK: [[X1:%.+]] = alloca [[UNION1_TYPE]] + // CHECK: [[X2:%.+]] = alloca [[UNION2_TYPE]] + // CHECK: [[X3:%.+]] = alloca [[UNION3_TYPE]] + // CHECK: [[Y1:%.+]] = alloca [[STRUCT1_TYPE]] + // CHECK: [[Y2:%.+]] = alloca [[STRUCT2_TYPE]] + // CHECK: call void @foo1([[UNION1_TYPE]]* sret [[X1]]) + // CHECK: call void @foo2([[UNION2_TYPE]]* sret [[X2]]) + // CHECK: {{.+}} = call i32 @foo3() + // CHECK: call void @bar1([[STRUCT1_TYPE]]* sret [[Y1]]) + // CHECK: {{.+}} = call i32 @bar2() +}