Skip to content

Commit 573cb26

Browse files
committed
[clang] Return larger CXX records in memory
We incorrectly return CXX records in AVX registers when they should be returned in memory. This is violation of x86-64 psABI. Detailed discussion is here: https://groups.google.com/g/x86-64-abi/c/BjOOyihHuqg/m/KurXdUcWAgAJ
1 parent f8d9f8e commit 573cb26

File tree

2 files changed

+19
-0
lines changed

2 files changed

+19
-0
lines changed

clang/include/clang/Basic/LangOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ class LangOptionsBase {
245245
/// construction vtable because it hasn't added 'type' as a substitution.
246246
/// - Skip mangling enclosing class templates of member-like friend
247247
/// function templates.
248+
/// - Incorrectly return C++ records in AVX registers.
248249
Ver19,
249250

250251
/// Conform to the underlying platform's C and C++ ABIs as closely

clang/lib/CodeGen/Targets/X86.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,6 +1334,20 @@ class X86_64ABIInfo : public ABIInfo {
13341334
return T.isOSLinux() || T.isOSNetBSD();
13351335
}
13361336

1337+
bool returnCXXRecordGreaterThan128InMem(unsigned Size, unsigned TypeSize,
1338+
unsigned NativeSize) const {
1339+
// Clang <= 19.0 did not do this.
1340+
if (getContext().getLangOpts().getClangABICompat() <=
1341+
LangOptions::ClangABI::Ver19)
1342+
return false;
1343+
1344+
// The only case a 256(or 512)-bit wide vector could be used to return
1345+
// is when CXX record contains a single 256(or 512)-bit element.
1346+
if (Size > 128 && (Size != TypeSize || Size > NativeSize))
1347+
return true;
1348+
return false;
1349+
}
1350+
13371351
X86AVXABILevel AVXLevel;
13381352
// Some ABIs (e.g. X32 ABI and Native Client OS) use 32 bit pointers on
13391353
// 64-bit hardware.
@@ -2067,6 +2081,10 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo,
20672081
classify(I.getType(), Offset, FieldLo, FieldHi, isNamedArg);
20682082
Lo = merge(Lo, FieldLo);
20692083
Hi = merge(Hi, FieldHi);
2084+
if (returnCXXRecordGreaterThan128InMem(
2085+
Size, getContext().getTypeSize(I.getType()),
2086+
getNativeVectorSizeForAVXABI(AVXLevel)))
2087+
Lo = Memory;
20702088
if (Lo == Memory || Hi == Memory) {
20712089
postMerge(Size, Lo, Hi);
20722090
return;

0 commit comments

Comments
 (0)