1259698Sdim//===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===// 2259698Sdim// 3259698Sdim// The LLVM Compiler Infrastructure 4259698Sdim// 5259698Sdim// This file is distributed under the University of Illinois Open Source 6259698Sdim// License. See LICENSE.TXT for details. 7259698Sdim// 8259698Sdim//===----------------------------------------------------------------------===// 9259698Sdim 10259698Sdim#ifndef LLVM_STACKMAPS 11259698Sdim#define LLVM_STACKMAPS 12259698Sdim 13259698Sdim#include "llvm/ADT/SmallVector.h" 14259698Sdim#include "llvm/CodeGen/MachineInstr.h" 15259698Sdim#include <map> 16259698Sdim#include <vector> 17259698Sdim 18259698Sdimnamespace llvm { 19259698Sdim 20259698Sdimclass AsmPrinter; 21259698Sdimclass MCExpr; 22259698Sdim 23259698Sdim/// \brief MI-level patchpoint operands. 24259698Sdim/// 25259698Sdim/// MI patchpoint operations take the form: 26259698Sdim/// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ... 27259698Sdim/// 28259698Sdim/// IR patchpoint intrinsics do not have the <cc> operand because calling 29259698Sdim/// convention is part of the subclass data. 30259698Sdim/// 31259698Sdim/// SD patchpoint nodes do not have a def operand because it is part of the 32259698Sdim/// SDValue. 33259698Sdim/// 34259698Sdim/// Patchpoints following the anyregcc convention are handled specially. For 35259698Sdim/// these, the stack map also records the location of the return value and 36259698Sdim/// arguments. 37259698Sdimclass PatchPointOpers { 38259698Sdimpublic: 39259698Sdim /// Enumerate the meta operands. 40259698Sdim enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd }; 41259698Sdimprivate: 42259698Sdim const MachineInstr *MI; 43259698Sdim bool HasDef; 44259698Sdim bool IsAnyReg; 45259698Sdimpublic: 46259698Sdim explicit PatchPointOpers(const MachineInstr *MI); 47259698Sdim 48259698Sdim bool isAnyReg() const { return IsAnyReg; } 49259698Sdim bool hasDef() const { return HasDef; } 50259698Sdim 51259698Sdim unsigned getMetaIdx(unsigned Pos = 0) const { 52259698Sdim assert(Pos < MetaEnd && "Meta operand index out of range."); 53259698Sdim return (HasDef ? 1 : 0) + Pos; 54259698Sdim } 55259698Sdim 56259698Sdim const MachineOperand &getMetaOper(unsigned Pos) { 57259698Sdim return MI->getOperand(getMetaIdx(Pos)); 58259698Sdim } 59259698Sdim 60259698Sdim unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; } 61259698Sdim 62259698Sdim /// Get the operand index of the variable list of non-argument operands. 63259698Sdim /// These hold the "live state". 64259698Sdim unsigned getVarIdx() const { 65259698Sdim return getMetaIdx() + MetaEnd 66259698Sdim + MI->getOperand(getMetaIdx(NArgPos)).getImm(); 67259698Sdim } 68259698Sdim 69259698Sdim /// Get the index at which stack map locations will be recorded. 70259698Sdim /// Arguments are not recorded unless the anyregcc convention is used. 71259698Sdim unsigned getStackMapStartIdx() const { 72259698Sdim if (IsAnyReg) 73259698Sdim return getArgIdx(); 74259698Sdim return getVarIdx(); 75259698Sdim } 76259698Sdim 77259698Sdim /// \brief Get the next scratch register operand index. 78259698Sdim unsigned getNextScratchIdx(unsigned StartIdx = 0) const; 79259698Sdim}; 80259698Sdim 81259698Sdimclass StackMaps { 82259698Sdimpublic: 83259698Sdim struct Location { 84259698Sdim enum LocationType { Unprocessed, Register, Direct, Indirect, Constant, 85259698Sdim ConstantIndex }; 86259698Sdim LocationType LocType; 87259698Sdim unsigned Size; 88259698Sdim unsigned Reg; 89259698Sdim int64_t Offset; 90259698Sdim Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0) {} 91259698Sdim Location(LocationType LocType, unsigned Size, unsigned Reg, int64_t Offset) 92259698Sdim : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {} 93259698Sdim }; 94259698Sdim 95259698Sdim // Typedef a function pointer for functions that parse sequences of operands 96259698Sdim // and return a Location, plus a new "next" operand iterator. 97259698Sdim typedef std::pair<Location, MachineInstr::const_mop_iterator> 98259698Sdim (*OperandParser)(MachineInstr::const_mop_iterator, 99259698Sdim MachineInstr::const_mop_iterator, const TargetMachine&); 100259698Sdim 101259698Sdim // OpTypes are used to encode information about the following logical 102259698Sdim // operand (which may consist of several MachineOperands) for the 103259698Sdim // OpParser. 104259698Sdim typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType; 105259698Sdim 106259698Sdim StackMaps(AsmPrinter &AP, OperandParser OpParser) 107259698Sdim : AP(AP), OpParser(OpParser) {} 108259698Sdim 109259698Sdim /// \brief Generate a stackmap record for a stackmap instruction. 110259698Sdim /// 111259698Sdim /// MI must be a raw STACKMAP, not a PATCHPOINT. 112259698Sdim void recordStackMap(const MachineInstr &MI); 113259698Sdim 114259698Sdim /// \brief Generate a stackmap record for a patchpoint instruction. 115259698Sdim void recordPatchPoint(const MachineInstr &MI); 116259698Sdim 117259698Sdim /// If there is any stack map data, create a stack map section and serialize 118259698Sdim /// the map info into it. This clears the stack map data structures 119259698Sdim /// afterwards. 120259698Sdim void serializeToStackMapSection(); 121259698Sdim 122259698Sdimprivate: 123259698Sdim typedef SmallVector<Location, 8> LocationVec; 124259698Sdim 125259698Sdim struct CallsiteInfo { 126259698Sdim const MCExpr *CSOffsetExpr; 127259698Sdim unsigned ID; 128259698Sdim LocationVec Locations; 129259698Sdim CallsiteInfo() : CSOffsetExpr(0), ID(0) {} 130259698Sdim CallsiteInfo(const MCExpr *CSOffsetExpr, unsigned ID, 131259698Sdim LocationVec Locations) 132259698Sdim : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations) {} 133259698Sdim }; 134259698Sdim 135259698Sdim typedef std::vector<CallsiteInfo> CallsiteInfoList; 136259698Sdim 137259698Sdim struct ConstantPool { 138259698Sdim private: 139259698Sdim typedef std::map<int64_t, size_t> ConstantsMap; 140259698Sdim std::vector<int64_t> ConstantsList; 141259698Sdim ConstantsMap ConstantIndexes; 142259698Sdim 143259698Sdim public: 144259698Sdim size_t getNumConstants() const { return ConstantsList.size(); } 145259698Sdim int64_t getConstant(size_t Idx) const { return ConstantsList[Idx]; } 146259698Sdim size_t getConstantIndex(int64_t ConstVal) { 147259698Sdim size_t NextIdx = ConstantsList.size(); 148259698Sdim ConstantsMap::const_iterator I = 149259698Sdim ConstantIndexes.insert(ConstantIndexes.end(), 150259698Sdim std::make_pair(ConstVal, NextIdx)); 151259698Sdim if (I->second == NextIdx) 152259698Sdim ConstantsList.push_back(ConstVal); 153259698Sdim return I->second; 154259698Sdim } 155259698Sdim }; 156259698Sdim 157259698Sdim AsmPrinter &AP; 158259698Sdim OperandParser OpParser; 159259698Sdim CallsiteInfoList CSInfos; 160259698Sdim ConstantPool ConstPool; 161259698Sdim 162259698Sdim /// This should be called by the MC lowering code _immediately_ before 163259698Sdim /// lowering the MI to an MCInst. It records where the operands for the 164259698Sdim /// instruction are stored, and outputs a label to record the offset of 165259698Sdim /// the call from the start of the text section. In special cases (e.g. AnyReg 166259698Sdim /// calling convention) the return register is also recorded if requested. 167259698Sdim void recordStackMapOpers(const MachineInstr &MI, uint32_t ID, 168259698Sdim MachineInstr::const_mop_iterator MOI, 169259698Sdim MachineInstr::const_mop_iterator MOE, 170259698Sdim bool recordResult = false); 171259698Sdim}; 172259698Sdim 173259698Sdim} 174259698Sdim 175259698Sdim#endif // LLVM_STACKMAPS 176