@@ -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,9 @@ 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 ());
435-
436- bool IsCapability = Ty->isCHERICapabilityType (getContext ()) ||
437- IsSingleCapRecord;
447+ bool ForcePassInCapRegs = shouldPassStructDirectInCapRegisters (Size, Ty);
448+ bool IsCapability =
449+ Ty->isCHERICapabilityType (getContext ()) || ForcePassInCapRegs;
438450
439451 // Capabilities (including single-capability records, which are treated the
440452 // same as a single capability) are passed indirectly for hybrid varargs.
@@ -528,7 +540,7 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
528540 return ABIArgInfo::getDirect ();
529541 }
530542
531- if (IsSingleCapRecord )
543+ if (ForcePassInCapRegs )
532544 return ABIArgInfo::getDirect ();
533545
534546 if (const VectorType *VT = Ty->getAs <VectorType>())
@@ -593,15 +605,10 @@ RValue RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
593605 if (EABI && XLen == 32 && !IsCheriot)
594606 TInfo.Align = std::min (TInfo.Align , CharUnits::fromQuantity (4 ));
595607
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 ());
602-
603- bool IsCapability = Ty->isCHERICapabilityType (getContext ()) ||
604- IsSingleCapRecord;
608+ bool ForcePassInCapRegs =
609+ shouldPassStructDirectInCapRegisters (TInfo.Width .getQuantity (), Ty);
610+ bool IsCapability =
611+ Ty->isCHERICapabilityType (getContext ()) || ForcePassInCapRegs;
605612
606613 // Arguments bigger than 2*Xlen bytes are passed indirectly, as are
607614 // capabilities for the hybrid ABI.
0 commit comments