xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCFragment.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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 final : public MCEncodedFragmentWithFixups<8, 0> {
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 public:
439   MCLEBFragment(const MCExpr &Value, bool IsSigned, MCSection *Sec = nullptr)
440       : MCEncodedFragmentWithFixups<8, 0>(FT_LEB, false, Sec),
441         IsSigned(IsSigned), Value(&Value) {
442     getContents().push_back(0);
443   }
444 
445   const MCExpr &getValue() const { return *Value; }
446   void setValue(const MCExpr *Expr) { Value = Expr; }
447 
448   bool isSigned() const { return IsSigned; }
449 
450   /// @}
451 
452   static bool classof(const MCFragment *F) {
453     return F->getKind() == MCFragment::FT_LEB;
454   }
455 };
456 
457 class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
458   /// The value of the difference between the two line numbers
459   /// between two .loc dwarf directives.
460   int64_t LineDelta;
461 
462   /// The expression for the difference of the two symbols that
463   /// make up the address delta between two .loc dwarf directives.
464   const MCExpr *AddrDelta;
465 
466 public:
467   MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
468                           MCSection *Sec = nullptr)
469       : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec),
470         LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
471 
472   int64_t getLineDelta() const { return LineDelta; }
473 
474   const MCExpr &getAddrDelta() const { return *AddrDelta; }
475 
476   static bool classof(const MCFragment *F) {
477     return F->getKind() == MCFragment::FT_Dwarf;
478   }
479 };
480 
481 class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
482   /// The expression for the difference of the two symbols that
483   /// make up the address delta between two .cfi_* dwarf directives.
484   const MCExpr *AddrDelta;
485 
486 public:
487   MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
488       : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec),
489         AddrDelta(&AddrDelta) {}
490 
491   const MCExpr &getAddrDelta() const { return *AddrDelta; }
492   void setAddrDelta(const MCExpr *E) { AddrDelta = E; }
493 
494   static bool classof(const MCFragment *F) {
495     return F->getKind() == MCFragment::FT_DwarfFrame;
496   }
497 };
498 
499 /// Represents a symbol table index fragment.
500 class MCSymbolIdFragment : public MCFragment {
501   const MCSymbol *Sym;
502 
503 public:
504   MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
505       : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {}
506 
507   const MCSymbol *getSymbol() { return Sym; }
508   const MCSymbol *getSymbol() const { return Sym; }
509 
510   static bool classof(const MCFragment *F) {
511     return F->getKind() == MCFragment::FT_SymbolId;
512   }
513 };
514 
515 /// Fragment representing the binary annotations produced by the
516 /// .cv_inline_linetable directive.
517 class MCCVInlineLineTableFragment : public MCFragment {
518   unsigned SiteFuncId;
519   unsigned StartFileId;
520   unsigned StartLineNum;
521   const MCSymbol *FnStartSym;
522   const MCSymbol *FnEndSym;
523   SmallString<8> Contents;
524 
525   /// CodeViewContext has the real knowledge about this format, so let it access
526   /// our members.
527   friend class CodeViewContext;
528 
529 public:
530   MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
531                               unsigned StartLineNum, const MCSymbol *FnStartSym,
532                               const MCSymbol *FnEndSym,
533                               MCSection *Sec = nullptr)
534       : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId),
535         StartFileId(StartFileId), StartLineNum(StartLineNum),
536         FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
537 
538   const MCSymbol *getFnStartSym() const { return FnStartSym; }
539   const MCSymbol *getFnEndSym() const { return FnEndSym; }
540 
541   SmallString<8> &getContents() { return Contents; }
542   const SmallString<8> &getContents() const { return Contents; }
543 
544   static bool classof(const MCFragment *F) {
545     return F->getKind() == MCFragment::FT_CVInlineLines;
546   }
547 };
548 
549 /// Fragment representing the .cv_def_range directive.
550 class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
551   SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
552   SmallString<32> FixedSizePortion;
553 
554   /// CodeViewContext has the real knowledge about this format, so let it access
555   /// our members.
556   friend class CodeViewContext;
557 
558 public:
559   MCCVDefRangeFragment(
560       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
561       StringRef FixedSizePortion, MCSection *Sec = nullptr)
562       : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec),
563         Ranges(Ranges.begin(), Ranges.end()),
564         FixedSizePortion(FixedSizePortion) {}
565 
566   ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
567     return Ranges;
568   }
569 
570   StringRef getFixedSizePortion() const { return FixedSizePortion.str(); }
571 
572   static bool classof(const MCFragment *F) {
573     return F->getKind() == MCFragment::FT_CVDefRange;
574   }
575 };
576 
577 /// Represents required padding such that a particular other set of fragments
578 /// does not cross a particular power-of-two boundary. The other fragments must
579 /// follow this one within the same section.
580 class MCBoundaryAlignFragment : public MCFragment {
581   /// The alignment requirement of the branch to be aligned.
582   Align AlignBoundary;
583   /// The last fragment in the set of fragments to be aligned.
584   const MCFragment *LastFragment = nullptr;
585   /// The size of the fragment.  The size is lazily set during relaxation, and
586   /// is not meaningful before that.
587   uint64_t Size = 0;
588 
589   /// When emitting Nops some subtargets have specific nop encodings.
590   const MCSubtargetInfo &STI;
591 
592 public:
593   MCBoundaryAlignFragment(Align AlignBoundary, const MCSubtargetInfo &STI,
594                           MCSection *Sec = nullptr)
595       : MCFragment(FT_BoundaryAlign, false, Sec), AlignBoundary(AlignBoundary),
596         STI(STI) {}
597 
598   uint64_t getSize() const { return Size; }
599   void setSize(uint64_t Value) { Size = Value; }
600 
601   Align getAlignment() const { return AlignBoundary; }
602   void setAlignment(Align Value) { AlignBoundary = Value; }
603 
604   const MCFragment *getLastFragment() const { return LastFragment; }
605   void setLastFragment(const MCFragment *F) {
606     assert(!F || getParent() == F->getParent());
607     LastFragment = F;
608   }
609 
610   const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
611 
612   static bool classof(const MCFragment *F) {
613     return F->getKind() == MCFragment::FT_BoundaryAlign;
614   }
615 };
616 
617 class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
618   /// The expression for the difference of the two symbols that
619   /// make up the address delta between two .pseudoprobe directives.
620   const MCExpr *AddrDelta;
621 
622 public:
623   MCPseudoProbeAddrFragment(const MCExpr *AddrDelta, MCSection *Sec = nullptr)
624       : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false, Sec),
625         AddrDelta(AddrDelta) {}
626 
627   const MCExpr &getAddrDelta() const { return *AddrDelta; }
628 
629   static bool classof(const MCFragment *F) {
630     return F->getKind() == MCFragment::FT_PseudoProbe;
631   }
632 };
633 } // end namespace llvm
634 
635 #endif // LLVM_MC_MCFRAGMENT_H
636