CGCXXABI::RecordArgABI
MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {
+ // Use the default C calling convention rules for things that can be passed in
+ // registers, i.e. non-trivially copyable records or records marked with
+ // [[trivial_abi]].
+ if (RD->canPassInRegisters())
+ return RAA_Default;
+
switch (CGM.getTarget().getTriple().getArch()) {
default:
// FIXME: Implement for other architectures.
return RAA_Default;
case llvm::Triple::thumb:
- // Use the simple Itanium rules for now.
+ // Pass things indirectly for now because it is simple.
// FIXME: This is incompatible with MSVC for arguments with a dtor and no
// copy ctor.
- return !RD->canPassInRegisters() ? RAA_Indirect : RAA_Default;
+ return RAA_Indirect;
case llvm::Triple::x86: {
// If the argument has *required* alignment greater than four bytes, pass
// If C++ prohibits us from making a copy, construct the arguments directly
// into argument memory.
- if (!RD->canPassInRegisters())
- return RAA_DirectInMemory;
-
- // Otherwise, construct the argument into a temporary and copy the bytes
- // into the outgoing argument memory.
- return RAA_Default;
+ return RAA_DirectInMemory;
}
case llvm::Triple::x86_64:
case llvm::Triple::aarch64:
- return !RD->canPassInRegisters() ? RAA_Indirect : RAA_Default;
+ return RAA_Indirect;
}
llvm_unreachable("invalid enum");
// CHECK: [[TMP:%[^ ]*]] = alloca %struct.Both, align 8
// CHECK: call x86_thiscallcc %struct.Both* @"??0Both@@QAE@XZ"(%struct.Both* [[TMP]])
// CHECK: call i32 @"?receive_inalloca_both@@Y{{.*}}"(<{ %struct.NonTrivial, %struct.Both* }>* inalloca %argmem)
+
+// Here we have a type that is:
+// - overaligned
+// - not trivially copyable
+// - can be "passed in registers" due to [[trivial_abi]]
+// Clang should pass it directly.
+struct [[trivial_abi]] alignas(8) MyPtr {
+ MyPtr();
+ MyPtr(const MyPtr &o);
+ ~MyPtr();
+ int *ptr;
+};
+
+int receiveMyPtr(MyPtr o) { return *o.ptr; }
+
+// CHECK-LABEL: define dso_local i32 @"?receiveMyPtr@@Y{{.*}}"
+// CHECK-SAME: (%struct.MyPtr* %o)
+
+int passMyPtr() { return receiveMyPtr(MyPtr()); }
+
+// CHECK-LABEL: define dso_local i32 @"?passMyPtr@@Y{{.*}}"
+// CHECK: [[TMP:%[^ ]*]] = alloca %struct.MyPtr, align 8
+// CHECK: call x86_thiscallcc %struct.MyPtr* @"??0MyPtr@@QAE@XZ"(%struct.MyPtr* [[TMP]])
+// CHECK: call i32 @"?receiveMyPtr@@Y{{.*}}"(%struct.MyPtr* [[TMP]])