blob: a68e06e661beab9aa9c43e2b301dc93265d5d428 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- MCSection.h - Machine Code Sections ----------------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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/ADT/ilist.h"
18#include "llvm/MC/MCFragment.h"
19#include "llvm/MC/SectionKind.h"
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020020#include "llvm/Support/Alignment.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010021#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:
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020041 static constexpr unsigned NonUniqueID = ~0U;
42
Andrew Walbran3d2c1972020-04-07 12:24:26 +010043 enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm, SV_XCOFF };
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010044
Andrew Scullcdfcccc2018-10-05 20:58:37 +010045 /// Express the state of bundle locked groups while emitting code.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010046 enum BundleLockStateType {
47 NotBundleLocked,
48 BundleLocked,
49 BundleLockedAlignToEnd
50 };
51
52 using FragmentListType = iplist<MCFragment>;
53
54 using const_iterator = FragmentListType::const_iterator;
55 using iterator = FragmentListType::iterator;
56
57 using const_reverse_iterator = FragmentListType::const_reverse_iterator;
58 using reverse_iterator = FragmentListType::reverse_iterator;
59
60private:
61 MCSymbol *Begin;
62 MCSymbol *End = nullptr;
63 /// The alignment requirement of this section.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020064 Align Alignment;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010065 /// The section index in the assemblers section list.
66 unsigned Ordinal = 0;
67 /// The index of this section in the layout order.
68 unsigned LayoutOrder;
69
Andrew Scullcdfcccc2018-10-05 20:58:37 +010070 /// Keeping track of bundle-locked state.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010071 BundleLockStateType BundleLockState = NotBundleLocked;
72
Andrew Scullcdfcccc2018-10-05 20:58:37 +010073 /// Current nesting depth of bundle_lock directives.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010074 unsigned BundleLockNestingDepth = 0;
75
Andrew Scullcdfcccc2018-10-05 20:58:37 +010076 /// We've seen a bundle_lock directive but not its first instruction
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010077 /// yet.
78 bool BundleGroupBeforeFirstInst : 1;
79
80 /// Whether this section has had instructions emitted into it.
81 bool HasInstructions : 1;
82
83 bool IsRegistered : 1;
84
85 MCDummyFragment DummyFragment;
86
87 FragmentListType Fragments;
88
89 /// Mapping from subsection number to insertion point for subsection numbers
90 /// below that number.
91 SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap;
92
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020093 /// State for tracking labels that don't yet have Fragments
94 struct PendingLabel {
95 MCSymbol* Sym;
96 unsigned Subsection;
97 PendingLabel(MCSymbol* Sym, unsigned Subsection = 0)
98 : Sym(Sym), Subsection(Subsection) {}
99 };
100 SmallVector<PendingLabel, 2> PendingLabels;
101
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100102protected:
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200103 // TODO Make Name private when possible.
104 StringRef Name;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100105 SectionVariant Variant;
106 SectionKind Kind;
107
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200108 MCSection(SectionVariant V, StringRef Name, SectionKind K, MCSymbol *Begin);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100109 ~MCSection();
110
111public:
112 MCSection(const MCSection &) = delete;
113 MCSection &operator=(const MCSection &) = delete;
114
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200115 StringRef getName() const { return Name; }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100116 SectionKind getKind() const { return Kind; }
117
118 SectionVariant getVariant() const { return Variant; }
119
120 MCSymbol *getBeginSymbol() { return Begin; }
121 const MCSymbol *getBeginSymbol() const {
122 return const_cast<MCSection *>(this)->getBeginSymbol();
123 }
124 void setBeginSymbol(MCSymbol *Sym) {
125 assert(!Begin);
126 Begin = Sym;
127 }
128 MCSymbol *getEndSymbol(MCContext &Ctx);
129 bool hasEnded() const;
130
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200131 unsigned getAlignment() const { return Alignment.value(); }
132 void setAlignment(Align Value) { Alignment = Value; }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100133
134 unsigned getOrdinal() const { return Ordinal; }
135 void setOrdinal(unsigned Value) { Ordinal = Value; }
136
137 unsigned getLayoutOrder() const { return LayoutOrder; }
138 void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
139
140 BundleLockStateType getBundleLockState() const { return BundleLockState; }
141 void setBundleLockState(BundleLockStateType NewState);
142 bool isBundleLocked() const { return BundleLockState != NotBundleLocked; }
143
144 bool isBundleGroupBeforeFirstInst() const {
145 return BundleGroupBeforeFirstInst;
146 }
147 void setBundleGroupBeforeFirstInst(bool IsFirst) {
148 BundleGroupBeforeFirstInst = IsFirst;
149 }
150
151 bool hasInstructions() const { return HasInstructions; }
152 void setHasInstructions(bool Value) { HasInstructions = Value; }
153
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100154 bool isRegistered() const { return IsRegistered; }
155 void setIsRegistered(bool Value) { IsRegistered = Value; }
156
157 MCSection::FragmentListType &getFragmentList() { return Fragments; }
158 const MCSection::FragmentListType &getFragmentList() const {
159 return const_cast<MCSection *>(this)->getFragmentList();
160 }
161
162 /// Support for MCFragment::getNextNode().
163 static FragmentListType MCSection::*getSublistAccess(MCFragment *) {
164 return &MCSection::Fragments;
165 }
166
167 const MCDummyFragment &getDummyFragment() const { return DummyFragment; }
168 MCDummyFragment &getDummyFragment() { return DummyFragment; }
169
170 iterator begin() { return Fragments.begin(); }
171 const_iterator begin() const { return Fragments.begin(); }
172
173 iterator end() { return Fragments.end(); }
174 const_iterator end() const { return Fragments.end(); }
175
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100176 MCSection::iterator getSubsectionInsertionPoint(unsigned Subsection);
177
178 void dump() const;
179
180 virtual void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
181 raw_ostream &OS,
182 const MCExpr *Subsection) const = 0;
183
184 /// Return true if a .align directive should use "optimized nops" to fill
185 /// instead of 0s.
186 virtual bool UseCodeAlign() const = 0;
187
188 /// Check whether this section is "virtual", that is has no actual object
189 /// file contents.
190 virtual bool isVirtualSection() const = 0;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200191
192 virtual StringRef getVirtualSectionKind() const;
193
194 /// Add a pending label for the requested subsection. This label will be
195 /// associated with a fragment in flushPendingLabels()
196 void addPendingLabel(MCSymbol* label, unsigned Subsection = 0);
197
198 /// Associate all pending labels in a subsection with a fragment.
199 void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0,
200 unsigned Subsection = 0);
201
202 /// Associate all pending labels with empty data fragments. One fragment
203 /// will be created for each subsection as necessary.
204 void flushPendingLabels();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100205};
206
207} // end namespace llvm
208
209#endif // LLVM_MC_MCSECTION_H