xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/CodeGen/StackMaps.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
17330f729Sjoerg //===- StackMaps.cpp ------------------------------------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg 
97330f729Sjoerg #include "llvm/CodeGen/StackMaps.h"
107330f729Sjoerg #include "llvm/ADT/DenseMapInfo.h"
117330f729Sjoerg #include "llvm/ADT/STLExtras.h"
127330f729Sjoerg #include "llvm/ADT/Twine.h"
137330f729Sjoerg #include "llvm/CodeGen/AsmPrinter.h"
147330f729Sjoerg #include "llvm/CodeGen/MachineFrameInfo.h"
157330f729Sjoerg #include "llvm/CodeGen/MachineFunction.h"
167330f729Sjoerg #include "llvm/CodeGen/MachineInstr.h"
177330f729Sjoerg #include "llvm/CodeGen/MachineOperand.h"
187330f729Sjoerg #include "llvm/CodeGen/TargetOpcodes.h"
197330f729Sjoerg #include "llvm/CodeGen/TargetRegisterInfo.h"
207330f729Sjoerg #include "llvm/CodeGen/TargetSubtargetInfo.h"
217330f729Sjoerg #include "llvm/IR/DataLayout.h"
227330f729Sjoerg #include "llvm/MC/MCContext.h"
237330f729Sjoerg #include "llvm/MC/MCExpr.h"
247330f729Sjoerg #include "llvm/MC/MCObjectFileInfo.h"
257330f729Sjoerg #include "llvm/MC/MCRegisterInfo.h"
267330f729Sjoerg #include "llvm/MC/MCStreamer.h"
277330f729Sjoerg #include "llvm/Support/CommandLine.h"
287330f729Sjoerg #include "llvm/Support/Debug.h"
297330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
307330f729Sjoerg #include "llvm/Support/MathExtras.h"
317330f729Sjoerg #include "llvm/Support/raw_ostream.h"
327330f729Sjoerg #include <algorithm>
337330f729Sjoerg #include <cassert>
347330f729Sjoerg #include <cstdint>
357330f729Sjoerg #include <iterator>
367330f729Sjoerg #include <utility>
377330f729Sjoerg 
387330f729Sjoerg using namespace llvm;
397330f729Sjoerg 
407330f729Sjoerg #define DEBUG_TYPE "stackmaps"
417330f729Sjoerg 
427330f729Sjoerg static cl::opt<int> StackMapVersion(
437330f729Sjoerg     "stackmap-version", cl::init(3), cl::Hidden,
447330f729Sjoerg     cl::desc("Specify the stackmap encoding version (default = 3)"));
457330f729Sjoerg 
467330f729Sjoerg const char *StackMaps::WSMP = "Stack Maps: ";
477330f729Sjoerg 
getConstMetaVal(const MachineInstr & MI,unsigned Idx)48*82d56013Sjoerg static uint64_t getConstMetaVal(const MachineInstr &MI, unsigned Idx) {
49*82d56013Sjoerg   assert(MI.getOperand(Idx).isImm() &&
50*82d56013Sjoerg          MI.getOperand(Idx).getImm() == StackMaps::ConstantOp);
51*82d56013Sjoerg   const auto &MO = MI.getOperand(Idx + 1);
52*82d56013Sjoerg   assert(MO.isImm());
53*82d56013Sjoerg   return MO.getImm();
54*82d56013Sjoerg }
55*82d56013Sjoerg 
StackMapOpers(const MachineInstr * MI)567330f729Sjoerg StackMapOpers::StackMapOpers(const MachineInstr *MI)
577330f729Sjoerg   : MI(MI) {
587330f729Sjoerg   assert(getVarIdx() <= MI->getNumOperands() &&
597330f729Sjoerg          "invalid stackmap definition");
607330f729Sjoerg }
617330f729Sjoerg 
PatchPointOpers(const MachineInstr * MI)627330f729Sjoerg PatchPointOpers::PatchPointOpers(const MachineInstr *MI)
637330f729Sjoerg     : MI(MI), HasDef(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() &&
647330f729Sjoerg                      !MI->getOperand(0).isImplicit()) {
657330f729Sjoerg #ifndef NDEBUG
667330f729Sjoerg   unsigned CheckStartIdx = 0, e = MI->getNumOperands();
677330f729Sjoerg   while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).isReg() &&
687330f729Sjoerg          MI->getOperand(CheckStartIdx).isDef() &&
697330f729Sjoerg          !MI->getOperand(CheckStartIdx).isImplicit())
707330f729Sjoerg     ++CheckStartIdx;
717330f729Sjoerg 
727330f729Sjoerg   assert(getMetaIdx() == CheckStartIdx &&
737330f729Sjoerg          "Unexpected additional definition in Patchpoint intrinsic.");
747330f729Sjoerg #endif
757330f729Sjoerg }
767330f729Sjoerg 
getNextScratchIdx(unsigned StartIdx) const777330f729Sjoerg unsigned PatchPointOpers::getNextScratchIdx(unsigned StartIdx) const {
787330f729Sjoerg   if (!StartIdx)
797330f729Sjoerg     StartIdx = getVarIdx();
807330f729Sjoerg 
817330f729Sjoerg   // Find the next scratch register (implicit def and early clobber)
827330f729Sjoerg   unsigned ScratchIdx = StartIdx, e = MI->getNumOperands();
837330f729Sjoerg   while (ScratchIdx < e &&
847330f729Sjoerg          !(MI->getOperand(ScratchIdx).isReg() &&
857330f729Sjoerg            MI->getOperand(ScratchIdx).isDef() &&
867330f729Sjoerg            MI->getOperand(ScratchIdx).isImplicit() &&
877330f729Sjoerg            MI->getOperand(ScratchIdx).isEarlyClobber()))
887330f729Sjoerg     ++ScratchIdx;
897330f729Sjoerg 
907330f729Sjoerg   assert(ScratchIdx != e && "No scratch register available");
917330f729Sjoerg   return ScratchIdx;
927330f729Sjoerg }
937330f729Sjoerg 
getNumGcMapEntriesIdx()94*82d56013Sjoerg unsigned StatepointOpers::getNumGcMapEntriesIdx() {
95*82d56013Sjoerg   // Take index of num of allocas and skip all allocas records.
96*82d56013Sjoerg   unsigned CurIdx = getNumAllocaIdx();
97*82d56013Sjoerg   unsigned NumAllocas = getConstMetaVal(*MI, CurIdx - 1);
98*82d56013Sjoerg   CurIdx++;
99*82d56013Sjoerg   while (NumAllocas--)
100*82d56013Sjoerg     CurIdx = StackMaps::getNextMetaArgIdx(MI, CurIdx);
101*82d56013Sjoerg   return CurIdx + 1; // skip <StackMaps::ConstantOp>
102*82d56013Sjoerg }
103*82d56013Sjoerg 
getNumAllocaIdx()104*82d56013Sjoerg unsigned StatepointOpers::getNumAllocaIdx() {
105*82d56013Sjoerg   // Take index of num of gc ptrs and skip all gc ptr records.
106*82d56013Sjoerg   unsigned CurIdx = getNumGCPtrIdx();
107*82d56013Sjoerg   unsigned NumGCPtrs = getConstMetaVal(*MI, CurIdx - 1);
108*82d56013Sjoerg   CurIdx++;
109*82d56013Sjoerg   while (NumGCPtrs--)
110*82d56013Sjoerg     CurIdx = StackMaps::getNextMetaArgIdx(MI, CurIdx);
111*82d56013Sjoerg   return CurIdx + 1; // skip <StackMaps::ConstantOp>
112*82d56013Sjoerg }
113*82d56013Sjoerg 
getNumGCPtrIdx()114*82d56013Sjoerg unsigned StatepointOpers::getNumGCPtrIdx() {
115*82d56013Sjoerg   // Take index of num of deopt args and skip all deopt records.
116*82d56013Sjoerg   unsigned CurIdx = getNumDeoptArgsIdx();
117*82d56013Sjoerg   unsigned NumDeoptArgs = getConstMetaVal(*MI, CurIdx - 1);
118*82d56013Sjoerg   CurIdx++;
119*82d56013Sjoerg   while (NumDeoptArgs--) {
120*82d56013Sjoerg     CurIdx = StackMaps::getNextMetaArgIdx(MI, CurIdx);
121*82d56013Sjoerg   }
122*82d56013Sjoerg   return CurIdx + 1; // skip <StackMaps::ConstantOp>
123*82d56013Sjoerg }
124*82d56013Sjoerg 
getFirstGCPtrIdx()125*82d56013Sjoerg int StatepointOpers::getFirstGCPtrIdx() {
126*82d56013Sjoerg   unsigned NumGCPtrsIdx = getNumGCPtrIdx();
127*82d56013Sjoerg   unsigned NumGCPtrs = getConstMetaVal(*MI, NumGCPtrsIdx - 1);
128*82d56013Sjoerg   if (NumGCPtrs == 0)
129*82d56013Sjoerg     return -1;
130*82d56013Sjoerg   ++NumGCPtrsIdx; // skip <num gc ptrs>
131*82d56013Sjoerg   assert(NumGCPtrsIdx < MI->getNumOperands());
132*82d56013Sjoerg   return (int)NumGCPtrsIdx;
133*82d56013Sjoerg }
134*82d56013Sjoerg 
getGCPointerMap(SmallVectorImpl<std::pair<unsigned,unsigned>> & GCMap)135*82d56013Sjoerg unsigned StatepointOpers::getGCPointerMap(
136*82d56013Sjoerg     SmallVectorImpl<std::pair<unsigned, unsigned>> &GCMap) {
137*82d56013Sjoerg   unsigned CurIdx = getNumGcMapEntriesIdx();
138*82d56013Sjoerg   unsigned GCMapSize = getConstMetaVal(*MI, CurIdx - 1);
139*82d56013Sjoerg   CurIdx++;
140*82d56013Sjoerg   for (unsigned N = 0; N < GCMapSize; ++N) {
141*82d56013Sjoerg     unsigned B = MI->getOperand(CurIdx++).getImm();
142*82d56013Sjoerg     unsigned D = MI->getOperand(CurIdx++).getImm();
143*82d56013Sjoerg     GCMap.push_back(std::make_pair(B, D));
144*82d56013Sjoerg   }
145*82d56013Sjoerg 
146*82d56013Sjoerg   return GCMapSize;
147*82d56013Sjoerg }
148*82d56013Sjoerg 
StackMaps(AsmPrinter & AP)1497330f729Sjoerg StackMaps::StackMaps(AsmPrinter &AP) : AP(AP) {
1507330f729Sjoerg   if (StackMapVersion != 3)
1517330f729Sjoerg     llvm_unreachable("Unsupported stackmap version!");
1527330f729Sjoerg }
1537330f729Sjoerg 
getNextMetaArgIdx(const MachineInstr * MI,unsigned CurIdx)154*82d56013Sjoerg unsigned StackMaps::getNextMetaArgIdx(const MachineInstr *MI, unsigned CurIdx) {
155*82d56013Sjoerg   assert(CurIdx < MI->getNumOperands() && "Bad meta arg index");
156*82d56013Sjoerg   const auto &MO = MI->getOperand(CurIdx);
157*82d56013Sjoerg   if (MO.isImm()) {
158*82d56013Sjoerg     switch (MO.getImm()) {
159*82d56013Sjoerg     default:
160*82d56013Sjoerg       llvm_unreachable("Unrecognized operand type.");
161*82d56013Sjoerg     case StackMaps::DirectMemRefOp:
162*82d56013Sjoerg       CurIdx += 2;
163*82d56013Sjoerg       break;
164*82d56013Sjoerg     case StackMaps::IndirectMemRefOp:
165*82d56013Sjoerg       CurIdx += 3;
166*82d56013Sjoerg       break;
167*82d56013Sjoerg     case StackMaps::ConstantOp:
168*82d56013Sjoerg       ++CurIdx;
169*82d56013Sjoerg       break;
170*82d56013Sjoerg     }
171*82d56013Sjoerg   }
172*82d56013Sjoerg   ++CurIdx;
173*82d56013Sjoerg   assert(CurIdx < MI->getNumOperands() && "points past operand list");
174*82d56013Sjoerg   return CurIdx;
175*82d56013Sjoerg }
176*82d56013Sjoerg 
1777330f729Sjoerg /// Go up the super-register chain until we hit a valid dwarf register number.
getDwarfRegNum(unsigned Reg,const TargetRegisterInfo * TRI)1787330f729Sjoerg static unsigned getDwarfRegNum(unsigned Reg, const TargetRegisterInfo *TRI) {
1797330f729Sjoerg   int RegNum = TRI->getDwarfRegNum(Reg, false);
1807330f729Sjoerg   for (MCSuperRegIterator SR(Reg, TRI); SR.isValid() && RegNum < 0; ++SR)
1817330f729Sjoerg     RegNum = TRI->getDwarfRegNum(*SR, false);
1827330f729Sjoerg 
1837330f729Sjoerg   assert(RegNum >= 0 && "Invalid Dwarf register number.");
1847330f729Sjoerg   return (unsigned)RegNum;
1857330f729Sjoerg }
1867330f729Sjoerg 
1877330f729Sjoerg MachineInstr::const_mop_iterator
parseOperand(MachineInstr::const_mop_iterator MOI,MachineInstr::const_mop_iterator MOE,LocationVec & Locs,LiveOutVec & LiveOuts) const1887330f729Sjoerg StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
1897330f729Sjoerg                         MachineInstr::const_mop_iterator MOE, LocationVec &Locs,
1907330f729Sjoerg                         LiveOutVec &LiveOuts) const {
1917330f729Sjoerg   const TargetRegisterInfo *TRI = AP.MF->getSubtarget().getRegisterInfo();
1927330f729Sjoerg   if (MOI->isImm()) {
1937330f729Sjoerg     switch (MOI->getImm()) {
1947330f729Sjoerg     default:
1957330f729Sjoerg       llvm_unreachable("Unrecognized operand type.");
1967330f729Sjoerg     case StackMaps::DirectMemRefOp: {
1977330f729Sjoerg       auto &DL = AP.MF->getDataLayout();
1987330f729Sjoerg 
1997330f729Sjoerg       unsigned Size = DL.getPointerSizeInBits();
2007330f729Sjoerg       assert((Size % 8) == 0 && "Need pointer size in bytes.");
2017330f729Sjoerg       Size /= 8;
2027330f729Sjoerg       Register Reg = (++MOI)->getReg();
2037330f729Sjoerg       int64_t Imm = (++MOI)->getImm();
2047330f729Sjoerg       Locs.emplace_back(StackMaps::Location::Direct, Size,
2057330f729Sjoerg                         getDwarfRegNum(Reg, TRI), Imm);
2067330f729Sjoerg       break;
2077330f729Sjoerg     }
2087330f729Sjoerg     case StackMaps::IndirectMemRefOp: {
2097330f729Sjoerg       int64_t Size = (++MOI)->getImm();
2107330f729Sjoerg       assert(Size > 0 && "Need a valid size for indirect memory locations.");
2117330f729Sjoerg       Register Reg = (++MOI)->getReg();
2127330f729Sjoerg       int64_t Imm = (++MOI)->getImm();
2137330f729Sjoerg       Locs.emplace_back(StackMaps::Location::Indirect, Size,
2147330f729Sjoerg                         getDwarfRegNum(Reg, TRI), Imm);
2157330f729Sjoerg       break;
2167330f729Sjoerg     }
2177330f729Sjoerg     case StackMaps::ConstantOp: {
2187330f729Sjoerg       ++MOI;
2197330f729Sjoerg       assert(MOI->isImm() && "Expected constant operand.");
2207330f729Sjoerg       int64_t Imm = MOI->getImm();
2217330f729Sjoerg       Locs.emplace_back(Location::Constant, sizeof(int64_t), 0, Imm);
2227330f729Sjoerg       break;
2237330f729Sjoerg     }
2247330f729Sjoerg     }
2257330f729Sjoerg     return ++MOI;
2267330f729Sjoerg   }
2277330f729Sjoerg 
2287330f729Sjoerg   // The physical register number will ultimately be encoded as a DWARF regno.
2297330f729Sjoerg   // The stack map also records the size of a spill slot that can hold the
2307330f729Sjoerg   // register content. (The runtime can track the actual size of the data type
2317330f729Sjoerg   // if it needs to.)
2327330f729Sjoerg   if (MOI->isReg()) {
2337330f729Sjoerg     // Skip implicit registers (this includes our scratch registers)
2347330f729Sjoerg     if (MOI->isImplicit())
2357330f729Sjoerg       return ++MOI;
2367330f729Sjoerg 
237*82d56013Sjoerg     if (MOI->isUndef()) {
238*82d56013Sjoerg       // Record `undef` register as constant. Use same value as ISel uses.
239*82d56013Sjoerg       Locs.emplace_back(Location::Constant, sizeof(int64_t), 0, 0xFEFEFEFE);
240*82d56013Sjoerg       return ++MOI;
241*82d56013Sjoerg     }
242*82d56013Sjoerg 
2437330f729Sjoerg     assert(Register::isPhysicalRegister(MOI->getReg()) &&
2447330f729Sjoerg            "Virtreg operands should have been rewritten before now.");
2457330f729Sjoerg     const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(MOI->getReg());
2467330f729Sjoerg     assert(!MOI->getSubReg() && "Physical subreg still around.");
2477330f729Sjoerg 
2487330f729Sjoerg     unsigned Offset = 0;
2497330f729Sjoerg     unsigned DwarfRegNum = getDwarfRegNum(MOI->getReg(), TRI);
2507330f729Sjoerg     unsigned LLVMRegNum = *TRI->getLLVMRegNum(DwarfRegNum, false);
2517330f729Sjoerg     unsigned SubRegIdx = TRI->getSubRegIndex(LLVMRegNum, MOI->getReg());
2527330f729Sjoerg     if (SubRegIdx)
2537330f729Sjoerg       Offset = TRI->getSubRegIdxOffset(SubRegIdx);
2547330f729Sjoerg 
2557330f729Sjoerg     Locs.emplace_back(Location::Register, TRI->getSpillSize(*RC),
2567330f729Sjoerg                       DwarfRegNum, Offset);
2577330f729Sjoerg     return ++MOI;
2587330f729Sjoerg   }
2597330f729Sjoerg 
2607330f729Sjoerg   if (MOI->isRegLiveOut())
2617330f729Sjoerg     LiveOuts = parseRegisterLiveOutMask(MOI->getRegLiveOut());
2627330f729Sjoerg 
2637330f729Sjoerg   return ++MOI;
2647330f729Sjoerg }
2657330f729Sjoerg 
print(raw_ostream & OS)2667330f729Sjoerg void StackMaps::print(raw_ostream &OS) {
2677330f729Sjoerg   const TargetRegisterInfo *TRI =
2687330f729Sjoerg       AP.MF ? AP.MF->getSubtarget().getRegisterInfo() : nullptr;
2697330f729Sjoerg   OS << WSMP << "callsites:\n";
2707330f729Sjoerg   for (const auto &CSI : CSInfos) {
2717330f729Sjoerg     const LocationVec &CSLocs = CSI.Locations;
2727330f729Sjoerg     const LiveOutVec &LiveOuts = CSI.LiveOuts;
2737330f729Sjoerg 
2747330f729Sjoerg     OS << WSMP << "callsite " << CSI.ID << "\n";
2757330f729Sjoerg     OS << WSMP << "  has " << CSLocs.size() << " locations\n";
2767330f729Sjoerg 
2777330f729Sjoerg     unsigned Idx = 0;
2787330f729Sjoerg     for (const auto &Loc : CSLocs) {
2797330f729Sjoerg       OS << WSMP << "\t\tLoc " << Idx << ": ";
2807330f729Sjoerg       switch (Loc.Type) {
2817330f729Sjoerg       case Location::Unprocessed:
2827330f729Sjoerg         OS << "<Unprocessed operand>";
2837330f729Sjoerg         break;
2847330f729Sjoerg       case Location::Register:
2857330f729Sjoerg         OS << "Register ";
2867330f729Sjoerg         if (TRI)
2877330f729Sjoerg           OS << printReg(Loc.Reg, TRI);
2887330f729Sjoerg         else
2897330f729Sjoerg           OS << Loc.Reg;
2907330f729Sjoerg         break;
2917330f729Sjoerg       case Location::Direct:
2927330f729Sjoerg         OS << "Direct ";
2937330f729Sjoerg         if (TRI)
2947330f729Sjoerg           OS << printReg(Loc.Reg, TRI);
2957330f729Sjoerg         else
2967330f729Sjoerg           OS << Loc.Reg;
2977330f729Sjoerg         if (Loc.Offset)
2987330f729Sjoerg           OS << " + " << Loc.Offset;
2997330f729Sjoerg         break;
3007330f729Sjoerg       case Location::Indirect:
3017330f729Sjoerg         OS << "Indirect ";
3027330f729Sjoerg         if (TRI)
3037330f729Sjoerg           OS << printReg(Loc.Reg, TRI);
3047330f729Sjoerg         else
3057330f729Sjoerg           OS << Loc.Reg;
3067330f729Sjoerg         OS << "+" << Loc.Offset;
3077330f729Sjoerg         break;
3087330f729Sjoerg       case Location::Constant:
3097330f729Sjoerg         OS << "Constant " << Loc.Offset;
3107330f729Sjoerg         break;
3117330f729Sjoerg       case Location::ConstantIndex:
3127330f729Sjoerg         OS << "Constant Index " << Loc.Offset;
3137330f729Sjoerg         break;
3147330f729Sjoerg       }
3157330f729Sjoerg       OS << "\t[encoding: .byte " << Loc.Type << ", .byte 0"
3167330f729Sjoerg          << ", .short " << Loc.Size << ", .short " << Loc.Reg << ", .short 0"
3177330f729Sjoerg          << ", .int " << Loc.Offset << "]\n";
3187330f729Sjoerg       Idx++;
3197330f729Sjoerg     }
3207330f729Sjoerg 
3217330f729Sjoerg     OS << WSMP << "\thas " << LiveOuts.size() << " live-out registers\n";
3227330f729Sjoerg 
3237330f729Sjoerg     Idx = 0;
3247330f729Sjoerg     for (const auto &LO : LiveOuts) {
3257330f729Sjoerg       OS << WSMP << "\t\tLO " << Idx << ": ";
3267330f729Sjoerg       if (TRI)
3277330f729Sjoerg         OS << printReg(LO.Reg, TRI);
3287330f729Sjoerg       else
3297330f729Sjoerg         OS << LO.Reg;
3307330f729Sjoerg       OS << "\t[encoding: .short " << LO.DwarfRegNum << ", .byte 0, .byte "
3317330f729Sjoerg          << LO.Size << "]\n";
3327330f729Sjoerg       Idx++;
3337330f729Sjoerg     }
3347330f729Sjoerg   }
3357330f729Sjoerg }
3367330f729Sjoerg 
3377330f729Sjoerg /// Create a live-out register record for the given register Reg.
3387330f729Sjoerg StackMaps::LiveOutReg
createLiveOutReg(unsigned Reg,const TargetRegisterInfo * TRI) const3397330f729Sjoerg StackMaps::createLiveOutReg(unsigned Reg, const TargetRegisterInfo *TRI) const {
3407330f729Sjoerg   unsigned DwarfRegNum = getDwarfRegNum(Reg, TRI);
3417330f729Sjoerg   unsigned Size = TRI->getSpillSize(*TRI->getMinimalPhysRegClass(Reg));
3427330f729Sjoerg   return LiveOutReg(Reg, DwarfRegNum, Size);
3437330f729Sjoerg }
3447330f729Sjoerg 
3457330f729Sjoerg /// Parse the register live-out mask and return a vector of live-out registers
3467330f729Sjoerg /// that need to be recorded in the stackmap.
3477330f729Sjoerg StackMaps::LiveOutVec
parseRegisterLiveOutMask(const uint32_t * Mask) const3487330f729Sjoerg StackMaps::parseRegisterLiveOutMask(const uint32_t *Mask) const {
3497330f729Sjoerg   assert(Mask && "No register mask specified");
3507330f729Sjoerg   const TargetRegisterInfo *TRI = AP.MF->getSubtarget().getRegisterInfo();
3517330f729Sjoerg   LiveOutVec LiveOuts;
3527330f729Sjoerg 
3537330f729Sjoerg   // Create a LiveOutReg for each bit that is set in the register mask.
3547330f729Sjoerg   for (unsigned Reg = 0, NumRegs = TRI->getNumRegs(); Reg != NumRegs; ++Reg)
355*82d56013Sjoerg     if ((Mask[Reg / 32] >> (Reg % 32)) & 1)
3567330f729Sjoerg       LiveOuts.push_back(createLiveOutReg(Reg, TRI));
3577330f729Sjoerg 
3587330f729Sjoerg   // We don't need to keep track of a register if its super-register is already
3597330f729Sjoerg   // in the list. Merge entries that refer to the same dwarf register and use
3607330f729Sjoerg   // the maximum size that needs to be spilled.
3617330f729Sjoerg 
3627330f729Sjoerg   llvm::sort(LiveOuts, [](const LiveOutReg &LHS, const LiveOutReg &RHS) {
3637330f729Sjoerg     // Only sort by the dwarf register number.
3647330f729Sjoerg     return LHS.DwarfRegNum < RHS.DwarfRegNum;
3657330f729Sjoerg   });
3667330f729Sjoerg 
3677330f729Sjoerg   for (auto I = LiveOuts.begin(), E = LiveOuts.end(); I != E; ++I) {
3687330f729Sjoerg     for (auto II = std::next(I); II != E; ++II) {
3697330f729Sjoerg       if (I->DwarfRegNum != II->DwarfRegNum) {
3707330f729Sjoerg         // Skip all the now invalid entries.
3717330f729Sjoerg         I = --II;
3727330f729Sjoerg         break;
3737330f729Sjoerg       }
3747330f729Sjoerg       I->Size = std::max(I->Size, II->Size);
3757330f729Sjoerg       if (TRI->isSuperRegister(I->Reg, II->Reg))
3767330f729Sjoerg         I->Reg = II->Reg;
3777330f729Sjoerg       II->Reg = 0; // mark for deletion.
3787330f729Sjoerg     }
3797330f729Sjoerg   }
3807330f729Sjoerg 
381*82d56013Sjoerg   llvm::erase_if(LiveOuts, [](const LiveOutReg &LO) { return LO.Reg == 0; });
3827330f729Sjoerg 
3837330f729Sjoerg   return LiveOuts;
3847330f729Sjoerg }
3857330f729Sjoerg 
386*82d56013Sjoerg // See statepoint MI format description in StatepointOpers' class comment
387*82d56013Sjoerg // in include/llvm/CodeGen/StackMaps.h
parseStatepointOpers(const MachineInstr & MI,MachineInstr::const_mop_iterator MOI,MachineInstr::const_mop_iterator MOE,LocationVec & Locations,LiveOutVec & LiveOuts)388*82d56013Sjoerg void StackMaps::parseStatepointOpers(const MachineInstr &MI,
389*82d56013Sjoerg                                      MachineInstr::const_mop_iterator MOI,
390*82d56013Sjoerg                                      MachineInstr::const_mop_iterator MOE,
391*82d56013Sjoerg                                      LocationVec &Locations,
392*82d56013Sjoerg                                      LiveOutVec &LiveOuts) {
393*82d56013Sjoerg   LLVM_DEBUG(dbgs() << "record statepoint : " << MI << "\n");
394*82d56013Sjoerg   StatepointOpers SO(&MI);
395*82d56013Sjoerg   MOI = parseOperand(MOI, MOE, Locations, LiveOuts); // CC
396*82d56013Sjoerg   MOI = parseOperand(MOI, MOE, Locations, LiveOuts); // Flags
397*82d56013Sjoerg   MOI = parseOperand(MOI, MOE, Locations, LiveOuts); // Num Deopts
398*82d56013Sjoerg 
399*82d56013Sjoerg   // Record Deopt Args.
400*82d56013Sjoerg   unsigned NumDeoptArgs = Locations.back().Offset;
401*82d56013Sjoerg   assert(Locations.back().Type == Location::Constant);
402*82d56013Sjoerg   assert(NumDeoptArgs == SO.getNumDeoptArgs());
403*82d56013Sjoerg 
404*82d56013Sjoerg   while (NumDeoptArgs--)
405*82d56013Sjoerg     MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
406*82d56013Sjoerg 
407*82d56013Sjoerg   // Record gc base/derived pairs
408*82d56013Sjoerg   assert(MOI->isImm() && MOI->getImm() == StackMaps::ConstantOp);
409*82d56013Sjoerg   ++MOI;
410*82d56013Sjoerg   assert(MOI->isImm());
411*82d56013Sjoerg   unsigned NumGCPointers = MOI->getImm();
412*82d56013Sjoerg   ++MOI;
413*82d56013Sjoerg   if (NumGCPointers) {
414*82d56013Sjoerg     // Map logical index of GC ptr to MI operand index.
415*82d56013Sjoerg     SmallVector<unsigned, 8> GCPtrIndices;
416*82d56013Sjoerg     unsigned GCPtrIdx = (unsigned)SO.getFirstGCPtrIdx();
417*82d56013Sjoerg     assert((int)GCPtrIdx != -1);
418*82d56013Sjoerg     assert(MOI - MI.operands_begin() == GCPtrIdx + 0LL);
419*82d56013Sjoerg     while (NumGCPointers--) {
420*82d56013Sjoerg       GCPtrIndices.push_back(GCPtrIdx);
421*82d56013Sjoerg       GCPtrIdx = StackMaps::getNextMetaArgIdx(&MI, GCPtrIdx);
422*82d56013Sjoerg     }
423*82d56013Sjoerg 
424*82d56013Sjoerg     SmallVector<std::pair<unsigned, unsigned>, 8> GCPairs;
425*82d56013Sjoerg     unsigned NumGCPairs = SO.getGCPointerMap(GCPairs);
426*82d56013Sjoerg     (void)NumGCPairs;
427*82d56013Sjoerg     LLVM_DEBUG(dbgs() << "NumGCPairs = " << NumGCPairs << "\n");
428*82d56013Sjoerg 
429*82d56013Sjoerg     auto MOB = MI.operands_begin();
430*82d56013Sjoerg     for (auto &P : GCPairs) {
431*82d56013Sjoerg       assert(P.first < GCPtrIndices.size() && "base pointer index not found");
432*82d56013Sjoerg       assert(P.second < GCPtrIndices.size() &&
433*82d56013Sjoerg              "derived pointer index not found");
434*82d56013Sjoerg       unsigned BaseIdx = GCPtrIndices[P.first];
435*82d56013Sjoerg       unsigned DerivedIdx = GCPtrIndices[P.second];
436*82d56013Sjoerg       LLVM_DEBUG(dbgs() << "Base : " << BaseIdx << " Derived : " << DerivedIdx
437*82d56013Sjoerg                         << "\n");
438*82d56013Sjoerg       (void)parseOperand(MOB + BaseIdx, MOE, Locations, LiveOuts);
439*82d56013Sjoerg       (void)parseOperand(MOB + DerivedIdx, MOE, Locations, LiveOuts);
440*82d56013Sjoerg     }
441*82d56013Sjoerg 
442*82d56013Sjoerg     MOI = MOB + GCPtrIdx;
443*82d56013Sjoerg   }
444*82d56013Sjoerg 
445*82d56013Sjoerg   // Record gc allocas
446*82d56013Sjoerg   assert(MOI < MOE);
447*82d56013Sjoerg   assert(MOI->isImm() && MOI->getImm() == StackMaps::ConstantOp);
448*82d56013Sjoerg   ++MOI;
449*82d56013Sjoerg   unsigned NumAllocas = MOI->getImm();
450*82d56013Sjoerg   ++MOI;
451*82d56013Sjoerg   while (NumAllocas--) {
452*82d56013Sjoerg     MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
453*82d56013Sjoerg     assert(MOI < MOE);
454*82d56013Sjoerg   }
455*82d56013Sjoerg }
456*82d56013Sjoerg 
recordStackMapOpers(const MCSymbol & MILabel,const MachineInstr & MI,uint64_t ID,MachineInstr::const_mop_iterator MOI,MachineInstr::const_mop_iterator MOE,bool recordResult)457*82d56013Sjoerg void StackMaps::recordStackMapOpers(const MCSymbol &MILabel,
458*82d56013Sjoerg                                     const MachineInstr &MI, uint64_t ID,
4597330f729Sjoerg                                     MachineInstr::const_mop_iterator MOI,
4607330f729Sjoerg                                     MachineInstr::const_mop_iterator MOE,
4617330f729Sjoerg                                     bool recordResult) {
4627330f729Sjoerg   MCContext &OutContext = AP.OutStreamer->getContext();
4637330f729Sjoerg 
4647330f729Sjoerg   LocationVec Locations;
4657330f729Sjoerg   LiveOutVec LiveOuts;
4667330f729Sjoerg 
4677330f729Sjoerg   if (recordResult) {
4687330f729Sjoerg     assert(PatchPointOpers(&MI).hasDef() && "Stackmap has no return value.");
4697330f729Sjoerg     parseOperand(MI.operands_begin(), std::next(MI.operands_begin()), Locations,
4707330f729Sjoerg                  LiveOuts);
4717330f729Sjoerg   }
4727330f729Sjoerg 
4737330f729Sjoerg   // Parse operands.
474*82d56013Sjoerg   if (MI.getOpcode() == TargetOpcode::STATEPOINT)
475*82d56013Sjoerg     parseStatepointOpers(MI, MOI, MOE, Locations, LiveOuts);
476*82d56013Sjoerg   else
477*82d56013Sjoerg     while (MOI != MOE)
4787330f729Sjoerg       MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
4797330f729Sjoerg 
4807330f729Sjoerg   // Move large constants into the constant pool.
4817330f729Sjoerg   for (auto &Loc : Locations) {
4827330f729Sjoerg     // Constants are encoded as sign-extended integers.
4837330f729Sjoerg     // -1 is directly encoded as .long 0xFFFFFFFF with no constant pool.
4847330f729Sjoerg     if (Loc.Type == Location::Constant && !isInt<32>(Loc.Offset)) {
4857330f729Sjoerg       Loc.Type = Location::ConstantIndex;
4867330f729Sjoerg       // ConstPool is intentionally a MapVector of 'uint64_t's (as
4877330f729Sjoerg       // opposed to 'int64_t's).  We should never be in a situation
4887330f729Sjoerg       // where we have to insert either the tombstone or the empty
4897330f729Sjoerg       // keys into a map, and for a DenseMap<uint64_t, T> these are
4907330f729Sjoerg       // (uint64_t)0 and (uint64_t)-1.  They can be and are
4917330f729Sjoerg       // represented using 32 bit integers.
4927330f729Sjoerg       assert((uint64_t)Loc.Offset != DenseMapInfo<uint64_t>::getEmptyKey() &&
4937330f729Sjoerg              (uint64_t)Loc.Offset !=
4947330f729Sjoerg                  DenseMapInfo<uint64_t>::getTombstoneKey() &&
4957330f729Sjoerg              "empty and tombstone keys should fit in 32 bits!");
4967330f729Sjoerg       auto Result = ConstPool.insert(std::make_pair(Loc.Offset, Loc.Offset));
4977330f729Sjoerg       Loc.Offset = Result.first - ConstPool.begin();
4987330f729Sjoerg     }
4997330f729Sjoerg   }
5007330f729Sjoerg 
5017330f729Sjoerg   // Create an expression to calculate the offset of the callsite from function
5027330f729Sjoerg   // entry.
5037330f729Sjoerg   const MCExpr *CSOffsetExpr = MCBinaryExpr::createSub(
504*82d56013Sjoerg       MCSymbolRefExpr::create(&MILabel, OutContext),
5057330f729Sjoerg       MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);
5067330f729Sjoerg 
5077330f729Sjoerg   CSInfos.emplace_back(CSOffsetExpr, ID, std::move(Locations),
5087330f729Sjoerg                        std::move(LiveOuts));
5097330f729Sjoerg 
5107330f729Sjoerg   // Record the stack size of the current function and update callsite count.
5117330f729Sjoerg   const MachineFrameInfo &MFI = AP.MF->getFrameInfo();
5127330f729Sjoerg   const TargetRegisterInfo *RegInfo = AP.MF->getSubtarget().getRegisterInfo();
5137330f729Sjoerg   bool HasDynamicFrameSize =
514*82d56013Sjoerg       MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(*(AP.MF));
5157330f729Sjoerg   uint64_t FrameSize = HasDynamicFrameSize ? UINT64_MAX : MFI.getStackSize();
5167330f729Sjoerg 
5177330f729Sjoerg   auto CurrentIt = FnInfos.find(AP.CurrentFnSym);
5187330f729Sjoerg   if (CurrentIt != FnInfos.end())
5197330f729Sjoerg     CurrentIt->second.RecordCount++;
5207330f729Sjoerg   else
5217330f729Sjoerg     FnInfos.insert(std::make_pair(AP.CurrentFnSym, FunctionInfo(FrameSize)));
5227330f729Sjoerg }
5237330f729Sjoerg 
recordStackMap(const MCSymbol & L,const MachineInstr & MI)524*82d56013Sjoerg void StackMaps::recordStackMap(const MCSymbol &L, const MachineInstr &MI) {
5257330f729Sjoerg   assert(MI.getOpcode() == TargetOpcode::STACKMAP && "expected stackmap");
5267330f729Sjoerg 
5277330f729Sjoerg   StackMapOpers opers(&MI);
5287330f729Sjoerg   const int64_t ID = MI.getOperand(PatchPointOpers::IDPos).getImm();
529*82d56013Sjoerg   recordStackMapOpers(L, MI, ID, std::next(MI.operands_begin(),
530*82d56013Sjoerg                                            opers.getVarIdx()),
5317330f729Sjoerg                       MI.operands_end());
5327330f729Sjoerg }
5337330f729Sjoerg 
recordPatchPoint(const MCSymbol & L,const MachineInstr & MI)534*82d56013Sjoerg void StackMaps::recordPatchPoint(const MCSymbol &L, const MachineInstr &MI) {
5357330f729Sjoerg   assert(MI.getOpcode() == TargetOpcode::PATCHPOINT && "expected patchpoint");
5367330f729Sjoerg 
5377330f729Sjoerg   PatchPointOpers opers(&MI);
5387330f729Sjoerg   const int64_t ID = opers.getID();
5397330f729Sjoerg   auto MOI = std::next(MI.operands_begin(), opers.getStackMapStartIdx());
540*82d56013Sjoerg   recordStackMapOpers(L, MI, ID, MOI, MI.operands_end(),
5417330f729Sjoerg                       opers.isAnyReg() && opers.hasDef());
5427330f729Sjoerg 
5437330f729Sjoerg #ifndef NDEBUG
5447330f729Sjoerg   // verify anyregcc
5457330f729Sjoerg   auto &Locations = CSInfos.back().Locations;
5467330f729Sjoerg   if (opers.isAnyReg()) {
5477330f729Sjoerg     unsigned NArgs = opers.getNumCallArgs();
5487330f729Sjoerg     for (unsigned i = 0, e = (opers.hasDef() ? NArgs + 1 : NArgs); i != e; ++i)
5497330f729Sjoerg       assert(Locations[i].Type == Location::Register &&
5507330f729Sjoerg              "anyreg arg must be in reg.");
5517330f729Sjoerg   }
5527330f729Sjoerg #endif
5537330f729Sjoerg }
5547330f729Sjoerg 
recordStatepoint(const MCSymbol & L,const MachineInstr & MI)555*82d56013Sjoerg void StackMaps::recordStatepoint(const MCSymbol &L, const MachineInstr &MI) {
5567330f729Sjoerg   assert(MI.getOpcode() == TargetOpcode::STATEPOINT && "expected statepoint");
5577330f729Sjoerg 
5587330f729Sjoerg   StatepointOpers opers(&MI);
5597330f729Sjoerg   const unsigned StartIdx = opers.getVarIdx();
560*82d56013Sjoerg   recordStackMapOpers(L, MI, opers.getID(), MI.operands_begin() + StartIdx,
5617330f729Sjoerg                       MI.operands_end(), false);
5627330f729Sjoerg }
5637330f729Sjoerg 
5647330f729Sjoerg /// Emit the stackmap header.
5657330f729Sjoerg ///
5667330f729Sjoerg /// Header {
567*82d56013Sjoerg ///   uint8  : Stack Map Version (currently 3)
5687330f729Sjoerg ///   uint8  : Reserved (expected to be 0)
5697330f729Sjoerg ///   uint16 : Reserved (expected to be 0)
5707330f729Sjoerg /// }
5717330f729Sjoerg /// uint32 : NumFunctions
5727330f729Sjoerg /// uint32 : NumConstants
5737330f729Sjoerg /// uint32 : NumRecords
emitStackmapHeader(MCStreamer & OS)5747330f729Sjoerg void StackMaps::emitStackmapHeader(MCStreamer &OS) {
5757330f729Sjoerg   // Header.
576*82d56013Sjoerg   OS.emitIntValue(StackMapVersion, 1); // Version.
577*82d56013Sjoerg   OS.emitIntValue(0, 1);               // Reserved.
578*82d56013Sjoerg   OS.emitInt16(0);                     // Reserved.
5797330f729Sjoerg 
5807330f729Sjoerg   // Num functions.
5817330f729Sjoerg   LLVM_DEBUG(dbgs() << WSMP << "#functions = " << FnInfos.size() << '\n');
582*82d56013Sjoerg   OS.emitInt32(FnInfos.size());
5837330f729Sjoerg   // Num constants.
5847330f729Sjoerg   LLVM_DEBUG(dbgs() << WSMP << "#constants = " << ConstPool.size() << '\n');
585*82d56013Sjoerg   OS.emitInt32(ConstPool.size());
5867330f729Sjoerg   // Num callsites.
5877330f729Sjoerg   LLVM_DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << '\n');
588*82d56013Sjoerg   OS.emitInt32(CSInfos.size());
5897330f729Sjoerg }
5907330f729Sjoerg 
5917330f729Sjoerg /// Emit the function frame record for each function.
5927330f729Sjoerg ///
5937330f729Sjoerg /// StkSizeRecord[NumFunctions] {
5947330f729Sjoerg ///   uint64 : Function Address
5957330f729Sjoerg ///   uint64 : Stack Size
5967330f729Sjoerg ///   uint64 : Record Count
5977330f729Sjoerg /// }
emitFunctionFrameRecords(MCStreamer & OS)5987330f729Sjoerg void StackMaps::emitFunctionFrameRecords(MCStreamer &OS) {
5997330f729Sjoerg   // Function Frame records.
6007330f729Sjoerg   LLVM_DEBUG(dbgs() << WSMP << "functions:\n");
6017330f729Sjoerg   for (auto const &FR : FnInfos) {
6027330f729Sjoerg     LLVM_DEBUG(dbgs() << WSMP << "function addr: " << FR.first
6037330f729Sjoerg                       << " frame size: " << FR.second.StackSize
6047330f729Sjoerg                       << " callsite count: " << FR.second.RecordCount << '\n');
605*82d56013Sjoerg     OS.emitSymbolValue(FR.first, 8);
606*82d56013Sjoerg     OS.emitIntValue(FR.second.StackSize, 8);
607*82d56013Sjoerg     OS.emitIntValue(FR.second.RecordCount, 8);
6087330f729Sjoerg   }
6097330f729Sjoerg }
6107330f729Sjoerg 
6117330f729Sjoerg /// Emit the constant pool.
6127330f729Sjoerg ///
6137330f729Sjoerg /// int64  : Constants[NumConstants]
emitConstantPoolEntries(MCStreamer & OS)6147330f729Sjoerg void StackMaps::emitConstantPoolEntries(MCStreamer &OS) {
6157330f729Sjoerg   // Constant pool entries.
6167330f729Sjoerg   LLVM_DEBUG(dbgs() << WSMP << "constants:\n");
6177330f729Sjoerg   for (const auto &ConstEntry : ConstPool) {
6187330f729Sjoerg     LLVM_DEBUG(dbgs() << WSMP << ConstEntry.second << '\n');
619*82d56013Sjoerg     OS.emitIntValue(ConstEntry.second, 8);
6207330f729Sjoerg   }
6217330f729Sjoerg }
6227330f729Sjoerg 
6237330f729Sjoerg /// Emit the callsite info for each callsite.
6247330f729Sjoerg ///
6257330f729Sjoerg /// StkMapRecord[NumRecords] {
6267330f729Sjoerg ///   uint64 : PatchPoint ID
6277330f729Sjoerg ///   uint32 : Instruction Offset
6287330f729Sjoerg ///   uint16 : Reserved (record flags)
6297330f729Sjoerg ///   uint16 : NumLocations
6307330f729Sjoerg ///   Location[NumLocations] {
6317330f729Sjoerg ///     uint8  : Register | Direct | Indirect | Constant | ConstantIndex
6327330f729Sjoerg ///     uint8  : Size in Bytes
6337330f729Sjoerg ///     uint16 : Dwarf RegNum
6347330f729Sjoerg ///     int32  : Offset
6357330f729Sjoerg ///   }
6367330f729Sjoerg ///   uint16 : Padding
6377330f729Sjoerg ///   uint16 : NumLiveOuts
6387330f729Sjoerg ///   LiveOuts[NumLiveOuts] {
6397330f729Sjoerg ///     uint16 : Dwarf RegNum
6407330f729Sjoerg ///     uint8  : Reserved
6417330f729Sjoerg ///     uint8  : Size in Bytes
6427330f729Sjoerg ///   }
6437330f729Sjoerg ///   uint32 : Padding (only if required to align to 8 byte)
6447330f729Sjoerg /// }
6457330f729Sjoerg ///
6467330f729Sjoerg /// Location Encoding, Type, Value:
6477330f729Sjoerg ///   0x1, Register, Reg                 (value in register)
6487330f729Sjoerg ///   0x2, Direct, Reg + Offset          (frame index)
6497330f729Sjoerg ///   0x3, Indirect, [Reg + Offset]      (spilled value)
6507330f729Sjoerg ///   0x4, Constant, Offset              (small constant)
6517330f729Sjoerg ///   0x5, ConstIndex, Constants[Offset] (large constant)
emitCallsiteEntries(MCStreamer & OS)6527330f729Sjoerg void StackMaps::emitCallsiteEntries(MCStreamer &OS) {
6537330f729Sjoerg   LLVM_DEBUG(print(dbgs()));
6547330f729Sjoerg   // Callsite entries.
6557330f729Sjoerg   for (const auto &CSI : CSInfos) {
6567330f729Sjoerg     const LocationVec &CSLocs = CSI.Locations;
6577330f729Sjoerg     const LiveOutVec &LiveOuts = CSI.LiveOuts;
6587330f729Sjoerg 
6597330f729Sjoerg     // Verify stack map entry. It's better to communicate a problem to the
6607330f729Sjoerg     // runtime than crash in case of in-process compilation. Currently, we do
6617330f729Sjoerg     // simple overflow checks, but we may eventually communicate other
6627330f729Sjoerg     // compilation errors this way.
6637330f729Sjoerg     if (CSLocs.size() > UINT16_MAX || LiveOuts.size() > UINT16_MAX) {
664*82d56013Sjoerg       OS.emitIntValue(UINT64_MAX, 8); // Invalid ID.
665*82d56013Sjoerg       OS.emitValue(CSI.CSOffsetExpr, 4);
666*82d56013Sjoerg       OS.emitInt16(0); // Reserved.
667*82d56013Sjoerg       OS.emitInt16(0); // 0 locations.
668*82d56013Sjoerg       OS.emitInt16(0); // padding.
669*82d56013Sjoerg       OS.emitInt16(0); // 0 live-out registers.
670*82d56013Sjoerg       OS.emitInt32(0); // padding.
6717330f729Sjoerg       continue;
6727330f729Sjoerg     }
6737330f729Sjoerg 
674*82d56013Sjoerg     OS.emitIntValue(CSI.ID, 8);
675*82d56013Sjoerg     OS.emitValue(CSI.CSOffsetExpr, 4);
6767330f729Sjoerg 
6777330f729Sjoerg     // Reserved for flags.
678*82d56013Sjoerg     OS.emitInt16(0);
679*82d56013Sjoerg     OS.emitInt16(CSLocs.size());
6807330f729Sjoerg 
6817330f729Sjoerg     for (const auto &Loc : CSLocs) {
682*82d56013Sjoerg       OS.emitIntValue(Loc.Type, 1);
683*82d56013Sjoerg       OS.emitIntValue(0, 1);  // Reserved
684*82d56013Sjoerg       OS.emitInt16(Loc.Size);
685*82d56013Sjoerg       OS.emitInt16(Loc.Reg);
686*82d56013Sjoerg       OS.emitInt16(0); // Reserved
687*82d56013Sjoerg       OS.emitInt32(Loc.Offset);
6887330f729Sjoerg     }
6897330f729Sjoerg 
6907330f729Sjoerg     // Emit alignment to 8 byte.
691*82d56013Sjoerg     OS.emitValueToAlignment(8);
6927330f729Sjoerg 
6937330f729Sjoerg     // Num live-out registers and padding to align to 4 byte.
694*82d56013Sjoerg     OS.emitInt16(0);
695*82d56013Sjoerg     OS.emitInt16(LiveOuts.size());
6967330f729Sjoerg 
6977330f729Sjoerg     for (const auto &LO : LiveOuts) {
698*82d56013Sjoerg       OS.emitInt16(LO.DwarfRegNum);
699*82d56013Sjoerg       OS.emitIntValue(0, 1);
700*82d56013Sjoerg       OS.emitIntValue(LO.Size, 1);
7017330f729Sjoerg     }
7027330f729Sjoerg     // Emit alignment to 8 byte.
703*82d56013Sjoerg     OS.emitValueToAlignment(8);
7047330f729Sjoerg   }
7057330f729Sjoerg }
7067330f729Sjoerg 
7077330f729Sjoerg /// Serialize the stackmap data.
serializeToStackMapSection()7087330f729Sjoerg void StackMaps::serializeToStackMapSection() {
7097330f729Sjoerg   (void)WSMP;
7107330f729Sjoerg   // Bail out if there's no stack map data.
7117330f729Sjoerg   assert((!CSInfos.empty() || ConstPool.empty()) &&
7127330f729Sjoerg          "Expected empty constant pool too!");
7137330f729Sjoerg   assert((!CSInfos.empty() || FnInfos.empty()) &&
7147330f729Sjoerg          "Expected empty function record too!");
7157330f729Sjoerg   if (CSInfos.empty())
7167330f729Sjoerg     return;
7177330f729Sjoerg 
7187330f729Sjoerg   MCContext &OutContext = AP.OutStreamer->getContext();
7197330f729Sjoerg   MCStreamer &OS = *AP.OutStreamer;
7207330f729Sjoerg 
7217330f729Sjoerg   // Create the section.
7227330f729Sjoerg   MCSection *StackMapSection =
7237330f729Sjoerg       OutContext.getObjectFileInfo()->getStackMapSection();
7247330f729Sjoerg   OS.SwitchSection(StackMapSection);
7257330f729Sjoerg 
7267330f729Sjoerg   // Emit a dummy symbol to force section inclusion.
727*82d56013Sjoerg   OS.emitLabel(OutContext.getOrCreateSymbol(Twine("__LLVM_StackMaps")));
7287330f729Sjoerg 
7297330f729Sjoerg   // Serialize data.
7307330f729Sjoerg   LLVM_DEBUG(dbgs() << "********** Stack Map Output **********\n");
7317330f729Sjoerg   emitStackmapHeader(OS);
7327330f729Sjoerg   emitFunctionFrameRecords(OS);
7337330f729Sjoerg   emitConstantPoolEntries(OS);
7347330f729Sjoerg   emitCallsiteEntries(OS);
7357330f729Sjoerg   OS.AddBlankLine();
7367330f729Sjoerg 
7377330f729Sjoerg   // Clean up.
7387330f729Sjoerg   CSInfos.clear();
7397330f729Sjoerg   ConstPool.clear();
7407330f729Sjoerg }
741