Mercurial > hg > CbC > CbC_llvm
comparison lib/CodeGen/StackMaps.cpp @ 120:1172e4bd9c6f
update 4.0.0
author | mir3636 |
---|---|
date | Fri, 25 Nov 2016 19:14:25 +0900 |
parents | afa8332a0e37 |
children | 803732b1fca8 |
comparison
equal
deleted
inserted
replaced
101:34baf5011add | 120:1172e4bd9c6f |
---|---|
28 using namespace llvm; | 28 using namespace llvm; |
29 | 29 |
30 #define DEBUG_TYPE "stackmaps" | 30 #define DEBUG_TYPE "stackmaps" |
31 | 31 |
32 static cl::opt<int> StackMapVersion( | 32 static cl::opt<int> StackMapVersion( |
33 "stackmap-version", cl::init(1), | 33 "stackmap-version", cl::init(2), |
34 cl::desc("Specify the stackmap encoding version (default = 1)")); | 34 cl::desc("Specify the stackmap encoding version (default = 2)")); |
35 | 35 |
36 const char *StackMaps::WSMP = "Stack Maps: "; | 36 const char *StackMaps::WSMP = "Stack Maps: "; |
37 | |
38 StackMapOpers::StackMapOpers(const MachineInstr *MI) | |
39 : MI(MI) { | |
40 assert(getVarIdx() <= MI->getNumOperands() && | |
41 "invalid stackmap definition"); | |
42 } | |
37 | 43 |
38 PatchPointOpers::PatchPointOpers(const MachineInstr *MI) | 44 PatchPointOpers::PatchPointOpers(const MachineInstr *MI) |
39 : MI(MI), HasDef(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() && | 45 : MI(MI), HasDef(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() && |
40 !MI->getOperand(0).isImplicit()), | 46 !MI->getOperand(0).isImplicit()) { |
41 IsAnyReg(MI->getOperand(getMetaIdx(CCPos)).getImm() == | |
42 CallingConv::AnyReg) { | |
43 #ifndef NDEBUG | 47 #ifndef NDEBUG |
44 unsigned CheckStartIdx = 0, e = MI->getNumOperands(); | 48 unsigned CheckStartIdx = 0, e = MI->getNumOperands(); |
45 while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).isReg() && | 49 while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).isReg() && |
46 MI->getOperand(CheckStartIdx).isDef() && | 50 MI->getOperand(CheckStartIdx).isDef() && |
47 !MI->getOperand(CheckStartIdx).isImplicit()) | 51 !MI->getOperand(CheckStartIdx).isImplicit()) |
68 assert(ScratchIdx != e && "No scratch register available"); | 72 assert(ScratchIdx != e && "No scratch register available"); |
69 return ScratchIdx; | 73 return ScratchIdx; |
70 } | 74 } |
71 | 75 |
72 StackMaps::StackMaps(AsmPrinter &AP) : AP(AP) { | 76 StackMaps::StackMaps(AsmPrinter &AP) : AP(AP) { |
73 if (StackMapVersion != 1) | 77 if (StackMapVersion != 2) |
74 llvm_unreachable("Unsupported stackmap version!"); | 78 llvm_unreachable("Unsupported stackmap version!"); |
75 } | 79 } |
76 | 80 |
77 /// Go up the super-register chain until we hit a valid dwarf register number. | 81 /// Go up the super-register chain until we hit a valid dwarf register number. |
78 static unsigned getDwarfRegNum(unsigned Reg, const TargetRegisterInfo *TRI) { | 82 static unsigned getDwarfRegNum(unsigned Reg, const TargetRegisterInfo *TRI) { |
270 II->Reg = 0; // mark for deletion. | 274 II->Reg = 0; // mark for deletion. |
271 } | 275 } |
272 } | 276 } |
273 | 277 |
274 LiveOuts.erase( | 278 LiveOuts.erase( |
275 std::remove_if(LiveOuts.begin(), LiveOuts.end(), | 279 remove_if(LiveOuts, [](const LiveOutReg &LO) { return LO.Reg == 0; }), |
276 [](const LiveOutReg &LO) { return LO.Reg == 0; }), | |
277 LiveOuts.end()); | 280 LiveOuts.end()); |
278 | 281 |
279 return LiveOuts; | 282 return LiveOuts; |
280 } | 283 } |
281 | 284 |
330 MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext); | 333 MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext); |
331 | 334 |
332 CSInfos.emplace_back(CSOffsetExpr, ID, std::move(Locations), | 335 CSInfos.emplace_back(CSOffsetExpr, ID, std::move(Locations), |
333 std::move(LiveOuts)); | 336 std::move(LiveOuts)); |
334 | 337 |
335 // Record the stack size of the current function. | 338 // Record the stack size of the current function and update callsite count. |
336 const MachineFrameInfo *MFI = AP.MF->getFrameInfo(); | 339 const MachineFrameInfo &MFI = AP.MF->getFrameInfo(); |
337 const TargetRegisterInfo *RegInfo = AP.MF->getSubtarget().getRegisterInfo(); | 340 const TargetRegisterInfo *RegInfo = AP.MF->getSubtarget().getRegisterInfo(); |
338 bool HasDynamicFrameSize = | 341 bool HasDynamicFrameSize = |
339 MFI->hasVarSizedObjects() || RegInfo->needsStackRealignment(*(AP.MF)); | 342 MFI.hasVarSizedObjects() || RegInfo->needsStackRealignment(*(AP.MF)); |
340 FnStackSize[AP.CurrentFnSym] = | 343 uint64_t FrameSize = HasDynamicFrameSize ? UINT64_MAX : MFI.getStackSize(); |
341 HasDynamicFrameSize ? UINT64_MAX : MFI->getStackSize(); | 344 |
345 auto CurrentIt = FnInfos.find(AP.CurrentFnSym); | |
346 if (CurrentIt != FnInfos.end()) | |
347 CurrentIt->second.RecordCount++; | |
348 else | |
349 FnInfos.insert(std::make_pair(AP.CurrentFnSym, FunctionInfo(FrameSize))); | |
342 } | 350 } |
343 | 351 |
344 void StackMaps::recordStackMap(const MachineInstr &MI) { | 352 void StackMaps::recordStackMap(const MachineInstr &MI) { |
345 assert(MI.getOpcode() == TargetOpcode::STACKMAP && "expected stackmap"); | 353 assert(MI.getOpcode() == TargetOpcode::STACKMAP && "expected stackmap"); |
346 | 354 |
347 int64_t ID = MI.getOperand(0).getImm(); | 355 StackMapOpers opers(&MI); |
348 recordStackMapOpers(MI, ID, std::next(MI.operands_begin(), 2), | 356 const int64_t ID = MI.getOperand(PatchPointOpers::IDPos).getImm(); |
357 recordStackMapOpers(MI, ID, std::next(MI.operands_begin(), opers.getVarIdx()), | |
349 MI.operands_end()); | 358 MI.operands_end()); |
350 } | 359 } |
351 | 360 |
352 void StackMaps::recordPatchPoint(const MachineInstr &MI) { | 361 void StackMaps::recordPatchPoint(const MachineInstr &MI) { |
353 assert(MI.getOpcode() == TargetOpcode::PATCHPOINT && "expected patchpoint"); | 362 assert(MI.getOpcode() == TargetOpcode::PATCHPOINT && "expected patchpoint"); |
354 | 363 |
355 PatchPointOpers opers(&MI); | 364 PatchPointOpers opers(&MI); |
356 int64_t ID = opers.getMetaOper(PatchPointOpers::IDPos).getImm(); | 365 const int64_t ID = opers.getID(); |
357 | |
358 auto MOI = std::next(MI.operands_begin(), opers.getStackMapStartIdx()); | 366 auto MOI = std::next(MI.operands_begin(), opers.getStackMapStartIdx()); |
359 recordStackMapOpers(MI, ID, MOI, MI.operands_end(), | 367 recordStackMapOpers(MI, ID, MOI, MI.operands_end(), |
360 opers.isAnyReg() && opers.hasDef()); | 368 opers.isAnyReg() && opers.hasDef()); |
361 | 369 |
362 #ifndef NDEBUG | 370 #ifndef NDEBUG |
363 // verify anyregcc | 371 // verify anyregcc |
364 auto &Locations = CSInfos.back().Locations; | 372 auto &Locations = CSInfos.back().Locations; |
365 if (opers.isAnyReg()) { | 373 if (opers.isAnyReg()) { |
366 unsigned NArgs = opers.getMetaOper(PatchPointOpers::NArgPos).getImm(); | 374 unsigned NArgs = opers.getNumCallArgs(); |
367 for (unsigned i = 0, e = (opers.hasDef() ? NArgs + 1 : NArgs); i != e; ++i) | 375 for (unsigned i = 0, e = (opers.hasDef() ? NArgs + 1 : NArgs); i != e; ++i) |
368 assert(Locations[i].Type == Location::Register && | 376 assert(Locations[i].Type == Location::Register && |
369 "anyreg arg must be in reg."); | 377 "anyreg arg must be in reg."); |
370 } | 378 } |
371 #endif | 379 #endif |
382 } | 390 } |
383 | 391 |
384 /// Emit the stackmap header. | 392 /// Emit the stackmap header. |
385 /// | 393 /// |
386 /// Header { | 394 /// Header { |
387 /// uint8 : Stack Map Version (currently 1) | 395 /// uint8 : Stack Map Version (currently 2) |
388 /// uint8 : Reserved (expected to be 0) | 396 /// uint8 : Reserved (expected to be 0) |
389 /// uint16 : Reserved (expected to be 0) | 397 /// uint16 : Reserved (expected to be 0) |
390 /// } | 398 /// } |
391 /// uint32 : NumFunctions | 399 /// uint32 : NumFunctions |
392 /// uint32 : NumConstants | 400 /// uint32 : NumConstants |
396 OS.EmitIntValue(StackMapVersion, 1); // Version. | 404 OS.EmitIntValue(StackMapVersion, 1); // Version. |
397 OS.EmitIntValue(0, 1); // Reserved. | 405 OS.EmitIntValue(0, 1); // Reserved. |
398 OS.EmitIntValue(0, 2); // Reserved. | 406 OS.EmitIntValue(0, 2); // Reserved. |
399 | 407 |
400 // Num functions. | 408 // Num functions. |
401 DEBUG(dbgs() << WSMP << "#functions = " << FnStackSize.size() << '\n'); | 409 DEBUG(dbgs() << WSMP << "#functions = " << FnInfos.size() << '\n'); |
402 OS.EmitIntValue(FnStackSize.size(), 4); | 410 OS.EmitIntValue(FnInfos.size(), 4); |
403 // Num constants. | 411 // Num constants. |
404 DEBUG(dbgs() << WSMP << "#constants = " << ConstPool.size() << '\n'); | 412 DEBUG(dbgs() << WSMP << "#constants = " << ConstPool.size() << '\n'); |
405 OS.EmitIntValue(ConstPool.size(), 4); | 413 OS.EmitIntValue(ConstPool.size(), 4); |
406 // Num callsites. | 414 // Num callsites. |
407 DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << '\n'); | 415 DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << '\n'); |
411 /// Emit the function frame record for each function. | 419 /// Emit the function frame record for each function. |
412 /// | 420 /// |
413 /// StkSizeRecord[NumFunctions] { | 421 /// StkSizeRecord[NumFunctions] { |
414 /// uint64 : Function Address | 422 /// uint64 : Function Address |
415 /// uint64 : Stack Size | 423 /// uint64 : Stack Size |
424 /// uint64 : Record Count | |
416 /// } | 425 /// } |
417 void StackMaps::emitFunctionFrameRecords(MCStreamer &OS) { | 426 void StackMaps::emitFunctionFrameRecords(MCStreamer &OS) { |
418 // Function Frame records. | 427 // Function Frame records. |
419 DEBUG(dbgs() << WSMP << "functions:\n"); | 428 DEBUG(dbgs() << WSMP << "functions:\n"); |
420 for (auto const &FR : FnStackSize) { | 429 for (auto const &FR : FnInfos) { |
421 DEBUG(dbgs() << WSMP << "function addr: " << FR.first | 430 DEBUG(dbgs() << WSMP << "function addr: " << FR.first |
422 << " frame size: " << FR.second); | 431 << " frame size: " << FR.second.StackSize |
432 << " callsite count: " << FR.second.RecordCount << '\n'); | |
423 OS.EmitSymbolValue(FR.first, 8); | 433 OS.EmitSymbolValue(FR.first, 8); |
424 OS.EmitIntValue(FR.second, 8); | 434 OS.EmitIntValue(FR.second.StackSize, 8); |
435 OS.EmitIntValue(FR.second.RecordCount, 8); | |
425 } | 436 } |
426 } | 437 } |
427 | 438 |
428 /// Emit the constant pool. | 439 /// Emit the constant pool. |
429 /// | 440 /// |
518 | 529 |
519 /// Serialize the stackmap data. | 530 /// Serialize the stackmap data. |
520 void StackMaps::serializeToStackMapSection() { | 531 void StackMaps::serializeToStackMapSection() { |
521 (void)WSMP; | 532 (void)WSMP; |
522 // Bail out if there's no stack map data. | 533 // Bail out if there's no stack map data. |
523 assert((!CSInfos.empty() || (CSInfos.empty() && ConstPool.empty())) && | 534 assert((!CSInfos.empty() || ConstPool.empty()) && |
524 "Expected empty constant pool too!"); | 535 "Expected empty constant pool too!"); |
525 assert((!CSInfos.empty() || (CSInfos.empty() && FnStackSize.empty())) && | 536 assert((!CSInfos.empty() || FnInfos.empty()) && |
526 "Expected empty function record too!"); | 537 "Expected empty function record too!"); |
527 if (CSInfos.empty()) | 538 if (CSInfos.empty()) |
528 return; | 539 return; |
529 | 540 |
530 MCContext &OutContext = AP.OutStreamer->getContext(); | 541 MCContext &OutContext = AP.OutStreamer->getContext(); |