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