File indexing completed on 2026-05-10 08:43:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H
0015 #define LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H
0016
0017 #include "llvm/ADT/ArrayRef.h"
0018 #include "llvm/ADT/SmallVector.h"
0019 #include "llvm/CodeGen/CallingConvLower.h"
0020 #include "llvm/CodeGen/MachineOperand.h"
0021 #include "llvm/CodeGen/TargetCallingConv.h"
0022 #include "llvm/CodeGenTypes/LowLevelType.h"
0023 #include "llvm/CodeGenTypes/MachineValueType.h"
0024 #include "llvm/IR/CallingConv.h"
0025 #include "llvm/IR/Type.h"
0026 #include "llvm/IR/Value.h"
0027 #include "llvm/Support/ErrorHandling.h"
0028 #include <cstdint>
0029 #include <functional>
0030
0031 namespace llvm {
0032
0033 class AttributeList;
0034 class CallBase;
0035 class DataLayout;
0036 class Function;
0037 class FunctionLoweringInfo;
0038 class MachineIRBuilder;
0039 class MachineFunction;
0040 struct MachinePointerInfo;
0041 class MachineRegisterInfo;
0042 class TargetLowering;
0043
0044 class CallLowering {
0045 const TargetLowering *TLI;
0046
0047 virtual void anchor();
0048 public:
0049 struct BaseArgInfo {
0050 Type *Ty;
0051 SmallVector<ISD::ArgFlagsTy, 4> Flags;
0052 bool IsFixed;
0053
0054 BaseArgInfo(Type *Ty,
0055 ArrayRef<ISD::ArgFlagsTy> Flags = ArrayRef<ISD::ArgFlagsTy>(),
0056 bool IsFixed = true)
0057 : Ty(Ty), Flags(Flags), IsFixed(IsFixed) {}
0058
0059 BaseArgInfo() : Ty(nullptr), IsFixed(false) {}
0060 };
0061
0062 struct ArgInfo : public BaseArgInfo {
0063 SmallVector<Register, 4> Regs;
0064
0065
0066
0067 SmallVector<Register, 2> OrigRegs;
0068
0069
0070
0071
0072
0073 const Value *OrigValue = nullptr;
0074
0075
0076 unsigned OrigArgIndex;
0077
0078
0079 static const unsigned NoArgIndex = UINT_MAX;
0080
0081 ArgInfo(ArrayRef<Register> Regs, Type *Ty, unsigned OrigIndex,
0082 ArrayRef<ISD::ArgFlagsTy> Flags = ArrayRef<ISD::ArgFlagsTy>(),
0083 bool IsFixed = true, const Value *OrigValue = nullptr)
0084 : BaseArgInfo(Ty, Flags, IsFixed), Regs(Regs), OrigValue(OrigValue),
0085 OrigArgIndex(OrigIndex) {
0086 if (!Regs.empty() && Flags.empty())
0087 this->Flags.push_back(ISD::ArgFlagsTy());
0088
0089 assert(((Ty->isVoidTy() || Ty->isEmptyTy()) ==
0090 (Regs.empty() || Regs[0] == 0)) &&
0091 "only void types should have no register");
0092 }
0093
0094 ArgInfo(ArrayRef<Register> Regs, const Value &OrigValue, unsigned OrigIndex,
0095 ArrayRef<ISD::ArgFlagsTy> Flags = ArrayRef<ISD::ArgFlagsTy>(),
0096 bool IsFixed = true)
0097 : ArgInfo(Regs, OrigValue.getType(), OrigIndex, Flags, IsFixed, &OrigValue) {}
0098
0099 ArgInfo() = default;
0100 };
0101
0102 struct PtrAuthInfo {
0103 uint64_t Key;
0104 Register Discriminator;
0105 };
0106
0107 struct CallLoweringInfo {
0108
0109 CallingConv::ID CallConv = CallingConv::C;
0110
0111
0112
0113 MachineOperand Callee = MachineOperand::CreateImm(0);
0114
0115
0116 ArgInfo OrigRet;
0117
0118
0119 SmallVector<ArgInfo, 32> OrigArgs;
0120
0121
0122
0123 Register SwiftErrorVReg;
0124
0125
0126 Register ConvergenceCtrlToken;
0127
0128
0129 const CallBase *CB = nullptr;
0130
0131 MDNode *KnownCallees = nullptr;
0132
0133
0134 std::optional<PtrAuthInfo> PAI;
0135
0136
0137 bool IsMustTailCall = false;
0138
0139
0140
0141 bool IsTailCall = false;
0142
0143
0144
0145 bool LoweredTailCall = false;
0146
0147
0148 bool IsVarArg = false;
0149
0150
0151 bool CanLowerReturn = true;
0152
0153
0154 Register DemoteRegister;
0155
0156
0157 int DemoteStackIndex;
0158
0159
0160 const ConstantInt *CFIType = nullptr;
0161
0162
0163 bool IsConvergent = true;
0164 };
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 struct ValueAssigner {
0176 ValueAssigner(bool IsIncoming, CCAssignFn *AssignFn_,
0177 CCAssignFn *AssignFnVarArg_ = nullptr)
0178 : AssignFn(AssignFn_), AssignFnVarArg(AssignFnVarArg_),
0179 IsIncomingArgumentHandler(IsIncoming) {
0180
0181
0182
0183 if (!AssignFnVarArg)
0184 AssignFnVarArg = AssignFn;
0185 }
0186
0187 virtual ~ValueAssigner() = default;
0188
0189
0190
0191 bool isIncomingArgumentHandler() const {
0192 return IsIncomingArgumentHandler;
0193 }
0194
0195
0196
0197
0198
0199 virtual bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
0200 CCValAssign::LocInfo LocInfo, const ArgInfo &Info,
0201 ISD::ArgFlagsTy Flags, CCState &State) {
0202 if (getAssignFn(State.isVarArg())(ValNo, ValVT, LocVT, LocInfo, Flags,
0203 State))
0204 return true;
0205 StackSize = State.getStackSize();
0206 return false;
0207 }
0208
0209
0210 CCAssignFn *AssignFn;
0211
0212
0213
0214 CCAssignFn *AssignFnVarArg;
0215
0216
0217 uint64_t StackSize = 0;
0218
0219
0220
0221 CCAssignFn *getAssignFn(bool IsVarArg) const {
0222 return IsVarArg ? AssignFnVarArg : AssignFn;
0223 }
0224
0225 private:
0226 const bool IsIncomingArgumentHandler;
0227 virtual void anchor();
0228 };
0229
0230 struct IncomingValueAssigner : public ValueAssigner {
0231 IncomingValueAssigner(CCAssignFn *AssignFn_,
0232 CCAssignFn *AssignFnVarArg_ = nullptr)
0233 : ValueAssigner(true, AssignFn_, AssignFnVarArg_) {}
0234 };
0235
0236 struct OutgoingValueAssigner : public ValueAssigner {
0237 OutgoingValueAssigner(CCAssignFn *AssignFn_,
0238 CCAssignFn *AssignFnVarArg_ = nullptr)
0239 : ValueAssigner(false, AssignFn_, AssignFnVarArg_) {}
0240 };
0241
0242 struct ValueHandler {
0243 MachineIRBuilder &MIRBuilder;
0244 MachineRegisterInfo &MRI;
0245 const bool IsIncomingArgumentHandler;
0246
0247 ValueHandler(bool IsIncoming, MachineIRBuilder &MIRBuilder,
0248 MachineRegisterInfo &MRI)
0249 : MIRBuilder(MIRBuilder), MRI(MRI),
0250 IsIncomingArgumentHandler(IsIncoming) {}
0251
0252 virtual ~ValueHandler() = default;
0253
0254
0255
0256 bool isIncomingArgumentHandler() const {
0257 return IsIncomingArgumentHandler;
0258 }
0259
0260
0261
0262
0263
0264
0265 virtual Register getStackAddress(uint64_t MemSize, int64_t Offset,
0266 MachinePointerInfo &MPO,
0267 ISD::ArgFlagsTy Flags) = 0;
0268
0269
0270
0271
0272
0273
0274 virtual LLT getStackValueStoreType(const DataLayout &DL,
0275 const CCValAssign &VA,
0276 ISD::ArgFlagsTy Flags) const;
0277
0278
0279
0280
0281 virtual void assignValueToReg(Register ValVReg, Register PhysReg,
0282 const CCValAssign &VA) = 0;
0283
0284
0285
0286
0287 virtual void assignValueToAddress(Register ValVReg, Register Addr,
0288 LLT MemTy, const MachinePointerInfo &MPO,
0289 const CCValAssign &VA) = 0;
0290
0291
0292
0293
0294 virtual void assignValueToAddress(const ArgInfo &Arg, unsigned ValRegIndex,
0295 Register Addr, LLT MemTy,
0296 const MachinePointerInfo &MPO,
0297 const CCValAssign &VA) {
0298 assignValueToAddress(Arg.Regs[ValRegIndex], Addr, MemTy, MPO, VA);
0299 }
0300
0301
0302
0303
0304
0305
0306
0307
0308 virtual unsigned assignCustomValue(ArgInfo &Arg, ArrayRef<CCValAssign> VAs,
0309 std::function<void()> *Thunk = nullptr) {
0310
0311
0312 llvm_unreachable("Custom values not supported");
0313 }
0314
0315
0316
0317 void
0318 copyArgumentMemory(const ArgInfo &Arg, Register DstPtr, Register SrcPtr,
0319 const MachinePointerInfo &DstPtrInfo, Align DstAlign,
0320 const MachinePointerInfo &SrcPtrInfo, Align SrcAlign,
0321 uint64_t MemSize, CCValAssign &VA) const;
0322
0323
0324
0325 Register extendRegister(Register ValReg, const CCValAssign &VA,
0326 unsigned MaxSizeBits = 0);
0327 };
0328
0329
0330
0331 struct IncomingValueHandler : public ValueHandler {
0332 IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
0333 : ValueHandler( true, MIRBuilder, MRI) {}
0334
0335
0336
0337 Register buildExtensionHint(const CCValAssign &VA, Register SrcReg,
0338 LLT NarrowTy);
0339
0340
0341 void assignValueToReg(Register ValVReg, Register PhysReg,
0342 const CCValAssign &VA) override;
0343 };
0344
0345
0346
0347 struct OutgoingValueHandler : public ValueHandler {
0348 OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
0349 : ValueHandler( false, MIRBuilder, MRI) {}
0350 };
0351
0352 protected:
0353
0354 const TargetLowering *getTLI() const {
0355 return TLI;
0356 }
0357
0358
0359 template <class XXXTargetLowering>
0360 const XXXTargetLowering *getTLI() const {
0361 return static_cast<const XXXTargetLowering *>(TLI);
0362 }
0363
0364
0365
0366 ISD::ArgFlagsTy getAttributesForArgIdx(const CallBase &Call,
0367 unsigned ArgIdx) const;
0368
0369
0370 ISD::ArgFlagsTy getAttributesForReturn(const CallBase &Call) const;
0371
0372
0373
0374 void addArgFlagsFromAttributes(ISD::ArgFlagsTy &Flags,
0375 const AttributeList &Attrs,
0376 unsigned OpIdx) const;
0377
0378 template <typename FuncInfoTy>
0379 void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL,
0380 const FuncInfoTy &FuncInfo) const;
0381
0382
0383
0384
0385
0386
0387
0388 void splitToValueTypes(const ArgInfo &OrigArgInfo,
0389 SmallVectorImpl<ArgInfo> &SplitArgs,
0390 const DataLayout &DL, CallingConv::ID CallConv,
0391 SmallVectorImpl<uint64_t> *Offsets = nullptr) const;
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404 bool determineAssignments(ValueAssigner &Assigner,
0405 SmallVectorImpl<ArgInfo> &Args,
0406 CCState &CCInfo) const;
0407
0408
0409
0410
0411
0412 bool
0413 determineAndHandleAssignments(ValueHandler &Handler, ValueAssigner &Assigner,
0414 SmallVectorImpl<ArgInfo> &Args,
0415 MachineIRBuilder &MIRBuilder,
0416 CallingConv::ID CallConv, bool IsVarArg,
0417 ArrayRef<Register> ThisReturnRegs = {}) const;
0418
0419
0420
0421
0422 bool handleAssignments(ValueHandler &Handler, SmallVectorImpl<ArgInfo> &Args,
0423 CCState &CCState,
0424 SmallVectorImpl<CCValAssign> &ArgLocs,
0425 MachineIRBuilder &MIRBuilder,
0426 ArrayRef<Register> ThisReturnRegs = {}) const;
0427
0428
0429
0430
0431 bool parametersInCSRMatch(const MachineRegisterInfo &MRI,
0432 const uint32_t *CallerPreservedMask,
0433 const SmallVectorImpl<CCValAssign> &ArgLocs,
0434 const SmallVectorImpl<ArgInfo> &OutVals) const;
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446 bool resultsCompatible(CallLoweringInfo &Info, MachineFunction &MF,
0447 SmallVectorImpl<ArgInfo> &InArgs,
0448 ValueAssigner &CalleeAssigner,
0449 ValueAssigner &CallerAssigner) const;
0450
0451 public:
0452 CallLowering(const TargetLowering *TLI) : TLI(TLI) {}
0453 virtual ~CallLowering() = default;
0454
0455
0456
0457
0458 virtual bool supportSwiftError() const {
0459 return false;
0460 }
0461
0462
0463
0464
0465 void insertSRetLoads(MachineIRBuilder &MIRBuilder, Type *RetTy,
0466 ArrayRef<Register> VRegs, Register DemoteReg,
0467 int FI) const;
0468
0469
0470
0471 void insertSRetStores(MachineIRBuilder &MIRBuilder, Type *RetTy,
0472 ArrayRef<Register> VRegs, Register DemoteReg) const;
0473
0474
0475
0476
0477 void insertSRetIncomingArgument(const Function &F,
0478 SmallVectorImpl<ArgInfo> &SplitArgs,
0479 Register &DemoteReg, MachineRegisterInfo &MRI,
0480 const DataLayout &DL) const;
0481
0482
0483
0484 void insertSRetOutgoingArgument(MachineIRBuilder &MIRBuilder,
0485 const CallBase &CB,
0486 CallLoweringInfo &Info) const;
0487
0488
0489
0490 bool checkReturn(CCState &CCInfo, SmallVectorImpl<BaseArgInfo> &Outs,
0491 CCAssignFn *Fn) const;
0492
0493
0494
0495 void getReturnInfo(CallingConv::ID CallConv, Type *RetTy, AttributeList Attrs,
0496 SmallVectorImpl<BaseArgInfo> &Outs,
0497 const DataLayout &DL) const;
0498
0499
0500
0501
0502 bool checkReturnTypeForCallConv(MachineFunction &MF) const;
0503
0504
0505
0506
0507 virtual bool canLowerReturn(MachineFunction &MF, CallingConv::ID CallConv,
0508 SmallVectorImpl<BaseArgInfo> &Outs,
0509 bool IsVarArg) const {
0510 return true;
0511 }
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523 virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val,
0524 ArrayRef<Register> VRegs, FunctionLoweringInfo &FLI,
0525 Register SwiftErrorVReg) const {
0526 if (!supportSwiftError()) {
0527 assert(SwiftErrorVReg == 0 && "attempt to use unsupported swifterror");
0528 return lowerReturn(MIRBuilder, Val, VRegs, FLI);
0529 }
0530 return false;
0531 }
0532
0533
0534
0535 virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val,
0536 ArrayRef<Register> VRegs,
0537 FunctionLoweringInfo &FLI) const {
0538 return false;
0539 }
0540
0541 virtual bool fallBackToDAGISel(const MachineFunction &MF) const {
0542 return false;
0543 }
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555 virtual bool lowerFormalArguments(MachineIRBuilder &MIRBuilder,
0556 const Function &F,
0557 ArrayRef<ArrayRef<Register>> VRegs,
0558 FunctionLoweringInfo &FLI) const {
0559 return false;
0560 }
0561
0562
0563
0564
0565
0566
0567 virtual bool lowerCall(MachineIRBuilder &MIRBuilder,
0568 CallLoweringInfo &Info) const {
0569 return false;
0570 }
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596 bool lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &Call,
0597 ArrayRef<Register> ResRegs,
0598 ArrayRef<ArrayRef<Register>> ArgRegs, Register SwiftErrorVReg,
0599 std::optional<PtrAuthInfo> PAI, Register ConvergenceCtrlToken,
0600 std::function<unsigned()> GetCalleeReg) const;
0601
0602
0603
0604 virtual bool enableBigEndian() const { return false; }
0605
0606
0607
0608 virtual bool isTypeIsValidForThisReturn(EVT Ty) const { return false; }
0609 };
0610
0611 }
0612
0613 #endif