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