24
24
#include "llvm/ADT/Statistic.h"
25
25
#include "llvm/Analysis/MemoryLocation.h"
26
26
#include "llvm/Analysis/VectorUtils.h"
27
- #include "llvm/CHERI/cheri-compressed-cap/cheri_compressed_cap.h"
28
27
#include "llvm/CodeGen/MachineFrameInfo.h"
29
28
#include "llvm/CodeGen/MachineFunction.h"
30
29
#include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -6511,7 +6510,11 @@ SDValue RISCVTargetLowering::lowerVASTARTCap(SDValue Op, SelectionDAG &DAG) cons
6511
6510
MachinePointerInfo::getStack(MF, 0), Align(PtrSize));
6512
6511
SDValue Chain = VarPtr.getOperand(0);
6513
6512
if (UseBoundedMemArgsCallee) {
6514
- uint64_t PermMask = -1UL & ~(CAP_AP_X | CAP_AP_W);
6513
+ uint64_t ExecPerm =
6514
+ Subtarget.hasStdExtZCheriPureCap() ? (1 << 17) : (1 << 1);
6515
+ uint64_t WritePerm =
6516
+ Subtarget.hasStdExtZCheriPureCap() ? (1 << 0) : (1 << 3);
6517
+ uint64_t PermMask = -1UL & ~(ExecPerm | WritePerm);
6515
6518
VarPtr = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, PtrVT,
6516
6519
DAG.getConstant(Intrinsic::cheri_cap_perms_and, DL,
6517
6520
Subtarget.getXLenVT()),
@@ -15234,8 +15237,10 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
15234
15237
? Subtarget.typeForCapabilities()
15235
15238
: MVT();
15236
15239
MVT PtrVT = DL.isFatPointer(DL.getAllocaAddrSpace()) ? CLenVT : XLenVT;
15237
- bool IsPureCapVarArgs = !IsFixed && RISCVABI::isCheriPureCapABI(ABI);
15240
+ bool IsPureCap = RISCVABI::isCheriPureCapABI(ABI);
15241
+ bool IsPureCapVarArgs = !IsFixed && IsPureCap;
15238
15242
bool IsBoundedVarArgs = IsPureCapVarArgs && Subtarget.hasCheriBoundVarArg();
15243
+ unsigned SlotSize = PtrVT.getFixedSizeInBits() / 8;
15239
15244
15240
15245
// Static chain parameter must not be passed in normal argument registers,
15241
15246
// so we assign t2 for it as done in GCC's __builtin_call_with_static_chain
@@ -15309,7 +15314,7 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
15309
15314
// not apply.
15310
15315
// TODO: Pure capability varargs bounds
15311
15316
unsigned TwoXLenInBytes = (2 * XLen) / 8;
15312
- if (!IsFixed && !RISCVABI::isCheriPureCapABI(ABI) &&
15317
+ if (!IsFixed && !IsPureCap &&
15313
15318
ArgFlags.getNonZeroOrigAlign() == TwoXLenInBytes &&
15314
15319
DL.getTypeAllocSize(OrigTy) == TwoXLenInBytes) {
15315
15320
unsigned RegIdx = State.getFirstUnallocated(ArgGPRs);
@@ -15325,38 +15330,10 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
15325
15330
assert(PendingLocs.size() == PendingArgFlags.size() &&
15326
15331
"PendingLocs and PendingArgFlags out of sync");
15327
15332
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
15333
// Handle passing f64 on RV32D with a soft float ABI or when floating point
15357
15334
// registers are exhausted. Also handle for pure capability varargs which are
15358
15335
// always passed on the stack.
15359
- if (( UseGPRForF64 || IsPureCapVarArgs) && XLen == 32 && ValVT == MVT::f64) {
15336
+ if (UseGPRForF64 && XLen == 32 && ValVT == MVT::f64) {
15360
15337
assert(!ArgFlags.isSplit() && PendingLocs.empty() &&
15361
15338
"Can't lower f64 if it is split");
15362
15339
// Depending on available argument GPRS, f64 may be passed in a pair of
@@ -15366,7 +15343,9 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
15366
15343
Register Reg = IsPureCapVarArgs ? 0 : State.AllocateReg(ArgGPRs);
15367
15344
LocVT = MVT::i32;
15368
15345
if (!Reg) {
15369
- unsigned StackOffset = State.AllocateStack(8, Align(8));
15346
+ unsigned StackOffset =
15347
+ IsBoundedVarArgs ? State.AllocateStack(SlotSize, Align(SlotSize))
15348
+ : State.AllocateStack(8, Align(8));
15370
15349
State.addLoc(
15371
15350
CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));
15372
15351
return false;
@@ -15407,8 +15386,8 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
15407
15386
ISD::ArgFlagsTy AF = PendingArgFlags[0];
15408
15387
PendingLocs.clear();
15409
15388
PendingArgFlags.clear();
15410
- return CC_RISCVAssign2XLen(XLen, State, IsPureCapVarArgs, VA, AF,
15411
- ValNo, ValVT, LocVT, ArgFlags);
15389
+ return CC_RISCVAssign2XLen(XLen, State, IsPureCapVarArgs, VA, AF, ValNo,
15390
+ ValVT, LocVT, ArgFlags);
15412
15391
}
15413
15392
15414
15393
// Will be passed indirectly; make sure we allocate the right type of
@@ -15461,8 +15440,17 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
15461
15440
Reg = State.AllocateReg(ArgGPRs);
15462
15441
}
15463
15442
15443
+ // Aggregate types i.e. structs/arrays which can fit into 2*XLEN
15444
+ // Don't allocate a slot for each instead we make sure that the next element
15445
+ // is then properly aligned.
15446
+ bool AllocateSlot = IsBoundedVarArgs;
15447
+ if (OrigTy && OrigTy->isAggregateType())
15448
+ AllocateSlot = false;
15464
15449
unsigned StackOffset =
15465
- Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
15450
+ Reg ? 0
15451
+ : (AllocateSlot
15452
+ ? State.AllocateStack(SlotSize, Align(SlotSize))
15453
+ : State.AllocateStack(StoreSizeBytes, StackAlign));
15466
15454
15467
15455
// If we reach this point and PendingLocs is non-empty, we must be at the
15468
15456
// end of a split argument that must be passed indirectly.
@@ -16339,7 +16327,7 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
16339
16327
16340
16328
// Bookkeeping for cheri varargs/memargs
16341
16329
int VAArgStartOffset, VAArgEndOffset, MemArgStartOffset, MemArgEndOffset;
16342
- SDValue FirstAddr , FirstArgAddr;
16330
+ SDValue FirstVAAddr , FirstArgAddr;
16343
16331
16344
16332
// Copy argument values to their designated locations.
16345
16333
SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;
@@ -16466,34 +16454,23 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
16466
16454
SDValue Address =
16467
16455
DAG.getPointerAdd(DL, StackPtr, VA.getLocMemOffset());
16468
16456
16469
- if (UseBoundeMemArgsCaller) {
16457
+ if (UseBoundeMemArgsCaller && Outs[i].IsFixed ) {
16470
16458
if (FirstArgAddr == SDValue()) {
16471
16459
FirstArgAddr = Address;
16472
16460
MemArgStartOffset = VA.getLocMemOffset();
16473
16461
}
16474
16462
unsigned VTSize = VA.getValVT().getSizeInBits() / 8;
16475
16463
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
16464
}
16485
16465
if (UseBoundedVarArgs && !Outs[i].IsFixed) {
16486
- if (FirstAddr == SDValue()) {
16487
- FirstAddr = Address;
16466
+ if (FirstVAAddr == SDValue()) {
16467
+ FirstVAAddr = Address;
16488
16468
VAArgStartOffset = VA.getLocMemOffset();
16489
16469
}
16490
16470
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
16471
unsigned VTSize = VA.getValVT().getSizeInBits() / 8;
16496
16472
VAArgEndOffset = alignTo(VA.getLocMemOffset() + VTSize, OffsetAlign);
16473
+ MemArgEndOffset = VAArgEndOffset;
16497
16474
}
16498
16475
16499
16476
// Emit the store.
@@ -16503,15 +16480,19 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
16503
16480
}
16504
16481
16505
16482
if(IsVarArg && UseBoundedVarArgs && !UseBoundeMemArgsCaller) {
16506
- if (FirstAddr != SDValue()) {
16483
+ if (FirstVAAddr != SDValue()) {
16507
16484
SDValue VarArgs = DAG.getCSetBounds(
16508
- FirstAddr , DL, VAArgEndOffset - VAArgStartOffset, Align(),
16485
+ FirstVAAddr , DL, VAArgEndOffset - VAArgStartOffset, Align(),
16509
16486
"CHERI-RISCV variadic call lowering",
16510
16487
cheri::SetBoundsPointerSource::Stack, "varargs call bounds setting");
16511
16488
// clear write and execute permissions on varargs. Clearning other
16512
16489
// permissions shouldn't be necessary since the capability is derived from
16513
16490
// CSP and that shouldn't have these in the first place.
16514
- uint64_t PermMask = -1UL & ~(CAP_AP_X | CAP_AP_W);
16491
+ uint64_t ExecPerm =
16492
+ Subtarget.hasStdExtZCheriPureCap() ? (1 << 17) : (1 << 1);
16493
+ uint64_t WritePerm =
16494
+ Subtarget.hasStdExtZCheriPureCap() ? (1 << 0) : (1 << 3);
16495
+ uint64_t PermMask = -1UL & ~(ExecPerm | WritePerm);
16515
16496
VarArgs = DAG.getNode(
16516
16497
ISD::INTRINSIC_WO_CHAIN, DL, PtrVT,
16517
16498
DAG.getConstant(Intrinsic::cheri_cap_perms_and, DL, XLenVT), VarArgs,
@@ -16535,7 +16516,7 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
16535
16516
std::make_pair(RISCVABI::getCheriBoundedArgReg(), MemArgs));
16536
16517
} else {
16537
16518
bool ShouldClearArgReg = IsVarArg;
16538
- if (!ShouldClearArgReg && UseBoundeMemArgsCallee) {
16519
+ if (!ShouldClearArgReg && ! UseBoundeMemArgsCallee) {
16539
16520
auto *G = dyn_cast<GlobalAddressSDNode>(Callee);
16540
16521
ShouldClearArgReg = !G || !G->getGlobal()->hasInternalLinkage();
16541
16522
}
0 commit comments