================
@@ -2860,74 +2861,116 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty,
unsigned freeIntRegs,
return ABIArgInfo::getDirect(ResType);
}
-ABIArgInfo
-X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt,
- unsigned &NeededSSE,
- unsigned &MaxVectorWidth) const {
+// Returns true if the struct can be passed directly in registers. If so, the
+// number of registers required will be returned in `NeededInt` and
`NeededSSE`,
+// and `CoerceElts` will contain an expanded sequence of LLVM IR types that
each
+// field should coerce to.
+bool X86_64ABIInfo::passRegCallStructTypeDirectly(
+ QualType Ty, SmallVectorImpl<llvm::Type *> &CoerceElts, unsigned
&NeededInt,
+ unsigned &NeededSSE, unsigned &MaxVectorWidth) const {
+
auto *RD =
cast<RecordType>(Ty.getCanonicalType())->getDecl()->getDefinitionOrSelf();
-
if (RD->hasFlexibleArrayMember())
- return getIndirectReturnResult(Ty);
+ return false;
- // Sum up bases
+ // Classify the bases.
if (auto CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
- if (CXXRD->isDynamicClass()) {
- NeededInt = NeededSSE = 0;
- return getIndirectReturnResult(Ty);
- }
+ if (CXXRD->isDynamicClass())
+ return false;
- for (const auto &I : CXXRD->bases())
- if (classifyRegCallStructTypeImpl(I.getType(), NeededInt, NeededSSE,
- MaxVectorWidth)
- .isIndirect()) {
- NeededInt = NeededSSE = 0;
- return getIndirectReturnResult(Ty);
- }
+ for (const auto &I : CXXRD->bases()) {
+ QualType BaseTy = I.getType();
+ if (isEmptyRecord(getContext(), BaseTy, true))
+ continue;
+ if (!passRegCallStructTypeDirectly(BaseTy, CoerceElts, NeededInt,
+ NeededSSE, MaxVectorWidth))
+ return false;
+ }
}
- // Sum up members
+ // Classify the members.
for (const auto *FD : RD->fields()) {
QualType MTy = FD->getType();
if (MTy->isRecordType() && !MTy->isUnionType()) {
- if (classifyRegCallStructTypeImpl(MTy, NeededInt, NeededSSE,
- MaxVectorWidth)
- .isIndirect()) {
- NeededInt = NeededSSE = 0;
- return getIndirectReturnResult(Ty);
+ if (isEmptyRecord(getContext(), MTy, true))
+ continue;
+ if (!passRegCallStructTypeDirectly(MTy, CoerceElts, NeededInt, NeededSSE,
+ MaxVectorWidth))
+ return false;
+ continue;
+ }
+
+ const auto *AT = getContext().getAsConstantArrayType(MTy);
+ if (AT)
+ MTy = AT->getElementType();
+
+ unsigned LocalNeededInt, LocalNeededSSE;
+ ABIArgInfo AI = classifyArgumentType(MTy, UINT_MAX, LocalNeededInt,
+ LocalNeededSSE, true, true);
+ if (AI.isIgnore())
+ continue;
+ if (AI.isIndirect())
+ return false;
+
+ llvm::Type *CoerceTy = AI.getCoerceToType();
+ if (!CoerceTy) {
+ // We need to explicitly construct the coerce type for x87 long double
+ // arguments because X86_64ABIInfo::classifyArgumentType classifies them
+ // as direct without specifying a coerce type.
----------------
henrybw wrote:
Yeah, this is indeed pretty ugly.
I could modify `classifyArgumentType` so that it matches how
`classifyReturnType` handles class X87 types, and explicitly construct an
`X86_FP80Ty` (like I'm doing here in this special case). That *should* be
equivalent (it results in the same IR and generated code); however, it does
mean that my patch will be touching the SysV ABI implementation as well.
Does this seem like the right approach to you?
https://github.com/llvm/llvm-project/pull/187134
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits