diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp --- a/clang/lib/CodeGen/SwiftCallingConv.cpp +++ b/clang/lib/CodeGen/SwiftCallingConv.cpp @@ -93,11 +93,24 @@ // Just add it all as opaque. addOpaqueData(begin, begin + CGM.getContext().getTypeSizeInChars(type)); - // Everything else is scalar and should not convert as an LLVM aggregate. + // Atomic types. + } else if (const auto *atomicType = type->getAs()) { + auto valueType = atomicType->getValueType(); + auto atomicSize = CGM.getContext().getTypeSizeInChars(atomicType); + auto valueSize = CGM.getContext().getTypeSizeInChars(valueType); + + addTypedData(atomicType->getValueType(), begin); + + // Add atomic padding. + auto atomicPadding = atomicSize - valueSize; + if (atomicPadding > CharUnits::Zero()) + addOpaqueData(begin + valueSize, begin + atomicSize); + + // Everything else is scalar and should not convert as an LLVM aggregate. } else { // We intentionally convert as !ForMem because we want to preserve // that a type was an i1. - auto llvmType = CGM.getTypes().ConvertType(type); + auto *llvmType = CGM.getTypes().ConvertType(type); addTypedData(llvmType, begin); } } diff --git a/clang/test/CodeGen/64bit-swiftcall.c b/clang/test/CodeGen/64bit-swiftcall.c --- a/clang/test/CodeGen/64bit-swiftcall.c +++ b/clang/test/CodeGen/64bit-swiftcall.c @@ -10,6 +10,9 @@ #define ERROR __attribute__((swift_error_result)) #define CONTEXT __attribute__((swift_context)) +// CHECK-DAG: %struct.atomic_padded = type { { %struct.packed, [7 x i8] } } +// CHECK-DAG: %struct.packed = type <{ i64, i8 }> +// // CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, i32 0, i32 0 } /*****************************************************************************/ @@ -1042,3 +1045,27 @@ // CHECK-NOT: call void @llvm.lifetime. take_int5(return_int5()); } + +typedef struct { + unsigned long long a; + unsigned long long b; +} double_word; + +typedef struct { + _Atomic(double_word) a; +} atomic_double_word; + +// CHECK-LABEL: use_atomic(i64 %0, i64 %1) +SWIFTCALL void use_atomic(atomic_double_word a) {} + +typedef struct { + unsigned long long a; + unsigned char b; +} __attribute__((packed)) packed; + +typedef struct { + _Atomic(packed) a; +} atomic_padded; + +// CHECK-LABEL: use_atomic_padded(i64 %0, i64 %1) +SWIFTCALL void use_atomic_padded(atomic_padded a) {}