@@ -15234,8 +15234,10 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
15234
15234
? Subtarget.typeForCapabilities()
15235
15235
: MVT();
15236
15236
MVT PtrVT = DL.isFatPointer(DL.getAllocaAddrSpace()) ? CLenVT : XLenVT;
15237
- bool IsPureCapVarArgs = !IsFixed && RISCVABI::isCheriPureCapABI(ABI);
15237
+ bool IsPureCap = RISCVABI::isCheriPureCapABI(ABI);
15238
+ bool IsPureCapVarArgs = !IsFixed && IsPureCap;
15238
15239
bool IsBoundedVarArgs = IsPureCapVarArgs && Subtarget.hasCheriBoundVarArg();
15240
+ unsigned SlotSize = PtrVT.getFixedSizeInBits() / 8;
15239
15241
15240
15242
// Static chain parameter must not be passed in normal argument registers,
15241
15243
// so we assign t2 for it as done in GCC's __builtin_call_with_static_chain
@@ -15309,7 +15311,7 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
15309
15311
// not apply.
15310
15312
// TODO: Pure capability varargs bounds
15311
15313
unsigned TwoXLenInBytes = (2 * XLen) / 8;
15312
- if (!IsFixed && !RISCVABI::isCheriPureCapABI(ABI) &&
15314
+ if (!IsFixed && !IsPureCap &&
15313
15315
ArgFlags.getNonZeroOrigAlign() == TwoXLenInBytes &&
15314
15316
DL.getTypeAllocSize(OrigTy) == TwoXLenInBytes) {
15315
15317
unsigned RegIdx = State.getFirstUnallocated(ArgGPRs);
@@ -15325,38 +15327,10 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
15325
15327
assert(PendingLocs.size() == PendingArgFlags.size() &&
15326
15328
"PendingLocs and PendingArgFlags out of sync");
15327
15329
15328
- // Bounded VarArgs
15329
- // Each bounded varargs is assigned a 2*XLen slot on the stack
15330
- // If the value is small enough to fit into the slot it is passed
15331
- // directly - otherwise a capability to the value is filled into the
15332
- // slot.
15333
- if (!IsFixed && IsBoundedVarArgs) {
15334
- unsigned SlotSize = CLenVT.getFixedSizeInBits() / 8;
15335
- // Aggregates of size 2*XLen need special handling here
15336
- // as LLVM with treat them as two separate XLen wide arguments
15337
- if(LocVT == XLenVT && OrigTy && OrigTy->isAggregateType()){
15338
- PendingLocs.push_back(
15339
- CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo));
15340
- PendingArgFlags.push_back(ArgFlags);
15341
- if(PendingLocs.size() == 2){
15342
- CCValAssign VA = PendingLocs[0];
15343
- ISD::ArgFlagsTy AF = PendingArgFlags[0];
15344
- PendingLocs.clear();
15345
- PendingArgFlags.clear();
15346
- return CC_RISCVAssign2XLen(XLen, State, IsPureCapVarArgs, VA, AF,
15347
- ValNo, ValVT, LocVT, ArgFlags);
15348
- }
15349
- return false;
15350
- }
15351
- unsigned StackOffset = State.AllocateStack(SlotSize, Align(SlotSize));
15352
- State.addLoc(CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));
15353
- return false;
15354
- }
15355
-
15356
15330
// Handle passing f64 on RV32D with a soft float ABI or when floating point
15357
15331
// registers are exhausted. Also handle for pure capability varargs which are
15358
15332
// always passed on the stack.
15359
- if (( UseGPRForF64 || IsPureCapVarArgs) && XLen == 32 && ValVT == MVT::f64) {
15333
+ if (UseGPRForF64 && XLen == 32 && ValVT == MVT::f64) {
15360
15334
assert(!ArgFlags.isSplit() && PendingLocs.empty() &&
15361
15335
"Can't lower f64 if it is split");
15362
15336
// Depending on available argument GPRS, f64 may be passed in a pair of
@@ -15366,7 +15340,9 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
15366
15340
Register Reg = IsPureCapVarArgs ? 0 : State.AllocateReg(ArgGPRs);
15367
15341
LocVT = MVT::i32;
15368
15342
if (!Reg) {
15369
- unsigned StackOffset = State.AllocateStack(8, Align(8));
15343
+ unsigned StackOffset =
15344
+ IsBoundedVarArgs ? State.AllocateStack(SlotSize, Align(SlotSize))
15345
+ : State.AllocateStack(8, Align(8));
15370
15346
State.addLoc(
15371
15347
CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));
15372
15348
return false;
@@ -15407,8 +15383,8 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
15407
15383
ISD::ArgFlagsTy AF = PendingArgFlags[0];
15408
15384
PendingLocs.clear();
15409
15385
PendingArgFlags.clear();
15410
- return CC_RISCVAssign2XLen(XLen, State, IsPureCapVarArgs, VA, AF,
15411
- ValNo, ValVT, LocVT, ArgFlags);
15386
+ return CC_RISCVAssign2XLen(XLen, State, IsPureCapVarArgs, VA, AF, ValNo,
15387
+ ValVT, LocVT, ArgFlags);
15412
15388
}
15413
15389
15414
15390
// Will be passed indirectly; make sure we allocate the right type of
@@ -15461,8 +15437,17 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
15461
15437
Reg = State.AllocateReg(ArgGPRs);
15462
15438
}
15463
15439
15440
+ // Aggregate types i.e. structs/arrays which can fit into 2*XLEN
15441
+ // Don't allocate a slot for each instead we make sure that the next element
15442
+ // is then properly aligned.
15443
+ bool AllocateSlot = IsBoundedVarArgs;
15444
+ if (OrigTy && OrigTy->isAggregateType())
15445
+ AllocateSlot = false;
15464
15446
unsigned StackOffset =
15465
- Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
15447
+ Reg ? 0
15448
+ : (AllocateSlot
15449
+ ? State.AllocateStack(SlotSize, Align(SlotSize))
15450
+ : State.AllocateStack(StoreSizeBytes, StackAlign));
15466
15451
15467
15452
// If we reach this point and PendingLocs is non-empty, we must be at the
15468
15453
// end of a split argument that must be passed indirectly.
@@ -16339,7 +16324,7 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
16339
16324
16340
16325
// Bookkeeping for cheri varargs/memargs
16341
16326
int VAArgStartOffset, VAArgEndOffset, MemArgStartOffset, MemArgEndOffset;
16342
- SDValue FirstAddr , FirstArgAddr;
16327
+ SDValue FirstVAAddr , FirstArgAddr;
16343
16328
16344
16329
// Copy argument values to their designated locations.
16345
16330
SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;
@@ -16466,34 +16451,23 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
16466
16451
SDValue Address =
16467
16452
DAG.getPointerAdd(DL, StackPtr, VA.getLocMemOffset());
16468
16453
16469
- if (UseBoundeMemArgsCaller) {
16454
+ if (UseBoundeMemArgsCaller && Outs[i].IsFixed ) {
16470
16455
if (FirstArgAddr == SDValue()) {
16471
16456
FirstArgAddr = Address;
16472
16457
MemArgStartOffset = VA.getLocMemOffset();
16473
16458
}
16474
16459
unsigned VTSize = VA.getValVT().getSizeInBits() / 8;
16475
16460
MemArgEndOffset = VA.getLocMemOffset() + VTSize;
16476
- if (!Outs[i].IsFixed) {
16477
- // we need to align to 16-byte slot
16478
- Align OffsetAlign = Align(PtrLenBytes);
16479
- Type *OrigTy = CLI.getArgs()[Outs[i].OrigArgIndex].Ty;
16480
- if (OrigTy && OrigTy->isAggregateType())
16481
- OffsetAlign = Align(PtrLenBytes / 2);
16482
- MemArgEndOffset = alignTo(MemArgEndOffset, OffsetAlign);
16483
- }
16484
16461
}
16485
16462
if (UseBoundedVarArgs && !Outs[i].IsFixed) {
16486
- if (FirstAddr == SDValue()) {
16487
- FirstAddr = Address;
16463
+ if (FirstVAAddr == SDValue()) {
16464
+ FirstVAAddr = Address;
16488
16465
VAArgStartOffset = VA.getLocMemOffset();
16489
16466
}
16490
16467
Align OffsetAlign = Align(PtrLenBytes);
16491
- Type *OrigTy = CLI.getArgs()[Outs[i].OrigArgIndex].Ty;
16492
- if (OrigTy && OrigTy->isAggregateType())
16493
- OffsetAlign = Align(PtrLenBytes / 2);
16494
-
16495
16468
unsigned VTSize = VA.getValVT().getSizeInBits() / 8;
16496
16469
VAArgEndOffset = alignTo(VA.getLocMemOffset() + VTSize, OffsetAlign);
16470
+ MemArgEndOffset = VAArgEndOffset;
16497
16471
}
16498
16472
16499
16473
// Emit the store.
@@ -16503,15 +16477,19 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
16503
16477
}
16504
16478
16505
16479
if(IsVarArg && UseBoundedVarArgs && !UseBoundeMemArgsCaller) {
16506
- if (FirstAddr != SDValue()) {
16480
+ if (FirstVAAddr != SDValue()) {
16507
16481
SDValue VarArgs = DAG.getCSetBounds(
16508
- FirstAddr , DL, VAArgEndOffset - VAArgStartOffset, Align(),
16482
+ FirstVAAddr , DL, VAArgEndOffset - VAArgStartOffset, Align(),
16509
16483
"CHERI-RISCV variadic call lowering",
16510
16484
cheri::SetBoundsPointerSource::Stack, "varargs call bounds setting");
16511
16485
// clear write and execute permissions on varargs. Clearning other
16512
16486
// permissions shouldn't be necessary since the capability is derived from
16513
16487
// CSP and that shouldn't have these in the first place.
16514
- uint64_t PermMask = -1UL & ~(CAP_AP_X | CAP_AP_W);
16488
+ uint64_t ExecPerm =
16489
+ Subtarget.hasStdExtZCheriPureCap() ? (1 << 17) : (1 << 1);
16490
+ uint64_t WritePerm =
16491
+ Subtarget.hasStdExtZCheriPureCap() ? (1 << 1) : (1 << 3);
16492
+ uint64_t PermMask = -1UL & ~(ExecPerm | WritePerm);
16515
16493
VarArgs = DAG.getNode(
16516
16494
ISD::INTRINSIC_WO_CHAIN, DL, PtrVT,
16517
16495
DAG.getConstant(Intrinsic::cheri_cap_perms_and, DL, XLenVT), VarArgs,
0 commit comments