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