@@ -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,11 @@ 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
436450 bool IsCapability = Ty->isCHERICapabilityType (getContext ()) ||
437- IsSingleCapRecord ;
451+ (ForcePassInCapRegs && Size == CapabilityWidth) ;
438452
439453 // Capabilities (including single-capability records, which are treated the
440454 // same as a single capability) are passed indirectly for hybrid varargs.
@@ -528,7 +542,7 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
528542 return ABIArgInfo::getDirect ();
529543 }
530544
531- if (IsSingleCapRecord )
545+ if (ForcePassInCapRegs )
532546 return ABIArgInfo::getDirect ();
533547
534548 if (const VectorType *VT = Ty->getAs <VectorType>())
@@ -593,15 +607,12 @@ RValue RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
593607 if (EABI && XLen == 32 && !IsCheriot)
594608 TInfo.Align = std::min (TInfo.Align , CharUnits::fromQuantity (4 ));
595609
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 ());
610+ uint64_t Size = TInfo.Width .getQuantity () * 8 ;
611+ auto CapabilityWidth = getTarget ().getCHERICapabilityWidth ();
612+ bool ForcePassInCapRegs = shouldPassStructDirectInCapRegisters (Size, Ty);
602613
603614 bool IsCapability = Ty->isCHERICapabilityType (getContext ()) ||
604- IsSingleCapRecord ;
615+ (ForcePassInCapRegs && Size == CapabilityWidth) ;
605616
606617 // Arguments bigger than 2*Xlen bytes are passed indirectly, as are
607618 // capabilities for the hybrid ABI.
0 commit comments