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