xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceDefs.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceDefs.h - Common Subzero declarations ------*- C++ -*-===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker //                        The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Declares various useful types and classes that have widespread use
12*03ce13f7SAndroid Build Coastguard Worker /// across Subzero.
13*03ce13f7SAndroid Build Coastguard Worker ///
14*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*03ce13f7SAndroid Build Coastguard Worker 
16*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICEDEFS_H
17*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICEDEFS_H
18*03ce13f7SAndroid Build Coastguard Worker 
19*03ce13f7SAndroid Build Coastguard Worker #include "IceBuildDefs.h" // TODO(stichnot): move into individual files
20*03ce13f7SAndroid Build Coastguard Worker #include "IceMemory.h"
21*03ce13f7SAndroid Build Coastguard Worker #include "IceTLS.h"
22*03ce13f7SAndroid Build Coastguard Worker 
23*03ce13f7SAndroid Build Coastguard Worker #include "llvm/ADT/ArrayRef.h"
24*03ce13f7SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
25*03ce13f7SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
26*03ce13f7SAndroid Build Coastguard Worker #include "llvm/ADT/ilist.h"
27*03ce13f7SAndroid Build Coastguard Worker #include "llvm/ADT/ilist_node.h"
28*03ce13f7SAndroid Build Coastguard Worker #include "llvm/ADT/iterator_range.h"
29*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/Casting.h"
30*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/ELF.h"
31*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
32*03ce13f7SAndroid Build Coastguard Worker 
33*03ce13f7SAndroid Build Coastguard Worker #include <cassert>
34*03ce13f7SAndroid Build Coastguard Worker #include <cstdint>
35*03ce13f7SAndroid Build Coastguard Worker #include <cstdio>     // snprintf
36*03ce13f7SAndroid Build Coastguard Worker #include <functional> // std::less
37*03ce13f7SAndroid Build Coastguard Worker #include <limits>
38*03ce13f7SAndroid Build Coastguard Worker #include <list>
39*03ce13f7SAndroid Build Coastguard Worker #include <map>
40*03ce13f7SAndroid Build Coastguard Worker #include <memory>
41*03ce13f7SAndroid Build Coastguard Worker #include <mutex>
42*03ce13f7SAndroid Build Coastguard Worker #include <set>
43*03ce13f7SAndroid Build Coastguard Worker #include <string>
44*03ce13f7SAndroid Build Coastguard Worker #include <system_error>
45*03ce13f7SAndroid Build Coastguard Worker #include <unordered_map>
46*03ce13f7SAndroid Build Coastguard Worker #include <unordered_set>
47*03ce13f7SAndroid Build Coastguard Worker #include <utility>
48*03ce13f7SAndroid Build Coastguard Worker #include <vector>
49*03ce13f7SAndroid Build Coastguard Worker 
50*03ce13f7SAndroid Build Coastguard Worker #define XSTRINGIFY(x) STRINGIFY(x)
51*03ce13f7SAndroid Build Coastguard Worker #define STRINGIFY(x) #x
52*03ce13f7SAndroid Build Coastguard Worker 
53*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
54*03ce13f7SAndroid Build Coastguard Worker 
55*03ce13f7SAndroid Build Coastguard Worker class Assembler;
56*03ce13f7SAndroid Build Coastguard Worker template <template <typename> class> class BitVectorTmpl;
57*03ce13f7SAndroid Build Coastguard Worker class Cfg;
58*03ce13f7SAndroid Build Coastguard Worker class CfgNode;
59*03ce13f7SAndroid Build Coastguard Worker class Constant;
60*03ce13f7SAndroid Build Coastguard Worker class ELFFileStreamer;
61*03ce13f7SAndroid Build Coastguard Worker class ELFObjectWriter;
62*03ce13f7SAndroid Build Coastguard Worker class ELFStreamer;
63*03ce13f7SAndroid Build Coastguard Worker class FunctionDeclaration;
64*03ce13f7SAndroid Build Coastguard Worker class GlobalContext;
65*03ce13f7SAndroid Build Coastguard Worker class GlobalDeclaration;
66*03ce13f7SAndroid Build Coastguard Worker class Inst;
67*03ce13f7SAndroid Build Coastguard Worker class InstAssign;
68*03ce13f7SAndroid Build Coastguard Worker class InstJumpTable;
69*03ce13f7SAndroid Build Coastguard Worker class InstPhi;
70*03ce13f7SAndroid Build Coastguard Worker class InstSwitch;
71*03ce13f7SAndroid Build Coastguard Worker class InstTarget;
72*03ce13f7SAndroid Build Coastguard Worker class LiveRange;
73*03ce13f7SAndroid Build Coastguard Worker class Liveness;
74*03ce13f7SAndroid Build Coastguard Worker class Operand;
75*03ce13f7SAndroid Build Coastguard Worker class TargetDataLowering;
76*03ce13f7SAndroid Build Coastguard Worker class TargetLowering;
77*03ce13f7SAndroid Build Coastguard Worker class Variable;
78*03ce13f7SAndroid Build Coastguard Worker class VariableDeclaration;
79*03ce13f7SAndroid Build Coastguard Worker class VariablesMetadata;
80*03ce13f7SAndroid Build Coastguard Worker 
81*03ce13f7SAndroid Build Coastguard Worker /// SizeT is for holding small-ish limits like number of source operands in an
82*03ce13f7SAndroid Build Coastguard Worker /// instruction. It is used instead of size_t (which may be 64-bits wide) when
83*03ce13f7SAndroid Build Coastguard Worker /// we want to save space.
84*03ce13f7SAndroid Build Coastguard Worker using SizeT = uint32_t;
85*03ce13f7SAndroid Build Coastguard Worker 
86*03ce13f7SAndroid Build Coastguard Worker constexpr char GlobalOffsetTable[] = "_GLOBAL_OFFSET_TABLE_";
87*03ce13f7SAndroid Build Coastguard Worker // makeUnique should be used when memory is expected to be allocated from the
88*03ce13f7SAndroid Build Coastguard Worker // heap (as opposed to allocated from some Allocator.) It is intended to be
89*03ce13f7SAndroid Build Coastguard Worker // used instead of new.
90*03ce13f7SAndroid Build Coastguard Worker //
91*03ce13f7SAndroid Build Coastguard Worker // The expected usage is as follows
92*03ce13f7SAndroid Build Coastguard Worker //
93*03ce13f7SAndroid Build Coastguard Worker // class MyClass {
94*03ce13f7SAndroid Build Coastguard Worker // public:
95*03ce13f7SAndroid Build Coastguard Worker //   static std::unique_ptr<MyClass> create(<ctor_args>) {
96*03ce13f7SAndroid Build Coastguard Worker //     return makeUnique<MyClass>(<ctor_args>);
97*03ce13f7SAndroid Build Coastguard Worker //   }
98*03ce13f7SAndroid Build Coastguard Worker //
99*03ce13f7SAndroid Build Coastguard Worker // private:
100*03ce13f7SAndroid Build Coastguard Worker //   ENABLE_MAKE_UNIQUE;
101*03ce13f7SAndroid Build Coastguard Worker //
102*03ce13f7SAndroid Build Coastguard Worker //   MyClass(<ctor_args>) ...
103*03ce13f7SAndroid Build Coastguard Worker // }
104*03ce13f7SAndroid Build Coastguard Worker //
105*03ce13f7SAndroid Build Coastguard Worker // ENABLE_MAKE_UNIQUE is a trick that is necessary if MyClass' ctor is private.
106*03ce13f7SAndroid Build Coastguard Worker // Private ctors are highly encouraged when you're writing a class that you'd
107*03ce13f7SAndroid Build Coastguard Worker // like to have allocated with makeUnique as it would prevent users from
108*03ce13f7SAndroid Build Coastguard Worker // declaring stack allocated variables.
109*03ce13f7SAndroid Build Coastguard Worker namespace Internal {
110*03ce13f7SAndroid Build Coastguard Worker struct MakeUniqueEnabler {
111*03ce13f7SAndroid Build Coastguard Worker   template <class T, class... Args>
createMakeUniqueEnabler112*03ce13f7SAndroid Build Coastguard Worker   static std::unique_ptr<T> create(Args &&... TheArgs) {
113*03ce13f7SAndroid Build Coastguard Worker     std::unique_ptr<T> Unique(new T(std::forward<Args>(TheArgs)...));
114*03ce13f7SAndroid Build Coastguard Worker     return Unique;
115*03ce13f7SAndroid Build Coastguard Worker   }
116*03ce13f7SAndroid Build Coastguard Worker };
117*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Internal
118*03ce13f7SAndroid Build Coastguard Worker 
119*03ce13f7SAndroid Build Coastguard Worker template <class T, class... Args>
makeUnique(Args &&...TheArgs)120*03ce13f7SAndroid Build Coastguard Worker static std::unique_ptr<T> makeUnique(Args &&... TheArgs) {
121*03ce13f7SAndroid Build Coastguard Worker   return ::Ice::Internal::MakeUniqueEnabler::create<T>(
122*03ce13f7SAndroid Build Coastguard Worker       std::forward<Args>(TheArgs)...);
123*03ce13f7SAndroid Build Coastguard Worker }
124*03ce13f7SAndroid Build Coastguard Worker 
125*03ce13f7SAndroid Build Coastguard Worker #define ENABLE_MAKE_UNIQUE friend struct ::Ice::Internal::MakeUniqueEnabler
126*03ce13f7SAndroid Build Coastguard Worker 
127*03ce13f7SAndroid Build Coastguard Worker using InstList = llvm::ilist<Inst>;
128*03ce13f7SAndroid Build Coastguard Worker // Ideally PhiList would be llvm::ilist<InstPhi>, and similar for AssignList,
129*03ce13f7SAndroid Build Coastguard Worker // but this runs into issues with SFINAE.
130*03ce13f7SAndroid Build Coastguard Worker using PhiList = InstList;
131*03ce13f7SAndroid Build Coastguard Worker using AssignList = InstList;
132*03ce13f7SAndroid Build Coastguard Worker 
133*03ce13f7SAndroid Build Coastguard Worker // Standard library containers with CfgLocalAllocator.
134*03ce13f7SAndroid Build Coastguard Worker template <typename T> using CfgList = std::list<T, CfgLocalAllocator<T>>;
135*03ce13f7SAndroid Build Coastguard Worker template <typename T, typename H = std::hash<T>, typename Eq = std::equal_to<T>>
136*03ce13f7SAndroid Build Coastguard Worker using CfgUnorderedSet = std::unordered_set<T, H, Eq, CfgLocalAllocator<T>>;
137*03ce13f7SAndroid Build Coastguard Worker template <typename T, typename Cmp = std::less<T>>
138*03ce13f7SAndroid Build Coastguard Worker using CfgSet = std::set<T, Cmp, CfgLocalAllocator<T>>;
139*03ce13f7SAndroid Build Coastguard Worker template <typename T, typename U, typename H = std::hash<T>,
140*03ce13f7SAndroid Build Coastguard Worker           typename Eq = std::equal_to<T>>
141*03ce13f7SAndroid Build Coastguard Worker using CfgUnorderedMap =
142*03ce13f7SAndroid Build Coastguard Worker     std::unordered_map<T, U, H, Eq, CfgLocalAllocator<std::pair<const T, U>>>;
143*03ce13f7SAndroid Build Coastguard Worker template <typename T> using CfgVector = std::vector<T, CfgLocalAllocator<T>>;
144*03ce13f7SAndroid Build Coastguard Worker 
145*03ce13f7SAndroid Build Coastguard Worker // Containers that are arena-allocated from the Cfg's allocator.
146*03ce13f7SAndroid Build Coastguard Worker using OperandList = CfgVector<Operand *>;
147*03ce13f7SAndroid Build Coastguard Worker using VarList = CfgVector<Variable *>;
148*03ce13f7SAndroid Build Coastguard Worker using NodeList = CfgVector<CfgNode *>;
149*03ce13f7SAndroid Build Coastguard Worker 
150*03ce13f7SAndroid Build Coastguard Worker // Containers that use the default (global) allocator.
151*03ce13f7SAndroid Build Coastguard Worker using ConstantList = std::vector<Constant *>;
152*03ce13f7SAndroid Build Coastguard Worker using FunctionDeclarationList = std::vector<FunctionDeclaration *>;
153*03ce13f7SAndroid Build Coastguard Worker 
154*03ce13f7SAndroid Build Coastguard Worker /// VariableDeclarationList is a container for holding VariableDeclarations --
155*03ce13f7SAndroid Build Coastguard Worker /// i.e., Global Variables. It is also used to create said variables, and their
156*03ce13f7SAndroid Build Coastguard Worker /// initializers in an arena.
157*03ce13f7SAndroid Build Coastguard Worker class VariableDeclarationList {
158*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationList(const VariableDeclarationList &) = delete;
159*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationList &operator=(const VariableDeclarationList &) = delete;
160*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationList(VariableDeclarationList &&) = delete;
161*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationList &operator=(VariableDeclarationList &&) = delete;
162*03ce13f7SAndroid Build Coastguard Worker 
163*03ce13f7SAndroid Build Coastguard Worker public:
164*03ce13f7SAndroid Build Coastguard Worker   using VariableDeclarationArray = std::vector<VariableDeclaration *>;
165*03ce13f7SAndroid Build Coastguard Worker 
VariableDeclarationList()166*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationList() : Arena(new ArenaAllocator()) {}
167*03ce13f7SAndroid Build Coastguard Worker 
~VariableDeclarationList()168*03ce13f7SAndroid Build Coastguard Worker   ~VariableDeclarationList() { clearAndPurge(); }
169*03ce13f7SAndroid Build Coastguard Worker 
170*03ce13f7SAndroid Build Coastguard Worker   template <typename T> T *allocate_initializer(SizeT Count = 1) {
171*03ce13f7SAndroid Build Coastguard Worker     static_assert(
172*03ce13f7SAndroid Build Coastguard Worker         std::is_trivially_destructible<T>::value,
173*03ce13f7SAndroid Build Coastguard Worker         "allocate_initializer can only allocate trivially destructible types.");
174*03ce13f7SAndroid Build Coastguard Worker     return Arena->Allocate<T>(Count);
175*03ce13f7SAndroid Build Coastguard Worker   }
176*03ce13f7SAndroid Build Coastguard Worker 
allocate_variable_declaration()177*03ce13f7SAndroid Build Coastguard Worker   template <typename T> T *allocate_variable_declaration() {
178*03ce13f7SAndroid Build Coastguard Worker     static_assert(!std::is_trivially_destructible<T>::value,
179*03ce13f7SAndroid Build Coastguard Worker                   "allocate_variable_declaration expects non-trivially "
180*03ce13f7SAndroid Build Coastguard Worker                   "destructible types.");
181*03ce13f7SAndroid Build Coastguard Worker     T *Ret = Arena->Allocate<T>();
182*03ce13f7SAndroid Build Coastguard Worker     Dtors.emplace_back([Ret]() { Ret->~T(); });
183*03ce13f7SAndroid Build Coastguard Worker     return Ret;
184*03ce13f7SAndroid Build Coastguard Worker   }
185*03ce13f7SAndroid Build Coastguard Worker 
186*03ce13f7SAndroid Build Coastguard Worker   // This do nothing method is invoked when a global variable is created, but it
187*03ce13f7SAndroid Build Coastguard Worker   // will not be emitted. If we ever need to track the created variable, having
188*03ce13f7SAndroid Build Coastguard Worker   // this hook is handy.
willNotBeEmitted(VariableDeclaration *)189*03ce13f7SAndroid Build Coastguard Worker   void willNotBeEmitted(VariableDeclaration *) {}
190*03ce13f7SAndroid Build Coastguard Worker 
191*03ce13f7SAndroid Build Coastguard Worker   /// Merges Other with this, effectively resetting Other to an empty state.
merge(VariableDeclarationList * Other)192*03ce13f7SAndroid Build Coastguard Worker   void merge(VariableDeclarationList *Other) {
193*03ce13f7SAndroid Build Coastguard Worker     assert(Other != nullptr);
194*03ce13f7SAndroid Build Coastguard Worker     addArena(std::move(Other->Arena));
195*03ce13f7SAndroid Build Coastguard Worker     for (std::size_t i = 0; i < Other->MergedArenas.size(); ++i) {
196*03ce13f7SAndroid Build Coastguard Worker       addArena(std::move(Other->MergedArenas[i]));
197*03ce13f7SAndroid Build Coastguard Worker     }
198*03ce13f7SAndroid Build Coastguard Worker     Other->MergedArenas.clear();
199*03ce13f7SAndroid Build Coastguard Worker 
200*03ce13f7SAndroid Build Coastguard Worker     Dtors.insert(Dtors.end(), Other->Dtors.begin(), Other->Dtors.end());
201*03ce13f7SAndroid Build Coastguard Worker     Other->Dtors.clear();
202*03ce13f7SAndroid Build Coastguard Worker 
203*03ce13f7SAndroid Build Coastguard Worker     Globals.insert(Globals.end(), Other->Globals.begin(), Other->Globals.end());
204*03ce13f7SAndroid Build Coastguard Worker     Other->Globals.clear();
205*03ce13f7SAndroid Build Coastguard Worker   }
206*03ce13f7SAndroid Build Coastguard Worker 
207*03ce13f7SAndroid Build Coastguard Worker   /// Destroys all GlobalVariables and initializers that this knows about
208*03ce13f7SAndroid Build Coastguard Worker   /// (including those merged with it), and releases memory.
clearAndPurge()209*03ce13f7SAndroid Build Coastguard Worker   void clearAndPurge() {
210*03ce13f7SAndroid Build Coastguard Worker     if (Arena == nullptr) {
211*03ce13f7SAndroid Build Coastguard Worker       // Arena is only null if this was merged, so we ensure there's no state
212*03ce13f7SAndroid Build Coastguard Worker       // being held by this.
213*03ce13f7SAndroid Build Coastguard Worker       assert(Dtors.empty());
214*03ce13f7SAndroid Build Coastguard Worker       assert(Globals.empty());
215*03ce13f7SAndroid Build Coastguard Worker       assert(MergedArenas.empty());
216*03ce13f7SAndroid Build Coastguard Worker       return;
217*03ce13f7SAndroid Build Coastguard Worker     }
218*03ce13f7SAndroid Build Coastguard Worker     // Invokes destructors in reverse creation order.
219*03ce13f7SAndroid Build Coastguard Worker     for (auto Dtor = Dtors.rbegin(); Dtor != Dtors.rend(); ++Dtor) {
220*03ce13f7SAndroid Build Coastguard Worker       (*Dtor)();
221*03ce13f7SAndroid Build Coastguard Worker     }
222*03ce13f7SAndroid Build Coastguard Worker     Dtors.clear();
223*03ce13f7SAndroid Build Coastguard Worker     Globals.clear();
224*03ce13f7SAndroid Build Coastguard Worker     MergedArenas.clear();
225*03ce13f7SAndroid Build Coastguard Worker     Arena->Reset();
226*03ce13f7SAndroid Build Coastguard Worker   }
227*03ce13f7SAndroid Build Coastguard Worker 
228*03ce13f7SAndroid Build Coastguard Worker   /// Adapt the relevant parts of the std::vector<VariableDeclaration *>
229*03ce13f7SAndroid Build Coastguard Worker   /// interface.
230*03ce13f7SAndroid Build Coastguard Worker   /// @{
begin()231*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationArray::iterator begin() { return Globals.begin(); }
232*03ce13f7SAndroid Build Coastguard Worker 
end()233*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationArray::iterator end() { return Globals.end(); }
234*03ce13f7SAndroid Build Coastguard Worker 
begin()235*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationArray::const_iterator begin() const {
236*03ce13f7SAndroid Build Coastguard Worker     return Globals.begin();
237*03ce13f7SAndroid Build Coastguard Worker   }
238*03ce13f7SAndroid Build Coastguard Worker 
end()239*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationArray::const_iterator end() const { return Globals.end(); }
240*03ce13f7SAndroid Build Coastguard Worker 
empty()241*03ce13f7SAndroid Build Coastguard Worker   bool empty() const { return Globals.empty(); }
242*03ce13f7SAndroid Build Coastguard Worker 
size()243*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationArray::size_type size() const { return Globals.size(); }
244*03ce13f7SAndroid Build Coastguard Worker 
245*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationArray::reference
at(VariableDeclarationArray::size_type Pos)246*03ce13f7SAndroid Build Coastguard Worker   at(VariableDeclarationArray::size_type Pos) {
247*03ce13f7SAndroid Build Coastguard Worker     return Globals.at(Pos);
248*03ce13f7SAndroid Build Coastguard Worker   }
249*03ce13f7SAndroid Build Coastguard Worker 
push_back(VariableDeclaration * Global)250*03ce13f7SAndroid Build Coastguard Worker   void push_back(VariableDeclaration *Global) { Globals.push_back(Global); }
251*03ce13f7SAndroid Build Coastguard Worker 
reserve(VariableDeclarationArray::size_type Capacity)252*03ce13f7SAndroid Build Coastguard Worker   void reserve(VariableDeclarationArray::size_type Capacity) {
253*03ce13f7SAndroid Build Coastguard Worker     Globals.reserve(Capacity);
254*03ce13f7SAndroid Build Coastguard Worker   }
255*03ce13f7SAndroid Build Coastguard Worker 
clear()256*03ce13f7SAndroid Build Coastguard Worker   void clear() { Globals.clear(); }
257*03ce13f7SAndroid Build Coastguard Worker 
back()258*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationArray::reference back() { return Globals.back(); }
259*03ce13f7SAndroid Build Coastguard Worker   /// @}
260*03ce13f7SAndroid Build Coastguard Worker 
261*03ce13f7SAndroid Build Coastguard Worker private:
262*03ce13f7SAndroid Build Coastguard Worker   using ArenaPtr = std::unique_ptr<ArenaAllocator>;
263*03ce13f7SAndroid Build Coastguard Worker   using DestructorsArray = std::vector<std::function<void()>>;
264*03ce13f7SAndroid Build Coastguard Worker 
addArena(ArenaPtr NewArena)265*03ce13f7SAndroid Build Coastguard Worker   void addArena(ArenaPtr NewArena) {
266*03ce13f7SAndroid Build Coastguard Worker     MergedArenas.emplace_back(std::move(NewArena));
267*03ce13f7SAndroid Build Coastguard Worker   }
268*03ce13f7SAndroid Build Coastguard Worker 
269*03ce13f7SAndroid Build Coastguard Worker   ArenaPtr Arena;
270*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationArray Globals;
271*03ce13f7SAndroid Build Coastguard Worker   DestructorsArray Dtors;
272*03ce13f7SAndroid Build Coastguard Worker   std::vector<ArenaPtr> MergedArenas;
273*03ce13f7SAndroid Build Coastguard Worker };
274*03ce13f7SAndroid Build Coastguard Worker 
275*03ce13f7SAndroid Build Coastguard Worker /// InstNumberT is for holding an instruction number. Instruction numbers are
276*03ce13f7SAndroid Build Coastguard Worker /// used for representing Variable live ranges.
277*03ce13f7SAndroid Build Coastguard Worker using InstNumberT = int32_t;
278*03ce13f7SAndroid Build Coastguard Worker 
279*03ce13f7SAndroid Build Coastguard Worker /// A LiveBeginEndMapEntry maps a Variable::Number value to an Inst::Number
280*03ce13f7SAndroid Build Coastguard Worker /// value, giving the instruction number that begins or ends a variable's live
281*03ce13f7SAndroid Build Coastguard Worker /// range.
282*03ce13f7SAndroid Build Coastguard Worker template <typename T>
283*03ce13f7SAndroid Build Coastguard Worker using LivenessVector = std::vector<T, LivenessAllocator<T>>;
284*03ce13f7SAndroid Build Coastguard Worker using LiveBeginEndMapEntry = std::pair<SizeT, InstNumberT>;
285*03ce13f7SAndroid Build Coastguard Worker using LiveBeginEndMap = LivenessVector<LiveBeginEndMapEntry>;
286*03ce13f7SAndroid Build Coastguard Worker using LivenessBV = BitVectorTmpl<LivenessAllocator>;
287*03ce13f7SAndroid Build Coastguard Worker 
288*03ce13f7SAndroid Build Coastguard Worker using TimerStackIdT = uint32_t;
289*03ce13f7SAndroid Build Coastguard Worker using TimerIdT = uint32_t;
290*03ce13f7SAndroid Build Coastguard Worker 
291*03ce13f7SAndroid Build Coastguard Worker /// Use alignas(MaxCacheLineSize) to isolate variables/fields that might be
292*03ce13f7SAndroid Build Coastguard Worker /// contended while multithreading. Assumes the maximum cache line size is 64.
293*03ce13f7SAndroid Build Coastguard Worker enum { MaxCacheLineSize = 64 };
294*03ce13f7SAndroid Build Coastguard Worker // Use ICE_CACHELINE_BOUNDARY to force the next field in a declaration
295*03ce13f7SAndroid Build Coastguard Worker // list to be aligned to the next cache line.
296*03ce13f7SAndroid Build Coastguard Worker #if defined(_MSC_VER)
297*03ce13f7SAndroid Build Coastguard Worker #define ICE_CACHELINE_BOUNDARY __declspec(align(MaxCacheLineSize)) int : 0;
298*03ce13f7SAndroid Build Coastguard Worker #else // !defined(_MSC_VER)
299*03ce13f7SAndroid Build Coastguard Worker // Note: zero is added to work around the following GCC 4.8 bug (fixed in 4.9):
300*03ce13f7SAndroid Build Coastguard Worker //       https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55382
301*03ce13f7SAndroid Build Coastguard Worker #define ICE_CACHELINE_BOUNDARY                                                 \
302*03ce13f7SAndroid Build Coastguard Worker   __attribute__((aligned(MaxCacheLineSize + 0))) int : 0
303*03ce13f7SAndroid Build Coastguard Worker #endif // !defined(_MSC_VER)
304*03ce13f7SAndroid Build Coastguard Worker 
305*03ce13f7SAndroid Build Coastguard Worker using RelocOffsetT = int32_t;
306*03ce13f7SAndroid Build Coastguard Worker enum { RelocAddrSize = 4 };
307*03ce13f7SAndroid Build Coastguard Worker 
308*03ce13f7SAndroid Build Coastguard Worker enum LivenessMode {
309*03ce13f7SAndroid Build Coastguard Worker   /// Basic version of live-range-end calculation. Marks the last uses of
310*03ce13f7SAndroid Build Coastguard Worker   /// variables based on dataflow analysis. Records the set of live-in and
311*03ce13f7SAndroid Build Coastguard Worker   /// live-out variables for each block. Identifies and deletes dead
312*03ce13f7SAndroid Build Coastguard Worker   /// instructions (primarily stores).
313*03ce13f7SAndroid Build Coastguard Worker   Liveness_Basic,
314*03ce13f7SAndroid Build Coastguard Worker 
315*03ce13f7SAndroid Build Coastguard Worker   /// In addition to Liveness_Basic, also calculate the complete live range for
316*03ce13f7SAndroid Build Coastguard Worker   /// each variable in a form suitable for interference calculation and register
317*03ce13f7SAndroid Build Coastguard Worker   /// allocation.
318*03ce13f7SAndroid Build Coastguard Worker   Liveness_Intervals
319*03ce13f7SAndroid Build Coastguard Worker };
320*03ce13f7SAndroid Build Coastguard Worker 
321*03ce13f7SAndroid Build Coastguard Worker enum LCSEOptions {
322*03ce13f7SAndroid Build Coastguard Worker   LCSE_Disabled,
323*03ce13f7SAndroid Build Coastguard Worker   LCSE_EnabledSSA,  // Default Mode, assumes SSA.
324*03ce13f7SAndroid Build Coastguard Worker   LCSE_EnabledNoSSA // Does not assume SSA, to be enabled if CSE is done later.
325*03ce13f7SAndroid Build Coastguard Worker };
326*03ce13f7SAndroid Build Coastguard Worker 
327*03ce13f7SAndroid Build Coastguard Worker enum RegAllocKind {
328*03ce13f7SAndroid Build Coastguard Worker   RAK_Unknown,
329*03ce13f7SAndroid Build Coastguard Worker   RAK_Global,       /// full, global register allocation
330*03ce13f7SAndroid Build Coastguard Worker   RAK_SecondChance, /// second-chance bin-packing after full regalloc attempt
331*03ce13f7SAndroid Build Coastguard Worker   RAK_Phi,          /// infinite-weight Variables with active spilling/filling
332*03ce13f7SAndroid Build Coastguard Worker   RAK_InfOnly       /// allocation only for infinite-weight Variables
333*03ce13f7SAndroid Build Coastguard Worker };
334*03ce13f7SAndroid Build Coastguard Worker 
335*03ce13f7SAndroid Build Coastguard Worker enum VerboseItem {
336*03ce13f7SAndroid Build Coastguard Worker   IceV_None = 0,
337*03ce13f7SAndroid Build Coastguard Worker   IceV_Instructions = 1 << 0,
338*03ce13f7SAndroid Build Coastguard Worker   IceV_Deleted = 1 << 1,
339*03ce13f7SAndroid Build Coastguard Worker   IceV_InstNumbers = 1 << 2,
340*03ce13f7SAndroid Build Coastguard Worker   IceV_Preds = 1 << 3,
341*03ce13f7SAndroid Build Coastguard Worker   IceV_Succs = 1 << 4,
342*03ce13f7SAndroid Build Coastguard Worker   IceV_Liveness = 1 << 5,
343*03ce13f7SAndroid Build Coastguard Worker   IceV_RegOrigins = 1 << 6,
344*03ce13f7SAndroid Build Coastguard Worker   IceV_LinearScan = 1 << 7,
345*03ce13f7SAndroid Build Coastguard Worker   IceV_Frame = 1 << 8,
346*03ce13f7SAndroid Build Coastguard Worker   IceV_AddrOpt = 1 << 9,
347*03ce13f7SAndroid Build Coastguard Worker   IceV_Folding = 1 << 10,
348*03ce13f7SAndroid Build Coastguard Worker   IceV_RMW = 1 << 11,
349*03ce13f7SAndroid Build Coastguard Worker   IceV_Loop = 1 << 12,
350*03ce13f7SAndroid Build Coastguard Worker   IceV_Mem = 1 << 13,
351*03ce13f7SAndroid Build Coastguard Worker   // Leave some extra space to make it easier to add new per-pass items.
352*03ce13f7SAndroid Build Coastguard Worker   IceV_NO_PER_PASS_DUMP_BEYOND = 1 << 19,
353*03ce13f7SAndroid Build Coastguard Worker   // Items greater than IceV_NO_PER_PASS_DUMP_BEYOND don't by themselves trigger
354*03ce13f7SAndroid Build Coastguard Worker   // per-pass Cfg dump output.
355*03ce13f7SAndroid Build Coastguard Worker   IceV_Status = 1 << 20,
356*03ce13f7SAndroid Build Coastguard Worker   IceV_AvailableRegs = 1 << 21,
357*03ce13f7SAndroid Build Coastguard Worker   IceV_GlobalInit = 1 << 22,
358*03ce13f7SAndroid Build Coastguard Worker   IceV_ConstPoolStats = 1 << 23,
359*03ce13f7SAndroid Build Coastguard Worker   IceV_Wasm = 1 << 24,
360*03ce13f7SAndroid Build Coastguard Worker   IceV_ShufMat = 1 << 25,
361*03ce13f7SAndroid Build Coastguard Worker   IceV_All = ~IceV_None,
362*03ce13f7SAndroid Build Coastguard Worker   IceV_Most =
363*03ce13f7SAndroid Build Coastguard Worker       IceV_All & ~IceV_LinearScan & ~IceV_GlobalInit & ~IceV_ConstPoolStats
364*03ce13f7SAndroid Build Coastguard Worker };
365*03ce13f7SAndroid Build Coastguard Worker using VerboseMask = uint32_t;
366*03ce13f7SAndroid Build Coastguard Worker 
367*03ce13f7SAndroid Build Coastguard Worker enum FileType {
368*03ce13f7SAndroid Build Coastguard Worker   FT_Elf, /// ELF .o file
369*03ce13f7SAndroid Build Coastguard Worker   FT_Asm, /// Assembly .s file
370*03ce13f7SAndroid Build Coastguard Worker   FT_Iasm /// "Integrated assembler" .byte-style .s file
371*03ce13f7SAndroid Build Coastguard Worker };
372*03ce13f7SAndroid Build Coastguard Worker 
373*03ce13f7SAndroid Build Coastguard Worker using Ostream = llvm::raw_ostream;
374*03ce13f7SAndroid Build Coastguard Worker using Fdstream = llvm::raw_fd_ostream;
375*03ce13f7SAndroid Build Coastguard Worker 
376*03ce13f7SAndroid Build Coastguard Worker using GlobalLockType = std::mutex;
377*03ce13f7SAndroid Build Coastguard Worker 
378*03ce13f7SAndroid Build Coastguard Worker /// LockedPtr is an RAII wrapper that allows automatically locked access to a
379*03ce13f7SAndroid Build Coastguard Worker /// given pointer, automatically unlocking it when when the LockedPtr goes out
380*03ce13f7SAndroid Build Coastguard Worker /// of scope.
381*03ce13f7SAndroid Build Coastguard Worker template <typename T> class LockedPtr {
382*03ce13f7SAndroid Build Coastguard Worker   LockedPtr() = delete;
383*03ce13f7SAndroid Build Coastguard Worker   LockedPtr(const LockedPtr &) = delete;
384*03ce13f7SAndroid Build Coastguard Worker   LockedPtr &operator=(const LockedPtr &) = delete;
385*03ce13f7SAndroid Build Coastguard Worker 
386*03ce13f7SAndroid Build Coastguard Worker public:
LockedPtr(T * Value,GlobalLockType * Lock)387*03ce13f7SAndroid Build Coastguard Worker   LockedPtr(T *Value, GlobalLockType *Lock) : Value(Value), Lock(Lock) {
388*03ce13f7SAndroid Build Coastguard Worker     Lock->lock();
389*03ce13f7SAndroid Build Coastguard Worker   }
LockedPtr(LockedPtr && Other)390*03ce13f7SAndroid Build Coastguard Worker   LockedPtr(LockedPtr &&Other) : Value(Other.Value), Lock(Other.Lock) {
391*03ce13f7SAndroid Build Coastguard Worker     Other.Value = nullptr;
392*03ce13f7SAndroid Build Coastguard Worker     Other.Lock = nullptr;
393*03ce13f7SAndroid Build Coastguard Worker   }
~LockedPtr()394*03ce13f7SAndroid Build Coastguard Worker   ~LockedPtr() {
395*03ce13f7SAndroid Build Coastguard Worker     if (Lock != nullptr)
396*03ce13f7SAndroid Build Coastguard Worker       Lock->unlock();
397*03ce13f7SAndroid Build Coastguard Worker   }
398*03ce13f7SAndroid Build Coastguard Worker   T *operator->() const { return Value; }
399*03ce13f7SAndroid Build Coastguard Worker   T &operator*() const { return *Value; }
get()400*03ce13f7SAndroid Build Coastguard Worker   T *get() { return Value; }
401*03ce13f7SAndroid Build Coastguard Worker 
402*03ce13f7SAndroid Build Coastguard Worker private:
403*03ce13f7SAndroid Build Coastguard Worker   T *Value;
404*03ce13f7SAndroid Build Coastguard Worker   GlobalLockType *Lock;
405*03ce13f7SAndroid Build Coastguard Worker };
406*03ce13f7SAndroid Build Coastguard Worker 
407*03ce13f7SAndroid Build Coastguard Worker enum ErrorCodes { EC_None = 0, EC_Args, EC_Bitcode, EC_Translation };
408*03ce13f7SAndroid Build Coastguard Worker 
409*03ce13f7SAndroid Build Coastguard Worker /// Wrapper around std::error_code for allowing multiple errors to be folded
410*03ce13f7SAndroid Build Coastguard Worker /// into one. The current implementation keeps track of the first error, which
411*03ce13f7SAndroid Build Coastguard Worker /// is likely to be the most useful one, and this could be extended to e.g.
412*03ce13f7SAndroid Build Coastguard Worker /// collect a vector of errors.
413*03ce13f7SAndroid Build Coastguard Worker class ErrorCode : public std::error_code {
414*03ce13f7SAndroid Build Coastguard Worker   ErrorCode(const ErrorCode &) = delete;
415*03ce13f7SAndroid Build Coastguard Worker   ErrorCode &operator=(const ErrorCode &) = delete;
416*03ce13f7SAndroid Build Coastguard Worker 
417*03ce13f7SAndroid Build Coastguard Worker public:
418*03ce13f7SAndroid Build Coastguard Worker   ErrorCode() = default;
assign(ErrorCodes Code)419*03ce13f7SAndroid Build Coastguard Worker   void assign(ErrorCodes Code) {
420*03ce13f7SAndroid Build Coastguard Worker     if (!HasError) {
421*03ce13f7SAndroid Build Coastguard Worker       HasError = true;
422*03ce13f7SAndroid Build Coastguard Worker       std::error_code::assign(Code, std::generic_category());
423*03ce13f7SAndroid Build Coastguard Worker     }
424*03ce13f7SAndroid Build Coastguard Worker   }
assign(int Code)425*03ce13f7SAndroid Build Coastguard Worker   void assign(int Code) { assign(static_cast<ErrorCodes>(Code)); }
426*03ce13f7SAndroid Build Coastguard Worker 
427*03ce13f7SAndroid Build Coastguard Worker private:
428*03ce13f7SAndroid Build Coastguard Worker   bool HasError = false;
429*03ce13f7SAndroid Build Coastguard Worker };
430*03ce13f7SAndroid Build Coastguard Worker 
431*03ce13f7SAndroid Build Coastguard Worker /// Reverse range adaptors written in terms of llvm::make_range().
432*03ce13f7SAndroid Build Coastguard Worker template <typename T>
433*03ce13f7SAndroid Build Coastguard Worker llvm::iterator_range<typename T::const_reverse_iterator>
reverse_range(const T & Container)434*03ce13f7SAndroid Build Coastguard Worker reverse_range(const T &Container) {
435*03ce13f7SAndroid Build Coastguard Worker   return llvm::make_range(Container.rbegin(), Container.rend());
436*03ce13f7SAndroid Build Coastguard Worker }
437*03ce13f7SAndroid Build Coastguard Worker template <typename T>
reverse_range(T & Container)438*03ce13f7SAndroid Build Coastguard Worker llvm::iterator_range<typename T::reverse_iterator> reverse_range(T &Container) {
439*03ce13f7SAndroid Build Coastguard Worker   return llvm::make_range(Container.rbegin(), Container.rend());
440*03ce13f7SAndroid Build Coastguard Worker }
441*03ce13f7SAndroid Build Coastguard Worker 
442*03ce13f7SAndroid Build Coastguard Worker using RelocOffsetArray = llvm::SmallVector<class RelocOffset *, 4>;
443*03ce13f7SAndroid Build Coastguard Worker 
444*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
445*03ce13f7SAndroid Build Coastguard Worker 
446*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICEDEFS_H
447