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/ADT/ilist.h" 18 #include "llvm/MC/MCFragment.h" 19 #include "llvm/MC/SectionKind.h" 20 #include "llvm/Support/Alignment.h" 21 #include <cassert> 22 #include <utility> 23 24 namespace llvm { 25 26 class MCAsmInfo; 27 class MCContext; 28 class MCExpr; 29 class MCSymbol; 30 class raw_ostream; 31 class Triple; 32 33 template <> 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. 39 class MCSection { 40 public: 41 static constexpr unsigned NonUniqueID = ~0U; 42 43 enum SectionVariant { 44 SV_COFF = 0, 45 SV_ELF, 46 SV_GOFF, 47 SV_MachO, 48 SV_Wasm, 49 SV_XCOFF 50 }; 51 52 /// Express the state of bundle locked groups while emitting code. 53 enum BundleLockStateType { 54 NotBundleLocked, 55 BundleLocked, 56 BundleLockedAlignToEnd 57 }; 58 59 using FragmentListType = iplist<MCFragment>; 60 61 using const_iterator = FragmentListType::const_iterator; 62 using iterator = FragmentListType::iterator; 63 64 using const_reverse_iterator = FragmentListType::const_reverse_iterator; 65 using reverse_iterator = FragmentListType::reverse_iterator; 66 67 private: 68 MCSymbol *Begin; 69 MCSymbol *End = nullptr; 70 /// The alignment requirement of this section. 71 Align Alignment; 72 /// The section index in the assemblers section list. 73 unsigned Ordinal = 0; 74 /// The index of this section in the layout order. 75 unsigned LayoutOrder; 76 77 /// Keeping track of bundle-locked state. 78 BundleLockStateType BundleLockState = NotBundleLocked; 79 80 /// Current nesting depth of bundle_lock directives. 81 unsigned BundleLockNestingDepth = 0; 82 83 /// We've seen a bundle_lock directive but not its first instruction 84 /// yet. 85 bool BundleGroupBeforeFirstInst : 1; 86 87 /// Whether this section has had instructions emitted into it. 88 bool HasInstructions : 1; 89 90 bool IsRegistered : 1; 91 92 MCDummyFragment DummyFragment; 93 94 FragmentListType Fragments; 95 96 /// Mapping from subsection number to insertion point for subsection numbers 97 /// below that number. 98 SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap; 99 100 /// State for tracking labels that don't yet have Fragments 101 struct PendingLabel { 102 MCSymbol* Sym; 103 unsigned Subsection; 104 PendingLabel(MCSymbol* Sym, unsigned Subsection = 0) 105 : Sym(Sym), Subsection(Subsection) {} 106 }; 107 SmallVector<PendingLabel, 2> PendingLabels; 108 109 protected: 110 // TODO Make Name private when possible. 111 StringRef Name; 112 SectionVariant Variant; 113 SectionKind Kind; 114 115 MCSection(SectionVariant V, StringRef Name, SectionKind K, MCSymbol *Begin); 116 ~MCSection(); 117 118 public: 119 MCSection(const MCSection &) = delete; 120 MCSection &operator=(const MCSection &) = delete; 121 122 StringRef getName() const { return Name; } 123 SectionKind getKind() const { return Kind; } 124 125 SectionVariant getVariant() const { return Variant; } 126 127 MCSymbol *getBeginSymbol() { return Begin; } 128 const MCSymbol *getBeginSymbol() const { 129 return const_cast<MCSection *>(this)->getBeginSymbol(); 130 } 131 void setBeginSymbol(MCSymbol *Sym) { 132 assert(!Begin); 133 Begin = Sym; 134 } 135 MCSymbol *getEndSymbol(MCContext &Ctx); 136 bool hasEnded() const; 137 138 unsigned getAlignment() const { return Alignment.value(); } 139 void setAlignment(Align Value) { Alignment = Value; } 140 141 unsigned getOrdinal() const { return Ordinal; } 142 void setOrdinal(unsigned Value) { Ordinal = Value; } 143 144 unsigned getLayoutOrder() const { return LayoutOrder; } 145 void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } 146 147 BundleLockStateType getBundleLockState() const { return BundleLockState; } 148 void setBundleLockState(BundleLockStateType NewState); 149 bool isBundleLocked() const { return BundleLockState != NotBundleLocked; } 150 151 bool isBundleGroupBeforeFirstInst() const { 152 return BundleGroupBeforeFirstInst; 153 } 154 void setBundleGroupBeforeFirstInst(bool IsFirst) { 155 BundleGroupBeforeFirstInst = IsFirst; 156 } 157 158 bool hasInstructions() const { return HasInstructions; } 159 void setHasInstructions(bool Value) { HasInstructions = Value; } 160 161 bool isRegistered() const { return IsRegistered; } 162 void setIsRegistered(bool Value) { IsRegistered = Value; } 163 164 MCSection::FragmentListType &getFragmentList() { return Fragments; } 165 const MCSection::FragmentListType &getFragmentList() const { 166 return const_cast<MCSection *>(this)->getFragmentList(); 167 } 168 169 /// Support for MCFragment::getNextNode(). 170 static FragmentListType MCSection::*getSublistAccess(MCFragment *) { 171 return &MCSection::Fragments; 172 } 173 174 const MCDummyFragment &getDummyFragment() const { return DummyFragment; } 175 MCDummyFragment &getDummyFragment() { return DummyFragment; } 176 177 iterator begin() { return Fragments.begin(); } 178 const_iterator begin() const { return Fragments.begin(); } 179 180 iterator end() { return Fragments.end(); } 181 const_iterator end() const { return Fragments.end(); } 182 183 MCSection::iterator getSubsectionInsertionPoint(unsigned Subsection); 184 185 void dump() const; 186 187 virtual void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, 188 raw_ostream &OS, 189 const MCExpr *Subsection) const = 0; 190 191 /// Return true if a .align directive should use "optimized nops" to fill 192 /// instead of 0s. 193 virtual bool UseCodeAlign() const = 0; 194 195 /// Check whether this section is "virtual", that is has no actual object 196 /// file contents. 197 virtual bool isVirtualSection() const = 0; 198 199 virtual StringRef getVirtualSectionKind() const; 200 201 /// Add a pending label for the requested subsection. This label will be 202 /// associated with a fragment in flushPendingLabels() 203 void addPendingLabel(MCSymbol* label, unsigned Subsection = 0); 204 205 /// Associate all pending labels in a subsection with a fragment. 206 void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0, 207 unsigned Subsection = 0); 208 209 /// Associate all pending labels with empty data fragments. One fragment 210 /// will be created for each subsection as necessary. 211 void flushPendingLabels(); 212 }; 213 214 } // end namespace llvm 215 216 #endif // LLVM_MC_MCSECTION_H 217