1f785676fSDimitry Andric //===---------------------------- StackMaps.cpp ---------------------------===//
2f785676fSDimitry Andric //
3f785676fSDimitry Andric //                     The LLVM Compiler Infrastructure
4f785676fSDimitry Andric //
5f785676fSDimitry Andric // This file is distributed under the University of Illinois Open Source
6f785676fSDimitry Andric // License. See LICENSE.TXT for details.
7f785676fSDimitry Andric //
8f785676fSDimitry Andric //===----------------------------------------------------------------------===//
9f785676fSDimitry Andric 
10f785676fSDimitry Andric #include "llvm/CodeGen/StackMaps.h"
11f785676fSDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
1291bc56edSDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
1391bc56edSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
14f785676fSDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
1591bc56edSDimitry Andric #include "llvm/IR/DataLayout.h"
16f785676fSDimitry Andric #include "llvm/MC/MCContext.h"
17f785676fSDimitry Andric #include "llvm/MC/MCExpr.h"
18f785676fSDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
19f785676fSDimitry Andric #include "llvm/MC/MCSectionMachO.h"
20f785676fSDimitry Andric #include "llvm/MC/MCStreamer.h"
2191bc56edSDimitry Andric #include "llvm/Support/CommandLine.h"
22f785676fSDimitry Andric #include "llvm/Support/Debug.h"
23f785676fSDimitry Andric #include "llvm/Support/raw_ostream.h"
24f785676fSDimitry Andric #include "llvm/Target/TargetMachine.h"
2591bc56edSDimitry Andric #include "llvm/Target/TargetOpcodes.h"
26f785676fSDimitry Andric #include "llvm/Target/TargetRegisterInfo.h"
27f785676fSDimitry Andric #include <iterator>
28f785676fSDimitry Andric 
29f785676fSDimitry Andric using namespace llvm;
30f785676fSDimitry Andric 
3191bc56edSDimitry Andric #define DEBUG_TYPE "stackmaps"
3291bc56edSDimitry Andric 
3391bc56edSDimitry Andric static cl::opt<int> StackMapVersion("stackmap-version", cl::init(1),
3491bc56edSDimitry Andric   cl::desc("Specify the stackmap encoding version (default = 1)"));
3591bc56edSDimitry Andric 
3691bc56edSDimitry Andric const char *StackMaps::WSMP = "Stack Maps: ";
3791bc56edSDimitry Andric 
3891bc56edSDimitry Andric PatchPointOpers::PatchPointOpers(const MachineInstr *MI)
3991bc56edSDimitry Andric   : MI(MI),
40f785676fSDimitry Andric     HasDef(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() &&
41f785676fSDimitry Andric            !MI->getOperand(0).isImplicit()),
4291bc56edSDimitry Andric     IsAnyReg(MI->getOperand(getMetaIdx(CCPos)).getImm() == CallingConv::AnyReg)
43f785676fSDimitry Andric {
4491bc56edSDimitry Andric #ifndef NDEBUG
45f785676fSDimitry Andric   unsigned CheckStartIdx = 0, e = MI->getNumOperands();
46f785676fSDimitry Andric   while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).isReg() &&
47f785676fSDimitry Andric          MI->getOperand(CheckStartIdx).isDef() &&
48f785676fSDimitry Andric          !MI->getOperand(CheckStartIdx).isImplicit())
49f785676fSDimitry Andric     ++CheckStartIdx;
50f785676fSDimitry Andric 
51f785676fSDimitry Andric   assert(getMetaIdx() == CheckStartIdx &&
5291bc56edSDimitry Andric          "Unexpected additional definition in Patchpoint intrinsic.");
53f785676fSDimitry Andric #endif
54f785676fSDimitry Andric }
55f785676fSDimitry Andric 
56f785676fSDimitry Andric unsigned PatchPointOpers::getNextScratchIdx(unsigned StartIdx) const {
57f785676fSDimitry Andric   if (!StartIdx)
58f785676fSDimitry Andric     StartIdx = getVarIdx();
59f785676fSDimitry Andric 
60f785676fSDimitry Andric   // Find the next scratch register (implicit def and early clobber)
61f785676fSDimitry Andric   unsigned ScratchIdx = StartIdx, e = MI->getNumOperands();
62f785676fSDimitry Andric   while (ScratchIdx < e &&
63f785676fSDimitry Andric          !(MI->getOperand(ScratchIdx).isReg() &&
64f785676fSDimitry Andric            MI->getOperand(ScratchIdx).isDef() &&
65f785676fSDimitry Andric            MI->getOperand(ScratchIdx).isImplicit() &&
66f785676fSDimitry Andric            MI->getOperand(ScratchIdx).isEarlyClobber()))
67f785676fSDimitry Andric     ++ScratchIdx;
68f785676fSDimitry Andric 
69f785676fSDimitry Andric   assert(ScratchIdx != e && "No scratch register available");
70f785676fSDimitry Andric   return ScratchIdx;
71f785676fSDimitry Andric }
72f785676fSDimitry Andric 
7391bc56edSDimitry Andric StackMaps::StackMaps(AsmPrinter &AP) : AP(AP) {
7491bc56edSDimitry Andric   if (StackMapVersion != 1)
7591bc56edSDimitry Andric     llvm_unreachable("Unsupported stackmap version!");
7691bc56edSDimitry Andric }
7791bc56edSDimitry Andric 
7891bc56edSDimitry Andric MachineInstr::const_mop_iterator
7991bc56edSDimitry Andric StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
8091bc56edSDimitry Andric                         MachineInstr::const_mop_iterator MOE,
8191bc56edSDimitry Andric                         LocationVec &Locs, LiveOutVec &LiveOuts) const {
8291bc56edSDimitry Andric   if (MOI->isImm()) {
8391bc56edSDimitry Andric     switch (MOI->getImm()) {
8491bc56edSDimitry Andric     default: llvm_unreachable("Unrecognized operand type.");
8591bc56edSDimitry Andric     case StackMaps::DirectMemRefOp: {
8691bc56edSDimitry Andric       unsigned Size = AP.TM.getDataLayout()->getPointerSizeInBits();
8791bc56edSDimitry Andric       assert((Size % 8) == 0 && "Need pointer size in bytes.");
8891bc56edSDimitry Andric       Size /= 8;
8991bc56edSDimitry Andric       unsigned Reg = (++MOI)->getReg();
9091bc56edSDimitry Andric       int64_t Imm = (++MOI)->getImm();
9191bc56edSDimitry Andric       Locs.push_back(Location(StackMaps::Location::Direct, Size, Reg, Imm));
9291bc56edSDimitry Andric       break;
9391bc56edSDimitry Andric     }
9491bc56edSDimitry Andric     case StackMaps::IndirectMemRefOp: {
9591bc56edSDimitry Andric       int64_t Size = (++MOI)->getImm();
9691bc56edSDimitry Andric       assert(Size > 0 && "Need a valid size for indirect memory locations.");
9791bc56edSDimitry Andric       unsigned Reg = (++MOI)->getReg();
9891bc56edSDimitry Andric       int64_t Imm = (++MOI)->getImm();
9991bc56edSDimitry Andric       Locs.push_back(Location(StackMaps::Location::Indirect, Size, Reg, Imm));
10091bc56edSDimitry Andric       break;
10191bc56edSDimitry Andric     }
10291bc56edSDimitry Andric     case StackMaps::ConstantOp: {
10391bc56edSDimitry Andric       ++MOI;
10491bc56edSDimitry Andric       assert(MOI->isImm() && "Expected constant operand.");
10591bc56edSDimitry Andric       int64_t Imm = MOI->getImm();
10691bc56edSDimitry Andric       Locs.push_back(Location(Location::Constant, sizeof(int64_t), 0, Imm));
10791bc56edSDimitry Andric       break;
10891bc56edSDimitry Andric     }
10991bc56edSDimitry Andric     }
11091bc56edSDimitry Andric     return ++MOI;
11191bc56edSDimitry Andric   }
11291bc56edSDimitry Andric 
11391bc56edSDimitry Andric   // The physical register number will ultimately be encoded as a DWARF regno.
11491bc56edSDimitry Andric   // The stack map also records the size of a spill slot that can hold the
11591bc56edSDimitry Andric   // register content. (The runtime can track the actual size of the data type
11691bc56edSDimitry Andric   // if it needs to.)
11791bc56edSDimitry Andric   if (MOI->isReg()) {
11891bc56edSDimitry Andric     // Skip implicit registers (this includes our scratch registers)
11991bc56edSDimitry Andric     if (MOI->isImplicit())
12091bc56edSDimitry Andric       return ++MOI;
12191bc56edSDimitry Andric 
12291bc56edSDimitry Andric     assert(TargetRegisterInfo::isPhysicalRegister(MOI->getReg()) &&
12391bc56edSDimitry Andric            "Virtreg operands should have been rewritten before now.");
12491bc56edSDimitry Andric     const TargetRegisterClass *RC =
12591bc56edSDimitry Andric       AP.TM.getRegisterInfo()->getMinimalPhysRegClass(MOI->getReg());
12691bc56edSDimitry Andric     assert(!MOI->getSubReg() && "Physical subreg still around.");
12791bc56edSDimitry Andric     Locs.push_back(
12891bc56edSDimitry Andric       Location(Location::Register, RC->getSize(), MOI->getReg(), 0));
12991bc56edSDimitry Andric     return ++MOI;
13091bc56edSDimitry Andric   }
13191bc56edSDimitry Andric 
13291bc56edSDimitry Andric   if (MOI->isRegLiveOut())
13391bc56edSDimitry Andric     LiveOuts = parseRegisterLiveOutMask(MOI->getRegLiveOut());
13491bc56edSDimitry Andric 
13591bc56edSDimitry Andric   return ++MOI;
13691bc56edSDimitry Andric }
13791bc56edSDimitry Andric 
13891bc56edSDimitry Andric /// Go up the super-register chain until we hit a valid dwarf register number.
13991bc56edSDimitry Andric static unsigned getDwarfRegNum(unsigned Reg, const TargetRegisterInfo *TRI) {
14091bc56edSDimitry Andric   int RegNo = TRI->getDwarfRegNum(Reg, false);
14191bc56edSDimitry Andric   for (MCSuperRegIterator SR(Reg, TRI); SR.isValid() && RegNo < 0; ++SR)
14291bc56edSDimitry Andric     RegNo = TRI->getDwarfRegNum(*SR, false);
14391bc56edSDimitry Andric 
14491bc56edSDimitry Andric   assert(RegNo >= 0 && "Invalid Dwarf register number.");
14591bc56edSDimitry Andric   return (unsigned) RegNo;
14691bc56edSDimitry Andric }
14791bc56edSDimitry Andric 
14891bc56edSDimitry Andric /// Create a live-out register record for the given register Reg.
14991bc56edSDimitry Andric StackMaps::LiveOutReg
15091bc56edSDimitry Andric StackMaps::createLiveOutReg(unsigned Reg, const TargetRegisterInfo *TRI) const {
15191bc56edSDimitry Andric   unsigned RegNo = getDwarfRegNum(Reg, TRI);
15291bc56edSDimitry Andric   unsigned Size = TRI->getMinimalPhysRegClass(Reg)->getSize();
15391bc56edSDimitry Andric   return LiveOutReg(Reg, RegNo, Size);
15491bc56edSDimitry Andric }
15591bc56edSDimitry Andric 
15691bc56edSDimitry Andric /// Parse the register live-out mask and return a vector of live-out registers
15791bc56edSDimitry Andric /// that need to be recorded in the stackmap.
15891bc56edSDimitry Andric StackMaps::LiveOutVec
15991bc56edSDimitry Andric StackMaps::parseRegisterLiveOutMask(const uint32_t *Mask) const {
16091bc56edSDimitry Andric   assert(Mask && "No register mask specified");
16191bc56edSDimitry Andric   const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();
16291bc56edSDimitry Andric   LiveOutVec LiveOuts;
16391bc56edSDimitry Andric 
16491bc56edSDimitry Andric   // Create a LiveOutReg for each bit that is set in the register mask.
16591bc56edSDimitry Andric   for (unsigned Reg = 0, NumRegs = TRI->getNumRegs(); Reg != NumRegs; ++Reg)
16691bc56edSDimitry Andric     if ((Mask[Reg / 32] >> Reg % 32) & 1)
16791bc56edSDimitry Andric       LiveOuts.push_back(createLiveOutReg(Reg, TRI));
16891bc56edSDimitry Andric 
16991bc56edSDimitry Andric   // We don't need to keep track of a register if its super-register is already
17091bc56edSDimitry Andric   // in the list. Merge entries that refer to the same dwarf register and use
17191bc56edSDimitry Andric   // the maximum size that needs to be spilled.
17291bc56edSDimitry Andric   std::sort(LiveOuts.begin(), LiveOuts.end());
17391bc56edSDimitry Andric   for (LiveOutVec::iterator I = LiveOuts.begin(), E = LiveOuts.end();
17491bc56edSDimitry Andric        I != E; ++I) {
17591bc56edSDimitry Andric     for (LiveOutVec::iterator II = std::next(I); II != E; ++II) {
17691bc56edSDimitry Andric       if (I->RegNo != II->RegNo) {
17791bc56edSDimitry Andric         // Skip all the now invalid entries.
17891bc56edSDimitry Andric         I = --II;
17991bc56edSDimitry Andric         break;
18091bc56edSDimitry Andric       }
18191bc56edSDimitry Andric       I->Size = std::max(I->Size, II->Size);
18291bc56edSDimitry Andric       if (TRI->isSuperRegister(I->Reg, II->Reg))
18391bc56edSDimitry Andric         I->Reg = II->Reg;
18491bc56edSDimitry Andric       II->MarkInvalid();
18591bc56edSDimitry Andric     }
18691bc56edSDimitry Andric   }
18791bc56edSDimitry Andric   LiveOuts.erase(std::remove_if(LiveOuts.begin(), LiveOuts.end(),
18891bc56edSDimitry Andric                                 LiveOutReg::IsInvalid), LiveOuts.end());
18991bc56edSDimitry Andric   return LiveOuts;
19091bc56edSDimitry Andric }
19191bc56edSDimitry Andric 
19291bc56edSDimitry Andric void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
193f785676fSDimitry Andric                                     MachineInstr::const_mop_iterator MOI,
194f785676fSDimitry Andric                                     MachineInstr::const_mop_iterator MOE,
195f785676fSDimitry Andric                                     bool recordResult) {
196f785676fSDimitry Andric 
197f785676fSDimitry Andric   MCContext &OutContext = AP.OutStreamer.getContext();
198f785676fSDimitry Andric   MCSymbol *MILabel = OutContext.CreateTempSymbol();
199f785676fSDimitry Andric   AP.OutStreamer.EmitLabel(MILabel);
200f785676fSDimitry Andric 
20191bc56edSDimitry Andric   LocationVec Locations;
20291bc56edSDimitry Andric   LiveOutVec LiveOuts;
203f785676fSDimitry Andric 
204f785676fSDimitry Andric   if (recordResult) {
20591bc56edSDimitry Andric     assert(PatchPointOpers(&MI).hasDef() && "Stackmap has no return value.");
20691bc56edSDimitry Andric     parseOperand(MI.operands_begin(), std::next(MI.operands_begin()),
20791bc56edSDimitry Andric                  Locations, LiveOuts);
208f785676fSDimitry Andric   }
209f785676fSDimitry Andric 
21091bc56edSDimitry Andric   // Parse operands.
211f785676fSDimitry Andric   while (MOI != MOE) {
21291bc56edSDimitry Andric     MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
21391bc56edSDimitry Andric   }
214f785676fSDimitry Andric 
215f785676fSDimitry Andric   // Move large constants into the constant pool.
21691bc56edSDimitry Andric   for (LocationVec::iterator I = Locations.begin(), E = Locations.end();
21791bc56edSDimitry Andric        I != E; ++I) {
21891bc56edSDimitry Andric     // Constants are encoded as sign-extended integers.
21991bc56edSDimitry Andric     // -1 is directly encoded as .long 0xFFFFFFFF with no constant pool.
22091bc56edSDimitry Andric     if (I->LocType == Location::Constant &&
22191bc56edSDimitry Andric         ((I->Offset + (int64_t(1)<<31)) >> 32) != 0) {
22291bc56edSDimitry Andric       I->LocType = Location::ConstantIndex;
22391bc56edSDimitry Andric       auto Result = ConstPool.insert(std::make_pair(I->Offset, I->Offset));
22491bc56edSDimitry Andric       I->Offset = Result.first - ConstPool.begin();
22591bc56edSDimitry Andric     }
226f785676fSDimitry Andric   }
227f785676fSDimitry Andric 
22891bc56edSDimitry Andric   // Create an expression to calculate the offset of the callsite from function
22991bc56edSDimitry Andric   // entry.
230f785676fSDimitry Andric   const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub(
231f785676fSDimitry Andric     MCSymbolRefExpr::Create(MILabel, OutContext),
232f785676fSDimitry Andric     MCSymbolRefExpr::Create(AP.CurrentFnSym, OutContext),
233f785676fSDimitry Andric     OutContext);
234f785676fSDimitry Andric 
23591bc56edSDimitry Andric   CSInfos.push_back(CallsiteInfo(CSOffsetExpr, ID, Locations, LiveOuts));
236f785676fSDimitry Andric 
23791bc56edSDimitry Andric   // Record the stack size of the current function.
23891bc56edSDimitry Andric   const MachineFrameInfo *MFI = AP.MF->getFrameInfo();
23991bc56edSDimitry Andric   FnStackSize[AP.CurrentFnSym] =
24091bc56edSDimitry Andric     MFI->hasVarSizedObjects() ? UINT64_MAX : MFI->getStackSize();
241f785676fSDimitry Andric }
242f785676fSDimitry Andric 
243f785676fSDimitry Andric void StackMaps::recordStackMap(const MachineInstr &MI) {
24491bc56edSDimitry Andric   assert(MI.getOpcode() == TargetOpcode::STACKMAP && "expected stackmap");
245f785676fSDimitry Andric 
246f785676fSDimitry Andric   int64_t ID = MI.getOperand(0).getImm();
24791bc56edSDimitry Andric   recordStackMapOpers(MI, ID, std::next(MI.operands_begin(), 2),
24891bc56edSDimitry Andric                       MI.operands_end());
249f785676fSDimitry Andric }
250f785676fSDimitry Andric 
251f785676fSDimitry Andric void StackMaps::recordPatchPoint(const MachineInstr &MI) {
25291bc56edSDimitry Andric   assert(MI.getOpcode() == TargetOpcode::PATCHPOINT && "expected patchpoint");
253f785676fSDimitry Andric 
254f785676fSDimitry Andric   PatchPointOpers opers(&MI);
255f785676fSDimitry Andric   int64_t ID = opers.getMetaOper(PatchPointOpers::IDPos).getImm();
25691bc56edSDimitry Andric 
257f785676fSDimitry Andric   MachineInstr::const_mop_iterator MOI =
25891bc56edSDimitry Andric     std::next(MI.operands_begin(), opers.getStackMapStartIdx());
25991bc56edSDimitry Andric   recordStackMapOpers(MI, ID, MOI, MI.operands_end(),
260f785676fSDimitry Andric                       opers.isAnyReg() && opers.hasDef());
261f785676fSDimitry Andric 
262f785676fSDimitry Andric #ifndef NDEBUG
263f785676fSDimitry Andric   // verify anyregcc
264f785676fSDimitry Andric   LocationVec &Locations = CSInfos.back().Locations;
265f785676fSDimitry Andric   if (opers.isAnyReg()) {
266f785676fSDimitry Andric     unsigned NArgs = opers.getMetaOper(PatchPointOpers::NArgPos).getImm();
267f785676fSDimitry Andric     for (unsigned i = 0, e = (opers.hasDef() ? NArgs+1 : NArgs); i != e; ++i)
268f785676fSDimitry Andric       assert(Locations[i].LocType == Location::Register &&
269f785676fSDimitry Andric              "anyreg arg must be in reg.");
270f785676fSDimitry Andric   }
271f785676fSDimitry Andric #endif
272f785676fSDimitry Andric }
273f785676fSDimitry Andric 
27491bc56edSDimitry Andric /// Emit the stackmap header.
275f785676fSDimitry Andric ///
27691bc56edSDimitry Andric /// Header {
27791bc56edSDimitry Andric ///   uint8  : Stack Map Version (currently 1)
27891bc56edSDimitry Andric ///   uint8  : Reserved (expected to be 0)
27991bc56edSDimitry Andric ///   uint16 : Reserved (expected to be 0)
28091bc56edSDimitry Andric /// }
28191bc56edSDimitry Andric /// uint32 : NumFunctions
282f785676fSDimitry Andric /// uint32 : NumConstants
283f785676fSDimitry Andric /// uint32 : NumRecords
28491bc56edSDimitry Andric void StackMaps::emitStackmapHeader(MCStreamer &OS) {
28591bc56edSDimitry Andric   // Header.
28691bc56edSDimitry Andric   OS.EmitIntValue(StackMapVersion, 1); // Version.
28791bc56edSDimitry Andric   OS.EmitIntValue(0, 1); // Reserved.
28891bc56edSDimitry Andric   OS.EmitIntValue(0, 2); // Reserved.
28991bc56edSDimitry Andric 
29091bc56edSDimitry Andric   // Num functions.
29191bc56edSDimitry Andric   DEBUG(dbgs() << WSMP << "#functions = " << FnStackSize.size() << '\n');
29291bc56edSDimitry Andric   OS.EmitIntValue(FnStackSize.size(), 4);
29391bc56edSDimitry Andric   // Num constants.
29491bc56edSDimitry Andric   DEBUG(dbgs() << WSMP << "#constants = " << ConstPool.size() << '\n');
29591bc56edSDimitry Andric   OS.EmitIntValue(ConstPool.size(), 4);
29691bc56edSDimitry Andric   // Num callsites.
29791bc56edSDimitry Andric   DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << '\n');
29891bc56edSDimitry Andric   OS.EmitIntValue(CSInfos.size(), 4);
29991bc56edSDimitry Andric }
30091bc56edSDimitry Andric 
30191bc56edSDimitry Andric /// Emit the function frame record for each function.
30291bc56edSDimitry Andric ///
30391bc56edSDimitry Andric /// StkSizeRecord[NumFunctions] {
30491bc56edSDimitry Andric ///   uint64 : Function Address
30591bc56edSDimitry Andric ///   uint64 : Stack Size
30691bc56edSDimitry Andric /// }
30791bc56edSDimitry Andric void StackMaps::emitFunctionFrameRecords(MCStreamer &OS) {
30891bc56edSDimitry Andric   // Function Frame records.
30991bc56edSDimitry Andric   DEBUG(dbgs() << WSMP << "functions:\n");
31091bc56edSDimitry Andric   for (auto const &FR : FnStackSize) {
31191bc56edSDimitry Andric     DEBUG(dbgs() << WSMP << "function addr: " << FR.first
31291bc56edSDimitry Andric                          << " frame size: " << FR.second);
31391bc56edSDimitry Andric     OS.EmitSymbolValue(FR.first, 8);
31491bc56edSDimitry Andric     OS.EmitIntValue(FR.second, 8);
31591bc56edSDimitry Andric   }
31691bc56edSDimitry Andric }
31791bc56edSDimitry Andric 
31891bc56edSDimitry Andric /// Emit the constant pool.
31991bc56edSDimitry Andric ///
32091bc56edSDimitry Andric /// int64  : Constants[NumConstants]
32191bc56edSDimitry Andric void StackMaps::emitConstantPoolEntries(MCStreamer &OS) {
32291bc56edSDimitry Andric   // Constant pool entries.
32391bc56edSDimitry Andric   DEBUG(dbgs() << WSMP << "constants:\n");
32491bc56edSDimitry Andric   for (auto ConstEntry : ConstPool) {
32591bc56edSDimitry Andric     DEBUG(dbgs() << WSMP << ConstEntry.second << '\n');
32691bc56edSDimitry Andric     OS.EmitIntValue(ConstEntry.second, 8);
32791bc56edSDimitry Andric   }
32891bc56edSDimitry Andric }
32991bc56edSDimitry Andric 
33091bc56edSDimitry Andric /// Emit the callsite info for each callsite.
33191bc56edSDimitry Andric ///
332f785676fSDimitry Andric /// StkMapRecord[NumRecords] {
33391bc56edSDimitry Andric ///   uint64 : PatchPoint ID
334f785676fSDimitry Andric ///   uint32 : Instruction Offset
335f785676fSDimitry Andric ///   uint16 : Reserved (record flags)
336f785676fSDimitry Andric ///   uint16 : NumLocations
337f785676fSDimitry Andric ///   Location[NumLocations] {
338f785676fSDimitry Andric ///     uint8  : Register | Direct | Indirect | Constant | ConstantIndex
339f785676fSDimitry Andric ///     uint8  : Size in Bytes
340f785676fSDimitry Andric ///     uint16 : Dwarf RegNum
341f785676fSDimitry Andric ///     int32  : Offset
342f785676fSDimitry Andric ///   }
34391bc56edSDimitry Andric ///   uint16 : Padding
34491bc56edSDimitry Andric ///   uint16 : NumLiveOuts
34591bc56edSDimitry Andric ///   LiveOuts[NumLiveOuts] {
34691bc56edSDimitry Andric ///     uint16 : Dwarf RegNum
34791bc56edSDimitry Andric ///     uint8  : Reserved
34891bc56edSDimitry Andric ///     uint8  : Size in Bytes
34991bc56edSDimitry Andric ///   }
35091bc56edSDimitry Andric ///   uint32 : Padding (only if required to align to 8 byte)
351f785676fSDimitry Andric /// }
352f785676fSDimitry Andric ///
353f785676fSDimitry Andric /// Location Encoding, Type, Value:
354f785676fSDimitry Andric ///   0x1, Register, Reg                 (value in register)
355f785676fSDimitry Andric ///   0x2, Direct, Reg + Offset          (frame index)
356f785676fSDimitry Andric ///   0x3, Indirect, [Reg + Offset]      (spilled value)
357f785676fSDimitry Andric ///   0x4, Constant, Offset              (small constant)
358f785676fSDimitry Andric ///   0x5, ConstIndex, Constants[Offset] (large constant)
35991bc56edSDimitry Andric void StackMaps::emitCallsiteEntries(MCStreamer &OS,
36091bc56edSDimitry Andric                                     const TargetRegisterInfo *TRI) {
36191bc56edSDimitry Andric   // Callsite entries.
36291bc56edSDimitry Andric   DEBUG(dbgs() << WSMP << "callsites:\n");
36391bc56edSDimitry Andric   for (const auto &CSI : CSInfos) {
36491bc56edSDimitry Andric     const LocationVec &CSLocs = CSI.Locations;
36591bc56edSDimitry Andric     const LiveOutVec &LiveOuts = CSI.LiveOuts;
366f785676fSDimitry Andric 
36791bc56edSDimitry Andric     DEBUG(dbgs() << WSMP << "callsite " << CSI.ID << "\n");
368f785676fSDimitry Andric 
369f785676fSDimitry Andric     // Verify stack map entry. It's better to communicate a problem to the
370f785676fSDimitry Andric     // runtime than crash in case of in-process compilation. Currently, we do
371f785676fSDimitry Andric     // simple overflow checks, but we may eventually communicate other
372f785676fSDimitry Andric     // compilation errors this way.
37391bc56edSDimitry Andric     if (CSLocs.size() > UINT16_MAX || LiveOuts.size() > UINT16_MAX) {
37491bc56edSDimitry Andric       OS.EmitIntValue(UINT64_MAX, 8); // Invalid ID.
37591bc56edSDimitry Andric       OS.EmitValue(CSI.CSOffsetExpr, 4);
37691bc56edSDimitry Andric       OS.EmitIntValue(0, 2); // Reserved.
37791bc56edSDimitry Andric       OS.EmitIntValue(0, 2); // 0 locations.
37891bc56edSDimitry Andric       OS.EmitIntValue(0, 2); // padding.
37991bc56edSDimitry Andric       OS.EmitIntValue(0, 2); // 0 live-out registers.
38091bc56edSDimitry Andric       OS.EmitIntValue(0, 4); // padding.
381f785676fSDimitry Andric       continue;
382f785676fSDimitry Andric     }
383f785676fSDimitry Andric 
38491bc56edSDimitry Andric     OS.EmitIntValue(CSI.ID, 8);
38591bc56edSDimitry Andric     OS.EmitValue(CSI.CSOffsetExpr, 4);
386f785676fSDimitry Andric 
387f785676fSDimitry Andric     // Reserved for flags.
38891bc56edSDimitry Andric     OS.EmitIntValue(0, 2);
389f785676fSDimitry Andric 
390f785676fSDimitry Andric     DEBUG(dbgs() << WSMP << "  has " << CSLocs.size() << " locations\n");
391f785676fSDimitry Andric 
39291bc56edSDimitry Andric     OS.EmitIntValue(CSLocs.size(), 2);
393f785676fSDimitry Andric 
39491bc56edSDimitry Andric     unsigned OperIdx = 0;
39591bc56edSDimitry Andric     for (const auto &Loc : CSLocs) {
39691bc56edSDimitry Andric       unsigned RegNo = 0;
39791bc56edSDimitry Andric       int Offset = Loc.Offset;
39891bc56edSDimitry Andric       if(Loc.Reg) {
39991bc56edSDimitry Andric         RegNo = getDwarfRegNum(Loc.Reg, TRI);
40091bc56edSDimitry Andric 
40191bc56edSDimitry Andric         // If this is a register location, put the subregister byte offset in
40291bc56edSDimitry Andric         // the location offset.
40391bc56edSDimitry Andric         if (Loc.LocType == Location::Register) {
40491bc56edSDimitry Andric           assert(!Loc.Offset && "Register location should have zero offset");
40591bc56edSDimitry Andric           unsigned LLVMRegNo = TRI->getLLVMRegNum(RegNo, false);
40691bc56edSDimitry Andric           unsigned SubRegIdx = TRI->getSubRegIndex(LLVMRegNo, Loc.Reg);
40791bc56edSDimitry Andric           if (SubRegIdx)
40891bc56edSDimitry Andric             Offset = TRI->getSubRegIdxOffset(SubRegIdx);
40991bc56edSDimitry Andric         }
41091bc56edSDimitry Andric       }
41191bc56edSDimitry Andric       else {
41291bc56edSDimitry Andric         assert(Loc.LocType != Location::Register &&
41391bc56edSDimitry Andric                "Missing location register");
41491bc56edSDimitry Andric       }
41591bc56edSDimitry Andric 
41691bc56edSDimitry Andric       DEBUG(dbgs() << WSMP << "  Loc " << OperIdx << ": ";
417f785676fSDimitry Andric             switch (Loc.LocType) {
418f785676fSDimitry Andric             case Location::Unprocessed:
419f785676fSDimitry Andric               dbgs() << "<Unprocessed operand>";
420f785676fSDimitry Andric               break;
421f785676fSDimitry Andric             case Location::Register:
42291bc56edSDimitry Andric               dbgs() << "Register " << TRI->getName(Loc.Reg);
423f785676fSDimitry Andric               break;
424f785676fSDimitry Andric             case Location::Direct:
42591bc56edSDimitry Andric               dbgs() << "Direct " << TRI->getName(Loc.Reg);
426f785676fSDimitry Andric               if (Loc.Offset)
427f785676fSDimitry Andric               dbgs() << " + " << Loc.Offset;
428f785676fSDimitry Andric               break;
429f785676fSDimitry Andric             case Location::Indirect:
43091bc56edSDimitry Andric               dbgs() << "Indirect " << TRI->getName(Loc.Reg)
431f785676fSDimitry Andric               << " + " << Loc.Offset;
432f785676fSDimitry Andric               break;
433f785676fSDimitry Andric             case Location::Constant:
434f785676fSDimitry Andric               dbgs() << "Constant " << Loc.Offset;
435f785676fSDimitry Andric               break;
436f785676fSDimitry Andric             case Location::ConstantIndex:
437f785676fSDimitry Andric               dbgs() << "Constant Index " << Loc.Offset;
438f785676fSDimitry Andric               break;
439f785676fSDimitry Andric               }
44091bc56edSDimitry Andric             dbgs() << "     [encoding: .byte " << Loc.LocType
44191bc56edSDimitry Andric             << ", .byte " << Loc.Size
44291bc56edSDimitry Andric             << ", .short " << RegNo
44391bc56edSDimitry Andric             << ", .int " << Offset << "]\n";
444f785676fSDimitry Andric             );
445f785676fSDimitry Andric 
44691bc56edSDimitry Andric       OS.EmitIntValue(Loc.LocType, 1);
44791bc56edSDimitry Andric       OS.EmitIntValue(Loc.Size, 1);
44891bc56edSDimitry Andric       OS.EmitIntValue(RegNo, 2);
44991bc56edSDimitry Andric       OS.EmitIntValue(Offset, 4);
45091bc56edSDimitry Andric       OperIdx++;
451f785676fSDimitry Andric     }
45291bc56edSDimitry Andric 
45391bc56edSDimitry Andric     DEBUG(dbgs() << WSMP << "  has " << LiveOuts.size()
45491bc56edSDimitry Andric                          << " live-out registers\n");
45591bc56edSDimitry Andric 
45691bc56edSDimitry Andric     // Num live-out registers and padding to align to 4 byte.
45791bc56edSDimitry Andric     OS.EmitIntValue(0, 2);
45891bc56edSDimitry Andric     OS.EmitIntValue(LiveOuts.size(), 2);
45991bc56edSDimitry Andric 
46091bc56edSDimitry Andric     OperIdx = 0;
46191bc56edSDimitry Andric     for (const auto &LO : LiveOuts) {
46291bc56edSDimitry Andric       DEBUG(dbgs() << WSMP << "  LO " << OperIdx << ": "
46391bc56edSDimitry Andric                            << TRI->getName(LO.Reg)
46491bc56edSDimitry Andric                            << "     [encoding: .short " << LO.RegNo
46591bc56edSDimitry Andric                            << ", .byte 0, .byte " << LO.Size << "]\n");
46691bc56edSDimitry Andric       OS.EmitIntValue(LO.RegNo, 2);
46791bc56edSDimitry Andric       OS.EmitIntValue(0, 1);
46891bc56edSDimitry Andric       OS.EmitIntValue(LO.Size, 1);
469f785676fSDimitry Andric     }
47091bc56edSDimitry Andric     // Emit alignment to 8 byte.
47191bc56edSDimitry Andric     OS.EmitValueToAlignment(8);
472f785676fSDimitry Andric   }
473f785676fSDimitry Andric }
474f785676fSDimitry Andric 
47591bc56edSDimitry Andric /// Serialize the stackmap data.
47691bc56edSDimitry Andric void StackMaps::serializeToStackMapSection() {
47791bc56edSDimitry Andric   (void) WSMP;
47891bc56edSDimitry Andric   // Bail out if there's no stack map data.
47991bc56edSDimitry Andric   assert((!CSInfos.empty() || (CSInfos.empty() && ConstPool.empty())) &&
48091bc56edSDimitry Andric          "Expected empty constant pool too!");
48191bc56edSDimitry Andric   assert((!CSInfos.empty() || (CSInfos.empty() && FnStackSize.empty())) &&
48291bc56edSDimitry Andric          "Expected empty function record too!");
48391bc56edSDimitry Andric   if (CSInfos.empty())
48491bc56edSDimitry Andric     return;
485f785676fSDimitry Andric 
48691bc56edSDimitry Andric   MCContext &OutContext = AP.OutStreamer.getContext();
48791bc56edSDimitry Andric   MCStreamer &OS = AP.OutStreamer;
48891bc56edSDimitry Andric   const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();
48991bc56edSDimitry Andric 
49091bc56edSDimitry Andric   // Create the section.
49191bc56edSDimitry Andric   const MCSection *StackMapSection =
49291bc56edSDimitry Andric     OutContext.getObjectFileInfo()->getStackMapSection();
49391bc56edSDimitry Andric   OS.SwitchSection(StackMapSection);
49491bc56edSDimitry Andric 
49591bc56edSDimitry Andric   // Emit a dummy symbol to force section inclusion.
49691bc56edSDimitry Andric   OS.EmitLabel(OutContext.GetOrCreateSymbol(Twine("__LLVM_StackMaps")));
49791bc56edSDimitry Andric 
49891bc56edSDimitry Andric   // Serialize data.
49991bc56edSDimitry Andric   DEBUG(dbgs() << "********** Stack Map Output **********\n");
50091bc56edSDimitry Andric   emitStackmapHeader(OS);
50191bc56edSDimitry Andric   emitFunctionFrameRecords(OS);
50291bc56edSDimitry Andric   emitConstantPoolEntries(OS);
50391bc56edSDimitry Andric   emitCallsiteEntries(OS, TRI);
50491bc56edSDimitry Andric   OS.AddBlankLine();
50591bc56edSDimitry Andric 
50691bc56edSDimitry Andric   // Clean up.
507f785676fSDimitry Andric   CSInfos.clear();
50891bc56edSDimitry Andric   ConstPool.clear();
509f785676fSDimitry Andric }
510