xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCFragment.h (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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 MCAssembler;
27 class MCObjectStreamer;
28 class MCSection;
29 class MCSubtargetInfo;
30 class MCSymbol;
31 
32 class MCFragment {
33   friend class MCAssembler;
34   friend class MCObjectStreamer;
35   friend class MCSection;
36 
37 public:
38   enum FragmentType : uint8_t {
39     FT_Align,
40     FT_Data,
41     FT_CompactEncodedInst,
42     FT_Fill,
43     FT_Nops,
44     FT_Relaxable,
45     FT_Org,
46     FT_Dwarf,
47     FT_DwarfFrame,
48     FT_LEB,
49     FT_BoundaryAlign,
50     FT_SymbolId,
51     FT_CVInlineLines,
52     FT_CVDefRange,
53     FT_PseudoProbe,
54     FT_Dummy
55   };
56 
57 private:
58   // The next fragment within the section.
59   MCFragment *Next = nullptr;
60 
61   /// The data for the section this fragment is in.
62   MCSection *Parent = nullptr;
63 
64   /// The offset of this fragment in its section.
65   uint64_t Offset = 0;
66 
67   /// The layout order of this fragment.
68   unsigned LayoutOrder = 0;
69 
70   FragmentType Kind;
71 
72 protected:
73   bool HasInstructions : 1;
74   bool LinkerRelaxable : 1;
75 
76   MCFragment(FragmentType Kind, bool HasInstructions);
77 
78 public:
79   MCFragment() = delete;
80   MCFragment(const MCFragment &) = delete;
81   MCFragment &operator=(const MCFragment &) = delete;
82 
83   /// Destroys the current fragment.
84   ///
85   /// This must be used instead of delete as MCFragment is non-virtual.
86   /// This method will dispatch to the appropriate subclass.
87   void destroy();
88 
89   MCFragment *getNext() const { return Next; }
90 
91   FragmentType getKind() const { return Kind; }
92 
93   MCSection *getParent() const { return Parent; }
94   void setParent(MCSection *Value) { Parent = Value; }
95 
96   const MCSymbol *getAtom() const;
97 
98   unsigned getLayoutOrder() const { return LayoutOrder; }
99   void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
100 
101   /// Does this fragment have instructions emitted into it? By default
102   /// this is false, but specific fragment types may set it to true.
103   bool hasInstructions() const { return HasInstructions; }
104 
105   void dump() const;
106 };
107 
108 class MCDummyFragment : public MCFragment {
109 public:
110   explicit MCDummyFragment() : MCFragment(FT_Dummy, false) {}
111 
112   static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
113 };
114 
115 /// Interface implemented by fragments that contain encoded instructions and/or
116 /// data.
117 ///
118 class MCEncodedFragment : public MCFragment {
119   /// Should this fragment be aligned to the end of a bundle?
120   bool AlignToBundleEnd = false;
121 
122   uint8_t BundlePadding = 0;
123 
124 protected:
125   MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions)
126       : MCFragment(FType, HasInstructions) {}
127 
128   /// The MCSubtargetInfo in effect when the instruction was encoded.
129   /// It must be non-null for instructions.
130   const MCSubtargetInfo *STI = nullptr;
131 
132 public:
133   static bool classof(const MCFragment *F) {
134     MCFragment::FragmentType Kind = F->getKind();
135     switch (Kind) {
136     default:
137       return false;
138     case MCFragment::FT_Relaxable:
139     case MCFragment::FT_CompactEncodedInst:
140     case MCFragment::FT_Data:
141     case MCFragment::FT_Dwarf:
142     case MCFragment::FT_DwarfFrame:
143     case MCFragment::FT_PseudoProbe:
144       return true;
145     }
146   }
147 
148   /// Should this fragment be placed at the end of an aligned bundle?
149   bool alignToBundleEnd() const { return AlignToBundleEnd; }
150   void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
151 
152   /// Get the padding size that must be inserted before this fragment.
153   /// Used for bundling. By default, no padding is inserted.
154   /// Note that padding size is restricted to 8 bits. This is an optimization
155   /// to reduce the amount of space used for each fragment. In practice, larger
156   /// padding should never be required.
157   uint8_t getBundlePadding() const { return BundlePadding; }
158 
159   /// Set the padding size for this fragment. By default it's a no-op,
160   /// and only some fragments have a meaningful implementation.
161   void setBundlePadding(uint8_t N) { BundlePadding = N; }
162 
163   /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded.
164   /// Guaranteed to be non-null if hasInstructions() == true
165   const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
166 
167   /// Record that the fragment contains instructions with the MCSubtargetInfo in
168   /// effect when the instruction was encoded.
169   void setHasInstructions(const MCSubtargetInfo &STI) {
170     HasInstructions = true;
171     this->STI = &STI;
172   }
173 };
174 
175 /// Interface implemented by fragments that contain encoded instructions and/or
176 /// data.
177 ///
178 template<unsigned ContentsSize>
179 class MCEncodedFragmentWithContents : public MCEncodedFragment {
180   SmallVector<char, ContentsSize> Contents;
181 
182 protected:
183   MCEncodedFragmentWithContents(MCFragment::FragmentType FType,
184                                 bool HasInstructions)
185       : MCEncodedFragment(FType, HasInstructions) {}
186 
187 public:
188   SmallVectorImpl<char> &getContents() { return Contents; }
189   const SmallVectorImpl<char> &getContents() const { return Contents; }
190 };
191 
192 /// Interface implemented by fragments that contain encoded instructions and/or
193 /// data and also have fixups registered.
194 ///
195 template<unsigned ContentsSize, unsigned FixupsSize>
196 class MCEncodedFragmentWithFixups :
197   public MCEncodedFragmentWithContents<ContentsSize> {
198 
199   /// The list of fixups in this fragment.
200   SmallVector<MCFixup, FixupsSize> Fixups;
201 
202 protected:
203   MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
204                               bool HasInstructions)
205       : MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions) {}
206 
207 public:
208 
209   using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator;
210   using fixup_iterator = SmallVectorImpl<MCFixup>::iterator;
211 
212   SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
213   const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
214 
215   fixup_iterator fixup_begin() { return Fixups.begin(); }
216   const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
217 
218   fixup_iterator fixup_end() { return Fixups.end(); }
219   const_fixup_iterator fixup_end() const { return Fixups.end(); }
220 
221   static bool classof(const MCFragment *F) {
222     MCFragment::FragmentType Kind = F->getKind();
223     return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
224            Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
225            Kind == MCFragment::FT_DwarfFrame;
226   }
227 };
228 
229 /// Fragment for data and encoded instructions.
230 ///
231 class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
232 public:
233   MCDataFragment() : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false) {}
234 
235   static bool classof(const MCFragment *F) {
236     return F->getKind() == MCFragment::FT_Data;
237   }
238 
239   bool isLinkerRelaxable() const { return LinkerRelaxable; }
240   void setLinkerRelaxable() { LinkerRelaxable = true; }
241 };
242 
243 /// This is a compact (memory-size-wise) fragment for holding an encoded
244 /// instruction (non-relaxable) that has no fixups registered. When applicable,
245 /// it can be used instead of MCDataFragment and lead to lower memory
246 /// consumption.
247 ///
248 class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> {
249 public:
250   MCCompactEncodedInstFragment()
251       : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true) {}
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       : MCEncodedFragmentWithFixups(FT_Relaxable, true), Inst(Inst) {
271     this->STI = &STI;
272   }
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   Align 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   /// When emitting Nops some subtargets have specific nop encodings.
305   const MCSubtargetInfo *STI = nullptr;
306 
307 public:
308   MCAlignFragment(Align Alignment, int64_t Value, unsigned ValueSize,
309                   unsigned MaxBytesToEmit)
310       : MCFragment(FT_Align, false), Alignment(Alignment), EmitNops(false),
311         Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
312 
313   Align getAlignment() const { return Alignment; }
314 
315   int64_t getValue() const { return Value; }
316 
317   unsigned getValueSize() const { return ValueSize; }
318 
319   unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
320 
321   bool hasEmitNops() const { return EmitNops; }
322   void setEmitNops(bool Value, const MCSubtargetInfo *STI) {
323     EmitNops = Value;
324     this->STI = STI;
325   }
326 
327   const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
328 
329   static bool classof(const MCFragment *F) {
330     return F->getKind() == MCFragment::FT_Align;
331   }
332 };
333 
334 class MCFillFragment : public MCFragment {
335   uint8_t ValueSize;
336   /// Value to use for filling bytes.
337   uint64_t Value;
338   /// The number of bytes to insert.
339   const MCExpr &NumValues;
340 
341   /// Source location of the directive that this fragment was created for.
342   SMLoc Loc;
343 
344 public:
345   MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
346                  SMLoc Loc)
347       : MCFragment(FT_Fill, false), ValueSize(VSize), Value(Value),
348         NumValues(NumValues), Loc(Loc) {}
349 
350   uint64_t getValue() const { return Value; }
351   uint8_t getValueSize() const { return ValueSize; }
352   const MCExpr &getNumValues() const { return NumValues; }
353 
354   SMLoc getLoc() const { return Loc; }
355 
356   static bool classof(const MCFragment *F) {
357     return F->getKind() == MCFragment::FT_Fill;
358   }
359 };
360 
361 class MCNopsFragment : public MCFragment {
362   /// The number of bytes to insert.
363   int64_t Size;
364   /// Maximum number of bytes allowed in each NOP instruction.
365   int64_t ControlledNopLength;
366 
367   /// Source location of the directive that this fragment was created for.
368   SMLoc Loc;
369 
370   /// When emitting Nops some subtargets have specific nop encodings.
371   const MCSubtargetInfo &STI;
372 
373 public:
374   MCNopsFragment(int64_t NumBytes, int64_t ControlledNopLength, SMLoc L,
375                  const MCSubtargetInfo &STI)
376       : MCFragment(FT_Nops, false), Size(NumBytes),
377         ControlledNopLength(ControlledNopLength), Loc(L), STI(STI) {}
378 
379   int64_t getNumBytes() const { return Size; }
380   int64_t getControlledNopLength() const { return ControlledNopLength; }
381 
382   SMLoc getLoc() const { return Loc; }
383 
384   const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
385 
386   static bool classof(const MCFragment *F) {
387     return F->getKind() == MCFragment::FT_Nops;
388   }
389 };
390 
391 class MCOrgFragment : public MCFragment {
392   /// Value to use for filling bytes.
393   int8_t Value;
394 
395   /// The offset this fragment should start at.
396   const MCExpr *Offset;
397 
398   /// Source location of the directive that this fragment was created for.
399   SMLoc Loc;
400 
401 public:
402   MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc)
403       : MCFragment(FT_Org, false), Value(Value), Offset(&Offset), Loc(Loc) {}
404 
405   const MCExpr &getOffset() const { return *Offset; }
406 
407   uint8_t getValue() const { return Value; }
408 
409   SMLoc getLoc() const { return Loc; }
410 
411   static bool classof(const MCFragment *F) {
412     return F->getKind() == MCFragment::FT_Org;
413   }
414 };
415 
416 class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> {
417   /// True if this is a sleb128, false if uleb128.
418   bool IsSigned;
419 
420   /// The value this fragment should contain.
421   const MCExpr *Value;
422 
423 public:
424   MCLEBFragment(const MCExpr &Value, bool IsSigned)
425       : MCEncodedFragmentWithFixups<8, 0>(FT_LEB, false), IsSigned(IsSigned),
426         Value(&Value) {
427     getContents().push_back(0);
428   }
429 
430   const MCExpr &getValue() const { return *Value; }
431   void setValue(const MCExpr *Expr) { Value = Expr; }
432 
433   bool isSigned() const { return IsSigned; }
434 
435   /// @}
436 
437   static bool classof(const MCFragment *F) {
438     return F->getKind() == MCFragment::FT_LEB;
439   }
440 };
441 
442 class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
443   /// The value of the difference between the two line numbers
444   /// between two .loc dwarf directives.
445   int64_t LineDelta;
446 
447   /// The expression for the difference of the two symbols that
448   /// make up the address delta between two .loc dwarf directives.
449   const MCExpr *AddrDelta;
450 
451 public:
452   MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta)
453       : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false),
454         LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
455 
456   int64_t getLineDelta() const { return LineDelta; }
457 
458   const MCExpr &getAddrDelta() const { return *AddrDelta; }
459 
460   static bool classof(const MCFragment *F) {
461     return F->getKind() == MCFragment::FT_Dwarf;
462   }
463 };
464 
465 class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
466   /// The expression for the difference of the two symbols that
467   /// make up the address delta between two .cfi_* dwarf directives.
468   const MCExpr *AddrDelta;
469 
470 public:
471   MCDwarfCallFrameFragment(const MCExpr &AddrDelta)
472       : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false),
473         AddrDelta(&AddrDelta) {}
474 
475   const MCExpr &getAddrDelta() const { return *AddrDelta; }
476   void setAddrDelta(const MCExpr *E) { AddrDelta = E; }
477 
478   static bool classof(const MCFragment *F) {
479     return F->getKind() == MCFragment::FT_DwarfFrame;
480   }
481 };
482 
483 /// Represents a symbol table index fragment.
484 class MCSymbolIdFragment : public MCFragment {
485   const MCSymbol *Sym;
486 
487 public:
488   MCSymbolIdFragment(const MCSymbol *Sym)
489       : MCFragment(FT_SymbolId, false), Sym(Sym) {}
490 
491   const MCSymbol *getSymbol() { return Sym; }
492   const MCSymbol *getSymbol() const { return Sym; }
493 
494   static bool classof(const MCFragment *F) {
495     return F->getKind() == MCFragment::FT_SymbolId;
496   }
497 };
498 
499 /// Fragment representing the binary annotations produced by the
500 /// .cv_inline_linetable directive.
501 class MCCVInlineLineTableFragment : public MCFragment {
502   unsigned SiteFuncId;
503   unsigned StartFileId;
504   unsigned StartLineNum;
505   const MCSymbol *FnStartSym;
506   const MCSymbol *FnEndSym;
507   SmallString<8> Contents;
508 
509   /// CodeViewContext has the real knowledge about this format, so let it access
510   /// our members.
511   friend class CodeViewContext;
512 
513 public:
514   MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
515                               unsigned StartLineNum, const MCSymbol *FnStartSym,
516                               const MCSymbol *FnEndSym)
517       : MCFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId),
518         StartFileId(StartFileId), StartLineNum(StartLineNum),
519         FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
520 
521   const MCSymbol *getFnStartSym() const { return FnStartSym; }
522   const MCSymbol *getFnEndSym() const { return FnEndSym; }
523 
524   SmallString<8> &getContents() { return Contents; }
525   const SmallString<8> &getContents() const { return Contents; }
526 
527   static bool classof(const MCFragment *F) {
528     return F->getKind() == MCFragment::FT_CVInlineLines;
529   }
530 };
531 
532 /// Fragment representing the .cv_def_range directive.
533 class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
534   SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
535   SmallString<32> FixedSizePortion;
536 
537   /// CodeViewContext has the real knowledge about this format, so let it access
538   /// our members.
539   friend class CodeViewContext;
540 
541 public:
542   MCCVDefRangeFragment(
543       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
544       StringRef FixedSizePortion)
545       : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false),
546         Ranges(Ranges.begin(), Ranges.end()),
547         FixedSizePortion(FixedSizePortion) {}
548 
549   ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
550     return Ranges;
551   }
552 
553   StringRef getFixedSizePortion() const { return FixedSizePortion.str(); }
554 
555   static bool classof(const MCFragment *F) {
556     return F->getKind() == MCFragment::FT_CVDefRange;
557   }
558 };
559 
560 /// Represents required padding such that a particular other set of fragments
561 /// does not cross a particular power-of-two boundary. The other fragments must
562 /// follow this one within the same section.
563 class MCBoundaryAlignFragment : public MCFragment {
564   /// The alignment requirement of the branch to be aligned.
565   Align AlignBoundary;
566   /// The last fragment in the set of fragments to be aligned.
567   const MCFragment *LastFragment = nullptr;
568   /// The size of the fragment.  The size is lazily set during relaxation, and
569   /// is not meaningful before that.
570   uint64_t Size = 0;
571 
572   /// When emitting Nops some subtargets have specific nop encodings.
573   const MCSubtargetInfo &STI;
574 
575 public:
576   MCBoundaryAlignFragment(Align AlignBoundary, const MCSubtargetInfo &STI)
577       : MCFragment(FT_BoundaryAlign, false), AlignBoundary(AlignBoundary),
578         STI(STI) {}
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   const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
593 
594   static bool classof(const MCFragment *F) {
595     return F->getKind() == MCFragment::FT_BoundaryAlign;
596   }
597 };
598 
599 class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
600   /// The expression for the difference of the two symbols that
601   /// make up the address delta between two .pseudoprobe directives.
602   const MCExpr *AddrDelta;
603 
604 public:
605   MCPseudoProbeAddrFragment(const MCExpr *AddrDelta)
606       : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false),
607         AddrDelta(AddrDelta) {}
608 
609   const MCExpr &getAddrDelta() const { return *AddrDelta; }
610 
611   static bool classof(const MCFragment *F) {
612     return F->getKind() == MCFragment::FT_PseudoProbe;
613   }
614 };
615 } // end namespace llvm
616 
617 #endif // LLVM_MC_MCFRAGMENT_H
618