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
23namespace llvm {
24
25class MCAsmInfo;
26class MCAssembler;
27class MCContext;
28class MCExpr;
29class MCObjectStreamer;
30class MCSymbol;
31class raw_ostream;
32class 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.
36class MCSection {
37public:
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
78private:
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
117protected:
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
126public:
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