xref: /aosp_15_r20/external/llvm/lib/CodeGen/StackMaps.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===---------------------------- StackMaps.cpp ---------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/StackMaps.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/AsmPrinter.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstr.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DataLayout.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectFileInfo.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSectionMachO.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCStreamer.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetOpcodes.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetRegisterInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetSubtargetInfo.h"
26*9880d681SAndroid Build Coastguard Worker #include <iterator>
27*9880d681SAndroid Build Coastguard Worker 
28*9880d681SAndroid Build Coastguard Worker using namespace llvm;
29*9880d681SAndroid Build Coastguard Worker 
30*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "stackmaps"
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker static cl::opt<int> StackMapVersion(
33*9880d681SAndroid Build Coastguard Worker     "stackmap-version", cl::init(1),
34*9880d681SAndroid Build Coastguard Worker     cl::desc("Specify the stackmap encoding version (default = 1)"));
35*9880d681SAndroid Build Coastguard Worker 
36*9880d681SAndroid Build Coastguard Worker const char *StackMaps::WSMP = "Stack Maps: ";
37*9880d681SAndroid Build Coastguard Worker 
PatchPointOpers(const MachineInstr * MI)38*9880d681SAndroid Build Coastguard Worker PatchPointOpers::PatchPointOpers(const MachineInstr *MI)
39*9880d681SAndroid Build Coastguard Worker     : MI(MI), HasDef(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() &&
40*9880d681SAndroid Build Coastguard Worker                      !MI->getOperand(0).isImplicit()),
41*9880d681SAndroid Build Coastguard Worker       IsAnyReg(MI->getOperand(getMetaIdx(CCPos)).getImm() ==
42*9880d681SAndroid Build Coastguard Worker                CallingConv::AnyReg) {
43*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
44*9880d681SAndroid Build Coastguard Worker   unsigned CheckStartIdx = 0, e = MI->getNumOperands();
45*9880d681SAndroid Build Coastguard Worker   while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).isReg() &&
46*9880d681SAndroid Build Coastguard Worker          MI->getOperand(CheckStartIdx).isDef() &&
47*9880d681SAndroid Build Coastguard Worker          !MI->getOperand(CheckStartIdx).isImplicit())
48*9880d681SAndroid Build Coastguard Worker     ++CheckStartIdx;
49*9880d681SAndroid Build Coastguard Worker 
50*9880d681SAndroid Build Coastguard Worker   assert(getMetaIdx() == CheckStartIdx &&
51*9880d681SAndroid Build Coastguard Worker          "Unexpected additional definition in Patchpoint intrinsic.");
52*9880d681SAndroid Build Coastguard Worker #endif
53*9880d681SAndroid Build Coastguard Worker }
54*9880d681SAndroid Build Coastguard Worker 
getNextScratchIdx(unsigned StartIdx) const55*9880d681SAndroid Build Coastguard Worker unsigned PatchPointOpers::getNextScratchIdx(unsigned StartIdx) const {
56*9880d681SAndroid Build Coastguard Worker   if (!StartIdx)
57*9880d681SAndroid Build Coastguard Worker     StartIdx = getVarIdx();
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker   // Find the next scratch register (implicit def and early clobber)
60*9880d681SAndroid Build Coastguard Worker   unsigned ScratchIdx = StartIdx, e = MI->getNumOperands();
61*9880d681SAndroid Build Coastguard Worker   while (ScratchIdx < e &&
62*9880d681SAndroid Build Coastguard Worker          !(MI->getOperand(ScratchIdx).isReg() &&
63*9880d681SAndroid Build Coastguard Worker            MI->getOperand(ScratchIdx).isDef() &&
64*9880d681SAndroid Build Coastguard Worker            MI->getOperand(ScratchIdx).isImplicit() &&
65*9880d681SAndroid Build Coastguard Worker            MI->getOperand(ScratchIdx).isEarlyClobber()))
66*9880d681SAndroid Build Coastguard Worker     ++ScratchIdx;
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker   assert(ScratchIdx != e && "No scratch register available");
69*9880d681SAndroid Build Coastguard Worker   return ScratchIdx;
70*9880d681SAndroid Build Coastguard Worker }
71*9880d681SAndroid Build Coastguard Worker 
StackMaps(AsmPrinter & AP)72*9880d681SAndroid Build Coastguard Worker StackMaps::StackMaps(AsmPrinter &AP) : AP(AP) {
73*9880d681SAndroid Build Coastguard Worker   if (StackMapVersion != 1)
74*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Unsupported stackmap version!");
75*9880d681SAndroid Build Coastguard Worker }
76*9880d681SAndroid Build Coastguard Worker 
77*9880d681SAndroid Build Coastguard Worker /// Go up the super-register chain until we hit a valid dwarf register number.
getDwarfRegNum(unsigned Reg,const TargetRegisterInfo * TRI)78*9880d681SAndroid Build Coastguard Worker static unsigned getDwarfRegNum(unsigned Reg, const TargetRegisterInfo *TRI) {
79*9880d681SAndroid Build Coastguard Worker   int RegNum = TRI->getDwarfRegNum(Reg, false);
80*9880d681SAndroid Build Coastguard Worker   for (MCSuperRegIterator SR(Reg, TRI); SR.isValid() && RegNum < 0; ++SR)
81*9880d681SAndroid Build Coastguard Worker     RegNum = TRI->getDwarfRegNum(*SR, false);
82*9880d681SAndroid Build Coastguard Worker 
83*9880d681SAndroid Build Coastguard Worker   assert(RegNum >= 0 && "Invalid Dwarf register number.");
84*9880d681SAndroid Build Coastguard Worker   return (unsigned)RegNum;
85*9880d681SAndroid Build Coastguard Worker }
86*9880d681SAndroid Build Coastguard Worker 
87*9880d681SAndroid Build Coastguard Worker MachineInstr::const_mop_iterator
parseOperand(MachineInstr::const_mop_iterator MOI,MachineInstr::const_mop_iterator MOE,LocationVec & Locs,LiveOutVec & LiveOuts) const88*9880d681SAndroid Build Coastguard Worker StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
89*9880d681SAndroid Build Coastguard Worker                         MachineInstr::const_mop_iterator MOE, LocationVec &Locs,
90*9880d681SAndroid Build Coastguard Worker                         LiveOutVec &LiveOuts) const {
91*9880d681SAndroid Build Coastguard Worker   const TargetRegisterInfo *TRI = AP.MF->getSubtarget().getRegisterInfo();
92*9880d681SAndroid Build Coastguard Worker   if (MOI->isImm()) {
93*9880d681SAndroid Build Coastguard Worker     switch (MOI->getImm()) {
94*9880d681SAndroid Build Coastguard Worker     default:
95*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Unrecognized operand type.");
96*9880d681SAndroid Build Coastguard Worker     case StackMaps::DirectMemRefOp: {
97*9880d681SAndroid Build Coastguard Worker       auto &DL = AP.MF->getDataLayout();
98*9880d681SAndroid Build Coastguard Worker 
99*9880d681SAndroid Build Coastguard Worker       unsigned Size = DL.getPointerSizeInBits();
100*9880d681SAndroid Build Coastguard Worker       assert((Size % 8) == 0 && "Need pointer size in bytes.");
101*9880d681SAndroid Build Coastguard Worker       Size /= 8;
102*9880d681SAndroid Build Coastguard Worker       unsigned Reg = (++MOI)->getReg();
103*9880d681SAndroid Build Coastguard Worker       int64_t Imm = (++MOI)->getImm();
104*9880d681SAndroid Build Coastguard Worker       Locs.emplace_back(StackMaps::Location::Direct, Size,
105*9880d681SAndroid Build Coastguard Worker                         getDwarfRegNum(Reg, TRI), Imm);
106*9880d681SAndroid Build Coastguard Worker       break;
107*9880d681SAndroid Build Coastguard Worker     }
108*9880d681SAndroid Build Coastguard Worker     case StackMaps::IndirectMemRefOp: {
109*9880d681SAndroid Build Coastguard Worker       int64_t Size = (++MOI)->getImm();
110*9880d681SAndroid Build Coastguard Worker       assert(Size > 0 && "Need a valid size for indirect memory locations.");
111*9880d681SAndroid Build Coastguard Worker       unsigned Reg = (++MOI)->getReg();
112*9880d681SAndroid Build Coastguard Worker       int64_t Imm = (++MOI)->getImm();
113*9880d681SAndroid Build Coastguard Worker       Locs.emplace_back(StackMaps::Location::Indirect, Size,
114*9880d681SAndroid Build Coastguard Worker                         getDwarfRegNum(Reg, TRI), Imm);
115*9880d681SAndroid Build Coastguard Worker       break;
116*9880d681SAndroid Build Coastguard Worker     }
117*9880d681SAndroid Build Coastguard Worker     case StackMaps::ConstantOp: {
118*9880d681SAndroid Build Coastguard Worker       ++MOI;
119*9880d681SAndroid Build Coastguard Worker       assert(MOI->isImm() && "Expected constant operand.");
120*9880d681SAndroid Build Coastguard Worker       int64_t Imm = MOI->getImm();
121*9880d681SAndroid Build Coastguard Worker       Locs.emplace_back(Location::Constant, sizeof(int64_t), 0, Imm);
122*9880d681SAndroid Build Coastguard Worker       break;
123*9880d681SAndroid Build Coastguard Worker     }
124*9880d681SAndroid Build Coastguard Worker     }
125*9880d681SAndroid Build Coastguard Worker     return ++MOI;
126*9880d681SAndroid Build Coastguard Worker   }
127*9880d681SAndroid Build Coastguard Worker 
128*9880d681SAndroid Build Coastguard Worker   // The physical register number will ultimately be encoded as a DWARF regno.
129*9880d681SAndroid Build Coastguard Worker   // The stack map also records the size of a spill slot that can hold the
130*9880d681SAndroid Build Coastguard Worker   // register content. (The runtime can track the actual size of the data type
131*9880d681SAndroid Build Coastguard Worker   // if it needs to.)
132*9880d681SAndroid Build Coastguard Worker   if (MOI->isReg()) {
133*9880d681SAndroid Build Coastguard Worker     // Skip implicit registers (this includes our scratch registers)
134*9880d681SAndroid Build Coastguard Worker     if (MOI->isImplicit())
135*9880d681SAndroid Build Coastguard Worker       return ++MOI;
136*9880d681SAndroid Build Coastguard Worker 
137*9880d681SAndroid Build Coastguard Worker     assert(TargetRegisterInfo::isPhysicalRegister(MOI->getReg()) &&
138*9880d681SAndroid Build Coastguard Worker            "Virtreg operands should have been rewritten before now.");
139*9880d681SAndroid Build Coastguard Worker     const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(MOI->getReg());
140*9880d681SAndroid Build Coastguard Worker     assert(!MOI->getSubReg() && "Physical subreg still around.");
141*9880d681SAndroid Build Coastguard Worker 
142*9880d681SAndroid Build Coastguard Worker     unsigned Offset = 0;
143*9880d681SAndroid Build Coastguard Worker     unsigned DwarfRegNum = getDwarfRegNum(MOI->getReg(), TRI);
144*9880d681SAndroid Build Coastguard Worker     unsigned LLVMRegNum = TRI->getLLVMRegNum(DwarfRegNum, false);
145*9880d681SAndroid Build Coastguard Worker     unsigned SubRegIdx = TRI->getSubRegIndex(LLVMRegNum, MOI->getReg());
146*9880d681SAndroid Build Coastguard Worker     if (SubRegIdx)
147*9880d681SAndroid Build Coastguard Worker       Offset = TRI->getSubRegIdxOffset(SubRegIdx);
148*9880d681SAndroid Build Coastguard Worker 
149*9880d681SAndroid Build Coastguard Worker     Locs.emplace_back(Location::Register, RC->getSize(), DwarfRegNum, Offset);
150*9880d681SAndroid Build Coastguard Worker     return ++MOI;
151*9880d681SAndroid Build Coastguard Worker   }
152*9880d681SAndroid Build Coastguard Worker 
153*9880d681SAndroid Build Coastguard Worker   if (MOI->isRegLiveOut())
154*9880d681SAndroid Build Coastguard Worker     LiveOuts = parseRegisterLiveOutMask(MOI->getRegLiveOut());
155*9880d681SAndroid Build Coastguard Worker 
156*9880d681SAndroid Build Coastguard Worker   return ++MOI;
157*9880d681SAndroid Build Coastguard Worker }
158*9880d681SAndroid Build Coastguard Worker 
print(raw_ostream & OS)159*9880d681SAndroid Build Coastguard Worker void StackMaps::print(raw_ostream &OS) {
160*9880d681SAndroid Build Coastguard Worker   const TargetRegisterInfo *TRI =
161*9880d681SAndroid Build Coastguard Worker       AP.MF ? AP.MF->getSubtarget().getRegisterInfo() : nullptr;
162*9880d681SAndroid Build Coastguard Worker   OS << WSMP << "callsites:\n";
163*9880d681SAndroid Build Coastguard Worker   for (const auto &CSI : CSInfos) {
164*9880d681SAndroid Build Coastguard Worker     const LocationVec &CSLocs = CSI.Locations;
165*9880d681SAndroid Build Coastguard Worker     const LiveOutVec &LiveOuts = CSI.LiveOuts;
166*9880d681SAndroid Build Coastguard Worker 
167*9880d681SAndroid Build Coastguard Worker     OS << WSMP << "callsite " << CSI.ID << "\n";
168*9880d681SAndroid Build Coastguard Worker     OS << WSMP << "  has " << CSLocs.size() << " locations\n";
169*9880d681SAndroid Build Coastguard Worker 
170*9880d681SAndroid Build Coastguard Worker     unsigned Idx = 0;
171*9880d681SAndroid Build Coastguard Worker     for (const auto &Loc : CSLocs) {
172*9880d681SAndroid Build Coastguard Worker       OS << WSMP << "\t\tLoc " << Idx << ": ";
173*9880d681SAndroid Build Coastguard Worker       switch (Loc.Type) {
174*9880d681SAndroid Build Coastguard Worker       case Location::Unprocessed:
175*9880d681SAndroid Build Coastguard Worker         OS << "<Unprocessed operand>";
176*9880d681SAndroid Build Coastguard Worker         break;
177*9880d681SAndroid Build Coastguard Worker       case Location::Register:
178*9880d681SAndroid Build Coastguard Worker         OS << "Register ";
179*9880d681SAndroid Build Coastguard Worker         if (TRI)
180*9880d681SAndroid Build Coastguard Worker           OS << TRI->getName(Loc.Reg);
181*9880d681SAndroid Build Coastguard Worker         else
182*9880d681SAndroid Build Coastguard Worker           OS << Loc.Reg;
183*9880d681SAndroid Build Coastguard Worker         break;
184*9880d681SAndroid Build Coastguard Worker       case Location::Direct:
185*9880d681SAndroid Build Coastguard Worker         OS << "Direct ";
186*9880d681SAndroid Build Coastguard Worker         if (TRI)
187*9880d681SAndroid Build Coastguard Worker           OS << TRI->getName(Loc.Reg);
188*9880d681SAndroid Build Coastguard Worker         else
189*9880d681SAndroid Build Coastguard Worker           OS << Loc.Reg;
190*9880d681SAndroid Build Coastguard Worker         if (Loc.Offset)
191*9880d681SAndroid Build Coastguard Worker           OS << " + " << Loc.Offset;
192*9880d681SAndroid Build Coastguard Worker         break;
193*9880d681SAndroid Build Coastguard Worker       case Location::Indirect:
194*9880d681SAndroid Build Coastguard Worker         OS << "Indirect ";
195*9880d681SAndroid Build Coastguard Worker         if (TRI)
196*9880d681SAndroid Build Coastguard Worker           OS << TRI->getName(Loc.Reg);
197*9880d681SAndroid Build Coastguard Worker         else
198*9880d681SAndroid Build Coastguard Worker           OS << Loc.Reg;
199*9880d681SAndroid Build Coastguard Worker         OS << "+" << Loc.Offset;
200*9880d681SAndroid Build Coastguard Worker         break;
201*9880d681SAndroid Build Coastguard Worker       case Location::Constant:
202*9880d681SAndroid Build Coastguard Worker         OS << "Constant " << Loc.Offset;
203*9880d681SAndroid Build Coastguard Worker         break;
204*9880d681SAndroid Build Coastguard Worker       case Location::ConstantIndex:
205*9880d681SAndroid Build Coastguard Worker         OS << "Constant Index " << Loc.Offset;
206*9880d681SAndroid Build Coastguard Worker         break;
207*9880d681SAndroid Build Coastguard Worker       }
208*9880d681SAndroid Build Coastguard Worker       OS << "\t[encoding: .byte " << Loc.Type << ", .byte " << Loc.Size
209*9880d681SAndroid Build Coastguard Worker          << ", .short " << Loc.Reg << ", .int " << Loc.Offset << "]\n";
210*9880d681SAndroid Build Coastguard Worker       Idx++;
211*9880d681SAndroid Build Coastguard Worker     }
212*9880d681SAndroid Build Coastguard Worker 
213*9880d681SAndroid Build Coastguard Worker     OS << WSMP << "\thas " << LiveOuts.size() << " live-out registers\n";
214*9880d681SAndroid Build Coastguard Worker 
215*9880d681SAndroid Build Coastguard Worker     Idx = 0;
216*9880d681SAndroid Build Coastguard Worker     for (const auto &LO : LiveOuts) {
217*9880d681SAndroid Build Coastguard Worker       OS << WSMP << "\t\tLO " << Idx << ": ";
218*9880d681SAndroid Build Coastguard Worker       if (TRI)
219*9880d681SAndroid Build Coastguard Worker         OS << TRI->getName(LO.Reg);
220*9880d681SAndroid Build Coastguard Worker       else
221*9880d681SAndroid Build Coastguard Worker         OS << LO.Reg;
222*9880d681SAndroid Build Coastguard Worker       OS << "\t[encoding: .short " << LO.DwarfRegNum << ", .byte 0, .byte "
223*9880d681SAndroid Build Coastguard Worker          << LO.Size << "]\n";
224*9880d681SAndroid Build Coastguard Worker       Idx++;
225*9880d681SAndroid Build Coastguard Worker     }
226*9880d681SAndroid Build Coastguard Worker   }
227*9880d681SAndroid Build Coastguard Worker }
228*9880d681SAndroid Build Coastguard Worker 
229*9880d681SAndroid Build Coastguard Worker /// Create a live-out register record for the given register Reg.
230*9880d681SAndroid Build Coastguard Worker StackMaps::LiveOutReg
createLiveOutReg(unsigned Reg,const TargetRegisterInfo * TRI) const231*9880d681SAndroid Build Coastguard Worker StackMaps::createLiveOutReg(unsigned Reg, const TargetRegisterInfo *TRI) const {
232*9880d681SAndroid Build Coastguard Worker   unsigned DwarfRegNum = getDwarfRegNum(Reg, TRI);
233*9880d681SAndroid Build Coastguard Worker   unsigned Size = TRI->getMinimalPhysRegClass(Reg)->getSize();
234*9880d681SAndroid Build Coastguard Worker   return LiveOutReg(Reg, DwarfRegNum, Size);
235*9880d681SAndroid Build Coastguard Worker }
236*9880d681SAndroid Build Coastguard Worker 
237*9880d681SAndroid Build Coastguard Worker /// Parse the register live-out mask and return a vector of live-out registers
238*9880d681SAndroid Build Coastguard Worker /// that need to be recorded in the stackmap.
239*9880d681SAndroid Build Coastguard Worker StackMaps::LiveOutVec
parseRegisterLiveOutMask(const uint32_t * Mask) const240*9880d681SAndroid Build Coastguard Worker StackMaps::parseRegisterLiveOutMask(const uint32_t *Mask) const {
241*9880d681SAndroid Build Coastguard Worker   assert(Mask && "No register mask specified");
242*9880d681SAndroid Build Coastguard Worker   const TargetRegisterInfo *TRI = AP.MF->getSubtarget().getRegisterInfo();
243*9880d681SAndroid Build Coastguard Worker   LiveOutVec LiveOuts;
244*9880d681SAndroid Build Coastguard Worker 
245*9880d681SAndroid Build Coastguard Worker   // Create a LiveOutReg for each bit that is set in the register mask.
246*9880d681SAndroid Build Coastguard Worker   for (unsigned Reg = 0, NumRegs = TRI->getNumRegs(); Reg != NumRegs; ++Reg)
247*9880d681SAndroid Build Coastguard Worker     if ((Mask[Reg / 32] >> Reg % 32) & 1)
248*9880d681SAndroid Build Coastguard Worker       LiveOuts.push_back(createLiveOutReg(Reg, TRI));
249*9880d681SAndroid Build Coastguard Worker 
250*9880d681SAndroid Build Coastguard Worker   // We don't need to keep track of a register if its super-register is already
251*9880d681SAndroid Build Coastguard Worker   // in the list. Merge entries that refer to the same dwarf register and use
252*9880d681SAndroid Build Coastguard Worker   // the maximum size that needs to be spilled.
253*9880d681SAndroid Build Coastguard Worker 
254*9880d681SAndroid Build Coastguard Worker   std::sort(LiveOuts.begin(), LiveOuts.end(),
255*9880d681SAndroid Build Coastguard Worker             [](const LiveOutReg &LHS, const LiveOutReg &RHS) {
256*9880d681SAndroid Build Coastguard Worker               // Only sort by the dwarf register number.
257*9880d681SAndroid Build Coastguard Worker               return LHS.DwarfRegNum < RHS.DwarfRegNum;
258*9880d681SAndroid Build Coastguard Worker             });
259*9880d681SAndroid Build Coastguard Worker 
260*9880d681SAndroid Build Coastguard Worker   for (auto I = LiveOuts.begin(), E = LiveOuts.end(); I != E; ++I) {
261*9880d681SAndroid Build Coastguard Worker     for (auto II = std::next(I); II != E; ++II) {
262*9880d681SAndroid Build Coastguard Worker       if (I->DwarfRegNum != II->DwarfRegNum) {
263*9880d681SAndroid Build Coastguard Worker         // Skip all the now invalid entries.
264*9880d681SAndroid Build Coastguard Worker         I = --II;
265*9880d681SAndroid Build Coastguard Worker         break;
266*9880d681SAndroid Build Coastguard Worker       }
267*9880d681SAndroid Build Coastguard Worker       I->Size = std::max(I->Size, II->Size);
268*9880d681SAndroid Build Coastguard Worker       if (TRI->isSuperRegister(I->Reg, II->Reg))
269*9880d681SAndroid Build Coastguard Worker         I->Reg = II->Reg;
270*9880d681SAndroid Build Coastguard Worker       II->Reg = 0; // mark for deletion.
271*9880d681SAndroid Build Coastguard Worker     }
272*9880d681SAndroid Build Coastguard Worker   }
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker   LiveOuts.erase(
275*9880d681SAndroid Build Coastguard Worker       std::remove_if(LiveOuts.begin(), LiveOuts.end(),
276*9880d681SAndroid Build Coastguard Worker                      [](const LiveOutReg &LO) { return LO.Reg == 0; }),
277*9880d681SAndroid Build Coastguard Worker       LiveOuts.end());
278*9880d681SAndroid Build Coastguard Worker 
279*9880d681SAndroid Build Coastguard Worker   return LiveOuts;
280*9880d681SAndroid Build Coastguard Worker }
281*9880d681SAndroid Build Coastguard Worker 
recordStackMapOpers(const MachineInstr & MI,uint64_t ID,MachineInstr::const_mop_iterator MOI,MachineInstr::const_mop_iterator MOE,bool recordResult)282*9880d681SAndroid Build Coastguard Worker void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
283*9880d681SAndroid Build Coastguard Worker                                     MachineInstr::const_mop_iterator MOI,
284*9880d681SAndroid Build Coastguard Worker                                     MachineInstr::const_mop_iterator MOE,
285*9880d681SAndroid Build Coastguard Worker                                     bool recordResult) {
286*9880d681SAndroid Build Coastguard Worker 
287*9880d681SAndroid Build Coastguard Worker   MCContext &OutContext = AP.OutStreamer->getContext();
288*9880d681SAndroid Build Coastguard Worker   MCSymbol *MILabel = OutContext.createTempSymbol();
289*9880d681SAndroid Build Coastguard Worker   AP.OutStreamer->EmitLabel(MILabel);
290*9880d681SAndroid Build Coastguard Worker 
291*9880d681SAndroid Build Coastguard Worker   LocationVec Locations;
292*9880d681SAndroid Build Coastguard Worker   LiveOutVec LiveOuts;
293*9880d681SAndroid Build Coastguard Worker 
294*9880d681SAndroid Build Coastguard Worker   if (recordResult) {
295*9880d681SAndroid Build Coastguard Worker     assert(PatchPointOpers(&MI).hasDef() && "Stackmap has no return value.");
296*9880d681SAndroid Build Coastguard Worker     parseOperand(MI.operands_begin(), std::next(MI.operands_begin()), Locations,
297*9880d681SAndroid Build Coastguard Worker                  LiveOuts);
298*9880d681SAndroid Build Coastguard Worker   }
299*9880d681SAndroid Build Coastguard Worker 
300*9880d681SAndroid Build Coastguard Worker   // Parse operands.
301*9880d681SAndroid Build Coastguard Worker   while (MOI != MOE) {
302*9880d681SAndroid Build Coastguard Worker     MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
303*9880d681SAndroid Build Coastguard Worker   }
304*9880d681SAndroid Build Coastguard Worker 
305*9880d681SAndroid Build Coastguard Worker   // Move large constants into the constant pool.
306*9880d681SAndroid Build Coastguard Worker   for (auto &Loc : Locations) {
307*9880d681SAndroid Build Coastguard Worker     // Constants are encoded as sign-extended integers.
308*9880d681SAndroid Build Coastguard Worker     // -1 is directly encoded as .long 0xFFFFFFFF with no constant pool.
309*9880d681SAndroid Build Coastguard Worker     if (Loc.Type == Location::Constant && !isInt<32>(Loc.Offset)) {
310*9880d681SAndroid Build Coastguard Worker       Loc.Type = Location::ConstantIndex;
311*9880d681SAndroid Build Coastguard Worker       // ConstPool is intentionally a MapVector of 'uint64_t's (as
312*9880d681SAndroid Build Coastguard Worker       // opposed to 'int64_t's).  We should never be in a situation
313*9880d681SAndroid Build Coastguard Worker       // where we have to insert either the tombstone or the empty
314*9880d681SAndroid Build Coastguard Worker       // keys into a map, and for a DenseMap<uint64_t, T> these are
315*9880d681SAndroid Build Coastguard Worker       // (uint64_t)0 and (uint64_t)-1.  They can be and are
316*9880d681SAndroid Build Coastguard Worker       // represented using 32 bit integers.
317*9880d681SAndroid Build Coastguard Worker       assert((uint64_t)Loc.Offset != DenseMapInfo<uint64_t>::getEmptyKey() &&
318*9880d681SAndroid Build Coastguard Worker              (uint64_t)Loc.Offset !=
319*9880d681SAndroid Build Coastguard Worker                  DenseMapInfo<uint64_t>::getTombstoneKey() &&
320*9880d681SAndroid Build Coastguard Worker              "empty and tombstone keys should fit in 32 bits!");
321*9880d681SAndroid Build Coastguard Worker       auto Result = ConstPool.insert(std::make_pair(Loc.Offset, Loc.Offset));
322*9880d681SAndroid Build Coastguard Worker       Loc.Offset = Result.first - ConstPool.begin();
323*9880d681SAndroid Build Coastguard Worker     }
324*9880d681SAndroid Build Coastguard Worker   }
325*9880d681SAndroid Build Coastguard Worker 
326*9880d681SAndroid Build Coastguard Worker   // Create an expression to calculate the offset of the callsite from function
327*9880d681SAndroid Build Coastguard Worker   // entry.
328*9880d681SAndroid Build Coastguard Worker   const MCExpr *CSOffsetExpr = MCBinaryExpr::createSub(
329*9880d681SAndroid Build Coastguard Worker       MCSymbolRefExpr::create(MILabel, OutContext),
330*9880d681SAndroid Build Coastguard Worker       MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);
331*9880d681SAndroid Build Coastguard Worker 
332*9880d681SAndroid Build Coastguard Worker   CSInfos.emplace_back(CSOffsetExpr, ID, std::move(Locations),
333*9880d681SAndroid Build Coastguard Worker                        std::move(LiveOuts));
334*9880d681SAndroid Build Coastguard Worker 
335*9880d681SAndroid Build Coastguard Worker   // Record the stack size of the current function.
336*9880d681SAndroid Build Coastguard Worker   const MachineFrameInfo *MFI = AP.MF->getFrameInfo();
337*9880d681SAndroid Build Coastguard Worker   const TargetRegisterInfo *RegInfo = AP.MF->getSubtarget().getRegisterInfo();
338*9880d681SAndroid Build Coastguard Worker   bool HasDynamicFrameSize =
339*9880d681SAndroid Build Coastguard Worker       MFI->hasVarSizedObjects() || RegInfo->needsStackRealignment(*(AP.MF));
340*9880d681SAndroid Build Coastguard Worker   FnStackSize[AP.CurrentFnSym] =
341*9880d681SAndroid Build Coastguard Worker       HasDynamicFrameSize ? UINT64_MAX : MFI->getStackSize();
342*9880d681SAndroid Build Coastguard Worker }
343*9880d681SAndroid Build Coastguard Worker 
recordStackMap(const MachineInstr & MI)344*9880d681SAndroid Build Coastguard Worker void StackMaps::recordStackMap(const MachineInstr &MI) {
345*9880d681SAndroid Build Coastguard Worker   assert(MI.getOpcode() == TargetOpcode::STACKMAP && "expected stackmap");
346*9880d681SAndroid Build Coastguard Worker 
347*9880d681SAndroid Build Coastguard Worker   int64_t ID = MI.getOperand(0).getImm();
348*9880d681SAndroid Build Coastguard Worker   recordStackMapOpers(MI, ID, std::next(MI.operands_begin(), 2),
349*9880d681SAndroid Build Coastguard Worker                       MI.operands_end());
350*9880d681SAndroid Build Coastguard Worker }
351*9880d681SAndroid Build Coastguard Worker 
recordPatchPoint(const MachineInstr & MI)352*9880d681SAndroid Build Coastguard Worker void StackMaps::recordPatchPoint(const MachineInstr &MI) {
353*9880d681SAndroid Build Coastguard Worker   assert(MI.getOpcode() == TargetOpcode::PATCHPOINT && "expected patchpoint");
354*9880d681SAndroid Build Coastguard Worker 
355*9880d681SAndroid Build Coastguard Worker   PatchPointOpers opers(&MI);
356*9880d681SAndroid Build Coastguard Worker   int64_t ID = opers.getMetaOper(PatchPointOpers::IDPos).getImm();
357*9880d681SAndroid Build Coastguard Worker 
358*9880d681SAndroid Build Coastguard Worker   auto MOI = std::next(MI.operands_begin(), opers.getStackMapStartIdx());
359*9880d681SAndroid Build Coastguard Worker   recordStackMapOpers(MI, ID, MOI, MI.operands_end(),
360*9880d681SAndroid Build Coastguard Worker                       opers.isAnyReg() && opers.hasDef());
361*9880d681SAndroid Build Coastguard Worker 
362*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
363*9880d681SAndroid Build Coastguard Worker   // verify anyregcc
364*9880d681SAndroid Build Coastguard Worker   auto &Locations = CSInfos.back().Locations;
365*9880d681SAndroid Build Coastguard Worker   if (opers.isAnyReg()) {
366*9880d681SAndroid Build Coastguard Worker     unsigned NArgs = opers.getMetaOper(PatchPointOpers::NArgPos).getImm();
367*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = (opers.hasDef() ? NArgs + 1 : NArgs); i != e; ++i)
368*9880d681SAndroid Build Coastguard Worker       assert(Locations[i].Type == Location::Register &&
369*9880d681SAndroid Build Coastguard Worker              "anyreg arg must be in reg.");
370*9880d681SAndroid Build Coastguard Worker   }
371*9880d681SAndroid Build Coastguard Worker #endif
372*9880d681SAndroid Build Coastguard Worker }
recordStatepoint(const MachineInstr & MI)373*9880d681SAndroid Build Coastguard Worker void StackMaps::recordStatepoint(const MachineInstr &MI) {
374*9880d681SAndroid Build Coastguard Worker   assert(MI.getOpcode() == TargetOpcode::STATEPOINT && "expected statepoint");
375*9880d681SAndroid Build Coastguard Worker 
376*9880d681SAndroid Build Coastguard Worker   StatepointOpers opers(&MI);
377*9880d681SAndroid Build Coastguard Worker   // Record all the deopt and gc operands (they're contiguous and run from the
378*9880d681SAndroid Build Coastguard Worker   // initial index to the end of the operand list)
379*9880d681SAndroid Build Coastguard Worker   const unsigned StartIdx = opers.getVarIdx();
380*9880d681SAndroid Build Coastguard Worker   recordStackMapOpers(MI, opers.getID(), MI.operands_begin() + StartIdx,
381*9880d681SAndroid Build Coastguard Worker                       MI.operands_end(), false);
382*9880d681SAndroid Build Coastguard Worker }
383*9880d681SAndroid Build Coastguard Worker 
384*9880d681SAndroid Build Coastguard Worker /// Emit the stackmap header.
385*9880d681SAndroid Build Coastguard Worker ///
386*9880d681SAndroid Build Coastguard Worker /// Header {
387*9880d681SAndroid Build Coastguard Worker ///   uint8  : Stack Map Version (currently 1)
388*9880d681SAndroid Build Coastguard Worker ///   uint8  : Reserved (expected to be 0)
389*9880d681SAndroid Build Coastguard Worker ///   uint16 : Reserved (expected to be 0)
390*9880d681SAndroid Build Coastguard Worker /// }
391*9880d681SAndroid Build Coastguard Worker /// uint32 : NumFunctions
392*9880d681SAndroid Build Coastguard Worker /// uint32 : NumConstants
393*9880d681SAndroid Build Coastguard Worker /// uint32 : NumRecords
emitStackmapHeader(MCStreamer & OS)394*9880d681SAndroid Build Coastguard Worker void StackMaps::emitStackmapHeader(MCStreamer &OS) {
395*9880d681SAndroid Build Coastguard Worker   // Header.
396*9880d681SAndroid Build Coastguard Worker   OS.EmitIntValue(StackMapVersion, 1); // Version.
397*9880d681SAndroid Build Coastguard Worker   OS.EmitIntValue(0, 1);               // Reserved.
398*9880d681SAndroid Build Coastguard Worker   OS.EmitIntValue(0, 2);               // Reserved.
399*9880d681SAndroid Build Coastguard Worker 
400*9880d681SAndroid Build Coastguard Worker   // Num functions.
401*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << WSMP << "#functions = " << FnStackSize.size() << '\n');
402*9880d681SAndroid Build Coastguard Worker   OS.EmitIntValue(FnStackSize.size(), 4);
403*9880d681SAndroid Build Coastguard Worker   // Num constants.
404*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << WSMP << "#constants = " << ConstPool.size() << '\n');
405*9880d681SAndroid Build Coastguard Worker   OS.EmitIntValue(ConstPool.size(), 4);
406*9880d681SAndroid Build Coastguard Worker   // Num callsites.
407*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << '\n');
408*9880d681SAndroid Build Coastguard Worker   OS.EmitIntValue(CSInfos.size(), 4);
409*9880d681SAndroid Build Coastguard Worker }
410*9880d681SAndroid Build Coastguard Worker 
411*9880d681SAndroid Build Coastguard Worker /// Emit the function frame record for each function.
412*9880d681SAndroid Build Coastguard Worker ///
413*9880d681SAndroid Build Coastguard Worker /// StkSizeRecord[NumFunctions] {
414*9880d681SAndroid Build Coastguard Worker ///   uint64 : Function Address
415*9880d681SAndroid Build Coastguard Worker ///   uint64 : Stack Size
416*9880d681SAndroid Build Coastguard Worker /// }
emitFunctionFrameRecords(MCStreamer & OS)417*9880d681SAndroid Build Coastguard Worker void StackMaps::emitFunctionFrameRecords(MCStreamer &OS) {
418*9880d681SAndroid Build Coastguard Worker   // Function Frame records.
419*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << WSMP << "functions:\n");
420*9880d681SAndroid Build Coastguard Worker   for (auto const &FR : FnStackSize) {
421*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << WSMP << "function addr: " << FR.first
422*9880d681SAndroid Build Coastguard Worker                  << " frame size: " << FR.second);
423*9880d681SAndroid Build Coastguard Worker     OS.EmitSymbolValue(FR.first, 8);
424*9880d681SAndroid Build Coastguard Worker     OS.EmitIntValue(FR.second, 8);
425*9880d681SAndroid Build Coastguard Worker   }
426*9880d681SAndroid Build Coastguard Worker }
427*9880d681SAndroid Build Coastguard Worker 
428*9880d681SAndroid Build Coastguard Worker /// Emit the constant pool.
429*9880d681SAndroid Build Coastguard Worker ///
430*9880d681SAndroid Build Coastguard Worker /// int64  : Constants[NumConstants]
emitConstantPoolEntries(MCStreamer & OS)431*9880d681SAndroid Build Coastguard Worker void StackMaps::emitConstantPoolEntries(MCStreamer &OS) {
432*9880d681SAndroid Build Coastguard Worker   // Constant pool entries.
433*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << WSMP << "constants:\n");
434*9880d681SAndroid Build Coastguard Worker   for (const auto &ConstEntry : ConstPool) {
435*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << WSMP << ConstEntry.second << '\n');
436*9880d681SAndroid Build Coastguard Worker     OS.EmitIntValue(ConstEntry.second, 8);
437*9880d681SAndroid Build Coastguard Worker   }
438*9880d681SAndroid Build Coastguard Worker }
439*9880d681SAndroid Build Coastguard Worker 
440*9880d681SAndroid Build Coastguard Worker /// Emit the callsite info for each callsite.
441*9880d681SAndroid Build Coastguard Worker ///
442*9880d681SAndroid Build Coastguard Worker /// StkMapRecord[NumRecords] {
443*9880d681SAndroid Build Coastguard Worker ///   uint64 : PatchPoint ID
444*9880d681SAndroid Build Coastguard Worker ///   uint32 : Instruction Offset
445*9880d681SAndroid Build Coastguard Worker ///   uint16 : Reserved (record flags)
446*9880d681SAndroid Build Coastguard Worker ///   uint16 : NumLocations
447*9880d681SAndroid Build Coastguard Worker ///   Location[NumLocations] {
448*9880d681SAndroid Build Coastguard Worker ///     uint8  : Register | Direct | Indirect | Constant | ConstantIndex
449*9880d681SAndroid Build Coastguard Worker ///     uint8  : Size in Bytes
450*9880d681SAndroid Build Coastguard Worker ///     uint16 : Dwarf RegNum
451*9880d681SAndroid Build Coastguard Worker ///     int32  : Offset
452*9880d681SAndroid Build Coastguard Worker ///   }
453*9880d681SAndroid Build Coastguard Worker ///   uint16 : Padding
454*9880d681SAndroid Build Coastguard Worker ///   uint16 : NumLiveOuts
455*9880d681SAndroid Build Coastguard Worker ///   LiveOuts[NumLiveOuts] {
456*9880d681SAndroid Build Coastguard Worker ///     uint16 : Dwarf RegNum
457*9880d681SAndroid Build Coastguard Worker ///     uint8  : Reserved
458*9880d681SAndroid Build Coastguard Worker ///     uint8  : Size in Bytes
459*9880d681SAndroid Build Coastguard Worker ///   }
460*9880d681SAndroid Build Coastguard Worker ///   uint32 : Padding (only if required to align to 8 byte)
461*9880d681SAndroid Build Coastguard Worker /// }
462*9880d681SAndroid Build Coastguard Worker ///
463*9880d681SAndroid Build Coastguard Worker /// Location Encoding, Type, Value:
464*9880d681SAndroid Build Coastguard Worker ///   0x1, Register, Reg                 (value in register)
465*9880d681SAndroid Build Coastguard Worker ///   0x2, Direct, Reg + Offset          (frame index)
466*9880d681SAndroid Build Coastguard Worker ///   0x3, Indirect, [Reg + Offset]      (spilled value)
467*9880d681SAndroid Build Coastguard Worker ///   0x4, Constant, Offset              (small constant)
468*9880d681SAndroid Build Coastguard Worker ///   0x5, ConstIndex, Constants[Offset] (large constant)
emitCallsiteEntries(MCStreamer & OS)469*9880d681SAndroid Build Coastguard Worker void StackMaps::emitCallsiteEntries(MCStreamer &OS) {
470*9880d681SAndroid Build Coastguard Worker   DEBUG(print(dbgs()));
471*9880d681SAndroid Build Coastguard Worker   // Callsite entries.
472*9880d681SAndroid Build Coastguard Worker   for (const auto &CSI : CSInfos) {
473*9880d681SAndroid Build Coastguard Worker     const LocationVec &CSLocs = CSI.Locations;
474*9880d681SAndroid Build Coastguard Worker     const LiveOutVec &LiveOuts = CSI.LiveOuts;
475*9880d681SAndroid Build Coastguard Worker 
476*9880d681SAndroid Build Coastguard Worker     // Verify stack map entry. It's better to communicate a problem to the
477*9880d681SAndroid Build Coastguard Worker     // runtime than crash in case of in-process compilation. Currently, we do
478*9880d681SAndroid Build Coastguard Worker     // simple overflow checks, but we may eventually communicate other
479*9880d681SAndroid Build Coastguard Worker     // compilation errors this way.
480*9880d681SAndroid Build Coastguard Worker     if (CSLocs.size() > UINT16_MAX || LiveOuts.size() > UINT16_MAX) {
481*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(UINT64_MAX, 8); // Invalid ID.
482*9880d681SAndroid Build Coastguard Worker       OS.EmitValue(CSI.CSOffsetExpr, 4);
483*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(0, 2); // Reserved.
484*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(0, 2); // 0 locations.
485*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(0, 2); // padding.
486*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(0, 2); // 0 live-out registers.
487*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(0, 4); // padding.
488*9880d681SAndroid Build Coastguard Worker       continue;
489*9880d681SAndroid Build Coastguard Worker     }
490*9880d681SAndroid Build Coastguard Worker 
491*9880d681SAndroid Build Coastguard Worker     OS.EmitIntValue(CSI.ID, 8);
492*9880d681SAndroid Build Coastguard Worker     OS.EmitValue(CSI.CSOffsetExpr, 4);
493*9880d681SAndroid Build Coastguard Worker 
494*9880d681SAndroid Build Coastguard Worker     // Reserved for flags.
495*9880d681SAndroid Build Coastguard Worker     OS.EmitIntValue(0, 2);
496*9880d681SAndroid Build Coastguard Worker     OS.EmitIntValue(CSLocs.size(), 2);
497*9880d681SAndroid Build Coastguard Worker 
498*9880d681SAndroid Build Coastguard Worker     for (const auto &Loc : CSLocs) {
499*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(Loc.Type, 1);
500*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(Loc.Size, 1);
501*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(Loc.Reg, 2);
502*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(Loc.Offset, 4);
503*9880d681SAndroid Build Coastguard Worker     }
504*9880d681SAndroid Build Coastguard Worker 
505*9880d681SAndroid Build Coastguard Worker     // Num live-out registers and padding to align to 4 byte.
506*9880d681SAndroid Build Coastguard Worker     OS.EmitIntValue(0, 2);
507*9880d681SAndroid Build Coastguard Worker     OS.EmitIntValue(LiveOuts.size(), 2);
508*9880d681SAndroid Build Coastguard Worker 
509*9880d681SAndroid Build Coastguard Worker     for (const auto &LO : LiveOuts) {
510*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(LO.DwarfRegNum, 2);
511*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(0, 1);
512*9880d681SAndroid Build Coastguard Worker       OS.EmitIntValue(LO.Size, 1);
513*9880d681SAndroid Build Coastguard Worker     }
514*9880d681SAndroid Build Coastguard Worker     // Emit alignment to 8 byte.
515*9880d681SAndroid Build Coastguard Worker     OS.EmitValueToAlignment(8);
516*9880d681SAndroid Build Coastguard Worker   }
517*9880d681SAndroid Build Coastguard Worker }
518*9880d681SAndroid Build Coastguard Worker 
519*9880d681SAndroid Build Coastguard Worker /// Serialize the stackmap data.
serializeToStackMapSection()520*9880d681SAndroid Build Coastguard Worker void StackMaps::serializeToStackMapSection() {
521*9880d681SAndroid Build Coastguard Worker   (void)WSMP;
522*9880d681SAndroid Build Coastguard Worker   // Bail out if there's no stack map data.
523*9880d681SAndroid Build Coastguard Worker   assert((!CSInfos.empty() || ConstPool.empty()) &&
524*9880d681SAndroid Build Coastguard Worker          "Expected empty constant pool too!");
525*9880d681SAndroid Build Coastguard Worker   assert((!CSInfos.empty() || FnStackSize.empty()) &&
526*9880d681SAndroid Build Coastguard Worker          "Expected empty function record too!");
527*9880d681SAndroid Build Coastguard Worker   if (CSInfos.empty())
528*9880d681SAndroid Build Coastguard Worker     return;
529*9880d681SAndroid Build Coastguard Worker 
530*9880d681SAndroid Build Coastguard Worker   MCContext &OutContext = AP.OutStreamer->getContext();
531*9880d681SAndroid Build Coastguard Worker   MCStreamer &OS = *AP.OutStreamer;
532*9880d681SAndroid Build Coastguard Worker 
533*9880d681SAndroid Build Coastguard Worker   // Create the section.
534*9880d681SAndroid Build Coastguard Worker   MCSection *StackMapSection =
535*9880d681SAndroid Build Coastguard Worker       OutContext.getObjectFileInfo()->getStackMapSection();
536*9880d681SAndroid Build Coastguard Worker   OS.SwitchSection(StackMapSection);
537*9880d681SAndroid Build Coastguard Worker 
538*9880d681SAndroid Build Coastguard Worker   // Emit a dummy symbol to force section inclusion.
539*9880d681SAndroid Build Coastguard Worker   OS.EmitLabel(OutContext.getOrCreateSymbol(Twine("__LLVM_StackMaps")));
540*9880d681SAndroid Build Coastguard Worker 
541*9880d681SAndroid Build Coastguard Worker   // Serialize data.
542*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "********** Stack Map Output **********\n");
543*9880d681SAndroid Build Coastguard Worker   emitStackmapHeader(OS);
544*9880d681SAndroid Build Coastguard Worker   emitFunctionFrameRecords(OS);
545*9880d681SAndroid Build Coastguard Worker   emitConstantPoolEntries(OS);
546*9880d681SAndroid Build Coastguard Worker   emitCallsiteEntries(OS);
547*9880d681SAndroid Build Coastguard Worker   OS.AddBlankLine();
548*9880d681SAndroid Build Coastguard Worker 
549*9880d681SAndroid Build Coastguard Worker   // Clean up.
550*9880d681SAndroid Build Coastguard Worker   CSInfos.clear();
551*9880d681SAndroid Build Coastguard Worker   ConstPool.clear();
552*9880d681SAndroid Build Coastguard Worker }
553