Skip to content

Commit 08214d8

Browse files
committed
[clang] Handle trivial_abi attribute for Microsoft ABI.
Previously the trivial_abi was ignored for records when targetting the microsoft abi, the MSVC rules where always enforced to ensure compatibility with MSVC. This commit changes it to be closer to the itanium abi when a record is marked with the trivial_abi attribute. Fixes #87993
1 parent 89071f3 commit 08214d8

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ ABI Changes in This Version
6363
MSVC uses a different mangling for these objects, compatibility is not affected.
6464
(#GH85423).
6565

66+
- Records carrying the trivial_abi attribute are now returned directly in registers
67+
in more cases when using the Microsoft ABI. It is not possible to pass trivial_abi
68+
records between MSVC and Clang, so there is no ABI compatibility requirement. This
69+
is an ABI break with old versions of Clang. (#GH87993)
70+
6671
AST Dumping Potentially Breaking Changes
6772
----------------------------------------
6873

clang/lib/CodeGen/MicrosoftCXXABI.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,11 @@ bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD) const {
11051105

11061106
static bool isTrivialForMSVC(const CXXRecordDecl *RD, QualType Ty,
11071107
CodeGenModule &CGM) {
1108+
// If the record is marked with the trivial_abi attribute, we don't
1109+
// have to conform to the standard MSVC ABI.
1110+
if (RD->hasAttr<TrivialABIAttr>())
1111+
return true;
1112+
11081113
// On AArch64, HVAs that can be passed in registers can also be returned
11091114
// in registers. (Note this is using the MSVC definition of an HVA; see
11101115
// isPermittedToBeHomogeneousAggregate().)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
2+
3+
// CHECK: %[[STRUCT_TRIVIAL:.*]] = type { ptr }
4+
struct __attribute__((trivial_abi)) Trivial {
5+
int *p;
6+
Trivial() : p(0) {}
7+
Trivial(const Trivial &) noexcept = default;
8+
};
9+
10+
// CHECK-LABEL: define{{.*}} i64 @"?retTrivial@@YA?AUTrivial@@XZ"(
11+
// CHECK: %retval = alloca %[[STRUCT_TRIVIAL]], align 8
12+
// CHECK: %call = call noundef ptr @"??0Trivial@@QEAA@XZ"(ptr noundef nonnull align 8 dereferenceable(8) %retval)
13+
// CHECK: %coerce.dive = getelementptr inbounds %[[STRUCT_TRIVIAL]], ptr %retval, i32 0, i32 0
14+
// CHECK: %0 = load ptr, ptr %coerce.dive, align 8
15+
// CHECK: %coerce.val.pi = ptrtoint ptr %0 to i64
16+
// CHECK: ret i64 %coerce.val.pi
17+
Trivial retTrivial() {
18+
Trivial s;
19+
return s;
20+
}
21+
22+
struct TrivialInstance {
23+
Trivial instanceMethod();
24+
static Trivial staticMethod();
25+
};
26+
27+
// We need to make sure that instanceMethod has a sret return value since `this` will always go in the register.
28+
// CHECK-LABEL: define{{.*}} void @"?instanceMethod@TrivialInstance@@QEAA?AUTrivial@@XZ"({{.*}} sret(%struct.Trivial{{.*}}
29+
Trivial TrivialInstance::instanceMethod() { return {}; }
30+
// CHECK-LABEL: define{{.*}} i64 @"?staticMethod@TrivialInstance@@SA?AUTrivial@@XZ"(
31+
Trivial TrivialInstance::staticMethod() { return {}; }

0 commit comments

Comments
 (0)