xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCFragment.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1 //===- MCFragment.h - Fragment type hierarchy -------------------*- C++ -*-===//
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 
9 #ifndef LLVM_MC_MCFRAGMENT_H
10 #define LLVM_MC_MCFRAGMENT_H
11 
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/SmallString.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/ilist_node.h"
17 #include "llvm/MC/MCFixup.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/Support/Alignment.h"
20 #include "llvm/Support/SMLoc.h"
21 #include <cstdint>
22 #include <utility>
23 
24 namespace llvm {
25 
26 class MCSection;
27 class MCSubtargetInfo;
28 class MCSymbol;
29 
30 class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
31   friend class MCAsmLayout;
32 
33 public:
34   enum FragmentType : uint8_t {
35     FT_Align,
36     FT_Data,
37     FT_CompactEncodedInst,
38     FT_Fill,
39     FT_Nops,
40     FT_Relaxable,
41     FT_Org,
42     FT_Dwarf,
43     FT_DwarfFrame,
44     FT_LEB,
45     FT_BoundaryAlign,
46     FT_SymbolId,
47     FT_CVInlineLines,
48     FT_CVDefRange,
49     FT_PseudoProbe,
50     FT_Dummy
51   };
52 
53 private:
54   /// The data for the section this fragment is in.
55   MCSection *Parent;
56 
57   /// The atom this fragment is in, as represented by its defining symbol.
58   const MCSymbol *Atom;
59 
60   /// The offset of this fragment in its section. This is ~0 until
61   /// initialized.
62   uint64_t Offset;
63 
64   /// The layout order of this fragment.
65   unsigned LayoutOrder;
66 
67   /// The subsection this fragment belongs to. This is 0 if the fragment is not
68   // in any subsection.
69   unsigned SubsectionNumber = 0;
70 
71   FragmentType Kind;
72 
73   /// Whether fragment is being laid out.
74   bool IsBeingLaidOut;
75 
76 protected:
77   bool HasInstructions;
78   bool LinkerRelaxable = false;
79 
80   MCFragment(FragmentType Kind, bool HasInstructions,
81              MCSection *Parent = nullptr);
82 
83 public:
84   MCFragment() = delete;
85   MCFragment(const MCFragment &) = delete;
86   MCFragment &operator=(const MCFragment &) = delete;
87 
88   /// Destroys the current fragment.
89   ///
90   /// This must be used instead of delete as MCFragment is non-virtual.
91   /// This method will dispatch to the appropriate subclass.
92   void destroy();
93 
94   FragmentType getKind() const { return Kind; }
95 
96   MCSection *getParent() const { return Parent; }
97   void setParent(MCSection *Value) { Parent = Value; }
98 
99   const MCSymbol *getAtom() const { return Atom; }
100   void setAtom(const MCSymbol *Value) { Atom = Value; }
101 
102   unsigned getLayoutOrder() const { return LayoutOrder; }
103   void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
104 
105   /// Does this fragment have instructions emitted into it? By default
106   /// this is false, but specific fragment types may set it to true.
107   bool hasInstructions() const { return HasInstructions; }
108 
109   void dump() const;
110 
111   void setSubsectionNumber(unsigned Value) { SubsectionNumber = Value; }
112   unsigned getSubsectionNumber() const { return SubsectionNumber; }
113 };
114 
115 class MCDummyFragment : public MCFragment {
116 public:
117   explicit MCDummyFragment(MCSection *Sec) : MCFragment(FT_Dummy, false, Sec) {}
118 
119   static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
120 };
121 
122 /// Interface implemented by fragments that contain encoded instructions and/or
123 /// data.
124 ///
125 class MCEncodedFragment : public MCFragment {
126   /// Should this fragment be aligned to the end of a bundle?
127   bool AlignToBundleEnd = false;
128 
129   uint8_t BundlePadding = 0;
130 
131 protected:
132   MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions,
133                     MCSection *Sec)
134       : MCFragment(FType, HasInstructions, Sec) {}
135 
136   /// The MCSubtargetInfo in effect when the instruction was encoded.
137   /// It must be non-null for instructions.
138   const MCSubtargetInfo *STI = nullptr;
139 
140 public:
141   static bool classof(const MCFragment *F) {
142     MCFragment::FragmentType Kind = F->getKind();
143     switch (Kind) {
144     default:
145       return false;
146     case MCFragment::FT_Relaxable:
147     case MCFragment::FT_CompactEncodedInst:
148     case MCFragment::FT_Data:
149     case MCFragment::FT_Dwarf:
150     case MCFragment::FT_DwarfFrame:
151     case MCFragment::FT_PseudoProbe:
152       return true;
153     }
154   }
155 
156   /// Should this fragment be placed at the end of an aligned bundle?
157   bool alignToBundleEnd() const { return AlignToBundleEnd; }
158   void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
159 
160   /// Get the padding size that must be inserted before this fragment.
161   /// Used for bundling. By default, no padding is inserted.
162   /// Note that padding size is restricted to 8 bits. This is an optimization
163   /// to reduce the amount of space used for each fragment. In practice, larger
164   /// padding should never be required.
165   uint8_t getBundlePadding() const { return BundlePadding; }
166 
167   /// Set the padding size for this fragment. By default it's a no-op,
168   /// and only some fragments have a meaningful implementation.
169   void setBundlePadding(uint8_t N) { BundlePadding = N; }
170 
171   /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded.
172   /// Guaranteed to be non-null if hasInstructions() == true
173   const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
174 
175   /// Record that the fragment contains instructions with the MCSubtargetInfo in
176   /// effect when the instruction was encoded.
177   void setHasInstructions(const MCSubtargetInfo &STI) {
178     HasInstructions = true;
179     this->STI = &STI;
180   }
181 };
182 
183 /// Interface implemented by fragments that contain encoded instructions and/or
184 /// data.
185 ///
186 template<unsigned ContentsSize>
187 class MCEncodedFragmentWithContents : public MCEncodedFragment {
188   SmallVector<char, ContentsSize> Contents;
189 
190 protected:
191   MCEncodedFragmentWithContents(MCFragment::FragmentType FType,
192                                 bool HasInstructions,
193                                 MCSection *Sec)
194       : MCEncodedFragment(FType, HasInstructions, Sec) {}
195 
196 public:
197   SmallVectorImpl<char> &getContents() { return Contents; }
198   const SmallVectorImpl<char> &getContents() const { return Contents; }
199 };
200 
201 /// Interface implemented by fragments that contain encoded instructions and/or
202 /// data and also have fixups registered.
203 ///
204 template<unsigned ContentsSize, unsigned FixupsSize>
205 class MCEncodedFragmentWithFixups :
206   public MCEncodedFragmentWithContents<ContentsSize> {
207 
208   /// The list of fixups in this fragment.
209   SmallVector<MCFixup, FixupsSize> Fixups;
210 
211 protected:
212   MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
213                               bool HasInstructions,
214                               MCSection *Sec)
215       : MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions,
216                                                     Sec) {}
217 
218 public:
219 
220   using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator;
221   using fixup_iterator = SmallVectorImpl<MCFixup>::iterator;
222 
223   SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
224   const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
225 
226   fixup_iterator fixup_begin() { return Fixups.begin(); }
227   const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
228 
229   fixup_iterator fixup_end() { return Fixups.end(); }
230   const_fixup_iterator fixup_end() const { return Fixups.end(); }
231 
232   static bool classof(const MCFragment *F) {
233     MCFragment::FragmentType Kind = F->getKind();
234     return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
235            Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
236            Kind == MCFragment::FT_DwarfFrame;
237   }
238 };
239 
240 /// Fragment for data and encoded instructions.
241 ///
242 class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
243 public:
244   MCDataFragment(MCSection *Sec = nullptr)
245       : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {}
246 
247   static bool classof(const MCFragment *F) {
248     return F->getKind() == MCFragment::FT_Data;
249   }
250 
251   bool isLinkerRelaxable() const { return LinkerRelaxable; }
252   void setLinkerRelaxable() { LinkerRelaxable = true; }
253 };
254 
255 /// This is a compact (memory-size-wise) fragment for holding an encoded
256 /// instruction (non-relaxable) that has no fixups registered. When applicable,
257 /// it can be used instead of MCDataFragment and lead to lower memory
258 /// consumption.
259 ///
260 class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> {
261 public:
262   MCCompactEncodedInstFragment(MCSection *Sec = nullptr)
263       : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) {
264   }
265 
266   static bool classof(const MCFragment *F) {
267     return F->getKind() == MCFragment::FT_CompactEncodedInst;
268   }
269 };
270 
271 /// A relaxable fragment holds on to its MCInst, since it may need to be
272 /// relaxed during the assembler layout and relaxation stage.
273 ///
274 class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
275 
276   /// The instruction this is a fragment for.
277   MCInst Inst;
278   /// Can we auto pad the instruction?
279   bool AllowAutoPadding = false;
280 
281 public:
282   MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI,
283                       MCSection *Sec = nullptr)
284       : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec),
285         Inst(Inst) { this->STI = &STI; }
286 
287   const MCInst &getInst() const { return Inst; }
288   void setInst(const MCInst &Value) { Inst = Value; }
289 
290   bool getAllowAutoPadding() const { return AllowAutoPadding; }
291   void setAllowAutoPadding(bool V) { AllowAutoPadding = V; }
292 
293   static bool classof(const MCFragment *F) {
294     return F->getKind() == MCFragment::FT_Relaxable;
295   }
296 };
297 
298 class MCAlignFragment : public MCFragment {
299   /// The alignment to ensure, in bytes.
300   Align Alignment;
301 
302   /// Flag to indicate that (optimal) NOPs should be emitted instead
303   /// of using the provided value. The exact interpretation of this flag is
304   /// target dependent.
305   bool EmitNops : 1;
306 
307   /// Value to use for filling padding bytes.
308   int64_t Value;
309 
310   /// The size of the integer (in bytes) of \p Value.
311   unsigned ValueSize;
312 
313   /// The maximum number of bytes to emit; if the alignment
314   /// cannot be satisfied in this width then this fragment is ignored.
315   unsigned MaxBytesToEmit;
316 
317   /// When emitting Nops some subtargets have specific nop encodings.
318   const MCSubtargetInfo *STI = nullptr;
319 
320 public:
321   MCAlignFragment(Align Alignment, int64_t Value, unsigned ValueSize,
322                   unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
323       : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false),
324         Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
325 
326   Align getAlignment() const { return Alignment; }
327 
328   int64_t getValue() const { return Value; }
329 
330   unsigned getValueSize() const { return ValueSize; }
331 
332   unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
333 
334   bool hasEmitNops() const { return EmitNops; }
335   void setEmitNops(bool Value, const MCSubtargetInfo *STI) {
336     EmitNops = Value;
337     this->STI = STI;
338   }
339 
340   const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
341 
342   static bool classof(const MCFragment *F) {
343     return F->getKind() == MCFragment::FT_Align;
344   }
345 };
346 
347 class MCFillFragment : public MCFragment {
348   uint8_t ValueSize;
349   /// Value to use for filling bytes.
350   uint64_t Value;
351   /// The number of bytes to insert.
352   const MCExpr &NumValues;
353 
354   /// Source location of the directive that this fragment was created for.
355   SMLoc Loc;
356 
357 public:
358   MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
359                  SMLoc Loc, MCSection *Sec = nullptr)
360       : MCFragment(FT_Fill, false, Sec), ValueSize(VSize), Value(Value),
361         NumValues(NumValues), Loc(Loc) {}
362 
363   uint64_t getValue() const { return Value; }
364   uint8_t getValueSize() const { return ValueSize; }
365   const MCExpr &getNumValues() const { return NumValues; }
366 
367   SMLoc getLoc() const { return Loc; }
368 
369   static bool classof(const MCFragment *F) {
370     return F->getKind() == MCFragment::FT_Fill;
371   }
372 };
373 
374 class MCNopsFragment : public MCFragment {
375   /// The number of bytes to insert.
376   int64_t Size;
377   /// Maximum number of bytes allowed in each NOP instruction.
378   int64_t ControlledNopLength;
379 
380   /// Source location of the directive that this fragment was created for.
381   SMLoc Loc;
382 
383   /// When emitting Nops some subtargets have specific nop encodings.
384   const MCSubtargetInfo &STI;
385 
386 public:
387   MCNopsFragment(int64_t NumBytes, int64_t ControlledNopLength, SMLoc L,
388                  const MCSubtargetInfo &STI, MCSection *Sec = nullptr)
389       : MCFragment(FT_Nops, false, Sec), Size(NumBytes),
390         ControlledNopLength(ControlledNopLength), Loc(L), STI(STI) {}
391 
392   int64_t getNumBytes() const { return Size; }
393   int64_t getControlledNopLength() const { return ControlledNopLength; }
394 
395   SMLoc getLoc() const { return Loc; }
396 
397   const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
398 
399   static bool classof(const MCFragment *F) {
400     return F->getKind() == MCFragment::FT_Nops;
401   }
402 };
403 
404 class MCOrgFragment : public MCFragment {
405   /// Value to use for filling bytes.
406   int8_t Value;
407 
408   /// The offset this fragment should start at.
409   const MCExpr *Offset;
410 
411   /// Source location of the directive that this fragment was created for.
412   SMLoc Loc;
413 
414 public:
415   MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc,
416                 MCSection *Sec = nullptr)
417       : MCFragment(FT_Org, false, Sec), Value(Value), Offset(&Offset),
418         Loc(Loc) {}
419 
420   const MCExpr &getOffset() const { return *Offset; }
421 
422   uint8_t getValue() const { return Value; }
423 
424   SMLoc getLoc() const { return Loc; }
425 
426   static bool classof(const MCFragment *F) {
427     return F->getKind() == MCFragment::FT_Org;
428   }
429 };
430 
431 class MCLEBFragment : public MCFragment {
432   /// True if this is a sleb128, false if uleb128.
433   bool IsSigned;
434 
435   /// The value this fragment should contain.
436   const MCExpr *Value;
437 
438   SmallString<8> Contents;
439 
440 public:
441   MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr)
442       : MCFragment(FT_LEB, false, Sec), IsSigned(IsSigned_), Value(&Value_) {
443     Contents.push_back(0);
444   }
445 
446   const MCExpr &getValue() const { return *Value; }
447 
448   bool isSigned() const { return IsSigned; }
449 
450   SmallString<8> &getContents() { return Contents; }
451   const SmallString<8> &getContents() const { return Contents; }
452 
453   /// @}
454 
455   static bool classof(const MCFragment *F) {
456     return F->getKind() == MCFragment::FT_LEB;
457   }
458 };
459 
460 class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
461   /// The value of the difference between the two line numbers
462   /// between two .loc dwarf directives.
463   int64_t LineDelta;
464 
465   /// The expression for the difference of the two symbols that
466   /// make up the address delta between two .loc dwarf directives.
467   const MCExpr *AddrDelta;
468 
469 public:
470   MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
471                           MCSection *Sec = nullptr)
472       : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec),
473         LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
474 
475   int64_t getLineDelta() const { return LineDelta; }
476 
477   const MCExpr &getAddrDelta() const { return *AddrDelta; }
478 
479   static bool classof(const MCFragment *F) {
480     return F->getKind() == MCFragment::FT_Dwarf;
481   }
482 };
483 
484 class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
485   /// The expression for the difference of the two symbols that
486   /// make up the address delta between two .cfi_* dwarf directives.
487   const MCExpr *AddrDelta;
488 
489 public:
490   MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
491       : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec),
492         AddrDelta(&AddrDelta) {}
493 
494   const MCExpr &getAddrDelta() const { return *AddrDelta; }
495   void setAddrDelta(const MCExpr *E) { AddrDelta = E; }
496 
497   static bool classof(const MCFragment *F) {
498     return F->getKind() == MCFragment::FT_DwarfFrame;
499   }
500 };
501 
502 /// Represents a symbol table index fragment.
503 class MCSymbolIdFragment : public MCFragment {
504   const MCSymbol *Sym;
505 
506 public:
507   MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
508       : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {}
509 
510   const MCSymbol *getSymbol() { return Sym; }
511   const MCSymbol *getSymbol() const { return Sym; }
512 
513   static bool classof(const MCFragment *F) {
514     return F->getKind() == MCFragment::FT_SymbolId;
515   }
516 };
517 
518 /// Fragment representing the binary annotations produced by the
519 /// .cv_inline_linetable directive.
520 class MCCVInlineLineTableFragment : public MCFragment {
521   unsigned SiteFuncId;
522   unsigned StartFileId;
523   unsigned StartLineNum;
524   const MCSymbol *FnStartSym;
525   const MCSymbol *FnEndSym;
526   SmallString<8> Contents;
527 
528   /// CodeViewContext has the real knowledge about this format, so let it access
529   /// our members.
530   friend class CodeViewContext;
531 
532 public:
533   MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
534                               unsigned StartLineNum, const MCSymbol *FnStartSym,
535                               const MCSymbol *FnEndSym,
536                               MCSection *Sec = nullptr)
537       : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId),
538         StartFileId(StartFileId), StartLineNum(StartLineNum),
539         FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
540 
541   const MCSymbol *getFnStartSym() const { return FnStartSym; }
542   const MCSymbol *getFnEndSym() const { return FnEndSym; }
543 
544   SmallString<8> &getContents() { return Contents; }
545   const SmallString<8> &getContents() const { return Contents; }
546 
547   static bool classof(const MCFragment *F) {
548     return F->getKind() == MCFragment::FT_CVInlineLines;
549   }
550 };
551 
552 /// Fragment representing the .cv_def_range directive.
553 class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
554   SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
555   SmallString<32> FixedSizePortion;
556 
557   /// CodeViewContext has the real knowledge about this format, so let it access
558   /// our members.
559   friend class CodeViewContext;
560 
561 public:
562   MCCVDefRangeFragment(
563       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
564       StringRef FixedSizePortion, MCSection *Sec = nullptr)
565       : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec),
566         Ranges(Ranges.begin(), Ranges.end()),
567         FixedSizePortion(FixedSizePortion) {}
568 
569   ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
570     return Ranges;
571   }
572 
573   StringRef getFixedSizePortion() const { return FixedSizePortion.str(); }
574 
575   static bool classof(const MCFragment *F) {
576     return F->getKind() == MCFragment::FT_CVDefRange;
577   }
578 };
579 
580 /// Represents required padding such that a particular other set of fragments
581 /// does not cross a particular power-of-two boundary. The other fragments must
582 /// follow this one within the same section.
583 class MCBoundaryAlignFragment : public MCFragment {
584   /// The alignment requirement of the branch to be aligned.
585   Align AlignBoundary;
586   /// The last fragment in the set of fragments to be aligned.
587   const MCFragment *LastFragment = nullptr;
588   /// The size of the fragment.  The size is lazily set during relaxation, and
589   /// is not meaningful before that.
590   uint64_t Size = 0;
591 
592   /// When emitting Nops some subtargets have specific nop encodings.
593   const MCSubtargetInfo &STI;
594 
595 public:
596   MCBoundaryAlignFragment(Align AlignBoundary, const MCSubtargetInfo &STI,
597                           MCSection *Sec = nullptr)
598       : MCFragment(FT_BoundaryAlign, false, Sec), AlignBoundary(AlignBoundary),
599         STI(STI) {}
600 
601   uint64_t getSize() const { return Size; }
602   void setSize(uint64_t Value) { Size = Value; }
603 
604   Align getAlignment() const { return AlignBoundary; }
605   void setAlignment(Align Value) { AlignBoundary = Value; }
606 
607   const MCFragment *getLastFragment() const { return LastFragment; }
608   void setLastFragment(const MCFragment *F) {
609     assert(!F || getParent() == F->getParent());
610     LastFragment = F;
611   }
612 
613   const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
614 
615   static bool classof(const MCFragment *F) {
616     return F->getKind() == MCFragment::FT_BoundaryAlign;
617   }
618 };
619 
620 class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
621   /// The expression for the difference of the two symbols that
622   /// make up the address delta between two .pseudoprobe directives.
623   const MCExpr *AddrDelta;
624 
625 public:
626   MCPseudoProbeAddrFragment(const MCExpr *AddrDelta, MCSection *Sec = nullptr)
627       : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false, Sec),
628         AddrDelta(AddrDelta) {}
629 
630   const MCExpr &getAddrDelta() const { return *AddrDelta; }
631 
632   static bool classof(const MCFragment *F) {
633     return F->getKind() == MCFragment::FT_PseudoProbe;
634   }
635 };
636 } // end namespace llvm
637 
638 #endif // LLVM_MC_MCFRAGMENT_H
639