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