Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:36

0001 //===- StackMaps.h - StackMaps ----------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
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 /// MI-level stackmap operands.
0032 ///
0033 /// MI stackmap operations take the form:
0034 /// <id>, <numBytes>, live args...
0035 class StackMapOpers {
0036 public:
0037   /// Enumerate the meta operands.
0038   enum { IDPos, NBytesPos };
0039 
0040 private:
0041   const MachineInstr* MI;
0042 
0043 public:
0044   explicit StackMapOpers(const MachineInstr *MI);
0045 
0046   /// Return the ID for the given stackmap
0047   uint64_t getID() const { return MI->getOperand(IDPos).getImm(); }
0048 
0049   /// Return the number of patchable bytes the given stackmap should emit.
0050   uint32_t getNumPatchBytes() const {
0051     return MI->getOperand(NBytesPos).getImm();
0052   }
0053 
0054   /// Get the operand index of the variable list of non-argument operands.
0055   /// These hold the "live state".
0056   unsigned getVarIdx() const {
0057     // Skip ID, nShadowBytes.
0058     return 2;
0059   }
0060 };
0061 
0062 /// MI-level patchpoint operands.
0063 ///
0064 /// MI patchpoint operations take the form:
0065 /// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ...
0066 ///
0067 /// IR patchpoint intrinsics do not have the <cc> operand because calling
0068 /// convention is part of the subclass data.
0069 ///
0070 /// SD patchpoint nodes do not have a def operand because it is part of the
0071 /// SDValue.
0072 ///
0073 /// Patchpoints following the anyregcc convention are handled specially. For
0074 /// these, the stack map also records the location of the return value and
0075 /// arguments.
0076 class PatchPointOpers {
0077 public:
0078   /// Enumerate the meta operands.
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   /// Return the ID for the given patchpoint.
0101   uint64_t getID() const { return getMetaOper(IDPos).getImm(); }
0102 
0103   /// Return the number of patchable bytes the given patchpoint should emit.
0104   uint32_t getNumPatchBytes() const {
0105     return getMetaOper(NBytesPos).getImm();
0106   }
0107 
0108   /// Returns the target of the underlying call.
0109   const MachineOperand &getCallTarget() const {
0110     return getMetaOper(TargetPos);
0111   }
0112 
0113   /// Returns the calling convention
0114   CallingConv::ID getCallingConv() const {
0115     return getMetaOper(CCPos).getImm();
0116   }
0117 
0118   unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; }
0119 
0120   /// Return the number of call arguments
0121   uint32_t getNumCallArgs() const {
0122     return MI->getOperand(getMetaIdx(NArgPos)).getImm();
0123   }
0124 
0125   /// Get the operand index of the variable list of non-argument operands.
0126   /// These hold the "live state".
0127   unsigned getVarIdx() const {
0128     return getMetaIdx() + MetaEnd + getNumCallArgs();
0129   }
0130 
0131   /// Get the index at which stack map locations will be recorded.
0132   /// Arguments are not recorded unless the anyregcc convention is used.
0133   unsigned getStackMapStartIdx() const {
0134     if (isAnyReg())
0135       return getArgIdx();
0136     return getVarIdx();
0137   }
0138 
0139   /// Get the next scratch register operand index.
0140   unsigned getNextScratchIdx(unsigned StartIdx = 0) const;
0141 };
0142 
0143 /// MI-level Statepoint operands
0144 ///
0145 /// Statepoint operands take the form:
0146 ///   <id>, <num patch bytes >, <num call arguments>, <call target>,
0147 ///   [call arguments...],
0148 ///   <StackMaps::ConstantOp>, <calling convention>,
0149 ///   <StackMaps::ConstantOp>, <statepoint flags>,
0150 ///   <StackMaps::ConstantOp>, <num deopt args>, [deopt args...],
0151 ///   <StackMaps::ConstantOp>, <num gc pointer args>, [gc pointer args...],
0152 ///   <StackMaps::ConstantOp>, <num gc allocas>, [gc allocas args...],
0153 ///   <StackMaps::ConstantOp>, <num  entries in gc map>, [base/derived pairs]
0154 ///   base/derived pairs in gc map are logical indices into <gc pointer args>
0155 ///   section.
0156 ///   All gc pointers assigned to VRegs produce new value (in form of MI Def
0157 ///   operand) and are tied to it.
0158 class StatepointOpers {
0159   // TODO:: we should change the STATEPOINT representation so that CC and
0160   // Flags should be part of meta operands, with args and deopt operands, and
0161   // gc operands all prefixed by their length and a type code. This would be
0162   // much more consistent.
0163 
0164   // These values are absolute offsets into the operands of the statepoint
0165   // instruction.
0166   enum { IDPos, NBytesPos, NCallArgsPos, CallTargetPos, MetaEnd };
0167 
0168   // These values are relative offsets from the start of the statepoint meta
0169   // arguments (i.e. the end of the call arguments).
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   /// Get index of statepoint ID operand.
0178   unsigned getIDPos() const { return NumDefs + IDPos; }
0179 
0180   /// Get index of Num Patch Bytes operand.
0181   unsigned getNBytesPos() const { return NumDefs + NBytesPos; }
0182 
0183   /// Get index of Num Call Arguments operand.
0184   unsigned getNCallArgsPos() const { return NumDefs + NCallArgsPos; }
0185 
0186   /// Get starting index of non call related arguments
0187   /// (calling convention, statepoint flags, vm state and gc state).
0188   unsigned getVarIdx() const {
0189     return MI->getOperand(NumDefs + NCallArgsPos).getImm() + MetaEnd + NumDefs;
0190   }
0191 
0192   /// Get index of Calling Convention operand.
0193   unsigned getCCIdx() const { return getVarIdx() + CCOffset; }
0194 
0195   /// Get index of Flags operand.
0196   unsigned getFlagsIdx() const { return getVarIdx() + FlagsOffset; }
0197 
0198   /// Get index of Number Deopt Arguments operand.
0199   unsigned getNumDeoptArgsIdx() const {
0200     return getVarIdx() + NumDeoptOperandsOffset;
0201   }
0202 
0203   /// Return the ID for the given statepoint.
0204   uint64_t getID() const { return MI->getOperand(NumDefs + IDPos).getImm(); }
0205 
0206   /// Return the number of patchable bytes the given statepoint should emit.
0207   uint32_t getNumPatchBytes() const {
0208     return MI->getOperand(NumDefs + NBytesPos).getImm();
0209   }
0210 
0211   /// Return the target of the underlying call.
0212   const MachineOperand &getCallTarget() const {
0213     return MI->getOperand(NumDefs + CallTargetPos);
0214   }
0215 
0216   /// Return the calling convention.
0217   CallingConv::ID getCallingConv() const {
0218     return MI->getOperand(getCCIdx()).getImm();
0219   }
0220 
0221   /// Return the statepoint flags.
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   /// Get index of number of gc map entries.
0229   unsigned getNumGcMapEntriesIdx();
0230 
0231   /// Get index of number of gc allocas.
0232   unsigned getNumAllocaIdx();
0233 
0234   /// Get index of number of GC pointers.
0235   unsigned getNumGCPtrIdx();
0236 
0237   /// Get index of first GC pointer operand of -1 if there are none.
0238   int getFirstGCPtrIdx();
0239 
0240   /// Get vector of base/derived pairs from statepoint.
0241   /// Elements are indices into GC Pointer operand list (logical).
0242   /// Returns number of elements in GCMap.
0243   unsigned
0244   getGCPointerMap(SmallVectorImpl<std::pair<unsigned, unsigned>> &GCMap);
0245 
0246   /// Return true if Reg is used only in operands which can be folded to
0247   /// stack usage.
0248   bool isFoldableReg(Register Reg) const;
0249 
0250   /// Return true if Reg is used only in operands of MI which can be folded to
0251   /// stack usage and MI is a statepoint instruction.
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   // OpTypes are used to encode information about the following logical
0291   // operand (which may consist of several MachineOperands) for the
0292   // OpParser.
0293   using OpType = enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp };
0294 
0295   StackMaps(AsmPrinter &AP);
0296 
0297   /// Get index of next meta operand.
0298   /// Similar to parseOperand, but does not actually parses operand meaning.
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   /// Generate a stackmap record for a stackmap instruction.
0336   ///
0337   /// MI must be a raw STACKMAP, not a PATCHPOINT.
0338   void recordStackMap(const MCSymbol &L,
0339                       const MachineInstr &MI);
0340 
0341   /// Generate a stackmap record for a patchpoint instruction.
0342   void recordPatchPoint(const MCSymbol &L,
0343                         const MachineInstr &MI);
0344 
0345   /// Generate a stackmap record for a statepoint instruction.
0346   void recordStatepoint(const MCSymbol &L,
0347                         const MachineInstr &MI);
0348 
0349   /// If there is any stack map data, create a stack map section and serialize
0350   /// the map info into it. This clears the stack map data structures
0351   /// afterwards.
0352   void serializeToStackMapSection();
0353 
0354   /// Get call site info.
0355   CallsiteInfoList &getCSInfos() { return CSInfos; }
0356 
0357   /// Get function info.
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   /// Specialized parser of statepoint operands.
0374   /// They do not directly correspond to StackMap record entries.
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   /// Create a live-out register record for the given register @p Reg.
0381   LiveOutReg createLiveOutReg(unsigned Reg,
0382                               const TargetRegisterInfo *TRI) const;
0383 
0384   /// Parse the register live-out mask and return a vector of live-out
0385   /// registers that need to be recorded in the stackmap.
0386   LiveOutVec parseRegisterLiveOutMask(const uint32_t *Mask) const;
0387 
0388   /// Record the locations of the operands of the provided instruction in a
0389   /// record keyed by the provided label.  For instructions w/AnyReg calling
0390   /// convention the return register is also recorded if requested.  For
0391   /// STACKMAP, and PATCHPOINT the label is expected to immediately *preceed*
0392   /// lowering of the MI to MCInsts.  For STATEPOINT, it expected to
0393   /// immediately *follow*.  It's not clear this difference was intentional,
0394   /// but it exists today.  
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   /// Emit the stackmap header.
0402   void emitStackmapHeader(MCStreamer &OS);
0403 
0404   /// Emit the function frame record for each function.
0405   void emitFunctionFrameRecords(MCStreamer &OS);
0406 
0407   /// Emit the constant pool.
0408   void emitConstantPoolEntries(MCStreamer &OS);
0409 
0410   /// Emit the callsite info for each stackmap/patchpoint intrinsic call.
0411   void emitCallsiteEntries(MCStreamer &OS);
0412 
0413   void print(raw_ostream &OS);
0414   void debug() { print(dbgs()); }
0415 };
0416 
0417 } // end namespace llvm
0418 
0419 #endif // LLVM_CODEGEN_STACKMAPS_H