| OLD | NEW |
| 1 //===- subzero/src/IceGlobalContext.h - Global context defs -----*- C++ -*-===// | 1 //===- subzero/src/IceGlobalContext.h - Global context defs -----*- C++ -*-===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 ThreadContext() = default; | 148 ThreadContext() = default; |
| 149 CodeStats StatsFunction; | 149 CodeStats StatsFunction; |
| 150 CodeStats StatsCumulative; | 150 CodeStats StatsCumulative; |
| 151 TimerList Timers; | 151 TimerList Timers; |
| 152 }; | 152 }; |
| 153 | 153 |
| 154 public: | 154 public: |
| 155 /// The dump stream is a log stream while emit is the stream code | 155 /// The dump stream is a log stream while emit is the stream code |
| 156 /// is emitted to. The error stream is strictly for logging errors. | 156 /// is emitted to. The error stream is strictly for logging errors. |
| 157 GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError, | 157 GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError, |
| 158 ELFStreamer *ELFStreamer, const ClFlags &Flags); | 158 ELFStreamer *ELFStreamer); |
| 159 ~GlobalContext(); | 159 ~GlobalContext(); |
| 160 | 160 |
| 161 /// | 161 /// |
| 162 /// The dump, error, and emit streams need to be used by only one | 162 /// The dump, error, and emit streams need to be used by only one |
| 163 /// thread at a time. This is done by exclusively reserving the | 163 /// thread at a time. This is done by exclusively reserving the |
| 164 /// streams via lockStr() and unlockStr(). The OstreamLocker class | 164 /// streams via lockStr() and unlockStr(). The OstreamLocker class |
| 165 /// can be used to conveniently manage this. | 165 /// can be used to conveniently manage this. |
| 166 /// | 166 /// |
| 167 /// The model is that a thread grabs the stream lock, then does an | 167 /// The model is that a thread grabs the stream lock, then does an |
| 168 /// arbitrary amount of work during which far-away callees may grab | 168 /// arbitrary amount of work during which far-away callees may grab |
| 169 /// the stream and do something with it, and finally the thread | 169 /// the stream and do something with it, and finally the thread |
| 170 /// releases the stream lock. This allows large chunks of output to | 170 /// releases the stream lock. This allows large chunks of output to |
| 171 /// be dumped or emitted without risking interleaving from multiple | 171 /// be dumped or emitted without risking interleaving from multiple |
| 172 /// threads. | 172 /// threads. |
| 173 void lockStr() { StrLock.lock(); } | 173 void lockStr() { StrLock.lock(); } |
| 174 void unlockStr() { StrLock.unlock(); } | 174 void unlockStr() { StrLock.unlock(); } |
| 175 Ostream &getStrDump() { return *StrDump; } | 175 Ostream &getStrDump() { return *StrDump; } |
| 176 Ostream &getStrError() { return *StrError; } | 176 Ostream &getStrError() { return *StrError; } |
| 177 Ostream &getStrEmit() { return *StrEmit; } | 177 Ostream &getStrEmit() { return *StrEmit; } |
| 178 void setStrEmit(Ostream &NewStrEmit) { StrEmit = &NewStrEmit; } | 178 void setStrEmit(Ostream &NewStrEmit) { StrEmit = &NewStrEmit; } |
| 179 | 179 |
| 180 LockedPtr<ErrorCode> getErrorStatus() { | 180 LockedPtr<ErrorCode> getErrorStatus() { |
| 181 return LockedPtr<ErrorCode>(&ErrorStatus, &ErrorStatusLock); | 181 return LockedPtr<ErrorCode>(&ErrorStatus, &ErrorStatusLock); |
| 182 } | 182 } |
| 183 | 183 |
| 184 /// When emitting assembly, we allow a string to be prepended to | |
| 185 /// names of translated functions. This makes it easier to create an | |
| 186 /// execution test against a reference translator like llc, with both | |
| 187 /// translators using the same bitcode as input. | |
| 188 IceString mangleName(const IceString &Name) const; | |
| 189 | |
| 190 /// \name Manage Constants. | 184 /// \name Manage Constants. |
| 191 /// @{ | 185 /// @{ |
| 192 // getConstant*() functions are not const because they might add something to | 186 // getConstant*() functions are not const because they might add something to |
| 193 // the constant pool. | 187 // the constant pool. |
| 194 Constant *getConstantInt(Type Ty, int64_t Value); | 188 Constant *getConstantInt(Type Ty, int64_t Value); |
| 195 Constant *getConstantInt1(int8_t ConstantInt1); | 189 Constant *getConstantInt1(int8_t ConstantInt1); |
| 196 Constant *getConstantInt8(int8_t ConstantInt8); | 190 Constant *getConstantInt8(int8_t ConstantInt8); |
| 197 Constant *getConstantInt16(int16_t ConstantInt16); | 191 Constant *getConstantInt16(int16_t ConstantInt16); |
| 198 Constant *getConstantInt32(int32_t ConstantInt32); | 192 Constant *getConstantInt32(int32_t ConstantInt32); |
| 199 Constant *getConstantInt64(int64_t ConstantInt64); | 193 Constant *getConstantInt64(int64_t ConstantInt64); |
| 200 Constant *getConstantFloat(float Value); | 194 Constant *getConstantFloat(float Value); |
| 201 Constant *getConstantDouble(double Value); | 195 Constant *getConstantDouble(double Value); |
| 202 /// Returns a symbolic constant. | 196 /// Returns a symbolic constant. |
| 203 Constant *getConstantSym(const RelocOffsetT Offset, | 197 Constant *getConstantSym(const RelocOffsetT Offset, |
| 204 const RelocOffsetArray &OffsetExpr, | 198 const RelocOffsetArray &OffsetExpr, |
| 205 const IceString &Name, const IceString &EmitString, | 199 const IceString &Name, const IceString &EmitString); |
| 206 bool SuppressMangling); | 200 Constant *getConstantSym(RelocOffsetT Offset, const IceString &Name); |
| 207 Constant *getConstantSym(RelocOffsetT Offset, const IceString &Name, | |
| 208 bool SuppressMangling); | |
| 209 Constant *getConstantExternSym(const IceString &Name); | 201 Constant *getConstantExternSym(const IceString &Name); |
| 210 /// Returns an undef. | 202 /// Returns an undef. |
| 211 Constant *getConstantUndef(Type Ty); | 203 Constant *getConstantUndef(Type Ty); |
| 212 /// Returns a zero value. | 204 /// Returns a zero value. |
| 213 Constant *getConstantZero(Type Ty); | 205 Constant *getConstantZero(Type Ty); |
| 214 /// getConstantPool() returns a copy of the constant pool for constants of a | 206 /// getConstantPool() returns a copy of the constant pool for constants of a |
| 215 /// given type. | 207 /// given type. |
| 216 ConstantList getConstantPool(Type Ty); | 208 ConstantList getConstantPool(Type Ty); |
| 217 /// Returns a copy of the list of external symbols. | 209 /// Returns a copy of the list of external symbols. |
| 218 ConstantList getConstantExternSyms(); | 210 ConstantList getConstantExternSyms(); |
| 219 /// @} | 211 /// @} |
| 220 | 212 |
| 221 /// Return a locked pointer to the registered jump tables. | 213 /// Return a locked pointer to the registered jump tables. |
| 222 JumpTableDataList getJumpTables(); | 214 JumpTableDataList getJumpTables(); |
| 223 /// Create a new jump table entry and return a reference to it. | 215 /// Create a new jump table entry and return a reference to it. |
| 224 JumpTableData &addJumpTable(IceString FuncName, SizeT Id, | 216 JumpTableData &addJumpTable(const IceString &FuncName, SizeT Id, |
| 225 const JumpTableData::TargetList &TargetList); | 217 const JumpTableData::TargetList &TargetList); |
| 226 | 218 |
| 227 const ClFlags &getFlags() const { return Flags; } | 219 static const ClFlags &getFlags() { return Flags; } |
| 228 | 220 |
| 229 /// Allocate data of type T using the global allocator. We allow entities | 221 /// Allocate data of type T using the global allocator. We allow entities |
| 230 /// allocated from this global allocator to be either trivially or | 222 /// allocated from this global allocator to be either trivially or |
| 231 /// non-trivially destructible. We optimize the case when T is trivially | 223 /// non-trivially destructible. We optimize the case when T is trivially |
| 232 /// destructible by not registering a destructor. Destructors will be invoked | 224 /// destructible by not registering a destructor. Destructors will be invoked |
| 233 /// during GlobalContext destruction in the reverse object creation order. | 225 /// during GlobalContext destruction in the reverse object creation order. |
| 234 template <typename T> | 226 template <typename T> |
| 235 typename std::enable_if<std::is_trivially_destructible<T>::value, T>::type * | 227 typename std::enable_if<std::is_trivially_destructible<T>::value, T>::type * |
| 236 allocate() { | 228 allocate() { |
| 237 return getAllocator()->Allocate<T>(); | 229 return getAllocator()->Allocate<T>(); |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 /// Utility function to match a symbol name against a match string. This is | 423 /// Utility function to match a symbol name against a match string. This is |
| 432 /// used in a few cases where we want to take some action on a particular | 424 /// used in a few cases where we want to take some action on a particular |
| 433 /// function or symbol based on a command-line argument, such as changing the | 425 /// function or symbol based on a command-line argument, such as changing the |
| 434 /// verbose level for a particular function. An empty Match argument means | 426 /// verbose level for a particular function. An empty Match argument means |
| 435 /// match everything. Returns true if there is a match. | 427 /// match everything. Returns true if there is a match. |
| 436 static bool matchSymbolName(const IceString &SymbolName, | 428 static bool matchSymbolName(const IceString &SymbolName, |
| 437 const IceString &Match) { | 429 const IceString &Match) { |
| 438 return Match.empty() || Match == SymbolName; | 430 return Match.empty() || Match == SymbolName; |
| 439 } | 431 } |
| 440 | 432 |
| 433 static ClFlags Flags; |
| 434 static ClFlagsExtra ExtraFlags; |
| 435 |
| 441 private: | 436 private: |
| 442 // Try to ensure mutexes are allocated on separate cache lines. | 437 // Try to ensure mutexes are allocated on separate cache lines. |
| 443 | 438 |
| 444 // Destructors collaborate with Allocator | 439 // Destructors collaborate with Allocator |
| 445 ICE_CACHELINE_BOUNDARY; | 440 ICE_CACHELINE_BOUNDARY; |
| 446 // Managed by getAllocator() | 441 // Managed by getAllocator() |
| 447 GlobalLockType AllocLock; | 442 GlobalLockType AllocLock; |
| 448 ArenaAllocator Allocator; | 443 ArenaAllocator Allocator; |
| 449 | 444 |
| 450 ICE_CACHELINE_BOUNDARY; | 445 ICE_CACHELINE_BOUNDARY; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 /// StrLock is a global lock on the dump and emit output streams. | 477 /// StrLock is a global lock on the dump and emit output streams. |
| 483 using StrLockType = std::mutex; | 478 using StrLockType = std::mutex; |
| 484 StrLockType StrLock; | 479 StrLockType StrLock; |
| 485 Ostream *StrDump; /// Stream for dumping / diagnostics | 480 Ostream *StrDump; /// Stream for dumping / diagnostics |
| 486 Ostream *StrEmit; /// Stream for code emission | 481 Ostream *StrEmit; /// Stream for code emission |
| 487 Ostream *StrError; /// Stream for logging errors. | 482 Ostream *StrError; /// Stream for logging errors. |
| 488 | 483 |
| 489 ICE_CACHELINE_BOUNDARY; | 484 ICE_CACHELINE_BOUNDARY; |
| 490 | 485 |
| 491 Intrinsics IntrinsicsInfo; | 486 Intrinsics IntrinsicsInfo; |
| 492 const ClFlags &Flags; | |
| 493 // TODO(jpp): move to EmitterContext. | 487 // TODO(jpp): move to EmitterContext. |
| 494 std::unique_ptr<ELFObjectWriter> ObjectWriter; | 488 std::unique_ptr<ELFObjectWriter> ObjectWriter; |
| 495 BoundedProducerConsumerQueue<Cfg> OptQ; | 489 BoundedProducerConsumerQueue<Cfg> OptQ; |
| 496 BoundedProducerConsumerQueue<EmitterWorkItem> EmitQ; | 490 BoundedProducerConsumerQueue<EmitterWorkItem> EmitQ; |
| 497 // DataLowering is only ever used by a single thread at a time (either in | 491 // DataLowering is only ever used by a single thread at a time (either in |
| 498 // emitItems(), or in IceCompiler::run before the compilation is over.) | 492 // emitItems(), or in IceCompiler::run before the compilation is over.) |
| 499 // TODO(jpp): move to EmitterContext. | 493 // TODO(jpp): move to EmitterContext. |
| 500 std::unique_ptr<TargetDataLowering> DataLowering; | 494 std::unique_ptr<TargetDataLowering> DataLowering; |
| 501 /// If !HasEmittedCode, SubZero will accumulate all Globals (which are "true" | 495 /// If !HasEmittedCode, SubZero will accumulate all Globals (which are "true" |
| 502 /// program global variables) until the first code WorkItem is seen. | 496 /// program global variables) until the first code WorkItem is seen. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 | 535 |
| 542 void addBlockInfoPtrs(VariableDeclaration *ProfileBlockInfo); | 536 void addBlockInfoPtrs(VariableDeclaration *ProfileBlockInfo); |
| 543 | 537 |
| 544 llvm::SmallVector<ThreadContext *, 128> AllThreadContexts; | 538 llvm::SmallVector<ThreadContext *, 128> AllThreadContexts; |
| 545 llvm::SmallVector<std::thread, 128> TranslationThreads; | 539 llvm::SmallVector<std::thread, 128> TranslationThreads; |
| 546 llvm::SmallVector<std::thread, 128> EmitterThreads; | 540 llvm::SmallVector<std::thread, 128> EmitterThreads; |
| 547 // Each thread has its own TLS pointer which is also held in | 541 // Each thread has its own TLS pointer which is also held in |
| 548 // AllThreadContexts. | 542 // AllThreadContexts. |
| 549 ICE_TLS_DECLARE_FIELD(ThreadContext *, TLS); | 543 ICE_TLS_DECLARE_FIELD(ThreadContext *, TLS); |
| 550 | 544 |
| 551 // Private helpers for mangleName() | |
| 552 using ManglerVector = llvm::SmallVector<char, 32>; | |
| 553 void incrementSubstitutions(ManglerVector &OldName) const; | |
| 554 | |
| 555 public: | 545 public: |
| 556 static void TlsInit() { ICE_TLS_INIT_FIELD(TLS); } | 546 static void TlsInit() { ICE_TLS_INIT_FIELD(TLS); } |
| 557 }; | 547 }; |
| 558 | 548 |
| 559 /// Helper class to push and pop a timer marker. The constructor pushes a | 549 /// Helper class to push and pop a timer marker. The constructor pushes a |
| 560 /// marker, and the destructor pops it. This is for convenient timing of regions | 550 /// marker, and the destructor pops it. This is for convenient timing of regions |
| 561 /// of code. | 551 /// of code. |
| 562 class TimerMarker { | 552 class TimerMarker { |
| 563 TimerMarker() = delete; | 553 TimerMarker() = delete; |
| 564 TimerMarker(const TimerMarker &) = delete; | 554 TimerMarker(const TimerMarker &) = delete; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 explicit OstreamLocker(GlobalContext *Ctx) : Ctx(Ctx) { Ctx->lockStr(); } | 594 explicit OstreamLocker(GlobalContext *Ctx) : Ctx(Ctx) { Ctx->lockStr(); } |
| 605 ~OstreamLocker() { Ctx->unlockStr(); } | 595 ~OstreamLocker() { Ctx->unlockStr(); } |
| 606 | 596 |
| 607 private: | 597 private: |
| 608 GlobalContext *const Ctx; | 598 GlobalContext *const Ctx; |
| 609 }; | 599 }; |
| 610 | 600 |
| 611 } // end of namespace Ice | 601 } // end of namespace Ice |
| 612 | 602 |
| 613 #endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H | 603 #endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H |
| OLD | NEW |