13d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick//===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===//
236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
33d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick//
43d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick//                     The LLVM Compiler Infrastructure
53d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick//
63d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick// This file is distributed under the University of Illinois Open Source
73d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick// License. See LICENSE.TXT for details.
83d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick//
93d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick//===----------------------------------------------------------------------===//
103d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
113d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick#ifndef LLVM_STACKMAPS
123d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick#define LLVM_STACKMAPS
133d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
1436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/ADT/MapVector.h"
153d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick#include "llvm/ADT/SmallVector.h"
163d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick#include "llvm/CodeGen/MachineInstr.h"
173d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick#include <map>
183d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick#include <vector>
193d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
203d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Tricknamespace llvm {
213d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
223d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trickclass AsmPrinter;
233d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trickclass MCExpr;
24dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass MCStreamer;
253d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
2672ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling/// \brief MI-level patchpoint operands.
2772ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling///
2872ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling/// MI patchpoint operations take the form:
2972ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling/// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ...
3072ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling///
31c00090b16b2b35f2d042d965945c4246d13321b5Bill Wendling/// IR patchpoint intrinsics do not have the <cc> operand because calling
32c00090b16b2b35f2d042d965945c4246d13321b5Bill Wendling/// convention is part of the subclass data.
33c00090b16b2b35f2d042d965945c4246d13321b5Bill Wendling///
34c00090b16b2b35f2d042d965945c4246d13321b5Bill Wendling/// SD patchpoint nodes do not have a def operand because it is part of the
35c00090b16b2b35f2d042d965945c4246d13321b5Bill Wendling/// SDValue.
3672ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling///
3772ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling/// Patchpoints following the anyregcc convention are handled specially. For
3872ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling/// these, the stack map also records the location of the return value and
3972ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling/// arguments.
4072ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendlingclass PatchPointOpers {
4172ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendlingpublic:
4272ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// Enumerate the meta operands.
4372ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd };
4472ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendlingprivate:
4572ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  const MachineInstr *MI;
4672ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  bool HasDef;
4772ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  bool IsAnyReg;
4872ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendlingpublic:
4972ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  explicit PatchPointOpers(const MachineInstr *MI);
5072ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling
5172ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  bool isAnyReg() const { return IsAnyReg; }
5272ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  bool hasDef() const { return HasDef; }
5372ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling
5472ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  unsigned getMetaIdx(unsigned Pos = 0) const {
5572ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling    assert(Pos < MetaEnd && "Meta operand index out of range.");
5672ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling    return (HasDef ? 1 : 0) + Pos;
5772ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  }
5872ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling
5972ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  const MachineOperand &getMetaOper(unsigned Pos) {
6072ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling    return MI->getOperand(getMetaIdx(Pos));
6172ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  }
6272ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling
6372ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; }
6472ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling
6572ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// Get the operand index of the variable list of non-argument operands.
6672ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// These hold the "live state".
6772ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  unsigned getVarIdx() const {
6872ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling    return getMetaIdx() + MetaEnd
6972ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling      + MI->getOperand(getMetaIdx(NArgPos)).getImm();
7072ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  }
7172ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling
7272ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// Get the index at which stack map locations will be recorded.
7372ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// Arguments are not recorded unless the anyregcc convention is used.
7472ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  unsigned getStackMapStartIdx() const {
7572ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling    if (IsAnyReg)
7672ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling      return getArgIdx();
7772ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling    return getVarIdx();
7872ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  }
7972ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling
8072ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// \brief Get the next scratch register operand index.
8172ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  unsigned getNextScratchIdx(unsigned StartIdx = 0) const;
8272ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling};
8372ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling
843d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trickclass StackMaps {
853d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trickpublic:
863d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  struct Location {
873d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick    enum LocationType { Unprocessed, Register, Direct, Indirect, Constant,
883d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick                        ConstantIndex };
893d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick    LocationType LocType;
90bb756ca24401e190e3b704e5d92759c7a79cc6b7Andrew Trick    unsigned Size;
913d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick    unsigned Reg;
923d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick    int64_t Offset;
93bb756ca24401e190e3b704e5d92759c7a79cc6b7Andrew Trick    Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0) {}
94bb756ca24401e190e3b704e5d92759c7a79cc6b7Andrew Trick    Location(LocationType LocType, unsigned Size, unsigned Reg, int64_t Offset)
95bb756ca24401e190e3b704e5d92759c7a79cc6b7Andrew Trick      : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {}
963d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  };
973d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
9836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  struct LiveOutReg {
9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned short Reg;
10036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned short RegNo;
10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned short Size;
10236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    LiveOutReg() : Reg(0), RegNo(0), Size(0) {}
10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    LiveOutReg(unsigned short Reg, unsigned short RegNo, unsigned short Size)
10536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      : Reg(Reg), RegNo(RegNo), Size(Size) {}
10636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void MarkInvalid() { Reg = 0; }
10836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
10936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Only sort by the dwarf register number.
11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool operator< (const LiveOutReg &LO) const { return RegNo < LO.RegNo; }
11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    static bool IsInvalid(const LiveOutReg &LO) { return LO.Reg == 0; }
11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  };
1133d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
1143d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  // OpTypes are used to encode information about the following logical
1153d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  // operand (which may consist of several MachineOperands) for the
1163d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  // OpParser.
1173d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType;
1183d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
119dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  StackMaps(AsmPrinter &AP);
1203d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
12172ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// \brief Generate a stackmap record for a stackmap instruction.
12272ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  ///
12372ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// MI must be a raw STACKMAP, not a PATCHPOINT.
12472ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  void recordStackMap(const MachineInstr &MI);
12572ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling
12672ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// \brief Generate a stackmap record for a patchpoint instruction.
12772ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  void recordPatchPoint(const MachineInstr &MI);
1283d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
1293d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  /// If there is any stack map data, create a stack map section and serialize
1303d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  /// the map info into it. This clears the stack map data structures
1313d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  /// afterwards.
1323d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  void serializeToStackMapSection();
1333d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
1343d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trickprivate:
135dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  static const char *WSMP;
136dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
1373d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  typedef SmallVector<Location, 8> LocationVec;
13836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  typedef SmallVector<LiveOutReg, 8> LiveOutVec;
139dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  typedef MapVector<int64_t, int64_t> ConstantPool;
14036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  typedef MapVector<const MCSymbol *, uint64_t> FnStackSizeMap;
1413d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
1423d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  struct CallsiteInfo {
1433d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick    const MCExpr *CSOffsetExpr;
14436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint64_t ID;
1453d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick    LocationVec Locations;
14636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    LiveOutVec LiveOuts;
147dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    CallsiteInfo() : CSOffsetExpr(nullptr), ID(0) {}
14836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID,
14936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                 LocationVec &Locations, LiveOutVec &LiveOuts)
15036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations),
15136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        LiveOuts(LiveOuts) {}
1523d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  };
1533d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
1543d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  typedef std::vector<CallsiteInfo> CallsiteInfoList;
1553d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
1563d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  AsmPrinter &AP;
1573d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  CallsiteInfoList CSInfos;
1583d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick  ConstantPool ConstPool;
15936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  FnStackSizeMap FnStackSize;
16036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
16136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MachineInstr::const_mop_iterator
16236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  parseOperand(MachineInstr::const_mop_iterator MOI,
16336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines               MachineInstr::const_mop_iterator MOE,
16436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines               LocationVec &Locs, LiveOutVec &LiveOuts) const;
16536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
16636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// \brief Create a live-out register record for the given register @p Reg.
16736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  LiveOutReg createLiveOutReg(unsigned Reg,
16836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                              const TargetRegisterInfo *TRI) const;
16936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
17036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// \brief Parse the register live-out mask and return a vector of live-out
17136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// registers that need to be recorded in the stackmap.
17236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  LiveOutVec parseRegisterLiveOutMask(const uint32_t *Mask) const;
17372ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling
17472ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// This should be called by the MC lowering code _immediately_ before
17572ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// lowering the MI to an MCInst. It records where the operands for the
17672ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// instruction are stored, and outputs a label to record the offset of
17772ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// the call from the start of the text section. In special cases (e.g. AnyReg
17872ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling  /// calling convention) the return register is also recorded if requested.
17936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
18072ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling                           MachineInstr::const_mop_iterator MOI,
18172ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling                           MachineInstr::const_mop_iterator MOE,
18272ef53ad21cf2df7cdf6f2a0470b4eaa98d9e7edBill Wendling                           bool recordResult = false);
183dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
184dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Emit the stackmap header.
185dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void emitStackmapHeader(MCStreamer &OS);
186dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
187dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Emit the function frame record for each function.
188dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void emitFunctionFrameRecords(MCStreamer &OS);
189dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
190dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Emit the constant pool.
191dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void emitConstantPoolEntries(MCStreamer &OS);
192dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
193dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Emit the callsite info for each stackmap/patchpoint intrinsic call.
194dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void emitCallsiteEntries(MCStreamer &OS, const TargetRegisterInfo *TRI);
1953d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick};
1963d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
1973d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick}
1983d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick
1993d74dea4bddc84d1881efc21eb5eefbddbfa9aedAndrew Trick#endif // LLVM_STACKMAPS
200