xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceGlobalContext.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceGlobalContext.h - Global context defs -----*- 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 aspects of the compilation that persist across multiple
12*03ce13f7SAndroid Build Coastguard Worker /// functions.
13*03ce13f7SAndroid Build Coastguard Worker ///
14*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*03ce13f7SAndroid Build Coastguard Worker 
16*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICEGLOBALCONTEXT_H
17*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICEGLOBALCONTEXT_H
18*03ce13f7SAndroid Build Coastguard Worker 
19*03ce13f7SAndroid Build Coastguard Worker #include "IceClFlags.h"
20*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h"
21*03ce13f7SAndroid Build Coastguard Worker #include "IceInstrumentation.h"
22*03ce13f7SAndroid Build Coastguard Worker #include "IceIntrinsics.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "IceStringPool.h"
24*03ce13f7SAndroid Build Coastguard Worker #include "IceSwitchLowering.h"
25*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLowering.def"
26*03ce13f7SAndroid Build Coastguard Worker #include "IceThreading.h"
27*03ce13f7SAndroid Build Coastguard Worker #include "IceTimerTree.h"
28*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.h"
29*03ce13f7SAndroid Build Coastguard Worker #include "IceUtils.h"
30*03ce13f7SAndroid Build Coastguard Worker 
31*03ce13f7SAndroid Build Coastguard Worker #include <array>
32*03ce13f7SAndroid Build Coastguard Worker #include <atomic>
33*03ce13f7SAndroid Build Coastguard Worker #include <cassert>
34*03ce13f7SAndroid Build Coastguard Worker #include <functional>
35*03ce13f7SAndroid Build Coastguard Worker #include <memory>
36*03ce13f7SAndroid Build Coastguard Worker #include <mutex>
37*03ce13f7SAndroid Build Coastguard Worker #include <thread>
38*03ce13f7SAndroid Build Coastguard Worker #include <type_traits>
39*03ce13f7SAndroid Build Coastguard Worker #include <utility>
40*03ce13f7SAndroid Build Coastguard Worker #include <vector>
41*03ce13f7SAndroid Build Coastguard Worker 
42*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
43*03ce13f7SAndroid Build Coastguard Worker 
44*03ce13f7SAndroid Build Coastguard Worker class ConstantPool;
45*03ce13f7SAndroid Build Coastguard Worker class EmitterWorkItem;
46*03ce13f7SAndroid Build Coastguard Worker class FuncSigType;
47*03ce13f7SAndroid Build Coastguard Worker class Instrumentation;
48*03ce13f7SAndroid Build Coastguard Worker 
49*03ce13f7SAndroid Build Coastguard Worker // Runtime helper function IDs
50*03ce13f7SAndroid Build Coastguard Worker 
51*03ce13f7SAndroid Build Coastguard Worker enum class RuntimeHelper {
52*03ce13f7SAndroid Build Coastguard Worker #define X(Tag, Name) H_##Tag,
53*03ce13f7SAndroid Build Coastguard Worker   RUNTIME_HELPER_FUNCTIONS_TABLE
54*03ce13f7SAndroid Build Coastguard Worker #undef X
55*03ce13f7SAndroid Build Coastguard Worker       H_Num
56*03ce13f7SAndroid Build Coastguard Worker };
57*03ce13f7SAndroid Build Coastguard Worker 
58*03ce13f7SAndroid Build Coastguard Worker /// OptWorkItem is a simple wrapper used to pass parse information on a function
59*03ce13f7SAndroid Build Coastguard Worker /// block, to a translator thread.
60*03ce13f7SAndroid Build Coastguard Worker class OptWorkItem {
61*03ce13f7SAndroid Build Coastguard Worker   OptWorkItem(const OptWorkItem &) = delete;
62*03ce13f7SAndroid Build Coastguard Worker   OptWorkItem &operator=(const OptWorkItem &) = delete;
63*03ce13f7SAndroid Build Coastguard Worker 
64*03ce13f7SAndroid Build Coastguard Worker public:
65*03ce13f7SAndroid Build Coastguard Worker   // Get the Cfg for the funtion to translate.
66*03ce13f7SAndroid Build Coastguard Worker   virtual std::unique_ptr<Cfg> getParsedCfg() = 0;
67*03ce13f7SAndroid Build Coastguard Worker   virtual ~OptWorkItem() = default;
68*03ce13f7SAndroid Build Coastguard Worker 
69*03ce13f7SAndroid Build Coastguard Worker protected:
70*03ce13f7SAndroid Build Coastguard Worker   OptWorkItem() = default;
71*03ce13f7SAndroid Build Coastguard Worker };
72*03ce13f7SAndroid Build Coastguard Worker 
73*03ce13f7SAndroid Build Coastguard Worker class GlobalContext {
74*03ce13f7SAndroid Build Coastguard Worker   GlobalContext() = delete;
75*03ce13f7SAndroid Build Coastguard Worker   GlobalContext(const GlobalContext &) = delete;
76*03ce13f7SAndroid Build Coastguard Worker   GlobalContext &operator=(const GlobalContext &) = delete;
77*03ce13f7SAndroid Build Coastguard Worker 
78*03ce13f7SAndroid Build Coastguard Worker   /// CodeStats collects rudimentary statistics during translation.
79*03ce13f7SAndroid Build Coastguard Worker   class CodeStats {
80*03ce13f7SAndroid Build Coastguard Worker     CodeStats(const CodeStats &) = delete;
81*03ce13f7SAndroid Build Coastguard Worker     CodeStats &operator=(const CodeStats &) = default;
82*03ce13f7SAndroid Build Coastguard Worker #define CODESTATS_TABLE                                                        \
83*03ce13f7SAndroid Build Coastguard Worker   /* dump string, enum value */                                                \
84*03ce13f7SAndroid Build Coastguard Worker   X("Inst Count  ", InstCount)                                                 \
85*03ce13f7SAndroid Build Coastguard Worker   X("Regs Saved  ", RegsSaved)                                                 \
86*03ce13f7SAndroid Build Coastguard Worker   X("Frame Bytes ", FrameByte)                                                 \
87*03ce13f7SAndroid Build Coastguard Worker   X("Spills      ", NumSpills)                                                 \
88*03ce13f7SAndroid Build Coastguard Worker   X("Fills       ", NumFills)                                                  \
89*03ce13f7SAndroid Build Coastguard Worker   X("R/P Imms    ", NumRPImms)
90*03ce13f7SAndroid Build Coastguard Worker     //#define X(str, tag)
91*03ce13f7SAndroid Build Coastguard Worker 
92*03ce13f7SAndroid Build Coastguard Worker   public:
93*03ce13f7SAndroid Build Coastguard Worker     enum CSTag {
94*03ce13f7SAndroid Build Coastguard Worker #define X(str, tag) CS_##tag,
95*03ce13f7SAndroid Build Coastguard Worker       CODESTATS_TABLE
96*03ce13f7SAndroid Build Coastguard Worker #undef X
97*03ce13f7SAndroid Build Coastguard Worker           CS_NUM
98*03ce13f7SAndroid Build Coastguard Worker     };
CodeStats()99*03ce13f7SAndroid Build Coastguard Worker     CodeStats() { reset(); }
reset()100*03ce13f7SAndroid Build Coastguard Worker     void reset() { Stats.fill(0); }
101*03ce13f7SAndroid Build Coastguard Worker     void update(CSTag Tag, uint32_t Count = 1) {
102*03ce13f7SAndroid Build Coastguard Worker       assert(static_cast<SizeT>(Tag) < Stats.size());
103*03ce13f7SAndroid Build Coastguard Worker       Stats[Tag] += Count;
104*03ce13f7SAndroid Build Coastguard Worker     }
add(const CodeStats & Other)105*03ce13f7SAndroid Build Coastguard Worker     void add(const CodeStats &Other) {
106*03ce13f7SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < Stats.size(); ++i)
107*03ce13f7SAndroid Build Coastguard Worker         Stats[i] += Other.Stats[i];
108*03ce13f7SAndroid Build Coastguard Worker     }
109*03ce13f7SAndroid Build Coastguard Worker     /// Dumps the stats for the given Cfg.  If Func==nullptr, it identifies it
110*03ce13f7SAndroid Build Coastguard Worker     /// as the "final" cumulative stats instead as a specific function's name.
111*03ce13f7SAndroid Build Coastguard Worker     void dump(const Cfg *Func, GlobalContext *Ctx);
112*03ce13f7SAndroid Build Coastguard Worker 
113*03ce13f7SAndroid Build Coastguard Worker   private:
114*03ce13f7SAndroid Build Coastguard Worker     std::array<uint32_t, CS_NUM> Stats;
115*03ce13f7SAndroid Build Coastguard Worker   };
116*03ce13f7SAndroid Build Coastguard Worker 
117*03ce13f7SAndroid Build Coastguard Worker   /// TimerList is a vector of TimerStack objects, with extra methods
118*03ce13f7SAndroid Build Coastguard Worker   /// to initialize and merge these vectors.
119*03ce13f7SAndroid Build Coastguard Worker   class TimerList : public std::vector<TimerStack> {
120*03ce13f7SAndroid Build Coastguard Worker     TimerList(const TimerList &) = delete;
121*03ce13f7SAndroid Build Coastguard Worker     TimerList &operator=(const TimerList &) = delete;
122*03ce13f7SAndroid Build Coastguard Worker 
123*03ce13f7SAndroid Build Coastguard Worker   public:
124*03ce13f7SAndroid Build Coastguard Worker     TimerList() = default;
125*03ce13f7SAndroid Build Coastguard Worker     /// initInto() initializes a target list of timers based on the
126*03ce13f7SAndroid Build Coastguard Worker     /// current list.  In particular, it creates the same number of
127*03ce13f7SAndroid Build Coastguard Worker     /// timers, in the same order, with the same names, but initially
128*03ce13f7SAndroid Build Coastguard Worker     /// empty of timing data.
initInto(TimerList & Dest)129*03ce13f7SAndroid Build Coastguard Worker     void initInto(TimerList &Dest) const {
130*03ce13f7SAndroid Build Coastguard Worker       if (!BuildDefs::timers())
131*03ce13f7SAndroid Build Coastguard Worker         return;
132*03ce13f7SAndroid Build Coastguard Worker       Dest.clear();
133*03ce13f7SAndroid Build Coastguard Worker       for (const TimerStack &Stack : *this) {
134*03ce13f7SAndroid Build Coastguard Worker         Dest.push_back(TimerStack(Stack.getName()));
135*03ce13f7SAndroid Build Coastguard Worker       }
136*03ce13f7SAndroid Build Coastguard Worker     }
mergeFrom(TimerList & Src)137*03ce13f7SAndroid Build Coastguard Worker     void mergeFrom(TimerList &Src) {
138*03ce13f7SAndroid Build Coastguard Worker       if (!BuildDefs::timers())
139*03ce13f7SAndroid Build Coastguard Worker         return;
140*03ce13f7SAndroid Build Coastguard Worker       assert(size() == Src.size());
141*03ce13f7SAndroid Build Coastguard Worker       size_type i = 0;
142*03ce13f7SAndroid Build Coastguard Worker       for (TimerStack &Stack : *this) {
143*03ce13f7SAndroid Build Coastguard Worker         assert(Stack.getName() == Src[i].getName());
144*03ce13f7SAndroid Build Coastguard Worker         Stack.mergeFrom(Src[i]);
145*03ce13f7SAndroid Build Coastguard Worker         ++i;
146*03ce13f7SAndroid Build Coastguard Worker       }
147*03ce13f7SAndroid Build Coastguard Worker     }
148*03ce13f7SAndroid Build Coastguard Worker   };
149*03ce13f7SAndroid Build Coastguard Worker 
150*03ce13f7SAndroid Build Coastguard Worker   /// ThreadContext contains thread-local data.  This data can be
151*03ce13f7SAndroid Build Coastguard Worker   /// combined/reduced as needed after all threads complete.
152*03ce13f7SAndroid Build Coastguard Worker   class ThreadContext {
153*03ce13f7SAndroid Build Coastguard Worker     ThreadContext(const ThreadContext &) = delete;
154*03ce13f7SAndroid Build Coastguard Worker     ThreadContext &operator=(const ThreadContext &) = delete;
155*03ce13f7SAndroid Build Coastguard Worker 
156*03ce13f7SAndroid Build Coastguard Worker   public:
157*03ce13f7SAndroid Build Coastguard Worker     ThreadContext() = default;
158*03ce13f7SAndroid Build Coastguard Worker     CodeStats StatsFunction;
159*03ce13f7SAndroid Build Coastguard Worker     CodeStats StatsCumulative;
160*03ce13f7SAndroid Build Coastguard Worker     TimerList Timers;
161*03ce13f7SAndroid Build Coastguard Worker   };
162*03ce13f7SAndroid Build Coastguard Worker 
163*03ce13f7SAndroid Build Coastguard Worker public:
164*03ce13f7SAndroid Build Coastguard Worker   /// The dump stream is a log stream while emit is the stream code
165*03ce13f7SAndroid Build Coastguard Worker   /// is emitted to. The error stream is strictly for logging errors.
166*03ce13f7SAndroid Build Coastguard Worker   GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
167*03ce13f7SAndroid Build Coastguard Worker                 ELFStreamer *ELFStreamer);
168*03ce13f7SAndroid Build Coastguard Worker   ~GlobalContext();
169*03ce13f7SAndroid Build Coastguard Worker 
170*03ce13f7SAndroid Build Coastguard Worker   void dumpStrings();
171*03ce13f7SAndroid Build Coastguard Worker   ///
172*03ce13f7SAndroid Build Coastguard Worker   /// The dump, error, and emit streams need to be used by only one
173*03ce13f7SAndroid Build Coastguard Worker   /// thread at a time.  This is done by exclusively reserving the
174*03ce13f7SAndroid Build Coastguard Worker   /// streams via lockStr() and unlockStr().  The OstreamLocker class
175*03ce13f7SAndroid Build Coastguard Worker   /// can be used to conveniently manage this.
176*03ce13f7SAndroid Build Coastguard Worker   ///
177*03ce13f7SAndroid Build Coastguard Worker   /// The model is that a thread grabs the stream lock, then does an
178*03ce13f7SAndroid Build Coastguard Worker   /// arbitrary amount of work during which far-away callees may grab
179*03ce13f7SAndroid Build Coastguard Worker   /// the stream and do something with it, and finally the thread
180*03ce13f7SAndroid Build Coastguard Worker   /// releases the stream lock.  This allows large chunks of output to
181*03ce13f7SAndroid Build Coastguard Worker   /// be dumped or emitted without risking interleaving from multiple
182*03ce13f7SAndroid Build Coastguard Worker   /// threads.
lockStr()183*03ce13f7SAndroid Build Coastguard Worker   void lockStr() { StrLock.lock(); }
unlockStr()184*03ce13f7SAndroid Build Coastguard Worker   void unlockStr() { StrLock.unlock(); }
getStrDump()185*03ce13f7SAndroid Build Coastguard Worker   Ostream &getStrDump() { return *StrDump; }
getStrError()186*03ce13f7SAndroid Build Coastguard Worker   Ostream &getStrError() { return *StrError; }
getStrEmit()187*03ce13f7SAndroid Build Coastguard Worker   Ostream &getStrEmit() { return *StrEmit; }
setStrEmit(Ostream & NewStrEmit)188*03ce13f7SAndroid Build Coastguard Worker   void setStrEmit(Ostream &NewStrEmit) { StrEmit = &NewStrEmit; }
189*03ce13f7SAndroid Build Coastguard Worker 
getErrorStatus()190*03ce13f7SAndroid Build Coastguard Worker   LockedPtr<ErrorCode> getErrorStatus() {
191*03ce13f7SAndroid Build Coastguard Worker     return LockedPtr<ErrorCode>(&ErrorStatus, &ErrorStatusLock);
192*03ce13f7SAndroid Build Coastguard Worker   }
193*03ce13f7SAndroid Build Coastguard Worker 
194*03ce13f7SAndroid Build Coastguard Worker   /// \name Manage Constants.
195*03ce13f7SAndroid Build Coastguard Worker   /// @{
196*03ce13f7SAndroid Build Coastguard Worker   // getConstant*() functions are not const because they might add something to
197*03ce13f7SAndroid Build Coastguard Worker   // the constant pool.
198*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantInt(Type Ty, int64_t Value);
getConstantInt1(int8_t ConstantInt1)199*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantInt1(int8_t ConstantInt1) {
200*03ce13f7SAndroid Build Coastguard Worker     ConstantInt1 &= INT8_C(1);
201*03ce13f7SAndroid Build Coastguard Worker     switch (ConstantInt1) {
202*03ce13f7SAndroid Build Coastguard Worker     case 0:
203*03ce13f7SAndroid Build Coastguard Worker       return getConstantZero(IceType_i1);
204*03ce13f7SAndroid Build Coastguard Worker     case 1:
205*03ce13f7SAndroid Build Coastguard Worker       return ConstantTrue;
206*03ce13f7SAndroid Build Coastguard Worker     default:
207*03ce13f7SAndroid Build Coastguard Worker       assert(false && "getConstantInt1 not on true/false");
208*03ce13f7SAndroid Build Coastguard Worker       return getConstantInt1Internal(ConstantInt1);
209*03ce13f7SAndroid Build Coastguard Worker     }
210*03ce13f7SAndroid Build Coastguard Worker   }
getConstantInt8(int8_t ConstantInt8)211*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantInt8(int8_t ConstantInt8) {
212*03ce13f7SAndroid Build Coastguard Worker     switch (ConstantInt8) {
213*03ce13f7SAndroid Build Coastguard Worker     case 0:
214*03ce13f7SAndroid Build Coastguard Worker       return getConstantZero(IceType_i8);
215*03ce13f7SAndroid Build Coastguard Worker     default:
216*03ce13f7SAndroid Build Coastguard Worker       return getConstantInt8Internal(ConstantInt8);
217*03ce13f7SAndroid Build Coastguard Worker     }
218*03ce13f7SAndroid Build Coastguard Worker   }
getConstantInt16(int16_t ConstantInt16)219*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantInt16(int16_t ConstantInt16) {
220*03ce13f7SAndroid Build Coastguard Worker     switch (ConstantInt16) {
221*03ce13f7SAndroid Build Coastguard Worker     case 0:
222*03ce13f7SAndroid Build Coastguard Worker       return getConstantZero(IceType_i16);
223*03ce13f7SAndroid Build Coastguard Worker     default:
224*03ce13f7SAndroid Build Coastguard Worker       return getConstantInt16Internal(ConstantInt16);
225*03ce13f7SAndroid Build Coastguard Worker     }
226*03ce13f7SAndroid Build Coastguard Worker   }
getConstantInt32(int32_t ConstantInt32)227*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantInt32(int32_t ConstantInt32) {
228*03ce13f7SAndroid Build Coastguard Worker     switch (ConstantInt32) {
229*03ce13f7SAndroid Build Coastguard Worker     case 0:
230*03ce13f7SAndroid Build Coastguard Worker       return getConstantZero(IceType_i32);
231*03ce13f7SAndroid Build Coastguard Worker     default:
232*03ce13f7SAndroid Build Coastguard Worker       return getConstantInt32Internal(ConstantInt32);
233*03ce13f7SAndroid Build Coastguard Worker     }
234*03ce13f7SAndroid Build Coastguard Worker   }
getConstantInt64(int64_t ConstantInt64)235*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantInt64(int64_t ConstantInt64) {
236*03ce13f7SAndroid Build Coastguard Worker     switch (ConstantInt64) {
237*03ce13f7SAndroid Build Coastguard Worker     case 0:
238*03ce13f7SAndroid Build Coastguard Worker       return getConstantZero(IceType_i64);
239*03ce13f7SAndroid Build Coastguard Worker     default:
240*03ce13f7SAndroid Build Coastguard Worker       return getConstantInt64Internal(ConstantInt64);
241*03ce13f7SAndroid Build Coastguard Worker     }
242*03ce13f7SAndroid Build Coastguard Worker   }
243*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantFloat(float Value);
244*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantDouble(double Value);
245*03ce13f7SAndroid Build Coastguard Worker   /// Returns a symbolic constant.
246*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantSymWithEmitString(const RelocOffsetT Offset,
247*03ce13f7SAndroid Build Coastguard Worker                                          const RelocOffsetArray &OffsetExpr,
248*03ce13f7SAndroid Build Coastguard Worker                                          GlobalString Name,
249*03ce13f7SAndroid Build Coastguard Worker                                          const std::string &EmitString);
250*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantSym(RelocOffsetT Offset, GlobalString Name);
251*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantExternSym(GlobalString Name);
252*03ce13f7SAndroid Build Coastguard Worker   /// Returns an undef.
253*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantUndef(Type Ty);
254*03ce13f7SAndroid Build Coastguard Worker   /// Returns a zero value.
255*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantZero(Type Ty);
256*03ce13f7SAndroid Build Coastguard Worker   /// getConstantPool() returns a copy of the constant pool for constants of a
257*03ce13f7SAndroid Build Coastguard Worker   /// given type.
258*03ce13f7SAndroid Build Coastguard Worker   ConstantList getConstantPool(Type Ty);
259*03ce13f7SAndroid Build Coastguard Worker   /// Returns a copy of the list of external symbols.
260*03ce13f7SAndroid Build Coastguard Worker   ConstantList getConstantExternSyms();
261*03ce13f7SAndroid Build Coastguard Worker   /// @}
getRuntimeHelperFunc(RuntimeHelper FuncID)262*03ce13f7SAndroid Build Coastguard Worker   Constant *getRuntimeHelperFunc(RuntimeHelper FuncID) const {
263*03ce13f7SAndroid Build Coastguard Worker     assert(FuncID < RuntimeHelper::H_Num);
264*03ce13f7SAndroid Build Coastguard Worker     Constant *Result = RuntimeHelperFunc[static_cast<size_t>(FuncID)];
265*03ce13f7SAndroid Build Coastguard Worker     assert(Result != nullptr && "No such runtime helper function");
266*03ce13f7SAndroid Build Coastguard Worker     return Result;
267*03ce13f7SAndroid Build Coastguard Worker   }
268*03ce13f7SAndroid Build Coastguard Worker   GlobalString getGlobalString(const std::string &Name);
269*03ce13f7SAndroid Build Coastguard Worker 
270*03ce13f7SAndroid Build Coastguard Worker   /// Return a locked pointer to the registered jump tables.
271*03ce13f7SAndroid Build Coastguard Worker   JumpTableDataList getJumpTables();
272*03ce13f7SAndroid Build Coastguard Worker   /// Adds JumpTable to the list of know jump tables, for a posteriori emission.
273*03ce13f7SAndroid Build Coastguard Worker   void addJumpTableData(JumpTableData JumpTable);
274*03ce13f7SAndroid Build Coastguard Worker 
275*03ce13f7SAndroid Build Coastguard Worker   /// Allocate data of type T using the global allocator. We allow entities
276*03ce13f7SAndroid Build Coastguard Worker   /// allocated from this global allocator to be either trivially or
277*03ce13f7SAndroid Build Coastguard Worker   /// non-trivially destructible. We optimize the case when T is trivially
278*03ce13f7SAndroid Build Coastguard Worker   /// destructible by not registering a destructor. Destructors will be invoked
279*03ce13f7SAndroid Build Coastguard Worker   /// during GlobalContext destruction in the reverse object creation order.
280*03ce13f7SAndroid Build Coastguard Worker   template <typename T>
281*03ce13f7SAndroid Build Coastguard Worker   typename std::enable_if<std::is_trivially_destructible<T>::value, T>::type *
allocate()282*03ce13f7SAndroid Build Coastguard Worker   allocate() {
283*03ce13f7SAndroid Build Coastguard Worker     return getAllocator()->Allocate<T>();
284*03ce13f7SAndroid Build Coastguard Worker   }
285*03ce13f7SAndroid Build Coastguard Worker 
286*03ce13f7SAndroid Build Coastguard Worker   template <typename T>
287*03ce13f7SAndroid Build Coastguard Worker   typename std::enable_if<!std::is_trivially_destructible<T>::value, T>::type *
allocate()288*03ce13f7SAndroid Build Coastguard Worker   allocate() {
289*03ce13f7SAndroid Build Coastguard Worker     T *Ret = getAllocator()->Allocate<T>();
290*03ce13f7SAndroid Build Coastguard Worker     getDestructors()->emplace_back([Ret]() { Ret->~T(); });
291*03ce13f7SAndroid Build Coastguard Worker     return Ret;
292*03ce13f7SAndroid Build Coastguard Worker   }
293*03ce13f7SAndroid Build Coastguard Worker 
getObjectWriter()294*03ce13f7SAndroid Build Coastguard Worker   ELFObjectWriter *getObjectWriter() const { return ObjectWriter.get(); }
295*03ce13f7SAndroid Build Coastguard Worker 
296*03ce13f7SAndroid Build Coastguard Worker   /// Reset stats at the beginning of a function.
297*03ce13f7SAndroid Build Coastguard Worker   void resetStats();
298*03ce13f7SAndroid Build Coastguard Worker   void dumpStats(const Cfg *Func = nullptr);
299*03ce13f7SAndroid Build Coastguard Worker   void statsUpdateEmitted(uint32_t InstCount);
300*03ce13f7SAndroid Build Coastguard Worker   void statsUpdateRegistersSaved(uint32_t Num);
301*03ce13f7SAndroid Build Coastguard Worker   void statsUpdateFrameBytes(uint32_t Bytes);
302*03ce13f7SAndroid Build Coastguard Worker   void statsUpdateSpills();
303*03ce13f7SAndroid Build Coastguard Worker   void statsUpdateFills();
304*03ce13f7SAndroid Build Coastguard Worker 
305*03ce13f7SAndroid Build Coastguard Worker   /// Number of Randomized or Pooled Immediates
306*03ce13f7SAndroid Build Coastguard Worker   void statsUpdateRPImms();
307*03ce13f7SAndroid Build Coastguard Worker 
308*03ce13f7SAndroid Build Coastguard Worker   /// These are predefined TimerStackIdT values.
309*03ce13f7SAndroid Build Coastguard Worker   enum TimerStackKind { TSK_Default = 0, TSK_Funcs, TSK_Num };
310*03ce13f7SAndroid Build Coastguard Worker 
311*03ce13f7SAndroid Build Coastguard Worker   /// newTimerStackID() creates a new TimerStack in the global space. It does
312*03ce13f7SAndroid Build Coastguard Worker   /// not affect any TimerStack objects in TLS.
313*03ce13f7SAndroid Build Coastguard Worker   TimerStackIdT newTimerStackID(const std::string &Name);
314*03ce13f7SAndroid Build Coastguard Worker   /// dumpTimers() dumps the global timer data.  This assumes all the
315*03ce13f7SAndroid Build Coastguard Worker   /// thread-local copies of timer data have been merged into the global timer
316*03ce13f7SAndroid Build Coastguard Worker   /// data.
317*03ce13f7SAndroid Build Coastguard Worker   void dumpTimers(TimerStackIdT StackID = TSK_Default,
318*03ce13f7SAndroid Build Coastguard Worker                   bool DumpCumulative = true);
319*03ce13f7SAndroid Build Coastguard Worker   void dumpLocalTimers(const std::string &TimerNameOverride,
320*03ce13f7SAndroid Build Coastguard Worker                        TimerStackIdT StackID = TSK_Default,
321*03ce13f7SAndroid Build Coastguard Worker                        bool DumpCumulative = true);
322*03ce13f7SAndroid Build Coastguard Worker   /// The following methods affect only the calling thread's TLS timer data.
323*03ce13f7SAndroid Build Coastguard Worker   TimerIdT getTimerID(TimerStackIdT StackID, const std::string &Name);
324*03ce13f7SAndroid Build Coastguard Worker   void pushTimer(TimerIdT ID, TimerStackIdT StackID);
325*03ce13f7SAndroid Build Coastguard Worker   void popTimer(TimerIdT ID, TimerStackIdT StackID);
326*03ce13f7SAndroid Build Coastguard Worker   void resetTimer(TimerStackIdT StackID);
327*03ce13f7SAndroid Build Coastguard Worker   std::string getTimerName(TimerStackIdT StackID);
328*03ce13f7SAndroid Build Coastguard Worker   void setTimerName(TimerStackIdT StackID, const std::string &NewName);
329*03ce13f7SAndroid Build Coastguard Worker 
330*03ce13f7SAndroid Build Coastguard Worker   /// This is the first work item sequence number that the parser produces, and
331*03ce13f7SAndroid Build Coastguard Worker   /// correspondingly the first sequence number that the emitter thread will
332*03ce13f7SAndroid Build Coastguard Worker   /// wait for. Start numbering at 1 to leave room for a sentinel, in case e.g.
333*03ce13f7SAndroid Build Coastguard Worker   /// we wish to inject items with a special sequence number that may be
334*03ce13f7SAndroid Build Coastguard Worker   /// executed out of order.
getFirstSequenceNumber()335*03ce13f7SAndroid Build Coastguard Worker   static constexpr uint32_t getFirstSequenceNumber() { return 1; }
336*03ce13f7SAndroid Build Coastguard Worker   /// Adds a newly parsed and constructed function to the Cfg work queue.
337*03ce13f7SAndroid Build Coastguard Worker   /// Notifies any idle workers that a new function is available for
338*03ce13f7SAndroid Build Coastguard Worker   /// translating. May block if the work queue is too large, in order to control
339*03ce13f7SAndroid Build Coastguard Worker   /// memory footprint.
340*03ce13f7SAndroid Build Coastguard Worker   void optQueueBlockingPush(std::unique_ptr<OptWorkItem> Item);
341*03ce13f7SAndroid Build Coastguard Worker   /// Takes a Cfg from the work queue for translating. May block if the work
342*03ce13f7SAndroid Build Coastguard Worker   /// queue is currently empty. Returns nullptr if there is no more work - the
343*03ce13f7SAndroid Build Coastguard Worker   /// queue is empty and either end() has been called or the Sequential flag was
344*03ce13f7SAndroid Build Coastguard Worker   /// set.
345*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<OptWorkItem> optQueueBlockingPop();
346*03ce13f7SAndroid Build Coastguard Worker   /// Notifies that no more work will be added to the work queue.
optQueueNotifyEnd()347*03ce13f7SAndroid Build Coastguard Worker   void optQueueNotifyEnd() { OptQ.notifyEnd(); }
348*03ce13f7SAndroid Build Coastguard Worker 
349*03ce13f7SAndroid Build Coastguard Worker   /// Emit file header for output file.
350*03ce13f7SAndroid Build Coastguard Worker   void emitFileHeader();
351*03ce13f7SAndroid Build Coastguard Worker 
352*03ce13f7SAndroid Build Coastguard Worker   void lowerConstants();
353*03ce13f7SAndroid Build Coastguard Worker 
354*03ce13f7SAndroid Build Coastguard Worker   void lowerJumpTables();
355*03ce13f7SAndroid Build Coastguard Worker 
356*03ce13f7SAndroid Build Coastguard Worker   /// Emit target specific read-only data sections if any. E.g., for MIPS this
357*03ce13f7SAndroid Build Coastguard Worker   /// generates a .MIPS.abiflags section.
358*03ce13f7SAndroid Build Coastguard Worker   void emitTargetRODataSections();
359*03ce13f7SAndroid Build Coastguard Worker 
360*03ce13f7SAndroid Build Coastguard Worker   void emitQueueBlockingPush(std::unique_ptr<EmitterWorkItem> Item);
361*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<EmitterWorkItem> emitQueueBlockingPop();
emitQueueNotifyEnd()362*03ce13f7SAndroid Build Coastguard Worker   void emitQueueNotifyEnd() { EmitQ.notifyEnd(); }
363*03ce13f7SAndroid Build Coastguard Worker 
364*03ce13f7SAndroid Build Coastguard Worker   void initParserThread();
365*03ce13f7SAndroid Build Coastguard Worker   void startWorkerThreads();
366*03ce13f7SAndroid Build Coastguard Worker 
367*03ce13f7SAndroid Build Coastguard Worker   void waitForWorkerThreads();
368*03ce13f7SAndroid Build Coastguard Worker 
369*03ce13f7SAndroid Build Coastguard Worker   /// sets the instrumentation object to use.
setInstrumentation(std::unique_ptr<Instrumentation> Instr)370*03ce13f7SAndroid Build Coastguard Worker   void setInstrumentation(std::unique_ptr<Instrumentation> Instr) {
371*03ce13f7SAndroid Build Coastguard Worker     if (!BuildDefs::minimal())
372*03ce13f7SAndroid Build Coastguard Worker       Instrumentor = std::move(Instr);
373*03ce13f7SAndroid Build Coastguard Worker   }
374*03ce13f7SAndroid Build Coastguard Worker 
instrumentFunc(Cfg * Func)375*03ce13f7SAndroid Build Coastguard Worker   void instrumentFunc(Cfg *Func) {
376*03ce13f7SAndroid Build Coastguard Worker     if (!BuildDefs::minimal() && Instrumentor)
377*03ce13f7SAndroid Build Coastguard Worker       Instrumentor->instrumentFunc(Func);
378*03ce13f7SAndroid Build Coastguard Worker   }
379*03ce13f7SAndroid Build Coastguard Worker 
380*03ce13f7SAndroid Build Coastguard Worker   /// Translation thread startup routine.
381*03ce13f7SAndroid Build Coastguard Worker   void translateFunctionsWrapper(ThreadContext *MyTLS);
382*03ce13f7SAndroid Build Coastguard Worker   /// Translate functions from the Cfg queue until the queue is empty.
383*03ce13f7SAndroid Build Coastguard Worker   void translateFunctions();
384*03ce13f7SAndroid Build Coastguard Worker 
385*03ce13f7SAndroid Build Coastguard Worker   /// Emitter thread startup routine.
386*03ce13f7SAndroid Build Coastguard Worker   void emitterWrapper(ThreadContext *MyTLS);
387*03ce13f7SAndroid Build Coastguard Worker   /// Emit functions and global initializers from the emitter queue until the
388*03ce13f7SAndroid Build Coastguard Worker   /// queue is empty.
389*03ce13f7SAndroid Build Coastguard Worker   void emitItems();
390*03ce13f7SAndroid Build Coastguard Worker 
391*03ce13f7SAndroid Build Coastguard Worker   /// Uses DataLowering to lower Globals. Side effects:
392*03ce13f7SAndroid Build Coastguard Worker   ///  - discards the initializer list for the global variable in Globals.
393*03ce13f7SAndroid Build Coastguard Worker   ///  - clears the Globals array.
394*03ce13f7SAndroid Build Coastguard Worker   void lowerGlobals(const std::string &SectionSuffix);
395*03ce13f7SAndroid Build Coastguard Worker 
396*03ce13f7SAndroid Build Coastguard Worker   void dumpConstantLookupCounts();
397*03ce13f7SAndroid Build Coastguard Worker 
398*03ce13f7SAndroid Build Coastguard Worker   /// DisposeGlobalVariablesAfterLowering controls whether the memory used by
399*03ce13f7SAndroid Build Coastguard Worker   /// GlobaleVariables can be reclaimed right after they have been lowered.
400*03ce13f7SAndroid Build Coastguard Worker   /// @{
getDisposeGlobalVariablesAfterLowering()401*03ce13f7SAndroid Build Coastguard Worker   bool getDisposeGlobalVariablesAfterLowering() const {
402*03ce13f7SAndroid Build Coastguard Worker     return DisposeGlobalVariablesAfterLowering;
403*03ce13f7SAndroid Build Coastguard Worker   }
404*03ce13f7SAndroid Build Coastguard Worker 
setDisposeGlobalVariablesAfterLowering(bool Value)405*03ce13f7SAndroid Build Coastguard Worker   void setDisposeGlobalVariablesAfterLowering(bool Value) {
406*03ce13f7SAndroid Build Coastguard Worker     DisposeGlobalVariablesAfterLowering = Value;
407*03ce13f7SAndroid Build Coastguard Worker   }
408*03ce13f7SAndroid Build Coastguard Worker   /// @}
409*03ce13f7SAndroid Build Coastguard Worker 
getStrings()410*03ce13f7SAndroid Build Coastguard Worker   LockedPtr<StringPool> getStrings() const {
411*03ce13f7SAndroid Build Coastguard Worker     return LockedPtr<StringPool>(Strings.get(), &StringsLock);
412*03ce13f7SAndroid Build Coastguard Worker   }
413*03ce13f7SAndroid Build Coastguard Worker 
getGlobals()414*03ce13f7SAndroid Build Coastguard Worker   LockedPtr<VariableDeclarationList> getGlobals() {
415*03ce13f7SAndroid Build Coastguard Worker     return LockedPtr<VariableDeclarationList>(&Globals, &InitAllocLock);
416*03ce13f7SAndroid Build Coastguard Worker   }
417*03ce13f7SAndroid Build Coastguard Worker 
418*03ce13f7SAndroid Build Coastguard Worker   /// Number of function blocks that can be queued before waiting for
419*03ce13f7SAndroid Build Coastguard Worker   /// translation
420*03ce13f7SAndroid Build Coastguard Worker   /// threads to consume.
421*03ce13f7SAndroid Build Coastguard Worker   static constexpr size_t MaxOptQSize = 1 << 16;
422*03ce13f7SAndroid Build Coastguard Worker 
423*03ce13f7SAndroid Build Coastguard Worker private:
424*03ce13f7SAndroid Build Coastguard Worker   // Try to ensure mutexes are allocated on separate cache lines.
425*03ce13f7SAndroid Build Coastguard Worker 
426*03ce13f7SAndroid Build Coastguard Worker   // Destructors collaborate with Allocator
427*03ce13f7SAndroid Build Coastguard Worker   ICE_CACHELINE_BOUNDARY;
428*03ce13f7SAndroid Build Coastguard Worker   // Managed by getAllocator()
429*03ce13f7SAndroid Build Coastguard Worker   mutable GlobalLockType AllocLock;
430*03ce13f7SAndroid Build Coastguard Worker   ArenaAllocator Allocator;
431*03ce13f7SAndroid Build Coastguard Worker 
432*03ce13f7SAndroid Build Coastguard Worker   ICE_CACHELINE_BOUNDARY;
433*03ce13f7SAndroid Build Coastguard Worker   // Managed by getInitializerAllocator()
434*03ce13f7SAndroid Build Coastguard Worker   mutable GlobalLockType InitAllocLock;
435*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationList Globals;
436*03ce13f7SAndroid Build Coastguard Worker 
437*03ce13f7SAndroid Build Coastguard Worker   ICE_CACHELINE_BOUNDARY;
438*03ce13f7SAndroid Build Coastguard Worker   // Managed by getDestructors()
439*03ce13f7SAndroid Build Coastguard Worker   using DestructorArray = std::vector<std::function<void()>>;
440*03ce13f7SAndroid Build Coastguard Worker   mutable GlobalLockType DestructorsLock;
441*03ce13f7SAndroid Build Coastguard Worker   DestructorArray Destructors;
442*03ce13f7SAndroid Build Coastguard Worker 
443*03ce13f7SAndroid Build Coastguard Worker   ICE_CACHELINE_BOUNDARY;
444*03ce13f7SAndroid Build Coastguard Worker   // Managed by getStrings()
445*03ce13f7SAndroid Build Coastguard Worker   mutable GlobalLockType StringsLock;
446*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<StringPool> Strings;
447*03ce13f7SAndroid Build Coastguard Worker 
448*03ce13f7SAndroid Build Coastguard Worker   ICE_CACHELINE_BOUNDARY;
449*03ce13f7SAndroid Build Coastguard Worker   // Managed by getConstPool()
450*03ce13f7SAndroid Build Coastguard Worker   mutable GlobalLockType ConstPoolLock;
451*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<ConstantPool> ConstPool;
452*03ce13f7SAndroid Build Coastguard Worker 
453*03ce13f7SAndroid Build Coastguard Worker   ICE_CACHELINE_BOUNDARY;
454*03ce13f7SAndroid Build Coastguard Worker   // Managed by getJumpTableList()
455*03ce13f7SAndroid Build Coastguard Worker   mutable GlobalLockType JumpTablesLock;
456*03ce13f7SAndroid Build Coastguard Worker   JumpTableDataList JumpTableList;
457*03ce13f7SAndroid Build Coastguard Worker 
458*03ce13f7SAndroid Build Coastguard Worker   ICE_CACHELINE_BOUNDARY;
459*03ce13f7SAndroid Build Coastguard Worker   // Managed by getErrorStatus()
460*03ce13f7SAndroid Build Coastguard Worker   mutable GlobalLockType ErrorStatusLock;
461*03ce13f7SAndroid Build Coastguard Worker   ErrorCode ErrorStatus;
462*03ce13f7SAndroid Build Coastguard Worker 
463*03ce13f7SAndroid Build Coastguard Worker   ICE_CACHELINE_BOUNDARY;
464*03ce13f7SAndroid Build Coastguard Worker   // Managed by getStatsCumulative()
465*03ce13f7SAndroid Build Coastguard Worker   mutable GlobalLockType StatsLock;
466*03ce13f7SAndroid Build Coastguard Worker   CodeStats StatsCumulative;
467*03ce13f7SAndroid Build Coastguard Worker 
468*03ce13f7SAndroid Build Coastguard Worker   ICE_CACHELINE_BOUNDARY;
469*03ce13f7SAndroid Build Coastguard Worker   // Managed by getTimers()
470*03ce13f7SAndroid Build Coastguard Worker   mutable GlobalLockType TimerLock;
471*03ce13f7SAndroid Build Coastguard Worker   TimerList Timers;
472*03ce13f7SAndroid Build Coastguard Worker 
473*03ce13f7SAndroid Build Coastguard Worker   ICE_CACHELINE_BOUNDARY;
474*03ce13f7SAndroid Build Coastguard Worker   /// StrLock is a global lock on the dump and emit output streams.
475*03ce13f7SAndroid Build Coastguard Worker   using StrLockType = std::mutex;
476*03ce13f7SAndroid Build Coastguard Worker   StrLockType StrLock;
477*03ce13f7SAndroid Build Coastguard Worker   Ostream *StrDump;  /// Stream for dumping / diagnostics
478*03ce13f7SAndroid Build Coastguard Worker   Ostream *StrEmit;  /// Stream for code emission
479*03ce13f7SAndroid Build Coastguard Worker   Ostream *StrError; /// Stream for logging errors.
480*03ce13f7SAndroid Build Coastguard Worker 
481*03ce13f7SAndroid Build Coastguard Worker   // True if waitForWorkerThreads() has been called.
482*03ce13f7SAndroid Build Coastguard Worker   std::atomic_bool WaitForWorkerThreadsCalled;
483*03ce13f7SAndroid Build Coastguard Worker 
484*03ce13f7SAndroid Build Coastguard Worker   ICE_CACHELINE_BOUNDARY;
485*03ce13f7SAndroid Build Coastguard Worker 
486*03ce13f7SAndroid Build Coastguard Worker   // TODO(jpp): move to EmitterContext.
487*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<ELFObjectWriter> ObjectWriter;
488*03ce13f7SAndroid Build Coastguard Worker   // Value defining when to wake up the main parse thread.
489*03ce13f7SAndroid Build Coastguard Worker   const size_t OptQWakeupSize;
490*03ce13f7SAndroid Build Coastguard Worker   BoundedProducerConsumerQueue<OptWorkItem, MaxOptQSize> OptQ;
491*03ce13f7SAndroid Build Coastguard Worker   BoundedProducerConsumerQueue<EmitterWorkItem> EmitQ;
492*03ce13f7SAndroid Build Coastguard Worker   // DataLowering is only ever used by a single thread at a time (either in
493*03ce13f7SAndroid Build Coastguard Worker   // emitItems(), or in IceCompiler::run before the compilation is over.)
494*03ce13f7SAndroid Build Coastguard Worker   // TODO(jpp): move to EmitterContext.
495*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<TargetDataLowering> DataLowering;
496*03ce13f7SAndroid Build Coastguard Worker   /// If !HasEmittedCode, SubZero will accumulate all Globals (which are "true"
497*03ce13f7SAndroid Build Coastguard Worker   /// program global variables) until the first code WorkItem is seen.
498*03ce13f7SAndroid Build Coastguard Worker   // TODO(jpp): move to EmitterContext.
499*03ce13f7SAndroid Build Coastguard Worker   bool HasSeenCode = false;
500*03ce13f7SAndroid Build Coastguard Worker   // If Instrumentor is not empty then it will be used to instrument globals and
501*03ce13f7SAndroid Build Coastguard Worker   // CFGs.
502*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<Instrumentation> Instrumentor = nullptr;
503*03ce13f7SAndroid Build Coastguard Worker   /// Indicates if global variable declarations can be disposed of right after
504*03ce13f7SAndroid Build Coastguard Worker   /// lowering.
505*03ce13f7SAndroid Build Coastguard Worker   bool DisposeGlobalVariablesAfterLowering = true;
506*03ce13f7SAndroid Build Coastguard Worker   Constant *ConstZeroForType[IceType_NUM];
507*03ce13f7SAndroid Build Coastguard Worker   Constant *ConstantTrue;
508*03ce13f7SAndroid Build Coastguard Worker   // Holds the constants representing each runtime helper function.
509*03ce13f7SAndroid Build Coastguard Worker   Constant *RuntimeHelperFunc[static_cast<size_t>(RuntimeHelper::H_Num)];
510*03ce13f7SAndroid Build Coastguard Worker 
511*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantZeroInternal(Type Ty);
512*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantIntInternal(Type Ty, int64_t Value);
513*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantInt1Internal(int8_t ConstantInt1);
514*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantInt8Internal(int8_t ConstantInt8);
515*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantInt16Internal(int16_t ConstantInt16);
516*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantInt32Internal(int32_t ConstantInt32);
517*03ce13f7SAndroid Build Coastguard Worker   Constant *getConstantInt64Internal(int64_t ConstantInt64);
getAllocator()518*03ce13f7SAndroid Build Coastguard Worker   LockedPtr<ArenaAllocator> getAllocator() {
519*03ce13f7SAndroid Build Coastguard Worker     return LockedPtr<ArenaAllocator>(&Allocator, &AllocLock);
520*03ce13f7SAndroid Build Coastguard Worker   }
getInitializerAllocator()521*03ce13f7SAndroid Build Coastguard Worker   LockedPtr<VariableDeclarationList> getInitializerAllocator() {
522*03ce13f7SAndroid Build Coastguard Worker     return LockedPtr<VariableDeclarationList>(&Globals, &InitAllocLock);
523*03ce13f7SAndroid Build Coastguard Worker   }
getConstPool()524*03ce13f7SAndroid Build Coastguard Worker   LockedPtr<ConstantPool> getConstPool() {
525*03ce13f7SAndroid Build Coastguard Worker     return LockedPtr<ConstantPool>(ConstPool.get(), &ConstPoolLock);
526*03ce13f7SAndroid Build Coastguard Worker   }
getJumpTableList()527*03ce13f7SAndroid Build Coastguard Worker   LockedPtr<JumpTableDataList> getJumpTableList() {
528*03ce13f7SAndroid Build Coastguard Worker     return LockedPtr<JumpTableDataList>(&JumpTableList, &JumpTablesLock);
529*03ce13f7SAndroid Build Coastguard Worker   }
getStatsCumulative()530*03ce13f7SAndroid Build Coastguard Worker   LockedPtr<CodeStats> getStatsCumulative() {
531*03ce13f7SAndroid Build Coastguard Worker     return LockedPtr<CodeStats>(&StatsCumulative, &StatsLock);
532*03ce13f7SAndroid Build Coastguard Worker   }
getTimers()533*03ce13f7SAndroid Build Coastguard Worker   LockedPtr<TimerList> getTimers() {
534*03ce13f7SAndroid Build Coastguard Worker     return LockedPtr<TimerList>(&Timers, &TimerLock);
535*03ce13f7SAndroid Build Coastguard Worker   }
getDestructors()536*03ce13f7SAndroid Build Coastguard Worker   LockedPtr<DestructorArray> getDestructors() {
537*03ce13f7SAndroid Build Coastguard Worker     return LockedPtr<DestructorArray>(&Destructors, &DestructorsLock);
538*03ce13f7SAndroid Build Coastguard Worker   }
539*03ce13f7SAndroid Build Coastguard Worker 
accumulateGlobals(std::unique_ptr<VariableDeclarationList> Globls)540*03ce13f7SAndroid Build Coastguard Worker   void accumulateGlobals(std::unique_ptr<VariableDeclarationList> Globls) {
541*03ce13f7SAndroid Build Coastguard Worker     LockedPtr<VariableDeclarationList> _(&Globals, &InitAllocLock);
542*03ce13f7SAndroid Build Coastguard Worker     if (Globls != nullptr) {
543*03ce13f7SAndroid Build Coastguard Worker       Globals.merge(Globls.get());
544*03ce13f7SAndroid Build Coastguard Worker       if (!BuildDefs::minimal() && Instrumentor != nullptr)
545*03ce13f7SAndroid Build Coastguard Worker         Instrumentor->setHasSeenGlobals();
546*03ce13f7SAndroid Build Coastguard Worker     }
547*03ce13f7SAndroid Build Coastguard Worker   }
548*03ce13f7SAndroid Build Coastguard Worker 
lowerGlobalsIfNoCodeHasBeenSeen()549*03ce13f7SAndroid Build Coastguard Worker   void lowerGlobalsIfNoCodeHasBeenSeen() {
550*03ce13f7SAndroid Build Coastguard Worker     if (HasSeenCode)
551*03ce13f7SAndroid Build Coastguard Worker       return;
552*03ce13f7SAndroid Build Coastguard Worker     constexpr char NoSuffix[] = "";
553*03ce13f7SAndroid Build Coastguard Worker     lowerGlobals(NoSuffix);
554*03ce13f7SAndroid Build Coastguard Worker     HasSeenCode = true;
555*03ce13f7SAndroid Build Coastguard Worker   }
556*03ce13f7SAndroid Build Coastguard Worker 
557*03ce13f7SAndroid Build Coastguard Worker   llvm::SmallVector<ThreadContext *, 128> AllThreadContexts;
558*03ce13f7SAndroid Build Coastguard Worker   llvm::SmallVector<std::thread, 128> TranslationThreads;
559*03ce13f7SAndroid Build Coastguard Worker   llvm::SmallVector<std::thread, 128> EmitterThreads;
560*03ce13f7SAndroid Build Coastguard Worker   // Each thread has its own TLS pointer which is also held in
561*03ce13f7SAndroid Build Coastguard Worker   // AllThreadContexts.
562*03ce13f7SAndroid Build Coastguard Worker   ICE_TLS_DECLARE_FIELD(ThreadContext *, TLS);
563*03ce13f7SAndroid Build Coastguard Worker 
564*03ce13f7SAndroid Build Coastguard Worker public:
565*03ce13f7SAndroid Build Coastguard Worker   static void TlsInit();
566*03ce13f7SAndroid Build Coastguard Worker };
567*03ce13f7SAndroid Build Coastguard Worker 
568*03ce13f7SAndroid Build Coastguard Worker /// Helper class to push and pop a timer marker. The constructor pushes a
569*03ce13f7SAndroid Build Coastguard Worker /// marker, and the destructor pops it. This is for convenient timing of regions
570*03ce13f7SAndroid Build Coastguard Worker /// of code.
571*03ce13f7SAndroid Build Coastguard Worker class TimerMarker {
572*03ce13f7SAndroid Build Coastguard Worker   TimerMarker() = delete;
573*03ce13f7SAndroid Build Coastguard Worker   TimerMarker(const TimerMarker &) = delete;
574*03ce13f7SAndroid Build Coastguard Worker   TimerMarker &operator=(const TimerMarker &) = delete;
575*03ce13f7SAndroid Build Coastguard Worker 
576*03ce13f7SAndroid Build Coastguard Worker public:
577*03ce13f7SAndroid Build Coastguard Worker   TimerMarker(TimerIdT ID, GlobalContext *Ctx,
578*03ce13f7SAndroid Build Coastguard Worker               TimerStackIdT StackID = GlobalContext::TSK_Default)
ID(ID)579*03ce13f7SAndroid Build Coastguard Worker       : ID(ID), Ctx(Ctx), StackID(StackID) {
580*03ce13f7SAndroid Build Coastguard Worker     if (BuildDefs::timers())
581*03ce13f7SAndroid Build Coastguard Worker       push();
582*03ce13f7SAndroid Build Coastguard Worker   }
583*03ce13f7SAndroid Build Coastguard Worker   TimerMarker(TimerIdT ID, const Cfg *Func,
584*03ce13f7SAndroid Build Coastguard Worker               TimerStackIdT StackID = GlobalContext::TSK_Default)
ID(ID)585*03ce13f7SAndroid Build Coastguard Worker       : ID(ID), Ctx(nullptr), StackID(StackID) {
586*03ce13f7SAndroid Build Coastguard Worker     // Ctx gets set at the beginning of pushCfg().
587*03ce13f7SAndroid Build Coastguard Worker     if (BuildDefs::timers())
588*03ce13f7SAndroid Build Coastguard Worker       pushCfg(Func);
589*03ce13f7SAndroid Build Coastguard Worker   }
TimerMarker(GlobalContext * Ctx,const std::string & FuncName)590*03ce13f7SAndroid Build Coastguard Worker   TimerMarker(GlobalContext *Ctx, const std::string &FuncName)
591*03ce13f7SAndroid Build Coastguard Worker       : ID(getTimerIdFromFuncName(Ctx, FuncName)), Ctx(Ctx),
592*03ce13f7SAndroid Build Coastguard Worker         StackID(GlobalContext::TSK_Funcs) {
593*03ce13f7SAndroid Build Coastguard Worker     if (BuildDefs::timers())
594*03ce13f7SAndroid Build Coastguard Worker       push();
595*03ce13f7SAndroid Build Coastguard Worker   }
596*03ce13f7SAndroid Build Coastguard Worker 
~TimerMarker()597*03ce13f7SAndroid Build Coastguard Worker   ~TimerMarker() {
598*03ce13f7SAndroid Build Coastguard Worker     if (BuildDefs::timers() && Active)
599*03ce13f7SAndroid Build Coastguard Worker       Ctx->popTimer(ID, StackID);
600*03ce13f7SAndroid Build Coastguard Worker   }
601*03ce13f7SAndroid Build Coastguard Worker 
602*03ce13f7SAndroid Build Coastguard Worker private:
603*03ce13f7SAndroid Build Coastguard Worker   void push();
604*03ce13f7SAndroid Build Coastguard Worker   void pushCfg(const Cfg *Func);
605*03ce13f7SAndroid Build Coastguard Worker   static TimerIdT getTimerIdFromFuncName(GlobalContext *Ctx,
606*03ce13f7SAndroid Build Coastguard Worker                                          const std::string &FuncName);
607*03ce13f7SAndroid Build Coastguard Worker   const TimerIdT ID;
608*03ce13f7SAndroid Build Coastguard Worker   GlobalContext *Ctx;
609*03ce13f7SAndroid Build Coastguard Worker   const TimerStackIdT StackID;
610*03ce13f7SAndroid Build Coastguard Worker   bool Active = false;
611*03ce13f7SAndroid Build Coastguard Worker };
612*03ce13f7SAndroid Build Coastguard Worker 
613*03ce13f7SAndroid Build Coastguard Worker /// Helper class for locking the streams and then automatically unlocking them.
614*03ce13f7SAndroid Build Coastguard Worker class OstreamLocker {
615*03ce13f7SAndroid Build Coastguard Worker private:
616*03ce13f7SAndroid Build Coastguard Worker   OstreamLocker() = delete;
617*03ce13f7SAndroid Build Coastguard Worker   OstreamLocker(const OstreamLocker &) = delete;
618*03ce13f7SAndroid Build Coastguard Worker   OstreamLocker &operator=(const OstreamLocker &) = delete;
619*03ce13f7SAndroid Build Coastguard Worker 
620*03ce13f7SAndroid Build Coastguard Worker public:
OstreamLocker(GlobalContext * Ctx)621*03ce13f7SAndroid Build Coastguard Worker   explicit OstreamLocker(GlobalContext *Ctx) : Ctx(Ctx) { Ctx->lockStr(); }
~OstreamLocker()622*03ce13f7SAndroid Build Coastguard Worker   ~OstreamLocker() { Ctx->unlockStr(); }
623*03ce13f7SAndroid Build Coastguard Worker 
624*03ce13f7SAndroid Build Coastguard Worker private:
625*03ce13f7SAndroid Build Coastguard Worker   GlobalContext *const Ctx;
626*03ce13f7SAndroid Build Coastguard Worker };
627*03ce13f7SAndroid Build Coastguard Worker 
628*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
629*03ce13f7SAndroid Build Coastguard Worker 
630*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H
631