@@ -429,9 +429,35 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
429429 return ABIArgInfo::getIgnore ();
430430
431431 bool IsSingleCapRecord = false ;
432- if (auto *RT = Ty->getAs <RecordType>())
432+ bool FitsInTwoRegs = false ;
433+ if (auto *RT = dyn_cast<RecordDecl>(Ty->getAsTagDecl ())) {
433434 IsSingleCapRecord = Size == getTarget ().getCHERICapabilityWidth () &&
434- getContext ().containsCapabilities (RT->getDecl ());
435+ getContext ().containsCapabilities (RT);
436+ FitsInTwoRegs = IsSingleCapRecord;
437+
438+ // Check if the record fits in two registers, that is:
439+ // 1. it has two fields
440+ // 2. any of the two fields is either a capability or a type whose size can
441+ // fit in the data part of a register
442+ if (!IsSingleCapRecord) {
443+ FitsInTwoRegs = true ;
444+ int SeenFields = 0 ;
445+ for (const FieldDecl *Field : RT->fields ()) {
446+ if (++SeenFields > 2 ) {
447+ FitsInTwoRegs = false ;
448+ break ;
449+ }
450+
451+ auto FieldTy = Field->getType ();
452+ auto FieldInfo = Field->getASTContext ().getTypeInfo (FieldTy);
453+ if (!FieldTy->isAnyPointerType () &&
454+ FieldInfo.Width > getTarget ().getRegisterWidth ()) {
455+ FitsInTwoRegs = false ;
456+ break ;
457+ }
458+ }
459+ }
460+ }
435461
436462 bool IsCapability = Ty->isCHERICapabilityType (getContext ()) ||
437463 IsSingleCapRecord;
@@ -528,7 +554,7 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
528554 return ABIArgInfo::getDirect ();
529555 }
530556
531- if (IsSingleCapRecord )
557+ if (FitsInTwoRegs )
532558 return ABIArgInfo::getDirect ();
533559
534560 if (const VectorType *VT = Ty->getAs <VectorType>())
0 commit comments