1//===- MCSection.h - Machine Code Sections ----------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file declares the MCSection class.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_MC_MCSECTION_H
15#define LLVM_MC_MCSECTION_H
16
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/ilist.h"
19#include "llvm/MC/MCFragment.h"
20#include "llvm/MC/SectionKind.h"
21#include <cassert>
22#include <utility>
23
24namespace llvm {
25
26class MCAsmInfo;
27class MCContext;
28class MCExpr;
29class MCSymbol;
30class raw_ostream;
31class Triple;
32
33template <> struct ilist_alloc_traits<MCFragment> {
34  static void deleteNode(MCFragment *V);
35};
36
37/// Instances of this class represent a uniqued identifier for a section in the
38/// current translation unit.  The MCContext class uniques and creates these.
39class MCSection {
40public:
41  enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm };
42
43  /// \brief Express the state of bundle locked groups while emitting code.
44  enum BundleLockStateType {
45    NotBundleLocked,
46    BundleLocked,
47    BundleLockedAlignToEnd
48  };
49
50  using FragmentListType = iplist<MCFragment>;
51
52  using const_iterator = FragmentListType::const_iterator;
53  using iterator = FragmentListType::iterator;
54
55  using const_reverse_iterator = FragmentListType::const_reverse_iterator;
56  using reverse_iterator = FragmentListType::reverse_iterator;
57
58private:
59  MCSymbol *Begin;
60  MCSymbol *End = nullptr;
61  /// The alignment requirement of this section.
62  unsigned Alignment = 1;
63  /// The section index in the assemblers section list.
64  unsigned Ordinal = 0;
65  /// The index of this section in the layout order.
66  unsigned LayoutOrder;
67
68  /// \brief Keeping track of bundle-locked state.
69  BundleLockStateType BundleLockState = NotBundleLocked;
70
71  /// \brief Current nesting depth of bundle_lock directives.
72  unsigned BundleLockNestingDepth = 0;
73
74  /// \brief We've seen a bundle_lock directive but not its first instruction
75  /// yet.
76  bool BundleGroupBeforeFirstInst : 1;
77
78  /// Whether this section has had instructions emitted into it.
79  bool HasInstructions : 1;
80
81  bool IsRegistered : 1;
82
83  MCDummyFragment DummyFragment;
84
85  FragmentListType Fragments;
86
87  /// Mapping from subsection number to insertion point for subsection numbers
88  /// below that number.
89  SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap;
90
91protected:
92  SectionVariant Variant;
93  SectionKind Kind;
94
95  MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin);
96  ~MCSection();
97
98public:
99  MCSection(const MCSection &) = delete;
100  MCSection &operator=(const MCSection &) = delete;
101
102  SectionKind getKind() const { return Kind; }
103
104  SectionVariant getVariant() const { return Variant; }
105
106  MCSymbol *getBeginSymbol() { return Begin; }
107  const MCSymbol *getBeginSymbol() const {
108    return const_cast<MCSection *>(this)->getBeginSymbol();
109  }
110  void setBeginSymbol(MCSymbol *Sym) {
111    assert(!Begin);
112    Begin = Sym;
113  }
114  MCSymbol *getEndSymbol(MCContext &Ctx);
115  bool hasEnded() const;
116
117  unsigned getAlignment() const { return Alignment; }
118  void setAlignment(unsigned Value) { Alignment = Value; }
119
120  unsigned getOrdinal() const { return Ordinal; }
121  void setOrdinal(unsigned Value) { Ordinal = Value; }
122
123  unsigned getLayoutOrder() const { return LayoutOrder; }
124  void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
125
126  BundleLockStateType getBundleLockState() const { return BundleLockState; }
127  void setBundleLockState(BundleLockStateType NewState);
128  bool isBundleLocked() const { return BundleLockState != NotBundleLocked; }
129
130  bool isBundleGroupBeforeFirstInst() const {
131    return BundleGroupBeforeFirstInst;
132  }
133  void setBundleGroupBeforeFirstInst(bool IsFirst) {
134    BundleGroupBeforeFirstInst = IsFirst;
135  }
136
137  bool hasInstructions() const { return HasInstructions; }
138  void setHasInstructions(bool Value) { HasInstructions = Value; }
139
140  bool isRegistered() const { return IsRegistered; }
141  void setIsRegistered(bool Value) { IsRegistered = Value; }
142
143  MCSection::FragmentListType &getFragmentList() { return Fragments; }
144  const MCSection::FragmentListType &getFragmentList() const {
145    return const_cast<MCSection *>(this)->getFragmentList();
146  }
147
148  /// Support for MCFragment::getNextNode().
149  static FragmentListType MCSection::*getSublistAccess(MCFragment *) {
150    return &MCSection::Fragments;
151  }
152
153  const MCDummyFragment &getDummyFragment() const { return DummyFragment; }
154  MCDummyFragment &getDummyFragment() { return DummyFragment; }
155
156  iterator begin() { return Fragments.begin(); }
157  const_iterator begin() const { return Fragments.begin(); }
158
159  iterator end() { return Fragments.end(); }
160  const_iterator end() const { return Fragments.end(); }
161
162  reverse_iterator rbegin() { return Fragments.rbegin(); }
163  const_reverse_iterator rbegin() const { return Fragments.rbegin(); }
164
165  reverse_iterator rend() { return Fragments.rend(); }
166  const_reverse_iterator rend() const  { return Fragments.rend(); }
167
168  MCSection::iterator getSubsectionInsertionPoint(unsigned Subsection);
169
170  void dump() const;
171
172  virtual void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
173                                    raw_ostream &OS,
174                                    const MCExpr *Subsection) const = 0;
175
176  /// Return true if a .align directive should use "optimized nops" to fill
177  /// instead of 0s.
178  virtual bool UseCodeAlign() const = 0;
179
180  /// Check whether this section is "virtual", that is has no actual object
181  /// file contents.
182  virtual bool isVirtualSection() const = 0;
183};
184
185} // end namespace llvm
186
187#endif // LLVM_MC_MCSECTION_H
188