xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCFragment.h (revision 1f1e2261e341e6ca6862f82261066ef1705f0a7a)
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/Casting.h"
21 #include "llvm/Support/SMLoc.h"
22 #include <cstdint>
23 #include <utility>
24 
25 namespace llvm {
26 
27 class MCSection;
28 class MCSubtargetInfo;
29 class MCSymbol;
30 
31 class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
32   friend class MCAsmLayout;
33 
34 public:
35   enum FragmentType : uint8_t {
36     FT_Align,
37     FT_Data,
38     FT_CompactEncodedInst,
39     FT_Fill,
40     FT_Nops,
41     FT_Relaxable,
42     FT_Org,
43     FT_Dwarf,
44     FT_DwarfFrame,
45     FT_LEB,
46     FT_BoundaryAlign,
47     FT_SymbolId,
48     FT_CVInlineLines,
49     FT_CVDefRange,
50     FT_PseudoProbe,
51     FT_Dummy
52   };
53 
54 private:
55   /// The data for the section this fragment is in.
56   MCSection *Parent;
57 
58   /// The atom this fragment is in, as represented by its defining symbol.
59   const MCSymbol *Atom;
60 
61   /// The offset of this fragment in its section. This is ~0 until
62   /// initialized.
63   uint64_t Offset;
64 
65   /// The layout order of this fragment.
66   unsigned LayoutOrder;
67 
68   /// The subsection this fragment belongs to. This is 0 if the fragment is not
69   // in any subsection.
70   unsigned SubsectionNumber = 0;
71 
72   FragmentType Kind;
73 
74   /// Whether fragment is being laid out.
75   bool IsBeingLaidOut;
76 
77 protected:
78   bool HasInstructions;
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 
252 /// This is a compact (memory-size-wise) fragment for holding an encoded
253 /// instruction (non-relaxable) that has no fixups registered. When applicable,
254 /// it can be used instead of MCDataFragment and lead to lower memory
255 /// consumption.
256 ///
257 class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> {
258 public:
259   MCCompactEncodedInstFragment(MCSection *Sec = nullptr)
260       : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) {
261   }
262 
263   static bool classof(const MCFragment *F) {
264     return F->getKind() == MCFragment::FT_CompactEncodedInst;
265   }
266 };
267 
268 /// A relaxable fragment holds on to its MCInst, since it may need to be
269 /// relaxed during the assembler layout and relaxation stage.
270 ///
271 class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
272 
273   /// The instruction this is a fragment for.
274   MCInst Inst;
275   /// Can we auto pad the instruction?
276   bool AllowAutoPadding = false;
277 
278 public:
279   MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI,
280                       MCSection *Sec = nullptr)
281       : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec),
282         Inst(Inst) { this->STI = &STI; }
283 
284   const MCInst &getInst() const { return Inst; }
285   void setInst(const MCInst &Value) { Inst = Value; }
286 
287   bool getAllowAutoPadding() const { return AllowAutoPadding; }
288   void setAllowAutoPadding(bool V) { AllowAutoPadding = V; }
289 
290   static bool classof(const MCFragment *F) {
291     return F->getKind() == MCFragment::FT_Relaxable;
292   }
293 };
294 
295 class MCAlignFragment : public MCFragment {
296   /// The alignment to ensure, in bytes.
297   unsigned Alignment;
298 
299   /// Flag to indicate that (optimal) NOPs should be emitted instead
300   /// of using the provided value. The exact interpretation of this flag is
301   /// target dependent.
302   bool EmitNops : 1;
303 
304   /// Value to use for filling padding bytes.
305   int64_t Value;
306 
307   /// The size of the integer (in bytes) of \p Value.
308   unsigned ValueSize;
309 
310   /// The maximum number of bytes to emit; if the alignment
311   /// cannot be satisfied in this width then this fragment is ignored.
312   unsigned MaxBytesToEmit;
313 
314   /// When emitting Nops some subtargets have specific nop encodings.
315   const MCSubtargetInfo *STI;
316 
317 public:
318   MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize,
319                   unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
320       : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false),
321         Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
322 
323   unsigned getAlignment() const { return Alignment; }
324 
325   int64_t getValue() const { return Value; }
326 
327   unsigned getValueSize() const { return ValueSize; }
328 
329   unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
330 
331   bool hasEmitNops() const { return EmitNops; }
332   void setEmitNops(bool Value, const MCSubtargetInfo *STI) {
333     EmitNops = Value;
334     this->STI = STI;
335   }
336 
337   const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
338 
339   static bool classof(const MCFragment *F) {
340     return F->getKind() == MCFragment::FT_Align;
341   }
342 };
343 
344 class MCFillFragment : public MCFragment {
345   uint8_t ValueSize;
346   /// Value to use for filling bytes.
347   uint64_t Value;
348   /// The number of bytes to insert.
349   const MCExpr &NumValues;
350 
351   /// Source location of the directive that this fragment was created for.
352   SMLoc Loc;
353 
354 public:
355   MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
356                  SMLoc Loc, MCSection *Sec = nullptr)
357       : MCFragment(FT_Fill, false, Sec), ValueSize(VSize), Value(Value),
358         NumValues(NumValues), Loc(Loc) {}
359 
360   uint64_t getValue() const { return Value; }
361   uint8_t getValueSize() const { return ValueSize; }
362   const MCExpr &getNumValues() const { return NumValues; }
363 
364   SMLoc getLoc() const { return Loc; }
365 
366   static bool classof(const MCFragment *F) {
367     return F->getKind() == MCFragment::FT_Fill;
368   }
369 };
370 
371 class MCNopsFragment : public MCFragment {
372   /// The number of bytes to insert.
373   int64_t Size;
374   /// Maximum number of bytes allowed in each NOP instruction.
375   int64_t ControlledNopLength;
376 
377   /// Source location of the directive that this fragment was created for.
378   SMLoc Loc;
379 
380   /// When emitting Nops some subtargets have specific nop encodings.
381   const MCSubtargetInfo &STI;
382 
383 public:
384   MCNopsFragment(int64_t NumBytes, int64_t ControlledNopLength, SMLoc L,
385                  const MCSubtargetInfo &STI, MCSection *Sec = nullptr)
386       : MCFragment(FT_Nops, false, Sec), Size(NumBytes),
387         ControlledNopLength(ControlledNopLength), Loc(L), STI(STI) {}
388 
389   int64_t getNumBytes() const { return Size; }
390   int64_t getControlledNopLength() const { return ControlledNopLength; }
391 
392   SMLoc getLoc() const { return Loc; }
393 
394   const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
395 
396   static bool classof(const MCFragment *F) {
397     return F->getKind() == MCFragment::FT_Nops;
398   }
399 };
400 
401 class MCOrgFragment : public MCFragment {
402   /// Value to use for filling bytes.
403   int8_t Value;
404 
405   /// The offset this fragment should start at.
406   const MCExpr *Offset;
407 
408   /// Source location of the directive that this fragment was created for.
409   SMLoc Loc;
410 
411 public:
412   MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc,
413                 MCSection *Sec = nullptr)
414       : MCFragment(FT_Org, false, Sec), Value(Value), Offset(&Offset),
415         Loc(Loc) {}
416 
417   const MCExpr &getOffset() const { return *Offset; }
418 
419   uint8_t getValue() const { return Value; }
420 
421   SMLoc getLoc() const { return Loc; }
422 
423   static bool classof(const MCFragment *F) {
424     return F->getKind() == MCFragment::FT_Org;
425   }
426 };
427 
428 class MCLEBFragment : public MCFragment {
429   /// True if this is a sleb128, false if uleb128.
430   bool IsSigned;
431 
432   /// The value this fragment should contain.
433   const MCExpr *Value;
434 
435   SmallString<8> Contents;
436 
437 public:
438   MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr)
439       : MCFragment(FT_LEB, false, Sec), IsSigned(IsSigned_), Value(&Value_) {
440     Contents.push_back(0);
441   }
442 
443   const MCExpr &getValue() const { return *Value; }
444 
445   bool isSigned() const { return IsSigned; }
446 
447   SmallString<8> &getContents() { return Contents; }
448   const SmallString<8> &getContents() const { return Contents; }
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 
493   static bool classof(const MCFragment *F) {
494     return F->getKind() == MCFragment::FT_DwarfFrame;
495   }
496 };
497 
498 /// Represents a symbol table index fragment.
499 class MCSymbolIdFragment : public MCFragment {
500   const MCSymbol *Sym;
501 
502 public:
503   MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
504       : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {}
505 
506   const MCSymbol *getSymbol() { return Sym; }
507   const MCSymbol *getSymbol() const { return Sym; }
508 
509   static bool classof(const MCFragment *F) {
510     return F->getKind() == MCFragment::FT_SymbolId;
511   }
512 };
513 
514 /// Fragment representing the binary annotations produced by the
515 /// .cv_inline_linetable directive.
516 class MCCVInlineLineTableFragment : public MCFragment {
517   unsigned SiteFuncId;
518   unsigned StartFileId;
519   unsigned StartLineNum;
520   const MCSymbol *FnStartSym;
521   const MCSymbol *FnEndSym;
522   SmallString<8> Contents;
523 
524   /// CodeViewContext has the real knowledge about this format, so let it access
525   /// our members.
526   friend class CodeViewContext;
527 
528 public:
529   MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
530                               unsigned StartLineNum, const MCSymbol *FnStartSym,
531                               const MCSymbol *FnEndSym,
532                               MCSection *Sec = nullptr)
533       : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId),
534         StartFileId(StartFileId), StartLineNum(StartLineNum),
535         FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
536 
537   const MCSymbol *getFnStartSym() const { return FnStartSym; }
538   const MCSymbol *getFnEndSym() const { return FnEndSym; }
539 
540   SmallString<8> &getContents() { return Contents; }
541   const SmallString<8> &getContents() const { return Contents; }
542 
543   static bool classof(const MCFragment *F) {
544     return F->getKind() == MCFragment::FT_CVInlineLines;
545   }
546 };
547 
548 /// Fragment representing the .cv_def_range directive.
549 class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
550   SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
551   SmallString<32> FixedSizePortion;
552 
553   /// CodeViewContext has the real knowledge about this format, so let it access
554   /// our members.
555   friend class CodeViewContext;
556 
557 public:
558   MCCVDefRangeFragment(
559       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
560       StringRef FixedSizePortion, MCSection *Sec = nullptr)
561       : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec),
562         Ranges(Ranges.begin(), Ranges.end()),
563         FixedSizePortion(FixedSizePortion) {}
564 
565   ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
566     return Ranges;
567   }
568 
569   StringRef getFixedSizePortion() const { return FixedSizePortion.str(); }
570 
571   static bool classof(const MCFragment *F) {
572     return F->getKind() == MCFragment::FT_CVDefRange;
573   }
574 };
575 
576 /// Represents required padding such that a particular other set of fragments
577 /// does not cross a particular power-of-two boundary. The other fragments must
578 /// follow this one within the same section.
579 class MCBoundaryAlignFragment : public MCFragment {
580   /// The alignment requirement of the branch to be aligned.
581   Align AlignBoundary;
582   /// The last fragment in the set of fragments to be aligned.
583   const MCFragment *LastFragment = nullptr;
584   /// The size of the fragment.  The size is lazily set during relaxation, and
585   /// is not meaningful before that.
586   uint64_t Size = 0;
587 
588   /// When emitting Nops some subtargets have specific nop encodings.
589   const MCSubtargetInfo &STI;
590 
591 public:
592   MCBoundaryAlignFragment(Align AlignBoundary, const MCSubtargetInfo &STI,
593                           MCSection *Sec = nullptr)
594       : MCFragment(FT_BoundaryAlign, false, Sec), AlignBoundary(AlignBoundary),
595         STI(STI) {}
596 
597   uint64_t getSize() const { return Size; }
598   void setSize(uint64_t Value) { Size = Value; }
599 
600   Align getAlignment() const { return AlignBoundary; }
601   void setAlignment(Align Value) { AlignBoundary = Value; }
602 
603   const MCFragment *getLastFragment() const { return LastFragment; }
604   void setLastFragment(const MCFragment *F) {
605     assert(!F || getParent() == F->getParent());
606     LastFragment = F;
607   }
608 
609   const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
610 
611   static bool classof(const MCFragment *F) {
612     return F->getKind() == MCFragment::FT_BoundaryAlign;
613   }
614 };
615 
616 class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
617   /// The expression for the difference of the two symbols that
618   /// make up the address delta between two .pseudoprobe directives.
619   const MCExpr *AddrDelta;
620 
621 public:
622   MCPseudoProbeAddrFragment(const MCExpr *AddrDelta, MCSection *Sec = nullptr)
623       : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false, Sec),
624         AddrDelta(AddrDelta) {}
625 
626   const MCExpr &getAddrDelta() const { return *AddrDelta; }
627 
628   static bool classof(const MCFragment *F) {
629     return F->getKind() == MCFragment::FT_PseudoProbe;
630   }
631 };
632 } // end namespace llvm
633 
634 #endif // LLVM_MC_MCFRAGMENT_H
635