@@ -35,6 +35,8 @@ class RISCVABIInfo : public DefaultABIInfo {
3535 llvm::Type *&Field2Ty,
3636 CharUnits &Field2Off) const ;
3737
38+ bool shouldPassStructDirectInCapRegisters (uint64_t Size, QualType Ty) const ;
39+
3840public:
3941 RISCVABIInfo (CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen,
4042 bool EABI)
@@ -406,6 +408,20 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty) const {
406408 return ABIArgInfo::getDirect (ResType);
407409}
408410
411+ bool RISCVABIInfo::shouldPassStructDirectInCapRegisters (uint64_t Size,
412+ QualType Ty) const {
413+ StringRef TargetABI = getTarget ().getABI ();
414+ bool IsCheriot = TargetABI == " cheriot" || TargetABI == " cheriot-baremetal" ;
415+
416+ if (auto *RT = Ty->getAs <RecordType>()) {
417+ unsigned MaxCapRegs = IsCheriot ? 2 : 1 ;
418+ return Size == MaxCapRegs * getTarget ().getCHERICapabilityWidth () &&
419+ getContext ().containsCapabilities (RT->getDecl ());
420+ }
421+
422+ return false ;
423+ }
424+
409425ABIArgInfo RISCVABIInfo::classifyArgumentType (QualType Ty, bool IsFixed,
410426 int &ArgGPRsLeft,
411427 int &ArgFPRsLeft) const {
@@ -428,13 +444,10 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
428444 if (isEmptyRecord (getContext (), Ty, true ) && Size == 0 )
429445 return ABIArgInfo::getIgnore ();
430446
431- bool IsSingleCapRecord = false ;
432- if (auto *RT = Ty->getAs <RecordType>())
433- IsSingleCapRecord = Size == getTarget ().getCHERICapabilityWidth () &&
434- getContext ().containsCapabilities (RT->getDecl ());
447+ auto CapabilityWidth = getTarget ().getCHERICapabilityWidth ();
448+ bool ForcePassInCapRegs = shouldPassStructDirectInCapRegisters (Size, Ty);
435449
436- bool IsCapability = Ty->isCHERICapabilityType (getContext ()) ||
437- IsSingleCapRecord;
450+ bool IsCapability = Ty->isCHERICapabilityType (getContext ()) || (ForcePassInCapRegs && Size == CapabilityWidth);
438451
439452 // Capabilities (including single-capability records, which are treated the
440453 // same as a single capability) are passed indirectly for hybrid varargs.
@@ -528,7 +541,7 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
528541 return ABIArgInfo::getDirect ();
529542 }
530543
531- if (IsSingleCapRecord )
544+ if (ForcePassInCapRegs )
532545 return ABIArgInfo::getDirect ();
533546
534547 if (const VectorType *VT = Ty->getAs <VectorType>())
@@ -593,15 +606,11 @@ RValue RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
593606 if (EABI && XLen == 32 && !IsCheriot)
594607 TInfo.Align = std::min (TInfo.Align , CharUnits::fromQuantity (4 ));
595608
596- bool IsSingleCapRecord = false ;
597- CharUnits CapabilityWidth =
598- CharUnits::fromQuantity (getTarget ().getCHERICapabilityWidth () / 8 );
599- if (const auto *RT = Ty->getAs <RecordType>())
600- IsSingleCapRecord = TInfo.Width == CapabilityWidth &&
601- getContext ().containsCapabilities (RT->getDecl ());
609+ uint64_t Size = TInfo.Width .getQuantity () * 8 ;
610+ auto CapabilityWidth = getTarget ().getCHERICapabilityWidth ();
611+ bool ForcePassInCapRegs = shouldPassStructDirectInCapRegisters (Size, Ty);
602612
603- bool IsCapability = Ty->isCHERICapabilityType (getContext ()) ||
604- IsSingleCapRecord;
613+ bool IsCapability = Ty->isCHERICapabilityType (getContext ()) || (ForcePassInCapRegs && Size == CapabilityWidth);
605614
606615 // Arguments bigger than 2*Xlen bytes are passed indirectly, as are
607616 // capabilities for the hybrid ABI.
0 commit comments