StackMaps.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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/MCSectionMachO.h"
  16. #include "llvm/MC/MCStreamer.h"
  17. #include "llvm/Support/Debug.h"
  18. #include "llvm/Support/raw_ostream.h"
  19. #include "llvm/Target/TargetOpcodes.h"
  20. #include "llvm/Target/TargetMachine.h"
  21. #include "llvm/Target/TargetRegisterInfo.h"
  22. #include <iterator>
  23. using namespace llvm;
  24. void StackMaps::recordStackMap(const MachineInstr &MI, uint32_t ID,
  25. MachineInstr::const_mop_iterator MOI,
  26. MachineInstr::const_mop_iterator MOE) {
  27. MCContext &OutContext = AP.OutStreamer.getContext();
  28. MCSymbol *MILabel = OutContext.CreateTempSymbol();
  29. AP.OutStreamer.EmitLabel(MILabel);
  30. LocationVec CallsiteLocs;
  31. while (MOI != MOE) {
  32. std::pair<Location, MachineInstr::const_mop_iterator> ParseResult =
  33. OpParser(MOI, MOE);
  34. Location &Loc = ParseResult.first;
  35. // Move large constants into the constant pool.
  36. if (Loc.LocType == Location::Constant && (Loc.Offset & ~0xFFFFFFFFULL)) {
  37. Loc.LocType = Location::ConstantIndex;
  38. Loc.Offset = ConstPool.getConstantIndex(Loc.Offset);
  39. }
  40. CallsiteLocs.push_back(Loc);
  41. MOI = ParseResult.second;
  42. }
  43. const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub(
  44. MCSymbolRefExpr::Create(MILabel, OutContext),
  45. MCSymbolRefExpr::Create(AP.CurrentFnSym, OutContext),
  46. OutContext);
  47. CSInfos.push_back(CallsiteInfo(CSOffsetExpr, ID, CallsiteLocs));
  48. }
  49. /// serializeToStackMapSection conceptually populates the following fields:
  50. ///
  51. /// uint32 : Reserved (header)
  52. /// uint32 : NumConstants
  53. /// int64 : Constants[NumConstants]
  54. /// uint32 : NumRecords
  55. /// StkMapRecord[NumRecords] {
  56. /// uint32 : PatchPoint ID
  57. /// uint32 : Instruction Offset
  58. /// uint16 : Reserved (record flags)
  59. /// uint16 : NumLocations
  60. /// Location[NumLocations] {
  61. /// uint8 : Register | Direct | Indirect | Constant | ConstantIndex
  62. /// uint8 : Reserved (location flags)
  63. /// uint16 : Dwarf RegNum
  64. /// int32 : Offset
  65. /// }
  66. /// }
  67. ///
  68. /// Location Encoding, Type, Value:
  69. /// 0x1, Register, Reg (value in register)
  70. /// 0x2, Direct, Reg + Offset (frame index)
  71. /// 0x3, Indirect, [Reg + Offset] (spilled value)
  72. /// 0x4, Constant, Offset (small constant)
  73. /// 0x5, ConstIndex, Constants[Offset] (large constant)
  74. ///
  75. void StackMaps::serializeToStackMapSection() {
  76. // Bail out if there's no stack map data.
  77. if (CSInfos.empty())
  78. return;
  79. MCContext &OutContext = AP.OutStreamer.getContext();
  80. const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();
  81. // Create the section.
  82. const MCSection *StackMapSection =
  83. OutContext.getObjectFileInfo().getStackMapSection();
  84. AP.OutStreamer.SwitchSection(StackMapSection);
  85. // Emit a dummy symbol to force section inclusion.
  86. AP.OutStreamer.EmitLabel(
  87. OutContext.GetOrCreateSymbol(Twine("__LLVM_StackMaps")));
  88. // Serialize data.
  89. const char *WSMP = "Stack Maps: ";
  90. (void)WSMP;
  91. const MCRegisterInfo &MCRI = *OutContext.getRegisterInfo();
  92. DEBUG(dbgs() << "********** Stack Map Output **********\n");
  93. // Header.
  94. AP.OutStreamer.EmitIntValue(0, 4);
  95. // Num constants.
  96. AP.OutStreamer.EmitIntValue(ConstPool.getNumConstants(), 4);
  97. // Constant pool entries.
  98. for (unsigned i = 0; i < ConstPool.getNumConstants(); ++i)
  99. AP.OutStreamer.EmitIntValue(ConstPool.getConstant(i), 8);
  100. DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << "\n");
  101. AP.OutStreamer.EmitIntValue(CSInfos.size(), 4);
  102. for (CallsiteInfoList::const_iterator CSII = CSInfos.begin(),
  103. CSIE = CSInfos.end();
  104. CSII != CSIE; ++CSII) {
  105. unsigned CallsiteID = CSII->ID;
  106. const LocationVec &CSLocs = CSII->Locations;
  107. DEBUG(dbgs() << WSMP << "callsite " << CallsiteID << "\n");
  108. // Verify stack map entry. It's better to communicate a problem to the
  109. // runtime than crash in case of in-process compilation. Currently, we do
  110. // simple overflow checks, but we may eventually communicate other
  111. // compilation errors this way.
  112. if (CSLocs.size() > UINT16_MAX) {
  113. AP.OutStreamer.EmitIntValue(UINT32_MAX, 4); // Invalid ID.
  114. AP.OutStreamer.EmitValue(CSII->CSOffsetExpr, 4);
  115. AP.OutStreamer.EmitIntValue(0, 2); // Reserved.
  116. AP.OutStreamer.EmitIntValue(0, 2); // 0 locations.
  117. continue;
  118. }
  119. AP.OutStreamer.EmitIntValue(CallsiteID, 4);
  120. AP.OutStreamer.EmitValue(CSII->CSOffsetExpr, 4);
  121. // Reserved for flags.
  122. AP.OutStreamer.EmitIntValue(0, 2);
  123. DEBUG(dbgs() << WSMP << " has " << CSLocs.size() << " locations\n");
  124. AP.OutStreamer.EmitIntValue(CSLocs.size(), 2);
  125. unsigned operIdx = 0;
  126. for (LocationVec::const_iterator LocI = CSLocs.begin(), LocE = CSLocs.end();
  127. LocI != LocE; ++LocI, ++operIdx) {
  128. const Location &Loc = *LocI;
  129. DEBUG(
  130. dbgs() << WSMP << " Loc " << operIdx << ": ";
  131. switch (Loc.LocType) {
  132. case Location::Unprocessed:
  133. dbgs() << "<Unprocessed operand>";
  134. break;
  135. case Location::Register:
  136. dbgs() << "Register " << MCRI.getName(Loc.Reg);
  137. break;
  138. case Location::Direct:
  139. dbgs() << "Direct " << MCRI.getName(Loc.Reg);
  140. if (Loc.Offset)
  141. dbgs() << " + " << Loc.Offset;
  142. break;
  143. case Location::Indirect:
  144. dbgs() << "Indirect " << MCRI.getName(Loc.Reg)
  145. << " + " << Loc.Offset;
  146. break;
  147. case Location::Constant:
  148. dbgs() << "Constant " << Loc.Offset;
  149. break;
  150. case Location::ConstantIndex:
  151. dbgs() << "Constant Index " << Loc.Offset;
  152. break;
  153. }
  154. dbgs() << "\n";
  155. );
  156. unsigned RegNo = 0;
  157. if(Loc.Reg) {
  158. RegNo = MCRI.getDwarfRegNum(Loc.Reg, false);
  159. for (MCSuperRegIterator SR(Loc.Reg, TRI);
  160. SR.isValid() && (int)RegNo < 0; ++SR) {
  161. RegNo = TRI->getDwarfRegNum(*SR, false);
  162. }
  163. }
  164. else {
  165. assert((Loc.LocType != Location::Register
  166. && Loc.LocType != Location::Register) &&
  167. "Missing location register");
  168. }
  169. AP.OutStreamer.EmitIntValue(Loc.LocType, 1);
  170. AP.OutStreamer.EmitIntValue(0, 1); // Reserved location flags.
  171. AP.OutStreamer.EmitIntValue(RegNo, 2);
  172. AP.OutStreamer.EmitIntValue(Loc.Offset, 4);
  173. }
  174. }
  175. AP.OutStreamer.AddBlankLine();
  176. CSInfos.clear();
  177. }