MCFragment.h revision 360784
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
25namespace llvm {
26
27class MCSection;
28class MCSubtargetInfo;
29class MCSymbol;
30
31class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
32  friend class MCAsmLayout;
33
34public:
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
52private:
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
68protected:
69  bool HasInstructions;
70
71  MCFragment(FragmentType Kind, bool HasInstructions,
72             MCSection *Parent = nullptr);
73
74public:
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
85  FragmentType getKind() const { return Kind; }
86
87  MCSection *getParent() const { return Parent; }
88  void setParent(MCSection *Value) { Parent = Value; }
89
90  const MCSymbol *getAtom() const { return Atom; }
91  void setAtom(const MCSymbol *Value) { Atom = Value; }
92
93  unsigned getLayoutOrder() const { return LayoutOrder; }
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.
98  bool hasInstructions() const { return HasInstructions; }
99
100  void dump() const;
101};
102
103class MCDummyFragment : public MCFragment {
104public:
105  explicit MCDummyFragment(MCSection *Sec) : MCFragment(FT_Dummy, false, Sec) {}
106
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///
113class 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
119protected:
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
128public:
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?
144  bool alignToBundleEnd() const { return AlignToBundleEnd; }
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.
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.
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
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.
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///
173template<unsigned ContentsSize>
174class MCEncodedFragmentWithContents : public MCEncodedFragment {
175  SmallVector<char, ContentsSize> Contents;
176
177protected:
178  MCEncodedFragmentWithContents(MCFragment::FragmentType FType,
179                                bool HasInstructions,
180                                MCSection *Sec)
181      : MCEncodedFragment(FType, HasInstructions, Sec) {}
182
183public:
184  SmallVectorImpl<char> &getContents() { return Contents; }
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///
191template<unsigned ContentsSize, unsigned FixupsSize>
192class MCEncodedFragmentWithFixups :
193  public MCEncodedFragmentWithContents<ContentsSize> {
194
195  /// The list of fixups in this fragment.
196  SmallVector<MCFixup, FixupsSize> Fixups;
197
198protected:
199  MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
200                              bool HasInstructions,
201                              MCSection *Sec)
202      : MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions,
203                                                    Sec) {}
204
205public:
206
207  using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator;
208  using fixup_iterator = SmallVectorImpl<MCFixup>::iterator;
209
210  SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
211  const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
212
213  fixup_iterator fixup_begin() { return Fixups.begin(); }
214  const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
215
216  fixup_iterator fixup_end() { return Fixups.end(); }
217  const_fixup_iterator fixup_end() const { return Fixups.end(); }
218
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///
229class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
230public:
231  MCDataFragment(MCSection *Sec = nullptr)
232      : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {}
233
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///
244class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> {
245public:
246  MCCompactEncodedInstFragment(MCSection *Sec = nullptr)
247      : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) {
248  }
249
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///
258class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
259
260  /// The instruction this is a fragment for.
261  MCInst Inst;
262
263public:
264  MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI,
265                      MCSection *Sec = nullptr)
266      : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec),
267        Inst(Inst) { this->STI = &STI; }
268
269  const MCInst &getInst() const { return Inst; }
270  void setInst(const MCInst &Value) { Inst = Value; }
271
272  static bool classof(const MCFragment *F) {
273    return F->getKind() == MCFragment::FT_Relaxable;
274  }
275};
276
277class 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
296public:
297  MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize,
298                  unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
299      : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false),
300        Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
301
302  unsigned getAlignment() const { return Alignment; }
303
304  int64_t getValue() const { return Value; }
305
306  unsigned getValueSize() const { return ValueSize; }
307
308  unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
309
310  bool hasEmitNops() const { return EmitNops; }
311  void setEmitNops(bool Value) { EmitNops = Value; }
312
313  static bool classof(const MCFragment *F) {
314    return F->getKind() == MCFragment::FT_Align;
315  }
316};
317
318class 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
328public:
329  MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
330                 SMLoc Loc, MCSection *Sec = nullptr)
331      : MCFragment(FT_Fill, false, Sec), ValueSize(VSize), Value(Value),
332        NumValues(NumValues), Loc(Loc) {}
333
334  uint64_t getValue() const { return Value; }
335  uint8_t getValueSize() const { return ValueSize; }
336  const MCExpr &getNumValues() const { return NumValues; }
337
338  SMLoc getLoc() const { return Loc; }
339
340  static bool classof(const MCFragment *F) {
341    return F->getKind() == MCFragment::FT_Fill;
342  }
343};
344
345class 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
355public:
356  MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc,
357                MCSection *Sec = nullptr)
358      : MCFragment(FT_Org, false, Sec), Value(Value), Offset(&Offset),
359        Loc(Loc) {}
360
361  const MCExpr &getOffset() const { return *Offset; }
362
363  uint8_t getValue() const { return Value; }
364
365  SMLoc getLoc() const { return Loc; }
366
367  static bool classof(const MCFragment *F) {
368    return F->getKind() == MCFragment::FT_Org;
369  }
370};
371
372class 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
381public:
382  MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr)
383      : MCFragment(FT_LEB, false, Sec), IsSigned(IsSigned_), Value(&Value_) {
384    Contents.push_back(0);
385  }
386
387  const MCExpr &getValue() const { return *Value; }
388
389  bool isSigned() const { return IsSigned; }
390
391  SmallString<8> &getContents() { return Contents; }
392  const SmallString<8> &getContents() const { return Contents; }
393
394  /// @}
395
396  static bool classof(const MCFragment *F) {
397    return F->getKind() == MCFragment::FT_LEB;
398  }
399};
400
401class 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
410public:
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
416  int64_t getLineDelta() const { return LineDelta; }
417
418  const MCExpr &getAddrDelta() const { return *AddrDelta; }
419
420  static bool classof(const MCFragment *F) {
421    return F->getKind() == MCFragment::FT_Dwarf;
422  }
423};
424
425class 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
430public:
431  MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
432      : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec),
433        AddrDelta(&AddrDelta) {}
434
435  const MCExpr &getAddrDelta() const { return *AddrDelta; }
436
437  static bool classof(const MCFragment *F) {
438    return F->getKind() == MCFragment::FT_DwarfFrame;
439  }
440};
441
442/// Represents a symbol table index fragment.
443class MCSymbolIdFragment : public MCFragment {
444  const MCSymbol *Sym;
445
446public:
447  MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
448      : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {}
449
450  const MCSymbol *getSymbol() { return Sym; }
451  const MCSymbol *getSymbol() const { return Sym; }
452
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.
460class 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
472public:
473  MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
474                              unsigned StartLineNum, const MCSymbol *FnStartSym,
475                              const MCSymbol *FnEndSym,
476                              MCSection *Sec = nullptr)
477      : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId),
478        StartFileId(StartFileId), StartLineNum(StartLineNum),
479        FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
480
481  const MCSymbol *getFnStartSym() const { return FnStartSym; }
482  const MCSymbol *getFnEndSym() const { return FnEndSym; }
483
484  SmallString<8> &getContents() { return Contents; }
485  const SmallString<8> &getContents() const { return Contents; }
486
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.
493class 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
501public:
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
509  ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
510    return Ranges;
511  }
512
513  StringRef getFixedSizePortion() const { return FixedSizePortion; }
514
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.
523class 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
535public:
536  MCBoundaryAlignFragment(Align AlignBoundary, bool Fused = false,
537                          bool EmitNops = false, MCSection *Sec = nullptr)
538      : MCFragment(FT_BoundaryAlign, false, Sec), AlignBoundary(AlignBoundary),
539        Fused(Fused), EmitNops(EmitNops) {}
540
541  uint64_t getSize() const { return Size; }
542  void setSize(uint64_t Value) { Size = Value; }
543
544  Align getAlignment() const { return AlignBoundary; }
545
546  bool isFused() const { return Fused; }
547  void setFused(bool Value) { Fused = Value; }
548
549  bool canEmitNops() const { return EmitNops; }
550  void setEmitNops(bool Value) { EmitNops = Value; }
551
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