1 | //===- MCSection.h - Machine Code Sections ----------------------*- 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 | // This file declares the MCSection class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_MC_MCSECTION_H |
14 | #define LLVM_MC_MCSECTION_H |
15 | |
16 | #include "llvm/ADT/SmallVector.h" |
17 | #include "llvm/MC/MCFragment.h" |
18 | #include "llvm/MC/SectionKind.h" |
19 | #include "llvm/Support/Alignment.h" |
20 | #include <cassert> |
21 | #include <utility> |
22 | |
23 | namespace llvm { |
24 | |
25 | class MCAsmInfo; |
26 | class MCAssembler; |
27 | class MCContext; |
28 | class MCExpr; |
29 | class MCObjectStreamer; |
30 | class MCSymbol; |
31 | class raw_ostream; |
32 | class Triple; |
33 | |
34 | /// Instances of this class represent a uniqued identifier for a section in the |
35 | /// current translation unit. The MCContext class uniques and creates these. |
36 | class MCSection { |
37 | public: |
38 | friend MCAssembler; |
39 | friend MCObjectStreamer; |
40 | static constexpr unsigned NonUniqueID = ~0U; |
41 | |
42 | enum SectionVariant { |
43 | SV_COFF = 0, |
44 | SV_ELF, |
45 | SV_GOFF, |
46 | SV_MachO, |
47 | SV_Wasm, |
48 | SV_XCOFF, |
49 | SV_SPIRV, |
50 | SV_DXContainer, |
51 | }; |
52 | |
53 | /// Express the state of bundle locked groups while emitting code. |
54 | enum BundleLockStateType { |
55 | NotBundleLocked, |
56 | BundleLocked, |
57 | BundleLockedAlignToEnd |
58 | }; |
59 | |
60 | struct iterator { |
61 | MCFragment *F = nullptr; |
62 | iterator() = default; |
63 | explicit iterator(MCFragment *F) : F(F) {} |
64 | MCFragment &operator*() const { return *F; } |
65 | bool operator==(const iterator &O) const { return F == O.F; } |
66 | bool operator!=(const iterator &O) const { return F != O.F; } |
67 | iterator &operator++() { |
68 | F = F->Next; |
69 | return *this; |
70 | } |
71 | }; |
72 | |
73 | struct FragList { |
74 | MCFragment *Head = nullptr; |
75 | MCFragment *Tail = nullptr; |
76 | }; |
77 | |
78 | private: |
79 | // At parse time, this holds the fragment list of the current subsection. At |
80 | // layout time, this holds the concatenated fragment lists of all subsections. |
81 | FragList *CurFragList; |
82 | MCSymbol *Begin; |
83 | MCSymbol *End = nullptr; |
84 | /// The alignment requirement of this section. |
85 | Align Alignment; |
86 | /// The section index in the assemblers section list. |
87 | unsigned Ordinal = 0; |
88 | |
89 | /// Keeping track of bundle-locked state. |
90 | BundleLockStateType BundleLockState = NotBundleLocked; |
91 | |
92 | /// Current nesting depth of bundle_lock directives. |
93 | unsigned BundleLockNestingDepth = 0; |
94 | |
95 | /// We've seen a bundle_lock directive but not its first instruction |
96 | /// yet. |
97 | bool BundleGroupBeforeFirstInst : 1; |
98 | |
99 | /// Whether this section has had instructions emitted into it. |
100 | bool HasInstructions : 1; |
101 | |
102 | bool HasLayout : 1; |
103 | |
104 | bool IsRegistered : 1; |
105 | |
106 | bool IsText : 1; |
107 | |
108 | bool IsVirtual : 1; |
109 | |
110 | MCDummyFragment DummyFragment; |
111 | |
112 | // Mapping from subsection number to fragment list. At layout time, the |
113 | // subsection 0 list is replaced with concatenated fragments from all |
114 | // subsections. |
115 | SmallVector<std::pair<unsigned, FragList>, 1> Subsections; |
116 | |
117 | protected: |
118 | // TODO Make Name private when possible. |
119 | StringRef Name; |
120 | SectionVariant Variant; |
121 | |
122 | MCSection(SectionVariant V, StringRef Name, bool IsText, bool IsVirtual, |
123 | MCSymbol *Begin); |
124 | ~MCSection(); |
125 | |
126 | public: |
127 | MCSection(const MCSection &) = delete; |
128 | MCSection &operator=(const MCSection &) = delete; |
129 | |
130 | StringRef getName() const { return Name; } |
131 | bool isText() const { return IsText; } |
132 | |
133 | SectionVariant getVariant() const { return Variant; } |
134 | |
135 | MCSymbol *getBeginSymbol() { return Begin; } |
136 | const MCSymbol *getBeginSymbol() const { |
137 | return const_cast<MCSection *>(this)->getBeginSymbol(); |
138 | } |
139 | void setBeginSymbol(MCSymbol *Sym) { |
140 | assert(!Begin); |
141 | Begin = Sym; |
142 | } |
143 | MCSymbol *getEndSymbol(MCContext &Ctx); |
144 | bool hasEnded() const; |
145 | |
146 | Align getAlign() const { return Alignment; } |
147 | void setAlignment(Align Value) { Alignment = Value; } |
148 | |
149 | /// Makes sure that Alignment is at least MinAlignment. |
150 | void ensureMinAlignment(Align MinAlignment) { |
151 | if (Alignment < MinAlignment) |
152 | Alignment = MinAlignment; |
153 | } |
154 | |
155 | unsigned getOrdinal() const { return Ordinal; } |
156 | void setOrdinal(unsigned Value) { Ordinal = Value; } |
157 | |
158 | BundleLockStateType getBundleLockState() const { return BundleLockState; } |
159 | void setBundleLockState(BundleLockStateType NewState); |
160 | bool isBundleLocked() const { return BundleLockState != NotBundleLocked; } |
161 | |
162 | bool isBundleGroupBeforeFirstInst() const { |
163 | return BundleGroupBeforeFirstInst; |
164 | } |
165 | void setBundleGroupBeforeFirstInst(bool IsFirst) { |
166 | BundleGroupBeforeFirstInst = IsFirst; |
167 | } |
168 | |
169 | bool hasInstructions() const { return HasInstructions; } |
170 | void setHasInstructions(bool Value) { HasInstructions = Value; } |
171 | |
172 | bool hasLayout() const { return HasLayout; } |
173 | void setHasLayout(bool Value) { HasLayout = Value; } |
174 | |
175 | bool isRegistered() const { return IsRegistered; } |
176 | void setIsRegistered(bool Value) { IsRegistered = Value; } |
177 | |
178 | const MCDummyFragment &getDummyFragment() const { return DummyFragment; } |
179 | MCDummyFragment &getDummyFragment() { return DummyFragment; } |
180 | |
181 | FragList *curFragList() const { return CurFragList; } |
182 | iterator begin() const { return iterator(CurFragList->Head); } |
183 | iterator end() const { return {}; } |
184 | bool empty() const { return !CurFragList->Head; } |
185 | |
186 | void dump() const; |
187 | |
188 | virtual void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T, |
189 | raw_ostream &OS, |
190 | uint32_t Subsection) const = 0; |
191 | |
192 | /// Return true if a .align directive should use "optimized nops" to fill |
193 | /// instead of 0s. |
194 | virtual bool useCodeAlign() const = 0; |
195 | |
196 | /// Check whether this section is "virtual", that is has no actual object |
197 | /// file contents. |
198 | bool isVirtualSection() const { return IsVirtual; } |
199 | |
200 | virtual StringRef getVirtualSectionKind() const; |
201 | }; |
202 | |
203 | } // end namespace llvm |
204 | |
205 | #endif // LLVM_MC_MCSECTION_H |
206 | |