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