Skip to content

Commit f7259fb

Browse files
committed
[CHERIoT] Pass two-cap-sized return values and arguments in registers
1 parent d2286ce commit f7259fb

File tree

3 files changed

+1511
-13
lines changed

3 files changed

+1511
-13
lines changed

clang/lib/CodeGen/Targets/RISCV.cpp

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
3840
public:
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+
409425
ABIArgInfo 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

Comments
 (0)