LLVM 22.0.0git
StackMaps.cpp
Go to the documentation of this file.
1//===- StackMaps.cpp ------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11#include "llvm/ADT/STLExtras.h"
12#include "llvm/ADT/Twine.h"
21#include "llvm/IR/DataLayout.h"
22#include "llvm/MC/MCContext.h"
23#include "llvm/MC/MCExpr.h"
25#include "llvm/MC/MCStreamer.h"
27#include "llvm/Support/Debug.h"
31#include <algorithm>
32#include <cassert>
33#include <cstdint>
34#include <iterator>
35#include <utility>
36
37using namespace llvm;
38
39#define DEBUG_TYPE "stackmaps"
40
42 "stackmap-version", cl::init(3), cl::Hidden,
43 cl::desc("Specify the stackmap encoding version (default = 3)"));
44
45const char *StackMaps::WSMP = "Stack Maps: ";
46
47static uint64_t getConstMetaVal(const MachineInstr &MI, unsigned Idx) {
48 assert(MI.getOperand(Idx).isImm() &&
49 MI.getOperand(Idx).getImm() == StackMaps::ConstantOp);
50 const auto &MO = MI.getOperand(Idx + 1);
51 assert(MO.isImm());
52 return MO.getImm();
53}
54
56 : MI(MI) {
57 assert(getVarIdx() <= MI->getNumOperands() &&
58 "invalid stackmap definition");
59}
60
62 : MI(MI), HasDef(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() &&
63 !MI->getOperand(0).isImplicit()) {
64#ifndef NDEBUG
65 unsigned CheckStartIdx = 0, e = MI->getNumOperands();
66 while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).isReg() &&
67 MI->getOperand(CheckStartIdx).isDef() &&
68 !MI->getOperand(CheckStartIdx).isImplicit())
69 ++CheckStartIdx;
70
71 assert(getMetaIdx() == CheckStartIdx &&
72 "Unexpected additional definition in Patchpoint intrinsic.");
73#endif
74}
75
76unsigned PatchPointOpers::getNextScratchIdx(unsigned StartIdx) const {
77 if (!StartIdx)
78 StartIdx = getVarIdx();
79
80 // Find the next scratch register (implicit def and early clobber)
81 unsigned ScratchIdx = StartIdx, e = MI->getNumOperands();
82 while (ScratchIdx < e &&
83 !(MI->getOperand(ScratchIdx).isReg() &&
84 MI->getOperand(ScratchIdx).isDef() &&
85 MI->getOperand(ScratchIdx).isImplicit() &&
86 MI->getOperand(ScratchIdx).isEarlyClobber()))
87 ++ScratchIdx;
88
89 assert(ScratchIdx != e && "No scratch register available");
90 return ScratchIdx;
91}
92
94 // Take index of num of allocas and skip all allocas records.
95 unsigned CurIdx = getNumAllocaIdx();
96 unsigned NumAllocas = getConstMetaVal(*MI, CurIdx - 1);
97 CurIdx++;
98 while (NumAllocas--)
99 CurIdx = StackMaps::getNextMetaArgIdx(MI, CurIdx);
100 return CurIdx + 1; // skip <StackMaps::ConstantOp>
101}
102
104 // Take index of num of gc ptrs and skip all gc ptr records.
105 unsigned CurIdx = getNumGCPtrIdx();
106 unsigned NumGCPtrs = getConstMetaVal(*MI, CurIdx - 1);
107 CurIdx++;
108 while (NumGCPtrs--)
109 CurIdx = StackMaps::getNextMetaArgIdx(MI, CurIdx);
110 return CurIdx + 1; // skip <StackMaps::ConstantOp>
111}
112
114 // Take index of num of deopt args and skip all deopt records.
115 unsigned CurIdx = getNumDeoptArgsIdx();
116 unsigned NumDeoptArgs = getConstMetaVal(*MI, CurIdx - 1);
117 CurIdx++;
118 while (NumDeoptArgs--) {
119 CurIdx = StackMaps::getNextMetaArgIdx(MI, CurIdx);
120 }
121 return CurIdx + 1; // skip <StackMaps::ConstantOp>
122}
123
125 unsigned NumGCPtrsIdx = getNumGCPtrIdx();
126 unsigned NumGCPtrs = getConstMetaVal(*MI, NumGCPtrsIdx - 1);
127 if (NumGCPtrs == 0)
128 return -1;
129 ++NumGCPtrsIdx; // skip <num gc ptrs>
130 assert(NumGCPtrsIdx < MI->getNumOperands());
131 return (int)NumGCPtrsIdx;
132}
133
135 SmallVectorImpl<std::pair<unsigned, unsigned>> &GCMap) {
136 unsigned CurIdx = getNumGcMapEntriesIdx();
137 unsigned GCMapSize = getConstMetaVal(*MI, CurIdx - 1);
138 CurIdx++;
139 for (unsigned N = 0; N < GCMapSize; ++N) {
140 unsigned B = MI->getOperand(CurIdx++).getImm();
141 unsigned D = MI->getOperand(CurIdx++).getImm();
142 GCMap.push_back(std::make_pair(B, D));
143 }
144
145 return GCMapSize;
146}
147
149 unsigned FoldableAreaStart = getVarIdx();
150 for (const MachineOperand &MO : MI->uses()) {
151 if (MO.getOperandNo() >= FoldableAreaStart)
152 break;
153 if (MO.isReg() && MO.getReg() == Reg)
154 return false;
155 }
156 return true;
157}
158
160 if (MI->getOpcode() != TargetOpcode::STATEPOINT)
161 return false;
162 return StatepointOpers(MI).isFoldableReg(Reg);
163}
164
166 if (StackMapVersion != 3)
167 llvm_unreachable("Unsupported stackmap version!");
168}
169
170unsigned StackMaps::getNextMetaArgIdx(const MachineInstr *MI, unsigned CurIdx) {
171 assert(CurIdx < MI->getNumOperands() && "Bad meta arg index");
172 const auto &MO = MI->getOperand(CurIdx);
173 if (MO.isImm()) {
174 switch (MO.getImm()) {
175 default:
176 llvm_unreachable("Unrecognized operand type.");
177 case StackMaps::DirectMemRefOp:
178 CurIdx += 2;
179 break;
180 case StackMaps::IndirectMemRefOp:
181 CurIdx += 3;
182 break;
183 case StackMaps::ConstantOp:
184 ++CurIdx;
185 break;
186 }
187 }
188 ++CurIdx;
189 assert(CurIdx < MI->getNumOperands() && "points past operand list");
190 return CurIdx;
191}
192
193/// Go up the super-register chain until we hit a valid dwarf register number.
195 int RegNum;
196 for (MCPhysReg SR : TRI->superregs_inclusive(Reg)) {
197 RegNum = TRI->getDwarfRegNum(SR, false);
198 if (RegNum >= 0)
199 break;
200 }
201
202 assert(RegNum >= 0 && isUInt<16>(RegNum) && "Invalid Dwarf register number.");
203 return (unsigned)RegNum;
204}
205
207StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
208 MachineInstr::const_mop_iterator MOE, LocationVec &Locs,
209 LiveOutVec &LiveOuts) {
210 const TargetRegisterInfo *TRI = AP.MF->getSubtarget().getRegisterInfo();
211 if (MOI->isImm()) {
212 switch (MOI->getImm()) {
213 default:
214 llvm_unreachable("Unrecognized operand type.");
215 case StackMaps::DirectMemRefOp: {
216 auto &DL = AP.MF->getDataLayout();
217
218 unsigned Size = DL.getPointerSizeInBits();
219 assert((Size % 8) == 0 && "Need pointer size in bytes.");
220 Size /= 8;
221 Register Reg = (++MOI)->getReg();
222 int64_t Imm = (++MOI)->getImm();
223 Locs.emplace_back(StackMaps::Location::Direct, Size,
224 getDwarfRegNum(Reg, TRI), Imm);
225 break;
226 }
227 case StackMaps::IndirectMemRefOp: {
228 int64_t Size = (++MOI)->getImm();
229 assert(Size > 0 && "Need a valid size for indirect memory locations.");
230 Register Reg = (++MOI)->getReg();
231 int64_t Imm = (++MOI)->getImm();
232 Locs.emplace_back(StackMaps::Location::Indirect, Size,
233 getDwarfRegNum(Reg, TRI), Imm);
234 break;
235 }
236 case StackMaps::ConstantOp: {
237 ++MOI;
238 assert(MOI->isImm() && "Expected constant operand.");
239 int64_t Imm = MOI->getImm();
240 if (isInt<32>(Imm)) {
241 Locs.emplace_back(Location::Constant, sizeof(int64_t), 0, Imm);
242 } else {
243 // ConstPool is intentionally a MapVector of 'uint64_t's (as
244 // opposed to 'int64_t's). We should never be in a situation
245 // where we have to insert either the tombstone or the empty
246 // keys into a map, and for a DenseMap<uint64_t, T> these are
247 // (uint64_t)0 and (uint64_t)-1. They can be and are
248 // represented using 32 bit integers.
249 assert((uint64_t)Imm != DenseMapInfo<uint64_t>::getEmptyKey() &&
250 (uint64_t)Imm != DenseMapInfo<uint64_t>::getTombstoneKey() &&
251 "empty and tombstone keys should fit in 32 bits!");
252 auto Result = ConstPool.insert(std::make_pair(Imm, Imm));
253 Locs.emplace_back(Location::ConstantIndex, sizeof(int64_t), 0,
254 Result.first - ConstPool.begin());
255 }
256 break;
257 }
258 }
259 return ++MOI;
260 }
261
262 // The physical register number will ultimately be encoded as a DWARF regno.
263 // The stack map also records the size of a spill slot that can hold the
264 // register content. (The runtime can track the actual size of the data type
265 // if it needs to.)
266 if (MOI->isReg()) {
267 // Skip implicit registers (this includes our scratch registers)
268 if (MOI->isImplicit())
269 return ++MOI;
270
271 assert(MOI->getReg().isPhysical() &&
272 "Virtreg operands should have been rewritten before now.");
273 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(MOI->getReg());
274 assert(!MOI->getSubReg() && "Physical subreg still around.");
275
276 unsigned Offset = 0;
277 unsigned DwarfRegNum = getDwarfRegNum(MOI->getReg(), TRI);
278 MCRegister LLVMRegNum = *TRI->getLLVMRegNum(DwarfRegNum, false);
279 unsigned SubRegIdx = TRI->getSubRegIndex(LLVMRegNum, MOI->getReg());
280 if (SubRegIdx)
281 Offset = TRI->getSubRegIdxOffset(SubRegIdx);
282
283 Locs.emplace_back(Location::Register, TRI->getSpillSize(*RC),
284 DwarfRegNum, Offset);
285 return ++MOI;
286 }
287
288 if (MOI->isRegLiveOut())
289 LiveOuts = parseRegisterLiveOutMask(MOI->getRegLiveOut());
290
291 return ++MOI;
292}
293
294void StackMaps::print(raw_ostream &OS) {
295 const TargetRegisterInfo *TRI =
296 AP.MF ? AP.MF->getSubtarget().getRegisterInfo() : nullptr;
297 OS << WSMP << "callsites:\n";
298 for (const auto &CSI : CSInfos) {
299 const LocationVec &CSLocs = CSI.Locations;
300 const LiveOutVec &LiveOuts = CSI.LiveOuts;
301
302 OS << WSMP << "callsite " << CSI.ID << "\n";
303 OS << WSMP << " has " << CSLocs.size() << " locations\n";
304
305 unsigned Idx = 0;
306 for (const auto &Loc : CSLocs) {
307 OS << WSMP << "\t\tLoc " << Idx << ": ";
308 switch (Loc.Type) {
310 OS << "<Unprocessed operand>";
311 break;
313 OS << "Register ";
314 if (TRI)
315 OS << printReg(Loc.Reg, TRI);
316 else
317 OS << Loc.Reg;
318 break;
319 case Location::Direct:
320 OS << "Direct ";
321 if (TRI)
322 OS << printReg(Loc.Reg, TRI);
323 else
324 OS << Loc.Reg;
325 if (Loc.Offset)
326 OS << " + " << Loc.Offset;
327 break;
329 OS << "Indirect ";
330 if (TRI)
331 OS << printReg(Loc.Reg, TRI);
332 else
333 OS << Loc.Reg;
334 OS << "+" << Loc.Offset;
335 break;
337 OS << "Constant " << Loc.Offset;
338 break;
340 OS << "Constant Index " << Loc.Offset;
341 break;
342 }
343 OS << "\t[encoding: .byte " << Loc.Type << ", .byte 0"
344 << ", .short " << Loc.Size << ", .short " << Loc.Reg << ", .short 0"
345 << ", .int " << Loc.Offset << "]\n";
346 Idx++;
347 }
348
349 OS << WSMP << "\thas " << LiveOuts.size() << " live-out registers\n";
350
351 Idx = 0;
352 for (const auto &LO : LiveOuts) {
353 OS << WSMP << "\t\tLO " << Idx << ": ";
354 if (TRI)
355 OS << printReg(LO.Reg, TRI);
356 else
357 OS << LO.Reg;
358 OS << "\t[encoding: .short " << LO.DwarfRegNum << ", .byte 0, .byte "
359 << LO.Size << "]\n";
360 Idx++;
361 }
362 }
363}
364
365/// Create a live-out register record for the given register Reg.
367StackMaps::createLiveOutReg(unsigned Reg, const TargetRegisterInfo *TRI) const {
368 unsigned DwarfRegNum = getDwarfRegNum(Reg, TRI);
369 unsigned Size = TRI->getSpillSize(*TRI->getMinimalPhysRegClass(Reg));
370 return LiveOutReg(Reg, DwarfRegNum, Size);
371}
372
373/// Parse the register live-out mask and return a vector of live-out registers
374/// that need to be recorded in the stackmap.
376StackMaps::parseRegisterLiveOutMask(const uint32_t *Mask) const {
377 assert(Mask && "No register mask specified");
378 const TargetRegisterInfo *TRI = AP.MF->getSubtarget().getRegisterInfo();
379 LiveOutVec LiveOuts;
380
381 // Create a LiveOutReg for each bit that is set in the register mask.
382 for (unsigned Reg = 0, NumRegs = TRI->getNumRegs(); Reg != NumRegs; ++Reg)
383 if ((Mask[Reg / 32] >> (Reg % 32)) & 1)
384 LiveOuts.push_back(createLiveOutReg(Reg, TRI));
385
386 // We don't need to keep track of a register if its super-register is already
387 // in the list. Merge entries that refer to the same dwarf register and use
388 // the maximum size that needs to be spilled.
389
390 llvm::sort(LiveOuts, [](const LiveOutReg &LHS, const LiveOutReg &RHS) {
391 // Only sort by the dwarf register number.
392 return LHS.DwarfRegNum < RHS.DwarfRegNum;
393 });
394
395 for (auto I = LiveOuts.begin(), E = LiveOuts.end(); I != E; ++I) {
396 for (auto *II = std::next(I); II != E; ++II) {
397 if (I->DwarfRegNum != II->DwarfRegNum) {
398 // Skip all the now invalid entries.
399 I = --II;
400 break;
401 }
402 I->Size = std::max(I->Size, II->Size);
403 if (I->Reg && TRI->isSuperRegister(I->Reg, II->Reg))
404 I->Reg = II->Reg;
405 II->Reg = 0; // mark for deletion.
406 }
407 }
408
409 llvm::erase_if(LiveOuts, [](const LiveOutReg &LO) { return LO.Reg == 0; });
410
411 return LiveOuts;
412}
413
414// See statepoint MI format description in StatepointOpers' class comment
415// in include/llvm/CodeGen/StackMaps.h
416void StackMaps::parseStatepointOpers(const MachineInstr &MI,
419 LocationVec &Locations,
420 LiveOutVec &LiveOuts) {
421 LLVM_DEBUG(dbgs() << "record statepoint : " << MI << "\n");
422 StatepointOpers SO(&MI);
423 MOI = parseOperand(MOI, MOE, Locations, LiveOuts); // CC
424 MOI = parseOperand(MOI, MOE, Locations, LiveOuts); // Flags
425 MOI = parseOperand(MOI, MOE, Locations, LiveOuts); // Num Deopts
426
427 // Record Deopt Args.
428 unsigned NumDeoptArgs = Locations.back().Offset;
429 assert(Locations.back().Type == Location::Constant);
430 assert(NumDeoptArgs == SO.getNumDeoptArgs());
431
432 while (NumDeoptArgs--)
433 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
434
435 // Record gc base/derived pairs
436 assert(MOI->isImm() && MOI->getImm() == StackMaps::ConstantOp);
437 ++MOI;
438 assert(MOI->isImm());
439 unsigned NumGCPointers = MOI->getImm();
440 ++MOI;
441 if (NumGCPointers) {
442 // Map logical index of GC ptr to MI operand index.
443 SmallVector<unsigned, 8> GCPtrIndices;
444 unsigned GCPtrIdx = (unsigned)SO.getFirstGCPtrIdx();
445 assert((int)GCPtrIdx != -1);
446 assert(MOI - MI.operands_begin() == GCPtrIdx + 0LL);
447 while (NumGCPointers--) {
448 GCPtrIndices.push_back(GCPtrIdx);
449 GCPtrIdx = StackMaps::getNextMetaArgIdx(&MI, GCPtrIdx);
450 }
451
453 unsigned NumGCPairs = SO.getGCPointerMap(GCPairs);
454 (void)NumGCPairs;
455 LLVM_DEBUG(dbgs() << "NumGCPairs = " << NumGCPairs << "\n");
456
457 auto MOB = MI.operands_begin();
458 for (auto &P : GCPairs) {
459 assert(P.first < GCPtrIndices.size() && "base pointer index not found");
460 assert(P.second < GCPtrIndices.size() &&
461 "derived pointer index not found");
462 unsigned BaseIdx = GCPtrIndices[P.first];
463 unsigned DerivedIdx = GCPtrIndices[P.second];
464 LLVM_DEBUG(dbgs() << "Base : " << BaseIdx << " Derived : " << DerivedIdx
465 << "\n");
466 (void)parseOperand(MOB + BaseIdx, MOE, Locations, LiveOuts);
467 (void)parseOperand(MOB + DerivedIdx, MOE, Locations, LiveOuts);
468 }
469
470 MOI = MOB + GCPtrIdx;
471 }
472
473 // Record gc allocas
474 assert(MOI < MOE);
475 assert(MOI->isImm() && MOI->getImm() == StackMaps::ConstantOp);
476 ++MOI;
477 unsigned NumAllocas = MOI->getImm();
478 ++MOI;
479 while (NumAllocas--) {
480 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
481 assert(MOI < MOE);
482 }
483}
484
485void StackMaps::recordStackMapOpers(const MCSymbol &MILabel,
486 const MachineInstr &MI, uint64_t ID,
489 bool recordResult) {
490 MCContext &OutContext = AP.OutStreamer->getContext();
491
493 LiveOutVec LiveOuts;
494
495 if (recordResult) {
496 assert(PatchPointOpers(&MI).hasDef() && "Stackmap has no return value.");
497 parseOperand(MI.operands_begin(), std::next(MI.operands_begin()), Locations,
498 LiveOuts);
499 }
500
501 // Parse operands.
502 if (MI.getOpcode() == TargetOpcode::STATEPOINT)
503 parseStatepointOpers(MI, MOI, MOE, Locations, LiveOuts);
504 else
505 while (MOI != MOE)
506 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
507
508 // Create an expression to calculate the offset of the callsite from function
509 // entry.
510 const MCExpr *CSOffsetExpr = MCBinaryExpr::createSub(
511 MCSymbolRefExpr::create(&MILabel, OutContext),
512 MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);
513
514 CSInfos.emplace_back(CSOffsetExpr, ID, std::move(Locations),
515 std::move(LiveOuts));
516
517 // Record the stack size of the current function and update callsite count.
518 const MachineFrameInfo &MFI = AP.MF->getFrameInfo();
519 const TargetRegisterInfo *RegInfo = AP.MF->getSubtarget().getRegisterInfo();
520 bool HasDynamicFrameSize =
521 MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(*(AP.MF));
522 uint64_t FrameSize = HasDynamicFrameSize ? UINT64_MAX : MFI.getStackSize();
523
524 auto [CurrentIt, Inserted] = FnInfos.try_emplace(AP.CurrentFnSym, FrameSize);
525 if (!Inserted)
526 CurrentIt->second.RecordCount++;
527}
528
530 assert(MI.getOpcode() == TargetOpcode::STACKMAP && "expected stackmap");
531
532 StackMapOpers opers(&MI);
533 const int64_t ID = MI.getOperand(PatchPointOpers::IDPos).getImm();
534 recordStackMapOpers(L, MI, ID, std::next(MI.operands_begin(),
535 opers.getVarIdx()),
536 MI.operands_end());
537}
538
540 assert(MI.getOpcode() == TargetOpcode::PATCHPOINT && "expected patchpoint");
541
542 PatchPointOpers opers(&MI);
543 const int64_t ID = opers.getID();
544 auto MOI = std::next(MI.operands_begin(), opers.getStackMapStartIdx());
545 recordStackMapOpers(L, MI, ID, MOI, MI.operands_end(),
546 opers.isAnyReg() && opers.hasDef());
547
548#ifndef NDEBUG
549 // verify anyregcc
550 auto &Locations = CSInfos.back().Locations;
551 if (opers.isAnyReg()) {
552 unsigned NArgs = opers.getNumCallArgs();
553 for (unsigned i = 0, e = (opers.hasDef() ? NArgs + 1 : NArgs); i != e; ++i)
554 assert(Locations[i].Type == Location::Register &&
555 "anyreg arg must be in reg.");
556 }
557#endif
558}
559
561 assert(MI.getOpcode() == TargetOpcode::STATEPOINT && "expected statepoint");
562
563 StatepointOpers opers(&MI);
564 const unsigned StartIdx = opers.getVarIdx();
565 recordStackMapOpers(L, MI, opers.getID(), MI.operands_begin() + StartIdx,
566 MI.operands_end(), false);
567}
568
569/// Emit the stackmap header.
570///
571/// Header {
572/// uint8 : Stack Map Version (currently 3)
573/// uint8 : Reserved (expected to be 0)
574/// uint16 : Reserved (expected to be 0)
575/// }
576/// uint32 : NumFunctions
577/// uint32 : NumConstants
578/// uint32 : NumRecords
579void StackMaps::emitStackmapHeader(MCStreamer &OS) {
580 // Header.
581 OS.emitIntValue(StackMapVersion, 1); // Version.
582 OS.emitIntValue(0, 1); // Reserved.
583 OS.emitInt16(0); // Reserved.
584
585 // Num functions.
586 LLVM_DEBUG(dbgs() << WSMP << "#functions = " << FnInfos.size() << '\n');
587 OS.emitInt32(FnInfos.size());
588 // Num constants.
589 LLVM_DEBUG(dbgs() << WSMP << "#constants = " << ConstPool.size() << '\n');
590 OS.emitInt32(ConstPool.size());
591 // Num callsites.
592 LLVM_DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << '\n');
593 OS.emitInt32(CSInfos.size());
594}
595
596/// Emit the function frame record for each function.
597///
598/// StkSizeRecord[NumFunctions] {
599/// uint64 : Function Address
600/// uint64 : Stack Size
601/// uint64 : Record Count
602/// }
603void StackMaps::emitFunctionFrameRecords(MCStreamer &OS) {
604 // Function Frame records.
605 LLVM_DEBUG(dbgs() << WSMP << "functions:\n");
606 for (auto const &FR : FnInfos) {
607 LLVM_DEBUG(dbgs() << WSMP << "function addr: " << FR.first
608 << " frame size: " << FR.second.StackSize
609 << " callsite count: " << FR.second.RecordCount << '\n');
610 OS.emitSymbolValue(FR.first, 8);
611 OS.emitIntValue(FR.second.StackSize, 8);
612 OS.emitIntValue(FR.second.RecordCount, 8);
613 }
614}
615
616/// Emit the constant pool.
617///
618/// int64 : Constants[NumConstants]
619void StackMaps::emitConstantPoolEntries(MCStreamer &OS) {
620 // Constant pool entries.
621 LLVM_DEBUG(dbgs() << WSMP << "constants:\n");
622 for (const auto &ConstEntry : ConstPool) {
623 LLVM_DEBUG(dbgs() << WSMP << ConstEntry.second << '\n');
624 OS.emitIntValue(ConstEntry.second, 8);
625 }
626}
627
628/// Emit the callsite info for each callsite.
629///
630/// StkMapRecord[NumRecords] {
631/// uint64 : PatchPoint ID
632/// uint32 : Instruction Offset
633/// uint16 : Reserved (record flags)
634/// uint16 : NumLocations
635/// Location[NumLocations] {
636/// uint8 : Register | Direct | Indirect | Constant | ConstantIndex
637/// uint8 : Size in Bytes
638/// uint16 : Dwarf RegNum
639/// int32 : Offset
640/// }
641/// uint16 : Padding
642/// uint16 : NumLiveOuts
643/// LiveOuts[NumLiveOuts] {
644/// uint16 : Dwarf RegNum
645/// uint8 : Reserved
646/// uint8 : Size in Bytes
647/// }
648/// uint32 : Padding (only if required to align to 8 byte)
649/// }
650///
651/// Location Encoding, Type, Value:
652/// 0x1, Register, Reg (value in register)
653/// 0x2, Direct, Reg + Offset (frame index)
654/// 0x3, Indirect, [Reg + Offset] (spilled value)
655/// 0x4, Constant, Offset (small constant)
656/// 0x5, ConstIndex, Constants[Offset] (large constant)
657void StackMaps::emitCallsiteEntries(MCStreamer &OS) {
658 LLVM_DEBUG(print(dbgs()));
659 // Callsite entries.
660 for (const auto &CSI : CSInfos) {
661 const LocationVec &CSLocs = CSI.Locations;
662 const LiveOutVec &LiveOuts = CSI.LiveOuts;
663
664 // Verify stack map entry. It's better to communicate a problem to the
665 // runtime than crash in case of in-process compilation. Currently, we do
666 // simple overflow checks, but we may eventually communicate other
667 // compilation errors this way.
668 if (CSLocs.size() > UINT16_MAX || LiveOuts.size() > UINT16_MAX) {
669 OS.emitIntValue(UINT64_MAX, 8); // Invalid ID.
670 OS.emitValue(CSI.CSOffsetExpr, 4);
671 OS.emitInt16(0); // Reserved.
672 OS.emitInt16(0); // 0 locations.
673 OS.emitInt16(0); // padding.
674 OS.emitInt16(0); // 0 live-out registers.
675 OS.emitInt32(0); // padding.
676 continue;
677 }
678
679 OS.emitIntValue(CSI.ID, 8);
680 OS.emitValue(CSI.CSOffsetExpr, 4);
681
682 // Reserved for flags.
683 OS.emitInt16(0);
684 OS.emitInt16(CSLocs.size());
685
686 for (const auto &Loc : CSLocs) {
687 OS.emitIntValue(Loc.Type, 1);
688 OS.emitIntValue(0, 1); // Reserved
689 OS.emitInt16(Loc.Size);
690 OS.emitInt16(Loc.Reg);
691 OS.emitInt16(0); // Reserved
692 OS.emitInt32(Loc.Offset);
693 }
694
695 // Emit alignment to 8 byte.
697
698 // Num live-out registers and padding to align to 4 byte.
699 OS.emitInt16(0);
700 OS.emitInt16(LiveOuts.size());
701
702 for (const auto &LO : LiveOuts) {
703 OS.emitInt16(LO.DwarfRegNum);
704 OS.emitIntValue(0, 1);
705 OS.emitIntValue(LO.Size, 1);
706 }
707 // Emit alignment to 8 byte.
709 }
710}
711
712/// Serialize the stackmap data.
714 (void)WSMP;
715 // Bail out if there's no stack map data.
716 assert((!CSInfos.empty() || ConstPool.empty()) &&
717 "Expected empty constant pool too!");
718 assert((!CSInfos.empty() || FnInfos.empty()) &&
719 "Expected empty function record too!");
720 if (CSInfos.empty())
721 return;
722
723 MCContext &OutContext = AP.OutStreamer->getContext();
724 MCStreamer &OS = *AP.OutStreamer;
725
726 // Create the section.
727 MCSection *StackMapSection =
729 OS.switchSection(StackMapSection);
730
731 // Emit a dummy symbol to force section inclusion.
732 OS.emitLabel(OutContext.getOrCreateSymbol(Twine("__LLVM_StackMaps")));
733
734 // Serialize data.
735 LLVM_DEBUG(dbgs() << "********** Stack Map Output **********\n");
736 emitStackmapHeader(OS);
737 emitFunctionFrameRecords(OS);
738 emitConstantPoolEntries(OS);
739 emitCallsiteEntries(OS);
740 OS.addBlankLine();
741
742 // Clean up.
743 CSInfos.clear();
744 ConstPool.clear();
745}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines DenseMapInfo traits for DenseMap.
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:58
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
uint64_t IntrinsicInst * II
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
static uint64_t getConstMetaVal(const MachineInstr &MI, unsigned Idx)
Definition StackMaps.cpp:47
static cl::opt< int > StackMapVersion("stackmap-version", cl::init(3), cl::Hidden, cl::desc("Specify the stackmap encoding version (default = 3)"))
static unsigned getDwarfRegNum(MCRegister Reg, const TargetRegisterInfo *TRI)
Go up the super-register chain until we hit a valid dwarf register number.
#define LLVM_DEBUG(...)
Definition Debug.h:114
Value * RHS
Value * LHS
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:90
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:428
Context object for machine code objects.
Definition MCContext.h:83
const MCObjectFileInfo * getObjectFileInfo() const
Definition MCContext.h:416
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
MCSection * getStackMapSection() const
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:33
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition MCSection.h:496
Streaming machine code generation interface.
Definition MCStreamer.h:220
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
Definition MCStreamer.h:408
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
void emitSymbolValue(const MCSymbol *Sym, unsigned Size, bool IsSectionRelative=false)
Special case of EmitValue that avoids the client having to pass in a MCExpr for MCSymbols.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitValueToAlignment(Align Alignment, int64_t Fill=0, uint8_t FillLen=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
virtual void emitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.
void emitInt16(uint64_t Value)
Definition MCStreamer.h:749
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
void emitInt32(uint64_t Value)
Definition MCStreamer.h:750
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
Representation of each machine instruction.
const MachineOperand * const_mop_iterator
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const uint32_t * getRegLiveOut() const
getRegLiveOut - Returns a bit mask of live-out registers.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isRegLiveOut() const
isRegLiveOut - Tests if this is a MO_RegisterLiveOut operand.
Register getReg() const
getReg - Returns the register number.
size_type size() const
Definition MapVector.h:56
MI-level patchpoint operands.
Definition StackMaps.h:77
uint32_t getNumCallArgs() const
Return the number of call arguments.
Definition StackMaps.h:122
LLVM_ABI PatchPointOpers(const MachineInstr *MI)
Definition StackMaps.cpp:61
LLVM_ABI unsigned getNextScratchIdx(unsigned StartIdx=0) const
Get the next scratch register operand index.
Definition StackMaps.cpp:76
uint64_t getID() const
Return the ID for the given patchpoint.
Definition StackMaps.h:102
bool isAnyReg() const
Definition StackMaps.h:98
unsigned getStackMapStartIdx() const
Get the index at which stack map locations will be recorded.
Definition StackMaps.h:134
unsigned getVarIdx() const
Get the operand index of the variable list of non-argument operands.
Definition StackMaps.h:128
bool hasDef() const
Definition StackMaps.h:99
Wrapper class representing virtual and physical registers.
Definition Register.h:19
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:78
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
MI-level stackmap operands.
Definition StackMaps.h:36
LLVM_ABI StackMapOpers(const MachineInstr *MI)
Definition StackMaps.cpp:55
unsigned getVarIdx() const
Get the operand index of the variable list of non-argument operands.
Definition StackMaps.h:57
static LLVM_ABI unsigned getNextMetaArgIdx(const MachineInstr *MI, unsigned CurIdx)
Get index of next meta operand.
LLVM_ABI StackMaps(AsmPrinter &AP)
LLVM_ABI void serializeToStackMapSection()
If there is any stack map data, create a stack map section and serialize the map info into it.
SmallVector< LiveOutReg, 8 > LiveOutVec
Definition StackMaps.h:310
SmallVector< Location, 8 > LocationVec
Definition StackMaps.h:309
LLVM_ABI void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
MI-level Statepoint operands.
Definition StackMaps.h:159
StatepointOpers(const MachineInstr *MI)
Definition StackMaps.h:174
LLVM_ABI unsigned getGCPointerMap(SmallVectorImpl< std::pair< unsigned, unsigned > > &GCMap)
Get vector of base/derived pairs from statepoint.
LLVM_ABI unsigned getNumAllocaIdx()
Get index of number of gc allocas.
LLVM_ABI unsigned getNumGcMapEntriesIdx()
Get index of number of gc map entries.
Definition StackMaps.cpp:93
LLVM_ABI int getFirstGCPtrIdx()
Get index of first GC pointer operand of -1 if there are none.
unsigned getNumDeoptArgsIdx() const
Get index of Number Deopt Arguments operand.
Definition StackMaps.h:200
uint64_t getID() const
Return the ID for the given statepoint.
Definition StackMaps.h:205
LLVM_ABI bool isFoldableReg(Register Reg) const
Return true if Reg is used only in operands which can be folded to stack usage.
unsigned getVarIdx() const
Get starting index of non call related arguments (calling convention, statepoint flags,...
Definition StackMaps.h:189
LLVM_ABI unsigned getNumGCPtrIdx()
Get index of number of GC pointers.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool hasStackRealignment(const MachineFunction &MF) const
True if stack realignment is required and still possible.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define UINT64_MAX
Definition DataTypes.h:77
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:174
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1632
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:198
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition STLExtras.h:2102
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
#define N