@@ -429,9 +429,38 @@ 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+ int SeenFields = 0 ;
444+ for (const FieldDecl *Field : RT->fields ()) {
445+ if (++SeenFields > 2 ) {
446+ FitsInTwoRegs = false ;
447+ break ;
448+ }
449+
450+ auto FieldTy = Field->getType ();
451+ auto FieldInfo = Field->getASTContext ().getTypeInfo (FieldTy);
452+ if (!FieldTy->isAnyPointerType () &&
453+ FieldInfo.Width > getTarget ().getRegisterWidth ()) {
454+ FitsInTwoRegs = false ;
455+ break ;
456+ }
457+
458+ if (SeenFields == 2 ) {
459+ FitsInTwoRegs = true ;
460+ }
461+ }
462+ }
463+ }
435464
436465 bool IsCapability = Ty->isCHERICapabilityType (getContext ()) ||
437466 IsSingleCapRecord;
@@ -528,7 +557,7 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
528557 return ABIArgInfo::getDirect ();
529558 }
530559
531- if (IsSingleCapRecord )
560+ if (FitsInTwoRegs )
532561 return ABIArgInfo::getDirect ();
533562
534563 if (const VectorType *VT = Ty->getAs <VectorType>())
0 commit comments