@@ -429,9 +429,40 @@ 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+ auto *TD = Ty->getAsTagDecl ();
434+ if (TD && dyn_cast<RecordDecl>(TD)) {
435+ auto *RD = dyn_cast<RecordDecl>(TD);
433436 IsSingleCapRecord = Size == getTarget ().getCHERICapabilityWidth () &&
434- getContext ().containsCapabilities (RT->getDecl ());
437+ getContext ().containsCapabilities (RD);
438+ FitsInTwoRegs = IsSingleCapRecord;
439+
440+ // Check if the record fits in two registers, that is:
441+ // 1. it has two fields
442+ // 2. any of the two fields is either a capability or a type whose size can
443+ // fit in the data part of a register
444+ if (!IsSingleCapRecord) {
445+ int SeenFields = 0 ;
446+ for (const FieldDecl *Field : RD->fields ()) {
447+ if (++SeenFields > 2 ) {
448+ FitsInTwoRegs = false ;
449+ break ;
450+ }
451+
452+ auto FieldTy = Field->getType ();
453+ auto FieldInfo = Field->getASTContext ().getTypeInfo (FieldTy);
454+ if (!FieldTy->isAnyPointerType () &&
455+ FieldInfo.Width > getTarget ().getRegisterWidth ()) {
456+ FitsInTwoRegs = false ;
457+ break ;
458+ }
459+
460+ if (SeenFields == 2 ) {
461+ FitsInTwoRegs = true ;
462+ }
463+ }
464+ }
465+ }
435466
436467 bool IsCapability = Ty->isCHERICapabilityType (getContext ()) ||
437468 IsSingleCapRecord;
@@ -528,7 +559,7 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
528559 return ABIArgInfo::getDirect ();
529560 }
530561
531- if (IsSingleCapRecord )
562+ if (FitsInTwoRegs )
532563 return ABIArgInfo::getDirect ();
533564
534565 if (const VectorType *VT = Ty->getAs <VectorType>())
0 commit comments