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