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