1195098Sed//===- MCSection.h - Machine Code Sections ----------------------*- C++ -*-===//
2195098Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6195098Sed//
7195098Sed//===----------------------------------------------------------------------===//
8195340Sed//
9195340Sed// This file declares the MCSection class.
10195340Sed//
11195340Sed//===----------------------------------------------------------------------===//
12195098Sed
13195098Sed#ifndef LLVM_MC_MCSECTION_H
14195098Sed#define LLVM_MC_MCSECTION_H
15195098Sed
16288943Sdim#include "llvm/ADT/SmallVector.h"
17288943Sdim#include "llvm/ADT/ilist.h"
18296417Sdim#include "llvm/MC/MCFragment.h"
19198090Srdivacky#include "llvm/MC/SectionKind.h"
20360784Sdim#include "llvm/Support/Alignment.h"
21321369Sdim#include <cassert>
22321369Sdim#include <utility>
23195098Sed
24195098Sednamespace llvm {
25321369Sdim
26296417Sdimclass MCAsmInfo;
27288943Sdimclass MCContext;
28288943Sdimclass MCExpr;
29288943Sdimclass MCSymbol;
30288943Sdimclass raw_ostream;
31321369Sdimclass Triple;
32210299Sed
33314564Sdimtemplate <> struct ilist_alloc_traits<MCFragment> {
34288943Sdim  static void deleteNode(MCFragment *V);
35288943Sdim};
36195098Sed
37288943Sdim/// Instances of this class represent a uniqued identifier for a section in the
38288943Sdim/// current translation unit.  The MCContext class uniques and creates these.
39288943Sdimclass MCSection {
40288943Sdimpublic:
41353358Sdim  enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm, SV_XCOFF };
42208599Srdivacky
43341825Sdim  /// Express the state of bundle locked groups while emitting code.
44288943Sdim  enum BundleLockStateType {
45288943Sdim    NotBundleLocked,
46288943Sdim    BundleLocked,
47288943Sdim    BundleLockedAlignToEnd
48288943Sdim  };
49210299Sed
50321369Sdim  using FragmentListType = iplist<MCFragment>;
51206274Srdivacky
52321369Sdim  using const_iterator = FragmentListType::const_iterator;
53321369Sdim  using iterator = FragmentListType::iterator;
54249423Sdim
55321369Sdim  using const_reverse_iterator = FragmentListType::const_reverse_iterator;
56321369Sdim  using reverse_iterator = FragmentListType::reverse_iterator;
57198090Srdivacky
58288943Sdimprivate:
59288943Sdim  MCSymbol *Begin;
60288943Sdim  MCSymbol *End = nullptr;
61288943Sdim  /// The alignment requirement of this section.
62360784Sdim  Align Alignment;
63288943Sdim  /// The section index in the assemblers section list.
64288943Sdim  unsigned Ordinal = 0;
65288943Sdim  /// The index of this section in the layout order.
66288943Sdim  unsigned LayoutOrder;
67210299Sed
68341825Sdim  /// Keeping track of bundle-locked state.
69288943Sdim  BundleLockStateType BundleLockState = NotBundleLocked;
70288943Sdim
71341825Sdim  /// Current nesting depth of bundle_lock directives.
72288943Sdim  unsigned BundleLockNestingDepth = 0;
73288943Sdim
74341825Sdim  /// We've seen a bundle_lock directive but not its first instruction
75288943Sdim  /// yet.
76321369Sdim  bool BundleGroupBeforeFirstInst : 1;
77288943Sdim
78288943Sdim  /// Whether this section has had instructions emitted into it.
79321369Sdim  bool HasInstructions : 1;
80288943Sdim
81321369Sdim  bool IsRegistered : 1;
82288943Sdim
83296417Sdim  MCDummyFragment DummyFragment;
84296417Sdim
85288943Sdim  FragmentListType Fragments;
86288943Sdim
87288943Sdim  /// Mapping from subsection number to insertion point for subsection numbers
88288943Sdim  /// below that number.
89288943Sdim  SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap;
90288943Sdim
91360784Sdim  /// State for tracking labels that don't yet have Fragments
92360784Sdim  struct PendingLabel {
93360784Sdim    MCSymbol* Sym;
94360784Sdim    unsigned Subsection;
95360784Sdim    PendingLabel(MCSymbol* Sym, unsigned Subsection = 0)
96360784Sdim      : Sym(Sym), Subsection(Subsection) {}
97360784Sdim  };
98360784Sdim  SmallVector<PendingLabel, 2> PendingLabels;
99360784Sdim
100288943Sdimprotected:
101288943Sdim  SectionVariant Variant;
102288943Sdim  SectionKind Kind;
103321369Sdim
104321369Sdim  MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin);
105296417Sdim  ~MCSection();
106288943Sdim
107288943Sdimpublic:
108321369Sdim  MCSection(const MCSection &) = delete;
109321369Sdim  MCSection &operator=(const MCSection &) = delete;
110321369Sdim
111288943Sdim  SectionKind getKind() const { return Kind; }
112288943Sdim
113288943Sdim  SectionVariant getVariant() const { return Variant; }
114288943Sdim
115288943Sdim  MCSymbol *getBeginSymbol() { return Begin; }
116288943Sdim  const MCSymbol *getBeginSymbol() const {
117288943Sdim    return const_cast<MCSection *>(this)->getBeginSymbol();
118288943Sdim  }
119288943Sdim  void setBeginSymbol(MCSymbol *Sym) {
120288943Sdim    assert(!Begin);
121288943Sdim    Begin = Sym;
122288943Sdim  }
123288943Sdim  MCSymbol *getEndSymbol(MCContext &Ctx);
124288943Sdim  bool hasEnded() const;
125288943Sdim
126360784Sdim  unsigned getAlignment() const { return Alignment.value(); }
127360784Sdim  void setAlignment(Align Value) { Alignment = Value; }
128288943Sdim
129288943Sdim  unsigned getOrdinal() const { return Ordinal; }
130288943Sdim  void setOrdinal(unsigned Value) { Ordinal = Value; }
131288943Sdim
132288943Sdim  unsigned getLayoutOrder() const { return LayoutOrder; }
133288943Sdim  void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
134288943Sdim
135288943Sdim  BundleLockStateType getBundleLockState() const { return BundleLockState; }
136288943Sdim  void setBundleLockState(BundleLockStateType NewState);
137288943Sdim  bool isBundleLocked() const { return BundleLockState != NotBundleLocked; }
138288943Sdim
139288943Sdim  bool isBundleGroupBeforeFirstInst() const {
140288943Sdim    return BundleGroupBeforeFirstInst;
141288943Sdim  }
142288943Sdim  void setBundleGroupBeforeFirstInst(bool IsFirst) {
143288943Sdim    BundleGroupBeforeFirstInst = IsFirst;
144288943Sdim  }
145288943Sdim
146288943Sdim  bool hasInstructions() const { return HasInstructions; }
147288943Sdim  void setHasInstructions(bool Value) { HasInstructions = Value; }
148288943Sdim
149288943Sdim  bool isRegistered() const { return IsRegistered; }
150288943Sdim  void setIsRegistered(bool Value) { IsRegistered = Value; }
151288943Sdim
152288943Sdim  MCSection::FragmentListType &getFragmentList() { return Fragments; }
153288943Sdim  const MCSection::FragmentListType &getFragmentList() const {
154288943Sdim    return const_cast<MCSection *>(this)->getFragmentList();
155288943Sdim  }
156288943Sdim
157296417Sdim  /// Support for MCFragment::getNextNode().
158296417Sdim  static FragmentListType MCSection::*getSublistAccess(MCFragment *) {
159296417Sdim    return &MCSection::Fragments;
160296417Sdim  }
161296417Sdim
162296417Sdim  const MCDummyFragment &getDummyFragment() const { return DummyFragment; }
163296417Sdim  MCDummyFragment &getDummyFragment() { return DummyFragment; }
164296417Sdim
165314564Sdim  iterator begin() { return Fragments.begin(); }
166314564Sdim  const_iterator begin() const { return Fragments.begin(); }
167288943Sdim
168314564Sdim  iterator end() { return Fragments.end(); }
169314564Sdim  const_iterator end() const { return Fragments.end(); }
170288943Sdim
171288943Sdim  MCSection::iterator getSubsectionInsertionPoint(unsigned Subsection);
172288943Sdim
173321369Sdim  void dump() const;
174288943Sdim
175321369Sdim  virtual void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
176321369Sdim                                    raw_ostream &OS,
177288943Sdim                                    const MCExpr *Subsection) const = 0;
178288943Sdim
179288943Sdim  /// Return true if a .align directive should use "optimized nops" to fill
180288943Sdim  /// instead of 0s.
181288943Sdim  virtual bool UseCodeAlign() const = 0;
182288943Sdim
183288943Sdim  /// Check whether this section is "virtual", that is has no actual object
184288943Sdim  /// file contents.
185288943Sdim  virtual bool isVirtualSection() const = 0;
186360784Sdim
187360784Sdim  /// Add a pending label for the requested subsection. This label will be
188360784Sdim  /// associated with a fragment in flushPendingLabels()
189360784Sdim  void addPendingLabel(MCSymbol* label, unsigned Subsection = 0);
190360784Sdim
191360784Sdim  /// Associate all pending labels in a subsection with a fragment.
192360784Sdim  void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0,
193360784Sdim			  unsigned Subsection = 0);
194360784Sdim
195360784Sdim  /// Associate all pending labels with empty data fragments. One fragment
196360784Sdim  /// will be created for each subsection as necessary.
197360784Sdim  void flushPendingLabels();
198288943Sdim};
199288943Sdim
200195098Sed} // end namespace llvm
201195098Sed
202321369Sdim#endif // LLVM_MC_MCSECTION_H
203