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