xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCSection.h (revision 52418fc2be8efa5172b90a3a9e617017173612c4)
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;
iteratoriterator63     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 
getName()130   StringRef getName() const { return Name; }
isText()131   bool isText() const { return IsText; }
132 
getVariant()133   SectionVariant getVariant() const { return Variant; }
134 
getBeginSymbol()135   MCSymbol *getBeginSymbol() { return Begin; }
getBeginSymbol()136   const MCSymbol *getBeginSymbol() const {
137     return const_cast<MCSection *>(this)->getBeginSymbol();
138   }
setBeginSymbol(MCSymbol * Sym)139   void setBeginSymbol(MCSymbol *Sym) {
140     assert(!Begin);
141     Begin = Sym;
142   }
143   MCSymbol *getEndSymbol(MCContext &Ctx);
144   bool hasEnded() const;
145 
getAlign()146   Align getAlign() const { return Alignment; }
setAlignment(Align Value)147   void setAlignment(Align Value) { Alignment = Value; }
148 
149   /// Makes sure that Alignment is at least MinAlignment.
ensureMinAlignment(Align MinAlignment)150   void ensureMinAlignment(Align MinAlignment) {
151     if (Alignment < MinAlignment)
152       Alignment = MinAlignment;
153   }
154 
getOrdinal()155   unsigned getOrdinal() const { return Ordinal; }
setOrdinal(unsigned Value)156   void setOrdinal(unsigned Value) { Ordinal = Value; }
157 
getBundleLockState()158   BundleLockStateType getBundleLockState() const { return BundleLockState; }
159   void setBundleLockState(BundleLockStateType NewState);
isBundleLocked()160   bool isBundleLocked() const { return BundleLockState != NotBundleLocked; }
161 
isBundleGroupBeforeFirstInst()162   bool isBundleGroupBeforeFirstInst() const {
163     return BundleGroupBeforeFirstInst;
164   }
setBundleGroupBeforeFirstInst(bool IsFirst)165   void setBundleGroupBeforeFirstInst(bool IsFirst) {
166     BundleGroupBeforeFirstInst = IsFirst;
167   }
168 
hasInstructions()169   bool hasInstructions() const { return HasInstructions; }
setHasInstructions(bool Value)170   void setHasInstructions(bool Value) { HasInstructions = Value; }
171 
hasLayout()172   bool hasLayout() const { return HasLayout; }
setHasLayout(bool Value)173   void setHasLayout(bool Value) { HasLayout = Value; }
174 
isRegistered()175   bool isRegistered() const { return IsRegistered; }
setIsRegistered(bool Value)176   void setIsRegistered(bool Value) { IsRegistered = Value; }
177 
getDummyFragment()178   const MCDummyFragment &getDummyFragment() const { return DummyFragment; }
getDummyFragment()179   MCDummyFragment &getDummyFragment() { return DummyFragment; }
180 
curFragList()181   FragList *curFragList() const { return CurFragList; }
begin()182   iterator begin() const { return iterator(CurFragList->Head); }
end()183   iterator end() const { return {}; }
empty()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.
isVirtualSection()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