xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCFragment.h (revision c1d255d3ffdbe447de3ab875bf4e7d7accc5bfc5)
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 public:
315   MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize,
316                   unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
317       : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false),
318         Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
319 
320   unsigned getAlignment() const { return Alignment; }
321 
322   int64_t getValue() const { return Value; }
323 
324   unsigned getValueSize() const { return ValueSize; }
325 
326   unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
327 
328   bool hasEmitNops() const { return EmitNops; }
329   void setEmitNops(bool Value) { EmitNops = Value; }
330 
331   static bool classof(const MCFragment *F) {
332     return F->getKind() == MCFragment::FT_Align;
333   }
334 };
335 
336 class MCFillFragment : public MCFragment {
337   uint8_t ValueSize;
338   /// Value to use for filling bytes.
339   uint64_t Value;
340   /// The number of bytes to insert.
341   const MCExpr &NumValues;
342 
343   /// Source location of the directive that this fragment was created for.
344   SMLoc Loc;
345 
346 public:
347   MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
348                  SMLoc Loc, MCSection *Sec = nullptr)
349       : MCFragment(FT_Fill, false, Sec), ValueSize(VSize), Value(Value),
350         NumValues(NumValues), Loc(Loc) {}
351 
352   uint64_t getValue() const { return Value; }
353   uint8_t getValueSize() const { return ValueSize; }
354   const MCExpr &getNumValues() const { return NumValues; }
355 
356   SMLoc getLoc() const { return Loc; }
357 
358   static bool classof(const MCFragment *F) {
359     return F->getKind() == MCFragment::FT_Fill;
360   }
361 };
362 
363 class MCNopsFragment : public MCFragment {
364   /// The number of bytes to insert.
365   int64_t Size;
366   /// Maximum number of bytes allowed in each NOP instruction.
367   int64_t ControlledNopLength;
368 
369   /// Source location of the directive that this fragment was created for.
370   SMLoc Loc;
371 
372 public:
373   MCNopsFragment(int64_t NumBytes, int64_t ControlledNopLength, SMLoc L,
374                  MCSection *Sec = nullptr)
375       : MCFragment(FT_Nops, false, Sec), Size(NumBytes),
376         ControlledNopLength(ControlledNopLength), Loc(L) {}
377 
378   int64_t getNumBytes() const { return Size; }
379   int64_t getControlledNopLength() const { return ControlledNopLength; }
380 
381   SMLoc getLoc() const { return Loc; }
382 
383   static bool classof(const MCFragment *F) {
384     return F->getKind() == MCFragment::FT_Nops;
385   }
386 };
387 
388 class MCOrgFragment : public MCFragment {
389   /// Value to use for filling bytes.
390   int8_t Value;
391 
392   /// The offset this fragment should start at.
393   const MCExpr *Offset;
394 
395   /// Source location of the directive that this fragment was created for.
396   SMLoc Loc;
397 
398 public:
399   MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc,
400                 MCSection *Sec = nullptr)
401       : MCFragment(FT_Org, false, Sec), Value(Value), Offset(&Offset),
402         Loc(Loc) {}
403 
404   const MCExpr &getOffset() const { return *Offset; }
405 
406   uint8_t getValue() const { return Value; }
407 
408   SMLoc getLoc() const { return Loc; }
409 
410   static bool classof(const MCFragment *F) {
411     return F->getKind() == MCFragment::FT_Org;
412   }
413 };
414 
415 class MCLEBFragment : public MCFragment {
416   /// True if this is a sleb128, false if uleb128.
417   bool IsSigned;
418 
419   /// The value this fragment should contain.
420   const MCExpr *Value;
421 
422   SmallString<8> Contents;
423 
424 public:
425   MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr)
426       : MCFragment(FT_LEB, false, Sec), IsSigned(IsSigned_), Value(&Value_) {
427     Contents.push_back(0);
428   }
429 
430   const MCExpr &getValue() const { return *Value; }
431 
432   bool isSigned() const { return IsSigned; }
433 
434   SmallString<8> &getContents() { return Contents; }
435   const SmallString<8> &getContents() const { return Contents; }
436 
437   /// @}
438 
439   static bool classof(const MCFragment *F) {
440     return F->getKind() == MCFragment::FT_LEB;
441   }
442 };
443 
444 class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
445   /// The value of the difference between the two line numbers
446   /// between two .loc dwarf directives.
447   int64_t LineDelta;
448 
449   /// The expression for the difference of the two symbols that
450   /// make up the address delta between two .loc dwarf directives.
451   const MCExpr *AddrDelta;
452 
453 public:
454   MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
455                           MCSection *Sec = nullptr)
456       : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec),
457         LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
458 
459   int64_t getLineDelta() const { return LineDelta; }
460 
461   const MCExpr &getAddrDelta() const { return *AddrDelta; }
462 
463   static bool classof(const MCFragment *F) {
464     return F->getKind() == MCFragment::FT_Dwarf;
465   }
466 };
467 
468 class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
469   /// The expression for the difference of the two symbols that
470   /// make up the address delta between two .cfi_* dwarf directives.
471   const MCExpr *AddrDelta;
472 
473 public:
474   MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
475       : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec),
476         AddrDelta(&AddrDelta) {}
477 
478   const MCExpr &getAddrDelta() const { return *AddrDelta; }
479 
480   static bool classof(const MCFragment *F) {
481     return F->getKind() == MCFragment::FT_DwarfFrame;
482   }
483 };
484 
485 /// Represents a symbol table index fragment.
486 class MCSymbolIdFragment : public MCFragment {
487   const MCSymbol *Sym;
488 
489 public:
490   MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
491       : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {}
492 
493   const MCSymbol *getSymbol() { return Sym; }
494   const MCSymbol *getSymbol() const { return Sym; }
495 
496   static bool classof(const MCFragment *F) {
497     return F->getKind() == MCFragment::FT_SymbolId;
498   }
499 };
500 
501 /// Fragment representing the binary annotations produced by the
502 /// .cv_inline_linetable directive.
503 class MCCVInlineLineTableFragment : public MCFragment {
504   unsigned SiteFuncId;
505   unsigned StartFileId;
506   unsigned StartLineNum;
507   const MCSymbol *FnStartSym;
508   const MCSymbol *FnEndSym;
509   SmallString<8> Contents;
510 
511   /// CodeViewContext has the real knowledge about this format, so let it access
512   /// our members.
513   friend class CodeViewContext;
514 
515 public:
516   MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
517                               unsigned StartLineNum, const MCSymbol *FnStartSym,
518                               const MCSymbol *FnEndSym,
519                               MCSection *Sec = nullptr)
520       : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId),
521         StartFileId(StartFileId), StartLineNum(StartLineNum),
522         FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
523 
524   const MCSymbol *getFnStartSym() const { return FnStartSym; }
525   const MCSymbol *getFnEndSym() const { return FnEndSym; }
526 
527   SmallString<8> &getContents() { return Contents; }
528   const SmallString<8> &getContents() const { return Contents; }
529 
530   static bool classof(const MCFragment *F) {
531     return F->getKind() == MCFragment::FT_CVInlineLines;
532   }
533 };
534 
535 /// Fragment representing the .cv_def_range directive.
536 class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
537   SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
538   SmallString<32> FixedSizePortion;
539 
540   /// CodeViewContext has the real knowledge about this format, so let it access
541   /// our members.
542   friend class CodeViewContext;
543 
544 public:
545   MCCVDefRangeFragment(
546       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
547       StringRef FixedSizePortion, MCSection *Sec = nullptr)
548       : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec),
549         Ranges(Ranges.begin(), Ranges.end()),
550         FixedSizePortion(FixedSizePortion) {}
551 
552   ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
553     return Ranges;
554   }
555 
556   StringRef getFixedSizePortion() const { return FixedSizePortion; }
557 
558   static bool classof(const MCFragment *F) {
559     return F->getKind() == MCFragment::FT_CVDefRange;
560   }
561 };
562 
563 /// Represents required padding such that a particular other set of fragments
564 /// does not cross a particular power-of-two boundary. The other fragments must
565 /// follow this one within the same section.
566 class MCBoundaryAlignFragment : public MCFragment {
567   /// The alignment requirement of the branch to be aligned.
568   Align AlignBoundary;
569   /// The last fragment in the set of fragments to be aligned.
570   const MCFragment *LastFragment = nullptr;
571   /// The size of the fragment.  The size is lazily set during relaxation, and
572   /// is not meaningful before that.
573   uint64_t Size = 0;
574 
575 public:
576   MCBoundaryAlignFragment(Align AlignBoundary, MCSection *Sec = nullptr)
577       : MCFragment(FT_BoundaryAlign, false, Sec), AlignBoundary(AlignBoundary) {
578   }
579 
580   uint64_t getSize() const { return Size; }
581   void setSize(uint64_t Value) { Size = Value; }
582 
583   Align getAlignment() const { return AlignBoundary; }
584   void setAlignment(Align Value) { AlignBoundary = Value; }
585 
586   const MCFragment *getLastFragment() const { return LastFragment; }
587   void setLastFragment(const MCFragment *F) {
588     assert(!F || getParent() == F->getParent());
589     LastFragment = F;
590   }
591 
592   static bool classof(const MCFragment *F) {
593     return F->getKind() == MCFragment::FT_BoundaryAlign;
594   }
595 };
596 
597 class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
598   /// The expression for the difference of the two symbols that
599   /// make up the address delta between two .pseudoprobe directives.
600   const MCExpr *AddrDelta;
601 
602 public:
603   MCPseudoProbeAddrFragment(const MCExpr *AddrDelta, MCSection *Sec = nullptr)
604       : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false, Sec),
605         AddrDelta(AddrDelta) {}
606 
607   const MCExpr &getAddrDelta() const { return *AddrDelta; }
608 
609   static bool classof(const MCFragment *F) {
610     return F->getKind() == MCFragment::FT_PseudoProbe;
611   }
612 };
613 } // end namespace llvm
614 
615 #endif // LLVM_MC_MCFRAGMENT_H
616