Home | History | Annotate | Download | only in CodeGen
      1 //===- StackMaps.h - StackMaps ----------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef LLVM_CODEGEN_STACKMAPS_H
     11 #define LLVM_CODEGEN_STACKMAPS_H
     12 
     13 #include "llvm/ADT/MapVector.h"
     14 #include "llvm/ADT/SmallVector.h"
     15 #include "llvm/CodeGen/MachineInstr.h"
     16 #include "llvm/IR/CallingConv.h"
     17 #include "llvm/Support/Debug.h"
     18 #include <algorithm>
     19 #include <cassert>
     20 #include <cstdint>
     21 #include <vector>
     22 
     23 namespace llvm {
     24 
     25 class AsmPrinter;
     26 class MCExpr;
     27 class MCStreamer;
     28 class MCSymbol;
     29 class raw_ostream;
     30 class TargetRegisterInfo;
     31 
     32 /// \brief MI-level stackmap operands.
     33 ///
     34 /// MI stackmap operations take the form:
     35 /// <id>, <numBytes>, live args...
     36 class StackMapOpers {
     37 public:
     38   /// Enumerate the meta operands.
     39   enum { IDPos, NBytesPos };
     40 
     41 private:
     42   const MachineInstr* MI;
     43 
     44 public:
     45   explicit StackMapOpers(const MachineInstr *MI);
     46 
     47   /// Return the ID for the given stackmap
     48   uint64_t getID() const { return MI->getOperand(IDPos).getImm(); }
     49 
     50   /// Return the number of patchable bytes the given stackmap should emit.
     51   uint32_t getNumPatchBytes() const {
     52     return MI->getOperand(NBytesPos).getImm();
     53   }
     54 
     55   /// Get the operand index of the variable list of non-argument operands.
     56   /// These hold the "live state".
     57   unsigned getVarIdx() const {
     58     // Skip ID, nShadowBytes.
     59     return 2;
     60   }
     61 };
     62 
     63 /// \brief MI-level patchpoint operands.
     64 ///
     65 /// MI patchpoint operations take the form:
     66 /// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ...
     67 ///
     68 /// IR patchpoint intrinsics do not have the <cc> operand because calling
     69 /// convention is part of the subclass data.
     70 ///
     71 /// SD patchpoint nodes do not have a def operand because it is part of the
     72 /// SDValue.
     73 ///
     74 /// Patchpoints following the anyregcc convention are handled specially. For
     75 /// these, the stack map also records the location of the return value and
     76 /// arguments.
     77 class PatchPointOpers {
     78 public:
     79   /// Enumerate the meta operands.
     80   enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd };
     81 
     82 private:
     83   const MachineInstr *MI;
     84   bool HasDef;
     85 
     86   unsigned getMetaIdx(unsigned Pos = 0) const {
     87     assert(Pos < MetaEnd && "Meta operand index out of range.");
     88     return (HasDef ? 1 : 0) + Pos;
     89   }
     90 
     91   const MachineOperand &getMetaOper(unsigned Pos) const {
     92     return MI->getOperand(getMetaIdx(Pos));
     93   }
     94 
     95 public:
     96   explicit PatchPointOpers(const MachineInstr *MI);
     97 
     98   bool isAnyReg() const { return (getCallingConv() == CallingConv::AnyReg); }
     99   bool hasDef() const { return HasDef; }
    100 
    101   /// Return the ID for the given patchpoint.
    102   uint64_t getID() const { return getMetaOper(IDPos).getImm(); }
    103 
    104   /// Return the number of patchable bytes the given patchpoint should emit.
    105   uint32_t getNumPatchBytes() const {
    106     return getMetaOper(NBytesPos).getImm();
    107   }
    108 
    109   /// Returns the target of the underlying call.
    110   const MachineOperand &getCallTarget() const {
    111     return getMetaOper(TargetPos);
    112   }
    113 
    114   /// Returns the calling convention
    115   CallingConv::ID getCallingConv() const {
    116     return getMetaOper(CCPos).getImm();
    117   }
    118 
    119   unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; }
    120 
    121   /// Return the number of call arguments
    122   uint32_t getNumCallArgs() const {
    123     return MI->getOperand(getMetaIdx(NArgPos)).getImm();
    124   }
    125 
    126   /// Get the operand index of the variable list of non-argument operands.
    127   /// These hold the "live state".
    128   unsigned getVarIdx() const {
    129     return getMetaIdx() + MetaEnd + getNumCallArgs();
    130   }
    131 
    132   /// Get the index at which stack map locations will be recorded.
    133   /// Arguments are not recorded unless the anyregcc convention is used.
    134   unsigned getStackMapStartIdx() const {
    135     if (isAnyReg())
    136       return getArgIdx();
    137     return getVarIdx();
    138   }
    139 
    140   /// \brief Get the next scratch register operand index.
    141   unsigned getNextScratchIdx(unsigned StartIdx = 0) const;
    142 };
    143 
    144 /// MI-level Statepoint operands
    145 ///
    146 /// Statepoint operands take the form:
    147 ///   <id>, <num patch bytes >, <num call arguments>, <call target>,
    148 ///   [call arguments...],
    149 ///   <StackMaps::ConstantOp>, <calling convention>,
    150 ///   <StackMaps::ConstantOp>, <statepoint flags>,
    151 ///   <StackMaps::ConstantOp>, <num deopt args>, [deopt args...],
    152 ///   <gc base/derived pairs...> <gc allocas...>
    153 /// Note that the last two sets of arguments are not currently length
    154 ///   prefixed.
    155 class StatepointOpers {
    156   // TODO:: we should change the STATEPOINT representation so that CC and
    157   // Flags should be part of meta operands, with args and deopt operands, and
    158   // gc operands all prefixed by their length and a type code. This would be
    159   // much more consistent.
    160 public:
    161   // These values are aboolute offsets into the operands of the statepoint
    162   // instruction.
    163   enum { IDPos, NBytesPos, NCallArgsPos, CallTargetPos, MetaEnd };
    164 
    165   // These values are relative offests from the start of the statepoint meta
    166   // arguments (i.e. the end of the call arguments).
    167   enum { CCOffset = 1, FlagsOffset = 3, NumDeoptOperandsOffset = 5 };
    168 
    169   explicit StatepointOpers(const MachineInstr *MI) : MI(MI) {}
    170 
    171   /// Get starting index of non call related arguments
    172   /// (calling convention, statepoint flags, vm state and gc state).
    173   unsigned getVarIdx() const {
    174     return MI->getOperand(NCallArgsPos).getImm() + MetaEnd;
    175   }
    176 
    177   /// Return the ID for the given statepoint.
    178   uint64_t getID() const { return MI->getOperand(IDPos).getImm(); }
    179 
    180   /// Return the number of patchable bytes the given statepoint should emit.
    181   uint32_t getNumPatchBytes() const {
    182     return MI->getOperand(NBytesPos).getImm();
    183   }
    184 
    185   /// Returns the target of the underlying call.
    186   const MachineOperand &getCallTarget() const {
    187     return MI->getOperand(CallTargetPos);
    188   }
    189 
    190 private:
    191   const MachineInstr *MI;
    192 };
    193 
    194 class StackMaps {
    195 public:
    196   struct Location {
    197     enum LocationType {
    198       Unprocessed,
    199       Register,
    200       Direct,
    201       Indirect,
    202       Constant,
    203       ConstantIndex
    204     };
    205     LocationType Type = Unprocessed;
    206     unsigned Size = 0;
    207     unsigned Reg = 0;
    208     int64_t Offset = 0;
    209 
    210     Location() = default;
    211     Location(LocationType Type, unsigned Size, unsigned Reg, int64_t Offset)
    212         : Type(Type), Size(Size), Reg(Reg), Offset(Offset) {}
    213   };
    214 
    215   struct LiveOutReg {
    216     unsigned short Reg = 0;
    217     unsigned short DwarfRegNum = 0;
    218     unsigned short Size = 0;
    219 
    220     LiveOutReg() = default;
    221     LiveOutReg(unsigned short Reg, unsigned short DwarfRegNum,
    222                unsigned short Size)
    223         : Reg(Reg), DwarfRegNum(DwarfRegNum), Size(Size) {}
    224   };
    225 
    226   // OpTypes are used to encode information about the following logical
    227   // operand (which may consist of several MachineOperands) for the
    228   // OpParser.
    229   using OpType = enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp };
    230 
    231   StackMaps(AsmPrinter &AP);
    232 
    233   void reset() {
    234     CSInfos.clear();
    235     ConstPool.clear();
    236     FnInfos.clear();
    237   }
    238 
    239   /// \brief Generate a stackmap record for a stackmap instruction.
    240   ///
    241   /// MI must be a raw STACKMAP, not a PATCHPOINT.
    242   void recordStackMap(const MachineInstr &MI);
    243 
    244   /// \brief Generate a stackmap record for a patchpoint instruction.
    245   void recordPatchPoint(const MachineInstr &MI);
    246 
    247   /// \brief Generate a stackmap record for a statepoint instruction.
    248   void recordStatepoint(const MachineInstr &MI);
    249 
    250   /// If there is any stack map data, create a stack map section and serialize
    251   /// the map info into it. This clears the stack map data structures
    252   /// afterwards.
    253   void serializeToStackMapSection();
    254 
    255 private:
    256   static const char *WSMP;
    257 
    258   using LocationVec = SmallVector<Location, 8>;
    259   using LiveOutVec = SmallVector<LiveOutReg, 8>;
    260   using ConstantPool = MapVector<uint64_t, uint64_t>;
    261 
    262   struct FunctionInfo {
    263     uint64_t StackSize = 0;
    264     uint64_t RecordCount = 1;
    265 
    266     FunctionInfo() = default;
    267     explicit FunctionInfo(uint64_t StackSize) : StackSize(StackSize) {}
    268   };
    269 
    270   struct CallsiteInfo {
    271     const MCExpr *CSOffsetExpr = nullptr;
    272     uint64_t ID = 0;
    273     LocationVec Locations;
    274     LiveOutVec LiveOuts;
    275 
    276     CallsiteInfo() = default;
    277     CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID,
    278                  LocationVec &&Locations, LiveOutVec &&LiveOuts)
    279         : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)),
    280           LiveOuts(std::move(LiveOuts)) {}
    281   };
    282 
    283   using FnInfoMap = MapVector<const MCSymbol *, FunctionInfo>;
    284   using CallsiteInfoList = std::vector<CallsiteInfo>;
    285 
    286   AsmPrinter &AP;
    287   CallsiteInfoList CSInfos;
    288   ConstantPool ConstPool;
    289   FnInfoMap FnInfos;
    290 
    291   MachineInstr::const_mop_iterator
    292   parseOperand(MachineInstr::const_mop_iterator MOI,
    293                MachineInstr::const_mop_iterator MOE, LocationVec &Locs,
    294                LiveOutVec &LiveOuts) const;
    295 
    296   /// \brief Create a live-out register record for the given register @p Reg.
    297   LiveOutReg createLiveOutReg(unsigned Reg,
    298                               const TargetRegisterInfo *TRI) const;
    299 
    300   /// \brief Parse the register live-out mask and return a vector of live-out
    301   /// registers that need to be recorded in the stackmap.
    302   LiveOutVec parseRegisterLiveOutMask(const uint32_t *Mask) const;
    303 
    304   /// This should be called by the MC lowering code _immediately_ before
    305   /// lowering the MI to an MCInst. It records where the operands for the
    306   /// instruction are stored, and outputs a label to record the offset of
    307   /// the call from the start of the text section. In special cases (e.g. AnyReg
    308   /// calling convention) the return register is also recorded if requested.
    309   void recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
    310                            MachineInstr::const_mop_iterator MOI,
    311                            MachineInstr::const_mop_iterator MOE,
    312                            bool recordResult = false);
    313 
    314   /// \brief Emit the stackmap header.
    315   void emitStackmapHeader(MCStreamer &OS);
    316 
    317   /// \brief Emit the function frame record for each function.
    318   void emitFunctionFrameRecords(MCStreamer &OS);
    319 
    320   /// \brief Emit the constant pool.
    321   void emitConstantPoolEntries(MCStreamer &OS);
    322 
    323   /// \brief Emit the callsite info for each stackmap/patchpoint intrinsic call.
    324   void emitCallsiteEntries(MCStreamer &OS);
    325 
    326   void print(raw_ostream &OS);
    327   void debug() { print(dbgs()); }
    328 };
    329 
    330 } // end namespace llvm
    331 
    332 #endif // LLVM_CODEGEN_STACKMAPS_H
    333