StackMaps.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. //===---------------------------- StackMaps.cpp ---------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #define DEBUG_TYPE "stackmaps"
  10. #include "llvm/CodeGen/StackMaps.h"
  11. #include "llvm/CodeGen/AsmPrinter.h"
  12. #include "llvm/CodeGen/MachineInstr.h"
  13. #include "llvm/MC/MCContext.h"
  14. #include "llvm/MC/MCExpr.h"
  15. #include "llvm/MC/MCObjectFileInfo.h"
  16. #include "llvm/MC/MCSectionMachO.h"
  17. #include "llvm/MC/MCStreamer.h"
  18. #include "llvm/Support/Debug.h"
  19. #include "llvm/Support/raw_ostream.h"
  20. #include "llvm/Target/TargetOpcodes.h"
  21. #include "llvm/Target/TargetMachine.h"
  22. #include "llvm/Target/TargetRegisterInfo.h"
  23. #include <iterator>
  24. using namespace llvm;
  25. PatchPointOpers::PatchPointOpers(const MachineInstr *MI):
  26. MI(MI),
  27. HasDef(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() &&
  28. !MI->getOperand(0).isImplicit()),
  29. IsAnyReg(MI->getOperand(getMetaIdx(CCPos)).getImm() == CallingConv::AnyReg) {
  30. #ifndef NDEBUG
  31. {
  32. unsigned CheckStartIdx = 0, e = MI->getNumOperands();
  33. while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).isReg() &&
  34. MI->getOperand(CheckStartIdx).isDef() &&
  35. !MI->getOperand(CheckStartIdx).isImplicit())
  36. ++CheckStartIdx;
  37. assert(getMetaIdx() == CheckStartIdx &&
  38. "Unexpected additonal definition in Patchpoint intrinsic.");
  39. }
  40. #endif
  41. }
  42. unsigned PatchPointOpers::getNextScratchIdx(unsigned StartIdx) const {
  43. if (!StartIdx)
  44. StartIdx = getVarIdx();
  45. // Find the next scratch register (implicit def and early clobber)
  46. unsigned ScratchIdx = StartIdx, e = MI->getNumOperands();
  47. while (ScratchIdx < e &&
  48. !(MI->getOperand(ScratchIdx).isReg() &&
  49. MI->getOperand(ScratchIdx).isDef() &&
  50. MI->getOperand(ScratchIdx).isImplicit() &&
  51. MI->getOperand(ScratchIdx).isEarlyClobber()))
  52. ++ScratchIdx;
  53. assert(ScratchIdx != e && "No scratch register available");
  54. return ScratchIdx;
  55. }
  56. void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint32_t ID,
  57. MachineInstr::const_mop_iterator MOI,
  58. MachineInstr::const_mop_iterator MOE,
  59. bool recordResult) {
  60. MCContext &OutContext = AP.OutStreamer.getContext();
  61. MCSymbol *MILabel = OutContext.CreateTempSymbol();
  62. AP.OutStreamer.EmitLabel(MILabel);
  63. LocationVec CallsiteLocs;
  64. if (recordResult) {
  65. std::pair<Location, MachineInstr::const_mop_iterator> ParseResult =
  66. OpParser(MI.operands_begin(), llvm::next(MI.operands_begin()), AP.TM);
  67. Location &Loc = ParseResult.first;
  68. assert(Loc.LocType == Location::Register &&
  69. "Stackmap return location must be a register.");
  70. CallsiteLocs.push_back(Loc);
  71. }
  72. while (MOI != MOE) {
  73. std::pair<Location, MachineInstr::const_mop_iterator> ParseResult =
  74. OpParser(MOI, MOE, AP.TM);
  75. Location &Loc = ParseResult.first;
  76. // Move large constants into the constant pool.
  77. if (Loc.LocType == Location::Constant && (Loc.Offset & ~0xFFFFFFFFULL)) {
  78. Loc.LocType = Location::ConstantIndex;
  79. Loc.Offset = ConstPool.getConstantIndex(Loc.Offset);
  80. }
  81. CallsiteLocs.push_back(Loc);
  82. MOI = ParseResult.second;
  83. }
  84. const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub(
  85. MCSymbolRefExpr::Create(MILabel, OutContext),
  86. MCSymbolRefExpr::Create(AP.CurrentFnSym, OutContext),
  87. OutContext);
  88. CSInfos.push_back(CallsiteInfo(CSOffsetExpr, ID, CallsiteLocs));
  89. }
  90. static MachineInstr::const_mop_iterator
  91. getStackMapEndMOP(MachineInstr::const_mop_iterator MOI,
  92. MachineInstr::const_mop_iterator MOE) {
  93. for (; MOI != MOE; ++MOI)
  94. if (MOI->isRegMask() || (MOI->isReg() && MOI->isImplicit()))
  95. break;
  96. return MOI;
  97. }
  98. void StackMaps::recordStackMap(const MachineInstr &MI) {
  99. assert(MI.getOpcode() == TargetOpcode::STACKMAP && "exected stackmap");
  100. int64_t ID = MI.getOperand(0).getImm();
  101. assert((int32_t)ID == ID && "Stack maps hold 32-bit IDs");
  102. recordStackMapOpers(MI, ID, llvm::next(MI.operands_begin(), 2),
  103. getStackMapEndMOP(MI.operands_begin(),
  104. MI.operands_end()));
  105. }
  106. void StackMaps::recordPatchPoint(const MachineInstr &MI) {
  107. assert(MI.getOpcode() == TargetOpcode::PATCHPOINT && "exected stackmap");
  108. PatchPointOpers opers(&MI);
  109. int64_t ID = opers.getMetaOper(PatchPointOpers::IDPos).getImm();
  110. assert((int32_t)ID == ID && "Stack maps hold 32-bit IDs");
  111. MachineInstr::const_mop_iterator MOI =
  112. llvm::next(MI.operands_begin(), opers.getStackMapStartIdx());
  113. recordStackMapOpers(MI, ID, MOI, getStackMapEndMOP(MOI, MI.operands_end()),
  114. opers.isAnyReg() && opers.hasDef());
  115. #ifndef NDEBUG
  116. // verify anyregcc
  117. LocationVec &Locations = CSInfos.back().Locations;
  118. if (opers.isAnyReg()) {
  119. unsigned NArgs = opers.getMetaOper(PatchPointOpers::NArgPos).getImm();
  120. for (unsigned i = 0, e = (opers.hasDef() ? NArgs+1 : NArgs); i != e; ++i)
  121. assert(Locations[i].LocType == Location::Register &&
  122. "anyreg arg must be in reg.");
  123. }
  124. #endif
  125. }
  126. /// serializeToStackMapSection conceptually populates the following fields:
  127. ///
  128. /// uint32 : Reserved (header)
  129. /// uint32 : NumConstants
  130. /// int64 : Constants[NumConstants]
  131. /// uint32 : NumRecords
  132. /// StkMapRecord[NumRecords] {
  133. /// uint32 : PatchPoint ID
  134. /// uint32 : Instruction Offset
  135. /// uint16 : Reserved (record flags)
  136. /// uint16 : NumLocations
  137. /// Location[NumLocations] {
  138. /// uint8 : Register | Direct | Indirect | Constant | ConstantIndex
  139. /// uint8 : Size in Bytes
  140. /// uint16 : Dwarf RegNum
  141. /// int32 : Offset
  142. /// }
  143. /// }
  144. ///
  145. /// Location Encoding, Type, Value:
  146. /// 0x1, Register, Reg (value in register)
  147. /// 0x2, Direct, Reg + Offset (frame index)
  148. /// 0x3, Indirect, [Reg + Offset] (spilled value)
  149. /// 0x4, Constant, Offset (small constant)
  150. /// 0x5, ConstIndex, Constants[Offset] (large constant)
  151. ///
  152. void StackMaps::serializeToStackMapSection() {
  153. // Bail out if there's no stack map data.
  154. if (CSInfos.empty())
  155. return;
  156. MCContext &OutContext = AP.OutStreamer.getContext();
  157. const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();
  158. // Create the section.
  159. const MCSection *StackMapSection =
  160. OutContext.getObjectFileInfo()->getStackMapSection();
  161. AP.OutStreamer.SwitchSection(StackMapSection);
  162. // Emit a dummy symbol to force section inclusion.
  163. AP.OutStreamer.EmitLabel(
  164. OutContext.GetOrCreateSymbol(Twine("__LLVM_StackMaps")));
  165. // Serialize data.
  166. const char *WSMP = "Stack Maps: ";
  167. (void)WSMP;
  168. const MCRegisterInfo &MCRI = *OutContext.getRegisterInfo();
  169. DEBUG(dbgs() << "********** Stack Map Output **********\n");
  170. // Header.
  171. AP.OutStreamer.EmitIntValue(0, 4);
  172. // Num constants.
  173. AP.OutStreamer.EmitIntValue(ConstPool.getNumConstants(), 4);
  174. // Constant pool entries.
  175. for (unsigned i = 0; i < ConstPool.getNumConstants(); ++i)
  176. AP.OutStreamer.EmitIntValue(ConstPool.getConstant(i), 8);
  177. DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << "\n");
  178. AP.OutStreamer.EmitIntValue(CSInfos.size(), 4);
  179. for (CallsiteInfoList::const_iterator CSII = CSInfos.begin(),
  180. CSIE = CSInfos.end();
  181. CSII != CSIE; ++CSII) {
  182. unsigned CallsiteID = CSII->ID;
  183. const LocationVec &CSLocs = CSII->Locations;
  184. DEBUG(dbgs() << WSMP << "callsite " << CallsiteID << "\n");
  185. // Verify stack map entry. It's better to communicate a problem to the
  186. // runtime than crash in case of in-process compilation. Currently, we do
  187. // simple overflow checks, but we may eventually communicate other
  188. // compilation errors this way.
  189. if (CSLocs.size() > UINT16_MAX) {
  190. AP.OutStreamer.EmitIntValue(UINT32_MAX, 4); // Invalid ID.
  191. AP.OutStreamer.EmitValue(CSII->CSOffsetExpr, 4);
  192. AP.OutStreamer.EmitIntValue(0, 2); // Reserved.
  193. AP.OutStreamer.EmitIntValue(0, 2); // 0 locations.
  194. continue;
  195. }
  196. AP.OutStreamer.EmitIntValue(CallsiteID, 4);
  197. AP.OutStreamer.EmitValue(CSII->CSOffsetExpr, 4);
  198. // Reserved for flags.
  199. AP.OutStreamer.EmitIntValue(0, 2);
  200. DEBUG(dbgs() << WSMP << " has " << CSLocs.size() << " locations\n");
  201. AP.OutStreamer.EmitIntValue(CSLocs.size(), 2);
  202. unsigned operIdx = 0;
  203. for (LocationVec::const_iterator LocI = CSLocs.begin(), LocE = CSLocs.end();
  204. LocI != LocE; ++LocI, ++operIdx) {
  205. const Location &Loc = *LocI;
  206. DEBUG(
  207. dbgs() << WSMP << " Loc " << operIdx << ": ";
  208. switch (Loc.LocType) {
  209. case Location::Unprocessed:
  210. dbgs() << "<Unprocessed operand>";
  211. break;
  212. case Location::Register:
  213. dbgs() << "Register " << MCRI.getName(Loc.Reg);
  214. break;
  215. case Location::Direct:
  216. dbgs() << "Direct " << MCRI.getName(Loc.Reg);
  217. if (Loc.Offset)
  218. dbgs() << " + " << Loc.Offset;
  219. break;
  220. case Location::Indirect:
  221. dbgs() << "Indirect " << MCRI.getName(Loc.Reg)
  222. << " + " << Loc.Offset;
  223. break;
  224. case Location::Constant:
  225. dbgs() << "Constant " << Loc.Offset;
  226. break;
  227. case Location::ConstantIndex:
  228. dbgs() << "Constant Index " << Loc.Offset;
  229. break;
  230. }
  231. dbgs() << "\n";
  232. );
  233. unsigned RegNo = 0;
  234. int Offset = Loc.Offset;
  235. if(Loc.Reg) {
  236. RegNo = MCRI.getDwarfRegNum(Loc.Reg, false);
  237. for (MCSuperRegIterator SR(Loc.Reg, TRI);
  238. SR.isValid() && (int)RegNo < 0; ++SR) {
  239. RegNo = TRI->getDwarfRegNum(*SR, false);
  240. }
  241. // If this is a register location, put the subregister byte offset in
  242. // the location offset.
  243. if (Loc.LocType == Location::Register) {
  244. assert(!Loc.Offset && "Register location should have zero offset");
  245. unsigned LLVMRegNo = MCRI.getLLVMRegNum(RegNo, false);
  246. unsigned SubRegIdx = MCRI.getSubRegIndex(LLVMRegNo, Loc.Reg);
  247. if (SubRegIdx)
  248. Offset = MCRI.getSubRegIdxOffset(SubRegIdx);
  249. }
  250. }
  251. else {
  252. assert((Loc.LocType != Location::Register
  253. && Loc.LocType != Location::Register) &&
  254. "Missing location register");
  255. }
  256. AP.OutStreamer.EmitIntValue(Loc.LocType, 1);
  257. AP.OutStreamer.EmitIntValue(Loc.Size, 1);
  258. AP.OutStreamer.EmitIntValue(RegNo, 2);
  259. AP.OutStreamer.EmitIntValue(Offset, 4);
  260. }
  261. }
  262. AP.OutStreamer.AddBlankLine();
  263. CSInfos.clear();
  264. }