File indexing completed on 2026-05-10 08:43:36
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_CODEGEN_STACKMAPS_H
0010 #define LLVM_CODEGEN_STACKMAPS_H
0011
0012 #include "llvm/ADT/MapVector.h"
0013 #include "llvm/ADT/SmallVector.h"
0014 #include "llvm/CodeGen/MachineInstr.h"
0015 #include "llvm/IR/CallingConv.h"
0016 #include "llvm/Support/Debug.h"
0017 #include <algorithm>
0018 #include <cassert>
0019 #include <cstdint>
0020 #include <vector>
0021
0022 namespace llvm {
0023
0024 class AsmPrinter;
0025 class MCSymbol;
0026 class MCExpr;
0027 class MCStreamer;
0028 class raw_ostream;
0029 class TargetRegisterInfo;
0030
0031
0032
0033
0034
0035 class StackMapOpers {
0036 public:
0037
0038 enum { IDPos, NBytesPos };
0039
0040 private:
0041 const MachineInstr* MI;
0042
0043 public:
0044 explicit StackMapOpers(const MachineInstr *MI);
0045
0046
0047 uint64_t getID() const { return MI->getOperand(IDPos).getImm(); }
0048
0049
0050 uint32_t getNumPatchBytes() const {
0051 return MI->getOperand(NBytesPos).getImm();
0052 }
0053
0054
0055
0056 unsigned getVarIdx() const {
0057
0058 return 2;
0059 }
0060 };
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 class PatchPointOpers {
0077 public:
0078
0079 enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd };
0080
0081 private:
0082 const MachineInstr *MI;
0083 bool HasDef;
0084
0085 unsigned getMetaIdx(unsigned Pos = 0) const {
0086 assert(Pos < MetaEnd && "Meta operand index out of range.");
0087 return (HasDef ? 1 : 0) + Pos;
0088 }
0089
0090 const MachineOperand &getMetaOper(unsigned Pos) const {
0091 return MI->getOperand(getMetaIdx(Pos));
0092 }
0093
0094 public:
0095 explicit PatchPointOpers(const MachineInstr *MI);
0096
0097 bool isAnyReg() const { return (getCallingConv() == CallingConv::AnyReg); }
0098 bool hasDef() const { return HasDef; }
0099
0100
0101 uint64_t getID() const { return getMetaOper(IDPos).getImm(); }
0102
0103
0104 uint32_t getNumPatchBytes() const {
0105 return getMetaOper(NBytesPos).getImm();
0106 }
0107
0108
0109 const MachineOperand &getCallTarget() const {
0110 return getMetaOper(TargetPos);
0111 }
0112
0113
0114 CallingConv::ID getCallingConv() const {
0115 return getMetaOper(CCPos).getImm();
0116 }
0117
0118 unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; }
0119
0120
0121 uint32_t getNumCallArgs() const {
0122 return MI->getOperand(getMetaIdx(NArgPos)).getImm();
0123 }
0124
0125
0126
0127 unsigned getVarIdx() const {
0128 return getMetaIdx() + MetaEnd + getNumCallArgs();
0129 }
0130
0131
0132
0133 unsigned getStackMapStartIdx() const {
0134 if (isAnyReg())
0135 return getArgIdx();
0136 return getVarIdx();
0137 }
0138
0139
0140 unsigned getNextScratchIdx(unsigned StartIdx = 0) const;
0141 };
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 class StatepointOpers {
0159
0160
0161
0162
0163
0164
0165
0166 enum { IDPos, NBytesPos, NCallArgsPos, CallTargetPos, MetaEnd };
0167
0168
0169
0170 enum { CCOffset = 1, FlagsOffset = 3, NumDeoptOperandsOffset = 5 };
0171
0172 public:
0173 explicit StatepointOpers(const MachineInstr *MI) : MI(MI) {
0174 NumDefs = MI->getNumDefs();
0175 }
0176
0177
0178 unsigned getIDPos() const { return NumDefs + IDPos; }
0179
0180
0181 unsigned getNBytesPos() const { return NumDefs + NBytesPos; }
0182
0183
0184 unsigned getNCallArgsPos() const { return NumDefs + NCallArgsPos; }
0185
0186
0187
0188 unsigned getVarIdx() const {
0189 return MI->getOperand(NumDefs + NCallArgsPos).getImm() + MetaEnd + NumDefs;
0190 }
0191
0192
0193 unsigned getCCIdx() const { return getVarIdx() + CCOffset; }
0194
0195
0196 unsigned getFlagsIdx() const { return getVarIdx() + FlagsOffset; }
0197
0198
0199 unsigned getNumDeoptArgsIdx() const {
0200 return getVarIdx() + NumDeoptOperandsOffset;
0201 }
0202
0203
0204 uint64_t getID() const { return MI->getOperand(NumDefs + IDPos).getImm(); }
0205
0206
0207 uint32_t getNumPatchBytes() const {
0208 return MI->getOperand(NumDefs + NBytesPos).getImm();
0209 }
0210
0211
0212 const MachineOperand &getCallTarget() const {
0213 return MI->getOperand(NumDefs + CallTargetPos);
0214 }
0215
0216
0217 CallingConv::ID getCallingConv() const {
0218 return MI->getOperand(getCCIdx()).getImm();
0219 }
0220
0221
0222 uint64_t getFlags() const { return MI->getOperand(getFlagsIdx()).getImm(); }
0223
0224 uint64_t getNumDeoptArgs() const {
0225 return MI->getOperand(getNumDeoptArgsIdx()).getImm();
0226 }
0227
0228
0229 unsigned getNumGcMapEntriesIdx();
0230
0231
0232 unsigned getNumAllocaIdx();
0233
0234
0235 unsigned getNumGCPtrIdx();
0236
0237
0238 int getFirstGCPtrIdx();
0239
0240
0241
0242
0243 unsigned
0244 getGCPointerMap(SmallVectorImpl<std::pair<unsigned, unsigned>> &GCMap);
0245
0246
0247
0248 bool isFoldableReg(Register Reg) const;
0249
0250
0251
0252 static bool isFoldableReg(const MachineInstr *MI, Register Reg);
0253
0254 private:
0255 const MachineInstr *MI;
0256 unsigned NumDefs;
0257 };
0258
0259 class StackMaps {
0260 public:
0261 struct Location {
0262 enum LocationType : uint16_t {
0263 Unprocessed,
0264 Register,
0265 Direct,
0266 Indirect,
0267 Constant,
0268 ConstantIndex
0269 };
0270 LocationType Type = Unprocessed;
0271 uint16_t Size = 0;
0272 uint16_t Reg = 0;
0273 int32_t Offset = 0;
0274
0275 Location() = default;
0276 Location(LocationType Type, uint16_t Size, uint16_t Reg, int32_t Offset)
0277 : Type(Type), Size(Size), Reg(Reg), Offset(Offset) {}
0278 };
0279
0280 struct LiveOutReg {
0281 uint16_t Reg = 0;
0282 uint16_t DwarfRegNum = 0;
0283 uint16_t Size = 0;
0284
0285 LiveOutReg() = default;
0286 LiveOutReg(uint16_t Reg, uint16_t DwarfRegNum, uint16_t Size)
0287 : Reg(Reg), DwarfRegNum(DwarfRegNum), Size(Size) {}
0288 };
0289
0290
0291
0292
0293 using OpType = enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp };
0294
0295 StackMaps(AsmPrinter &AP);
0296
0297
0298
0299 static unsigned getNextMetaArgIdx(const MachineInstr *MI, unsigned CurIdx);
0300
0301 void reset() {
0302 CSInfos.clear();
0303 ConstPool.clear();
0304 FnInfos.clear();
0305 }
0306
0307 using LocationVec = SmallVector<Location, 8>;
0308 using LiveOutVec = SmallVector<LiveOutReg, 8>;
0309 using ConstantPool = MapVector<uint64_t, uint64_t>;
0310
0311 struct FunctionInfo {
0312 uint64_t StackSize = 0;
0313 uint64_t RecordCount = 1;
0314
0315 FunctionInfo() = default;
0316 explicit FunctionInfo(uint64_t StackSize) : StackSize(StackSize) {}
0317 };
0318
0319 struct CallsiteInfo {
0320 const MCExpr *CSOffsetExpr = nullptr;
0321 uint64_t ID = 0;
0322 LocationVec Locations;
0323 LiveOutVec LiveOuts;
0324
0325 CallsiteInfo() = default;
0326 CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID,
0327 LocationVec &&Locations, LiveOutVec &&LiveOuts)
0328 : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)),
0329 LiveOuts(std::move(LiveOuts)) {}
0330 };
0331
0332 using FnInfoMap = MapVector<const MCSymbol *, FunctionInfo>;
0333 using CallsiteInfoList = std::vector<CallsiteInfo>;
0334
0335
0336
0337
0338 void recordStackMap(const MCSymbol &L,
0339 const MachineInstr &MI);
0340
0341
0342 void recordPatchPoint(const MCSymbol &L,
0343 const MachineInstr &MI);
0344
0345
0346 void recordStatepoint(const MCSymbol &L,
0347 const MachineInstr &MI);
0348
0349
0350
0351
0352 void serializeToStackMapSection();
0353
0354
0355 CallsiteInfoList &getCSInfos() { return CSInfos; }
0356
0357
0358 FnInfoMap &getFnInfos() { return FnInfos; }
0359
0360 private:
0361 static const char *WSMP;
0362
0363 AsmPrinter &AP;
0364 CallsiteInfoList CSInfos;
0365 ConstantPool ConstPool;
0366 FnInfoMap FnInfos;
0367
0368 MachineInstr::const_mop_iterator
0369 parseOperand(MachineInstr::const_mop_iterator MOI,
0370 MachineInstr::const_mop_iterator MOE, LocationVec &Locs,
0371 LiveOutVec &LiveOuts);
0372
0373
0374
0375 void parseStatepointOpers(const MachineInstr &MI,
0376 MachineInstr::const_mop_iterator MOI,
0377 MachineInstr::const_mop_iterator MOE,
0378 LocationVec &Locations, LiveOutVec &LiveOuts);
0379
0380
0381 LiveOutReg createLiveOutReg(unsigned Reg,
0382 const TargetRegisterInfo *TRI) const;
0383
0384
0385
0386 LiveOutVec parseRegisterLiveOutMask(const uint32_t *Mask) const;
0387
0388
0389
0390
0391
0392
0393
0394
0395 void recordStackMapOpers(const MCSymbol &L,
0396 const MachineInstr &MI, uint64_t ID,
0397 MachineInstr::const_mop_iterator MOI,
0398 MachineInstr::const_mop_iterator MOE,
0399 bool recordResult = false);
0400
0401
0402 void emitStackmapHeader(MCStreamer &OS);
0403
0404
0405 void emitFunctionFrameRecords(MCStreamer &OS);
0406
0407
0408 void emitConstantPoolEntries(MCStreamer &OS);
0409
0410
0411 void emitCallsiteEntries(MCStreamer &OS);
0412
0413 void print(raw_ostream &OS);
0414 void debug() { print(dbgs()); }
0415 };
0416
0417 }
0418
0419 #endif