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/Support/Debug.h"
17#include <map>
18#include <vector>
19
20namespace llvm {
21
22class AsmPrinter;
23class MCExpr;
24class MCStreamer;
25
26/// \brief MI-level patchpoint operands.
27///
28/// MI patchpoint operations take the form:
29/// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ...
30///
31/// IR patchpoint intrinsics do not have the <cc> operand because calling
32/// convention is part of the subclass data.
33///
34/// SD patchpoint nodes do not have a def operand because it is part of the
35/// SDValue.
36///
37/// Patchpoints following the anyregcc convention are handled specially. For
38/// these, the stack map also records the location of the return value and
39/// arguments.
40class PatchPointOpers {
41public:
42  /// Enumerate the meta operands.
43  enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd };
44
45private:
46  const MachineInstr *MI;
47  bool HasDef;
48  bool IsAnyReg;
49
50public:
51  explicit PatchPointOpers(const MachineInstr *MI);
52
53  bool isAnyReg() const { return IsAnyReg; }
54  bool hasDef() const { return HasDef; }
55
56  unsigned getMetaIdx(unsigned Pos = 0) const {
57    assert(Pos < MetaEnd && "Meta operand index out of range.");
58    return (HasDef ? 1 : 0) + Pos;
59  }
60
61  const MachineOperand &getMetaOper(unsigned Pos) {
62    return MI->getOperand(getMetaIdx(Pos));
63  }
64
65  unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; }
66
67  /// Get the operand index of the variable list of non-argument operands.
68  /// These hold the "live state".
69  unsigned getVarIdx() const {
70    return getMetaIdx() + MetaEnd +
71           MI->getOperand(getMetaIdx(NArgPos)).getImm();
72  }
73
74  /// Get the index at which stack map locations will be recorded.
75  /// Arguments are not recorded unless the anyregcc convention is used.
76  unsigned getStackMapStartIdx() const {
77    if (IsAnyReg)
78      return getArgIdx();
79    return getVarIdx();
80  }
81
82  /// \brief Get the next scratch register operand index.
83  unsigned getNextScratchIdx(unsigned StartIdx = 0) const;
84};
85
86/// MI-level Statepoint operands
87///
88/// Statepoint operands take the form:
89///   <id>, <num patch bytes >, <num call arguments>, <call target>,
90///   [call arguments], <StackMaps::ConstantOp>, <calling convention>,
91///   <StackMaps::ConstantOp>, <statepoint flags>,
92///   <StackMaps::ConstantOp>, <num other args>, [other args],
93///   [gc values]
94class StatepointOpers {
95private:
96  // These values are aboolute offsets into the operands of the statepoint
97  // instruction.
98  enum { IDPos, NBytesPos, NCallArgsPos, CallTargetPos, MetaEnd };
99
100  // These values are relative offests from the start of the statepoint meta
101  // arguments (i.e. the end of the call arguments).
102  enum { CCOffset = 1, FlagsOffset = 3, NumVMSArgsOffset = 5 };
103
104public:
105  explicit StatepointOpers(const MachineInstr *MI) : MI(MI) {}
106
107  /// Get starting index of non call related arguments
108  /// (calling convention, statepoint flags, vm state and gc state).
109  unsigned getVarIdx() const {
110    return MI->getOperand(NCallArgsPos).getImm() + MetaEnd;
111  }
112
113  /// Return the ID for the given statepoint.
114  uint64_t getID() const { return MI->getOperand(IDPos).getImm(); }
115
116  /// Return the number of patchable bytes the given statepoint should emit.
117  uint32_t getNumPatchBytes() const {
118    return MI->getOperand(NBytesPos).getImm();
119  }
120
121  /// Returns the target of the underlying call.
122  const MachineOperand &getCallTarget() const {
123    return MI->getOperand(CallTargetPos);
124  }
125
126private:
127  const MachineInstr *MI;
128};
129
130class StackMaps {
131public:
132  struct Location {
133    enum LocationType {
134      Unprocessed,
135      Register,
136      Direct,
137      Indirect,
138      Constant,
139      ConstantIndex
140    };
141    LocationType Type;
142    unsigned Size;
143    unsigned Reg;
144    int64_t Offset;
145    Location() : Type(Unprocessed), Size(0), Reg(0), Offset(0) {}
146    Location(LocationType Type, unsigned Size, unsigned Reg, int64_t Offset)
147        : Type(Type), Size(Size), Reg(Reg), Offset(Offset) {}
148  };
149
150  struct LiveOutReg {
151    unsigned short Reg;
152    unsigned short DwarfRegNum;
153    unsigned short Size;
154
155    LiveOutReg() : Reg(0), DwarfRegNum(0), Size(0) {}
156    LiveOutReg(unsigned short Reg, unsigned short DwarfRegNum,
157               unsigned short Size)
158        : Reg(Reg), DwarfRegNum(DwarfRegNum), Size(Size) {}
159  };
160
161  // OpTypes are used to encode information about the following logical
162  // operand (which may consist of several MachineOperands) for the
163  // OpParser.
164  typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType;
165
166  StackMaps(AsmPrinter &AP);
167
168  void reset() {
169    CSInfos.clear();
170    ConstPool.clear();
171    FnStackSize.clear();
172  }
173
174  /// \brief Generate a stackmap record for a stackmap instruction.
175  ///
176  /// MI must be a raw STACKMAP, not a PATCHPOINT.
177  void recordStackMap(const MachineInstr &MI);
178
179  /// \brief Generate a stackmap record for a patchpoint instruction.
180  void recordPatchPoint(const MachineInstr &MI);
181
182  /// \brief Generate a stackmap record for a statepoint instruction.
183  void recordStatepoint(const MachineInstr &MI);
184
185  /// If there is any stack map data, create a stack map section and serialize
186  /// the map info into it. This clears the stack map data structures
187  /// afterwards.
188  void serializeToStackMapSection();
189
190private:
191  static const char *WSMP;
192  typedef SmallVector<Location, 8> LocationVec;
193  typedef SmallVector<LiveOutReg, 8> LiveOutVec;
194  typedef MapVector<uint64_t, uint64_t> ConstantPool;
195  typedef MapVector<const MCSymbol *, uint64_t> FnStackSizeMap;
196
197  struct CallsiteInfo {
198    const MCExpr *CSOffsetExpr;
199    uint64_t ID;
200    LocationVec Locations;
201    LiveOutVec LiveOuts;
202    CallsiteInfo() : CSOffsetExpr(nullptr), ID(0) {}
203    CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID,
204                 LocationVec &&Locations, LiveOutVec &&LiveOuts)
205        : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)),
206          LiveOuts(std::move(LiveOuts)) {}
207  };
208
209  typedef std::vector<CallsiteInfo> CallsiteInfoList;
210
211  AsmPrinter &AP;
212  CallsiteInfoList CSInfos;
213  ConstantPool ConstPool;
214  FnStackSizeMap FnStackSize;
215
216  MachineInstr::const_mop_iterator
217  parseOperand(MachineInstr::const_mop_iterator MOI,
218               MachineInstr::const_mop_iterator MOE, LocationVec &Locs,
219               LiveOutVec &LiveOuts) const;
220
221  /// \brief Create a live-out register record for the given register @p Reg.
222  LiveOutReg createLiveOutReg(unsigned Reg,
223                              const TargetRegisterInfo *TRI) const;
224
225  /// \brief Parse the register live-out mask and return a vector of live-out
226  /// registers that need to be recorded in the stackmap.
227  LiveOutVec parseRegisterLiveOutMask(const uint32_t *Mask) const;
228
229  /// This should be called by the MC lowering code _immediately_ before
230  /// lowering the MI to an MCInst. It records where the operands for the
231  /// instruction are stored, and outputs a label to record the offset of
232  /// the call from the start of the text section. In special cases (e.g. AnyReg
233  /// calling convention) the return register is also recorded if requested.
234  void recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
235                           MachineInstr::const_mop_iterator MOI,
236                           MachineInstr::const_mop_iterator MOE,
237                           bool recordResult = false);
238
239  /// \brief Emit the stackmap header.
240  void emitStackmapHeader(MCStreamer &OS);
241
242  /// \brief Emit the function frame record for each function.
243  void emitFunctionFrameRecords(MCStreamer &OS);
244
245  /// \brief Emit the constant pool.
246  void emitConstantPoolEntries(MCStreamer &OS);
247
248  /// \brief Emit the callsite info for each stackmap/patchpoint intrinsic call.
249  void emitCallsiteEntries(MCStreamer &OS);
250
251  void print(raw_ostream &OS);
252  void debug() { print(dbgs()); }
253};
254}
255
256#endif
257