File indexing completed on 2026-05-10 08:43:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CODEGEN_CALLINGCONVLOWER_H
0015 #define LLVM_CODEGEN_CALLINGCONVLOWER_H
0016
0017 #include "llvm/ADT/ArrayRef.h"
0018 #include "llvm/ADT/SmallVector.h"
0019 #include "llvm/CodeGen/Register.h"
0020 #include "llvm/CodeGen/TargetCallingConv.h"
0021 #include "llvm/IR/CallingConv.h"
0022 #include "llvm/Support/Alignment.h"
0023 #include <variant>
0024
0025 namespace llvm {
0026
0027 class CCState;
0028 class MachineFunction;
0029 class MVT;
0030 class TargetRegisterInfo;
0031
0032
0033 class CCValAssign {
0034 public:
0035 enum LocInfo {
0036 Full,
0037 SExt,
0038 ZExt,
0039 AExt,
0040 SExtUpper,
0041
0042 ZExtUpper,
0043
0044 AExtUpper,
0045
0046 BCvt,
0047 Trunc,
0048 VExt,
0049
0050
0051 FPExt,
0052 Indirect
0053
0054 };
0055
0056 private:
0057
0058
0059
0060
0061
0062 std::variant<Register, int64_t, unsigned> Data;
0063
0064
0065 unsigned ValNo;
0066
0067
0068 unsigned isCustom : 1;
0069
0070
0071 LocInfo HTP : 6;
0072
0073
0074 MVT ValVT;
0075
0076
0077 MVT LocVT;
0078
0079 CCValAssign(LocInfo HTP, unsigned ValNo, MVT ValVT, MVT LocVT, bool IsCustom)
0080 : ValNo(ValNo), isCustom(IsCustom), HTP(HTP), ValVT(ValVT), LocVT(LocVT) {
0081 }
0082
0083 public:
0084 static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg,
0085 MVT LocVT, LocInfo HTP, bool IsCustom = false) {
0086 CCValAssign Ret(HTP, ValNo, ValVT, LocVT, IsCustom);
0087 Ret.Data = Register(Reg);
0088 return Ret;
0089 }
0090
0091 static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg,
0092 MVT LocVT, LocInfo HTP) {
0093 return getReg(ValNo, ValVT, Reg, LocVT, HTP, true);
0094 }
0095
0096 static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset,
0097 MVT LocVT, LocInfo HTP, bool IsCustom = false) {
0098 CCValAssign Ret(HTP, ValNo, ValVT, LocVT, IsCustom);
0099 Ret.Data = Offset;
0100 return Ret;
0101 }
0102
0103 static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset,
0104 MVT LocVT, LocInfo HTP) {
0105 return getMem(ValNo, ValVT, Offset, LocVT, HTP, true);
0106 }
0107
0108 static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT,
0109 LocInfo HTP, unsigned ExtraInfo = 0) {
0110 CCValAssign Ret(HTP, ValNo, ValVT, LocVT, false);
0111 Ret.Data = ExtraInfo;
0112 return Ret;
0113 }
0114
0115 void convertToReg(MCRegister Reg) { Data = Register(Reg); }
0116
0117 void convertToMem(int64_t Offset) { Data = Offset; }
0118
0119 unsigned getValNo() const { return ValNo; }
0120 MVT getValVT() const { return ValVT; }
0121
0122 bool isRegLoc() const { return std::holds_alternative<Register>(Data); }
0123 bool isMemLoc() const { return std::holds_alternative<int64_t>(Data); }
0124 bool isPendingLoc() const { return std::holds_alternative<unsigned>(Data); }
0125
0126 bool needsCustom() const { return isCustom; }
0127
0128 Register getLocReg() const { return std::get<Register>(Data); }
0129 int64_t getLocMemOffset() const { return std::get<int64_t>(Data); }
0130 unsigned getExtraInfo() const { return std::get<unsigned>(Data); }
0131
0132 MVT getLocVT() const { return LocVT; }
0133
0134 LocInfo getLocInfo() const { return HTP; }
0135 bool isExtInLoc() const {
0136 return (HTP == AExt || HTP == SExt || HTP == ZExt);
0137 }
0138
0139 bool isUpperBitsInLoc() const {
0140 return HTP == AExtUpper || HTP == SExtUpper || HTP == ZExtUpper;
0141 }
0142 };
0143
0144
0145
0146 struct ForwardedRegister {
0147 ForwardedRegister(Register VReg, MCPhysReg PReg, MVT VT)
0148 : VReg(VReg), PReg(PReg), VT(VT) {}
0149 Register VReg;
0150 MCPhysReg PReg;
0151 MVT VT;
0152 };
0153
0154
0155
0156 typedef bool CCAssignFn(unsigned ValNo, MVT ValVT,
0157 MVT LocVT, CCValAssign::LocInfo LocInfo,
0158 ISD::ArgFlagsTy ArgFlags, CCState &State);
0159
0160
0161
0162
0163 typedef bool CCCustomFn(unsigned &ValNo, MVT &ValVT,
0164 MVT &LocVT, CCValAssign::LocInfo &LocInfo,
0165 ISD::ArgFlagsTy &ArgFlags, CCState &State);
0166
0167
0168
0169
0170 class CCState {
0171 private:
0172 CallingConv::ID CallingConv;
0173 bool IsVarArg;
0174 bool AnalyzingMustTailForwardedRegs = false;
0175 MachineFunction &MF;
0176 const TargetRegisterInfo &TRI;
0177 SmallVectorImpl<CCValAssign> &Locs;
0178 LLVMContext &Context;
0179
0180 bool NegativeOffsets;
0181
0182 uint64_t StackSize;
0183 Align MaxStackArgAlign;
0184 SmallVector<uint32_t, 16> UsedRegs;
0185 SmallVector<CCValAssign, 4> PendingLocs;
0186 SmallVector<ISD::ArgFlagsTy, 4> PendingArgFlags;
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 struct ByValInfo {
0216 ByValInfo(unsigned B, unsigned E) : Begin(B), End(E) {}
0217
0218
0219 unsigned Begin;
0220
0221
0222 unsigned End;
0223 };
0224 SmallVector<ByValInfo, 4 > ByValRegs;
0225
0226
0227
0228 unsigned InRegsParamsProcessed;
0229
0230 public:
0231 CCState(CallingConv::ID CC, bool IsVarArg, MachineFunction &MF,
0232 SmallVectorImpl<CCValAssign> &Locs, LLVMContext &Context,
0233 bool NegativeOffsets = false);
0234
0235 void addLoc(const CCValAssign &V) {
0236 Locs.push_back(V);
0237 }
0238
0239 LLVMContext &getContext() const { return Context; }
0240 MachineFunction &getMachineFunction() const { return MF; }
0241 CallingConv::ID getCallingConv() const { return CallingConv; }
0242 bool isVarArg() const { return IsVarArg; }
0243
0244
0245 uint64_t getStackSize() const { return StackSize; }
0246
0247
0248
0249
0250 uint64_t getAlignedCallFrameSize() const {
0251 return alignTo(StackSize, MaxStackArgAlign);
0252 }
0253
0254
0255
0256 bool isAllocated(MCRegister Reg) const {
0257 return UsedRegs[Reg.id() / 32] & (1 << (Reg.id() & 31));
0258 }
0259
0260
0261
0262 void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
0263 CCAssignFn Fn);
0264
0265
0266 void AnalyzeArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
0267 CCAssignFn Fn) {
0268 AnalyzeFormalArguments(Ins, Fn);
0269 }
0270
0271
0272
0273 void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
0274 CCAssignFn Fn);
0275
0276
0277
0278
0279 bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
0280 CCAssignFn Fn);
0281
0282
0283
0284 void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
0285 CCAssignFn Fn);
0286
0287
0288
0289 void AnalyzeCallOperands(SmallVectorImpl<MVT> &ArgVTs,
0290 SmallVectorImpl<ISD::ArgFlagsTy> &Flags,
0291 CCAssignFn Fn);
0292
0293
0294 void AnalyzeArguments(const SmallVectorImpl<ISD::OutputArg> &Outs,
0295 CCAssignFn Fn) {
0296 AnalyzeCallOperands(Outs, Fn);
0297 }
0298
0299
0300
0301 void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
0302 CCAssignFn Fn);
0303
0304
0305
0306
0307 bool IsShadowAllocatedReg(MCRegister Reg) const;
0308
0309
0310
0311 void AnalyzeCallResult(MVT VT, CCAssignFn Fn);
0312
0313
0314
0315 unsigned getFirstUnallocated(ArrayRef<MCPhysReg> Regs) const {
0316 for (unsigned i = 0; i < Regs.size(); ++i)
0317 if (!isAllocated(Regs[i]))
0318 return i;
0319 return Regs.size();
0320 }
0321
0322 void DeallocateReg(MCPhysReg Reg) {
0323 assert(isAllocated(Reg) && "Trying to deallocate an unallocated register");
0324 MarkUnallocated(Reg);
0325 }
0326
0327
0328
0329
0330 MCRegister AllocateReg(MCPhysReg Reg) {
0331 if (isAllocated(Reg))
0332 return MCRegister();
0333 MarkAllocated(Reg);
0334 return Reg;
0335 }
0336
0337
0338 MCRegister AllocateReg(MCPhysReg Reg, MCPhysReg ShadowReg) {
0339 if (isAllocated(Reg))
0340 return MCRegister();
0341 MarkAllocated(Reg);
0342 MarkAllocated(ShadowReg);
0343 return Reg;
0344 }
0345
0346
0347
0348
0349 MCRegister AllocateReg(ArrayRef<MCPhysReg> Regs) {
0350 unsigned FirstUnalloc = getFirstUnallocated(Regs);
0351 if (FirstUnalloc == Regs.size())
0352 return MCRegister();
0353
0354
0355 MCPhysReg Reg = Regs[FirstUnalloc];
0356 MarkAllocated(Reg);
0357 return Reg;
0358 }
0359
0360
0361
0362
0363 ArrayRef<MCPhysReg> AllocateRegBlock(ArrayRef<MCPhysReg> Regs,
0364 unsigned RegsRequired) {
0365 if (RegsRequired > Regs.size())
0366 return {};
0367
0368 for (unsigned StartIdx = 0; StartIdx <= Regs.size() - RegsRequired;
0369 ++StartIdx) {
0370 bool BlockAvailable = true;
0371
0372 for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) {
0373 if (isAllocated(Regs[StartIdx + BlockIdx])) {
0374 BlockAvailable = false;
0375 break;
0376 }
0377 }
0378 if (BlockAvailable) {
0379
0380 for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) {
0381 MarkAllocated(Regs[StartIdx + BlockIdx]);
0382 }
0383 return Regs.slice(StartIdx, RegsRequired);
0384 }
0385 }
0386
0387 return {};
0388 }
0389
0390
0391 MCRegister AllocateReg(ArrayRef<MCPhysReg> Regs, const MCPhysReg *ShadowRegs) {
0392 unsigned FirstUnalloc = getFirstUnallocated(Regs);
0393 if (FirstUnalloc == Regs.size())
0394 return MCRegister();
0395
0396
0397 MCRegister Reg = Regs[FirstUnalloc], ShadowReg = ShadowRegs[FirstUnalloc];
0398 MarkAllocated(Reg);
0399 MarkAllocated(ShadowReg);
0400 return Reg;
0401 }
0402
0403
0404
0405 int64_t AllocateStack(unsigned Size, Align Alignment) {
0406 int64_t Offset;
0407 if (NegativeOffsets) {
0408 StackSize = alignTo(StackSize + Size, Alignment);
0409 Offset = -StackSize;
0410 } else {
0411 Offset = alignTo(StackSize, Alignment);
0412 StackSize = Offset + Size;
0413 }
0414 MaxStackArgAlign = std::max(Alignment, MaxStackArgAlign);
0415 ensureMaxAlignment(Alignment);
0416 return Offset;
0417 }
0418
0419 void ensureMaxAlignment(Align Alignment);
0420
0421
0422
0423 int64_t AllocateStack(unsigned Size, Align Alignment,
0424 ArrayRef<MCPhysReg> ShadowRegs) {
0425 for (MCPhysReg Reg : ShadowRegs)
0426 MarkAllocated(Reg);
0427 return AllocateStack(Size, Alignment);
0428 }
0429
0430
0431
0432
0433 void HandleByVal(unsigned ValNo, MVT ValVT, MVT LocVT,
0434 CCValAssign::LocInfo LocInfo, int MinSize, Align MinAlign,
0435 ISD::ArgFlagsTy ArgFlags);
0436
0437
0438
0439 unsigned getInRegsParamsCount() const { return ByValRegs.size(); }
0440
0441
0442 unsigned getInRegsParamsProcessed() const { return InRegsParamsProcessed; }
0443
0444
0445
0446 void getInRegsParamInfo(unsigned InRegsParamRecordIndex,
0447 unsigned& BeginReg, unsigned& EndReg) const {
0448 assert(InRegsParamRecordIndex < ByValRegs.size() &&
0449 "Wrong ByVal parameter index");
0450
0451 const ByValInfo& info = ByValRegs[InRegsParamRecordIndex];
0452 BeginReg = info.Begin;
0453 EndReg = info.End;
0454 }
0455
0456
0457 void addInRegsParamInfo(unsigned RegBegin, unsigned RegEnd) {
0458 ByValRegs.push_back(ByValInfo(RegBegin, RegEnd));
0459 }
0460
0461
0462
0463
0464 bool nextInRegsParam() {
0465 unsigned e = ByValRegs.size();
0466 if (InRegsParamsProcessed < e)
0467 ++InRegsParamsProcessed;
0468 return InRegsParamsProcessed < e;
0469 }
0470
0471
0472 void clearByValRegsInfo() {
0473 InRegsParamsProcessed = 0;
0474 ByValRegs.clear();
0475 }
0476
0477
0478 void rewindByValRegsInfo() {
0479 InRegsParamsProcessed = 0;
0480 }
0481
0482
0483 SmallVectorImpl<CCValAssign> &getPendingLocs() {
0484 return PendingLocs;
0485 }
0486
0487
0488 SmallVectorImpl<ISD::ArgFlagsTy> &getPendingArgFlags() {
0489 return PendingArgFlags;
0490 }
0491
0492
0493
0494
0495
0496 void getRemainingRegParmsForType(SmallVectorImpl<MCPhysReg> &Regs, MVT VT,
0497 CCAssignFn Fn);
0498
0499
0500
0501 void analyzeMustTailForwardedRegisters(
0502 SmallVectorImpl<ForwardedRegister> &Forwards, ArrayRef<MVT> RegParmTypes,
0503 CCAssignFn Fn);
0504
0505
0506
0507 static bool resultsCompatible(CallingConv::ID CalleeCC,
0508 CallingConv::ID CallerCC, MachineFunction &MF,
0509 LLVMContext &C,
0510 const SmallVectorImpl<ISD::InputArg> &Ins,
0511 CCAssignFn CalleeFn, CCAssignFn CallerFn);
0512
0513
0514
0515
0516 template <class T>
0517 void AnalyzeArgumentsSecondPass(const SmallVectorImpl<T> &Args,
0518 CCAssignFn Fn) {
0519 unsigned NumFirstPassLocs = Locs.size();
0520
0521
0522
0523 SmallVector<T, 16> SecPassArg;
0524
0525 for (auto Arg : Args) {
0526 Arg.Flags.setSecArgPass();
0527 SecPassArg.push_back(Arg);
0528 }
0529
0530
0531 AnalyzeArguments(SecPassArg, Fn);
0532
0533
0534 SmallVector<CCValAssign, 16> TmpArgLocs;
0535 TmpArgLocs.swap(Locs);
0536 auto B = TmpArgLocs.begin(), E = TmpArgLocs.end();
0537 std::merge(B, B + NumFirstPassLocs, B + NumFirstPassLocs, E,
0538 std::back_inserter(Locs),
0539 [](const CCValAssign &A, const CCValAssign &B) -> bool {
0540 return A.getValNo() < B.getValNo();
0541 });
0542 }
0543
0544 private:
0545
0546 void MarkAllocated(MCPhysReg Reg);
0547
0548 void MarkUnallocated(MCPhysReg Reg);
0549 };
0550
0551 }
0552
0553 #endif