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 |
11 /// This file declares aspects of the compilation that persist across | 11 /// This file declares aspects of the compilation that persist across multiple |
12 /// multiple functions. | 12 /// functions. |
13 /// | 13 /// |
14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
15 | 15 |
16 #ifndef SUBZERO_SRC_ICEGLOBALCONTEXT_H | 16 #ifndef SUBZERO_SRC_ICEGLOBALCONTEXT_H |
17 #define SUBZERO_SRC_ICEGLOBALCONTEXT_H | 17 #define SUBZERO_SRC_ICEGLOBALCONTEXT_H |
18 | 18 |
19 #include "IceDefs.h" | 19 #include "IceDefs.h" |
20 #include "IceClFlags.h" | 20 #include "IceClFlags.h" |
21 #include "IceIntrinsics.h" | 21 #include "IceIntrinsics.h" |
22 #include "IceRNG.h" | 22 #include "IceRNG.h" |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 LockedPtr<ErrorCode> getErrorStatus() { | 179 LockedPtr<ErrorCode> getErrorStatus() { |
180 return LockedPtr<ErrorCode>(&ErrorStatus, &ErrorStatusLock); | 180 return LockedPtr<ErrorCode>(&ErrorStatus, &ErrorStatusLock); |
181 } | 181 } |
182 | 182 |
183 /// When emitting assembly, we allow a string to be prepended to | 183 /// When emitting assembly, we allow a string to be prepended to |
184 /// names of translated functions. This makes it easier to create an | 184 /// names of translated functions. This makes it easier to create an |
185 /// execution test against a reference translator like llc, with both | 185 /// execution test against a reference translator like llc, with both |
186 /// translators using the same bitcode as input. | 186 /// translators using the same bitcode as input. |
187 IceString mangleName(const IceString &Name) const; | 187 IceString mangleName(const IceString &Name) const; |
188 | 188 |
189 // Manage Constants. | 189 /// \name Manage Constants. |
190 // getConstant*() functions are not const because they might add | 190 /// @{ |
191 // something to the constant pool. | 191 // getConstant*() functions are not const because they might add something to |
| 192 // the constant pool. |
192 Constant *getConstantInt(Type Ty, int64_t Value); | 193 Constant *getConstantInt(Type Ty, int64_t Value); |
193 Constant *getConstantInt1(int8_t ConstantInt1); | 194 Constant *getConstantInt1(int8_t ConstantInt1); |
194 Constant *getConstantInt8(int8_t ConstantInt8); | 195 Constant *getConstantInt8(int8_t ConstantInt8); |
195 Constant *getConstantInt16(int16_t ConstantInt16); | 196 Constant *getConstantInt16(int16_t ConstantInt16); |
196 Constant *getConstantInt32(int32_t ConstantInt32); | 197 Constant *getConstantInt32(int32_t ConstantInt32); |
197 Constant *getConstantInt64(int64_t ConstantInt64); | 198 Constant *getConstantInt64(int64_t ConstantInt64); |
198 Constant *getConstantFloat(float Value); | 199 Constant *getConstantFloat(float Value); |
199 Constant *getConstantDouble(double Value); | 200 Constant *getConstantDouble(double Value); |
200 /// Returns a symbolic constant. | 201 /// Returns a symbolic constant. |
201 Constant *getConstantSym(RelocOffsetT Offset, const IceString &Name, | 202 Constant *getConstantSym(RelocOffsetT Offset, const IceString &Name, |
202 bool SuppressMangling); | 203 bool SuppressMangling); |
203 Constant *getConstantExternSym(const IceString &Name); | 204 Constant *getConstantExternSym(const IceString &Name); |
204 /// Returns an undef. | 205 /// Returns an undef. |
205 Constant *getConstantUndef(Type Ty); | 206 Constant *getConstantUndef(Type Ty); |
206 /// Returns a zero value. | 207 /// Returns a zero value. |
207 Constant *getConstantZero(Type Ty); | 208 Constant *getConstantZero(Type Ty); |
208 /// getConstantPool() returns a copy of the constant pool for | 209 /// getConstantPool() returns a copy of the constant pool for constants of a |
209 /// constants of a given type. | 210 /// given type. |
210 ConstantList getConstantPool(Type Ty); | 211 ConstantList getConstantPool(Type Ty); |
211 /// Returns a copy of the list of external symbols. | 212 /// Returns a copy of the list of external symbols. |
212 ConstantList getConstantExternSyms(); | 213 ConstantList getConstantExternSyms(); |
| 214 /// @} |
213 | 215 |
214 /// Return a locked pointer to the registered jump tables. | 216 /// Return a locked pointer to the registered jump tables. |
215 JumpTableDataList getJumpTables(); | 217 JumpTableDataList getJumpTables(); |
216 /// Create a new jump table entry and return a reference to it. | 218 /// Create a new jump table entry and return a reference to it. |
217 JumpTableData &addJumpTable(IceString FuncName, SizeT Id, SizeT NumTargets); | 219 JumpTableData &addJumpTable(IceString FuncName, SizeT Id, SizeT NumTargets); |
218 | 220 |
219 const ClFlags &getFlags() const { return Flags; } | 221 const ClFlags &getFlags() const { return Flags; } |
220 | 222 |
221 bool isIRGenerationDisabled() const { | 223 bool isIRGenerationDisabled() const { |
222 return getFlags().getDisableIRGeneration(); | 224 return getFlags().getDisableIRGeneration(); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 if (!getFlags().getDumpStats()) | 294 if (!getFlags().getDumpStats()) |
293 return; | 295 return; |
294 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS); | 296 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS); |
295 Tls->StatsFunction.update(CodeStats::CS_NumRPImms); | 297 Tls->StatsFunction.update(CodeStats::CS_NumRPImms); |
296 Tls->StatsCumulative.update(CodeStats::CS_NumRPImms); | 298 Tls->StatsCumulative.update(CodeStats::CS_NumRPImms); |
297 } | 299 } |
298 | 300 |
299 /// These are predefined TimerStackIdT values. | 301 /// These are predefined TimerStackIdT values. |
300 enum TimerStackKind { TSK_Default = 0, TSK_Funcs, TSK_Num }; | 302 enum TimerStackKind { TSK_Default = 0, TSK_Funcs, TSK_Num }; |
301 | 303 |
302 /// newTimerStackID() creates a new TimerStack in the global space. | 304 /// newTimerStackID() creates a new TimerStack in the global space. It does |
303 /// It does not affect any TimerStack objects in TLS. | 305 /// not affect any TimerStack objects in TLS. |
304 TimerStackIdT newTimerStackID(const IceString &Name); | 306 TimerStackIdT newTimerStackID(const IceString &Name); |
305 /// dumpTimers() dumps the global timer data. As such, one probably | 307 /// dumpTimers() dumps the global timer data. As such, one probably wants to |
306 /// wants to call mergeTimerStacks() as a prerequisite. | 308 /// call mergeTimerStacks() as a prerequisite. |
307 void dumpTimers(TimerStackIdT StackID = TSK_Default, | 309 void dumpTimers(TimerStackIdT StackID = TSK_Default, |
308 bool DumpCumulative = true); | 310 bool DumpCumulative = true); |
309 /// The following methods affect only the calling thread's TLS timer | 311 /// The following methods affect only the calling thread's TLS timer data. |
310 /// data. | |
311 TimerIdT getTimerID(TimerStackIdT StackID, const IceString &Name); | 312 TimerIdT getTimerID(TimerStackIdT StackID, const IceString &Name); |
312 void pushTimer(TimerIdT ID, TimerStackIdT StackID); | 313 void pushTimer(TimerIdT ID, TimerStackIdT StackID); |
313 void popTimer(TimerIdT ID, TimerStackIdT StackID); | 314 void popTimer(TimerIdT ID, TimerStackIdT StackID); |
314 void resetTimer(TimerStackIdT StackID); | 315 void resetTimer(TimerStackIdT StackID); |
315 void setTimerName(TimerStackIdT StackID, const IceString &NewName); | 316 void setTimerName(TimerStackIdT StackID, const IceString &NewName); |
316 | 317 |
317 /// This is the first work item sequence number that the parser | 318 /// This is the first work item sequence number that the parser produces, and |
318 /// produces, and correspondingly the first sequence number that the | 319 /// correspondingly the first sequence number that the emitter thread will |
319 /// emitter thread will wait for. Start numbering at 1 to leave room | 320 /// wait for. Start numbering at 1 to leave room for a sentinel, in case e.g. |
320 /// for a sentinel, in case e.g. we wish to inject items with a | 321 /// we wish to inject items with a special sequence number that may be |
321 /// special sequence number that may be executed out of order. | 322 /// executed out of order. |
322 static uint32_t getFirstSequenceNumber() { return 1; } | 323 static uint32_t getFirstSequenceNumber() { return 1; } |
323 /// Adds a newly parsed and constructed function to the Cfg work | 324 /// Adds a newly parsed and constructed function to the Cfg work queue. |
324 /// queue. Notifies any idle workers that a new function is | 325 /// Notifies any idle workers that a new function is available for |
325 /// available for translating. May block if the work queue is too | 326 /// translating. May block if the work queue is too large, in order to control |
326 /// large, in order to control memory footprint. | 327 /// memory footprint. |
327 void optQueueBlockingPush(std::unique_ptr<Cfg> Func); | 328 void optQueueBlockingPush(std::unique_ptr<Cfg> Func); |
328 /// Takes a Cfg from the work queue for translating. May block if | 329 /// Takes a Cfg from the work queue for translating. May block if the work |
329 /// the work queue is currently empty. Returns nullptr if there is | 330 /// queue is currently empty. Returns nullptr if there is no more work - the |
330 /// no more work - the queue is empty and either end() has been | 331 /// queue is empty and either end() has been called or the Sequential flag was |
331 /// called or the Sequential flag was set. | 332 /// set. |
332 std::unique_ptr<Cfg> optQueueBlockingPop(); | 333 std::unique_ptr<Cfg> optQueueBlockingPop(); |
333 /// Notifies that no more work will be added to the work queue. | 334 /// Notifies that no more work will be added to the work queue. |
334 void optQueueNotifyEnd() { OptQ.notifyEnd(); } | 335 void optQueueNotifyEnd() { OptQ.notifyEnd(); } |
335 | 336 |
336 /// Emit file header for output file. | 337 /// Emit file header for output file. |
337 void emitFileHeader(); | 338 void emitFileHeader(); |
338 | 339 |
339 void lowerConstants(); | 340 void lowerConstants(); |
340 | 341 |
341 void lowerJumpTables(); | 342 void lowerJumpTables(); |
(...skipping 29 matching lines...) Expand all Loading... |
371 } | 372 } |
372 } | 373 } |
373 | 374 |
374 void waitForWorkerThreads() { | 375 void waitForWorkerThreads() { |
375 optQueueNotifyEnd(); | 376 optQueueNotifyEnd(); |
376 for (std::thread &Worker : TranslationThreads) { | 377 for (std::thread &Worker : TranslationThreads) { |
377 Worker.join(); | 378 Worker.join(); |
378 } | 379 } |
379 TranslationThreads.clear(); | 380 TranslationThreads.clear(); |
380 | 381 |
381 // Only notify the emit queue to end after all the translation | 382 // Only notify the emit queue to end after all the translation threads have |
382 // threads have ended. | 383 // ended. |
383 emitQueueNotifyEnd(); | 384 emitQueueNotifyEnd(); |
384 for (std::thread &Worker : EmitterThreads) { | 385 for (std::thread &Worker : EmitterThreads) { |
385 Worker.join(); | 386 Worker.join(); |
386 } | 387 } |
387 EmitterThreads.clear(); | 388 EmitterThreads.clear(); |
388 | 389 |
389 if (BuildDefs::dump()) { | 390 if (BuildDefs::dump()) { |
390 auto Timers = getTimers(); | 391 auto Timers = getTimers(); |
391 for (ThreadContext *TLS : AllThreadContexts) | 392 for (ThreadContext *TLS : AllThreadContexts) |
392 Timers->mergeFrom(TLS->Timers); | 393 Timers->mergeFrom(TLS->Timers); |
393 } | 394 } |
394 if (BuildDefs::dump()) { | 395 if (BuildDefs::dump()) { |
395 // Do a separate loop over AllThreadContexts to avoid holding | 396 // Do a separate loop over AllThreadContexts to avoid holding two locks |
396 // two locks at once. | 397 // at once. |
397 auto Stats = getStatsCumulative(); | 398 auto Stats = getStatsCumulative(); |
398 for (ThreadContext *TLS : AllThreadContexts) | 399 for (ThreadContext *TLS : AllThreadContexts) |
399 Stats->add(TLS->StatsCumulative); | 400 Stats->add(TLS->StatsCumulative); |
400 } | 401 } |
401 } | 402 } |
402 | 403 |
403 /// Translation thread startup routine. | 404 /// Translation thread startup routine. |
404 void translateFunctionsWrapper(ThreadContext *MyTLS) { | 405 void translateFunctionsWrapper(ThreadContext *MyTLS) { |
405 ICE_TLS_SET_FIELD(TLS, MyTLS); | 406 ICE_TLS_SET_FIELD(TLS, MyTLS); |
406 translateFunctions(); | 407 translateFunctions(); |
407 } | 408 } |
408 /// Translate functions from the Cfg queue until the queue is empty. | 409 /// Translate functions from the Cfg queue until the queue is empty. |
409 void translateFunctions(); | 410 void translateFunctions(); |
410 | 411 |
411 /// Emitter thread startup routine. | 412 /// Emitter thread startup routine. |
412 void emitterWrapper(ThreadContext *MyTLS) { | 413 void emitterWrapper(ThreadContext *MyTLS) { |
413 ICE_TLS_SET_FIELD(TLS, MyTLS); | 414 ICE_TLS_SET_FIELD(TLS, MyTLS); |
414 emitItems(); | 415 emitItems(); |
415 } | 416 } |
416 /// Emit functions and global initializers from the emitter queue | 417 /// Emit functions and global initializers from the emitter queue until the |
417 /// until the queue is empty. | 418 /// queue is empty. |
418 void emitItems(); | 419 void emitItems(); |
419 | 420 |
420 /// Uses DataLowering to lower Globals. Side effects: | 421 /// Uses DataLowering to lower Globals. Side effects: |
421 /// - discards the initializer list for the global variable in Globals. | 422 /// - discards the initializer list for the global variable in Globals. |
422 /// - clears the Globals array. | 423 /// - clears the Globals array. |
423 void lowerGlobals(const IceString &SectionSuffix); | 424 void lowerGlobals(const IceString &SectionSuffix); |
424 | 425 |
425 /// Lowers the profile information. | 426 /// Lowers the profile information. |
426 void lowerProfileData(); | 427 void lowerProfileData(); |
427 | 428 |
428 /// Utility function to match a symbol name against a match string. | 429 /// Utility function to match a symbol name against a match string. This is |
429 /// This is used in a few cases where we want to take some action on | 430 /// used in a few cases where we want to take some action on a particular |
430 /// a particular function or symbol based on a command-line argument, | 431 /// function or symbol based on a command-line argument, such as changing the |
431 /// such as changing the verbose level for a particular function. An | 432 /// verbose level for a particular function. An empty Match argument means |
432 /// empty Match argument means match everything. Returns true if | 433 /// match everything. Returns true if there is a match. |
433 /// there is a match. | |
434 static bool matchSymbolName(const IceString &SymbolName, | 434 static bool matchSymbolName(const IceString &SymbolName, |
435 const IceString &Match) { | 435 const IceString &Match) { |
436 return Match.empty() || Match == SymbolName; | 436 return Match.empty() || Match == SymbolName; |
437 } | 437 } |
438 | 438 |
439 private: | 439 private: |
440 // Try to ensure mutexes are allocated on separate cache lines. | 440 // Try to ensure mutexes are allocated on separate cache lines. |
441 | 441 |
442 // Destructors collaborate with Allocator | 442 // Destructors collaborate with Allocator |
443 ICE_CACHELINE_BOUNDARY; | 443 ICE_CACHELINE_BOUNDARY; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 ICE_TLS_DECLARE_FIELD(ThreadContext *, TLS); | 545 ICE_TLS_DECLARE_FIELD(ThreadContext *, TLS); |
546 | 546 |
547 // Private helpers for mangleName() | 547 // Private helpers for mangleName() |
548 using ManglerVector = llvm::SmallVector<char, 32>; | 548 using ManglerVector = llvm::SmallVector<char, 32>; |
549 void incrementSubstitutions(ManglerVector &OldName) const; | 549 void incrementSubstitutions(ManglerVector &OldName) const; |
550 | 550 |
551 public: | 551 public: |
552 static void TlsInit() { ICE_TLS_INIT_FIELD(TLS); } | 552 static void TlsInit() { ICE_TLS_INIT_FIELD(TLS); } |
553 }; | 553 }; |
554 | 554 |
555 /// Helper class to push and pop a timer marker. The constructor | 555 /// Helper class to push and pop a timer marker. The constructor pushes a |
556 /// pushes a marker, and the destructor pops it. This is for | 556 /// marker, and the destructor pops it. This is for convenient timing of regions |
557 /// convenient timing of regions of code. | 557 /// of code. |
558 class TimerMarker { | 558 class TimerMarker { |
559 TimerMarker() = delete; | 559 TimerMarker() = delete; |
560 TimerMarker(const TimerMarker &) = delete; | 560 TimerMarker(const TimerMarker &) = delete; |
561 TimerMarker &operator=(const TimerMarker &) = delete; | 561 TimerMarker &operator=(const TimerMarker &) = delete; |
562 | 562 |
563 public: | 563 public: |
564 TimerMarker(TimerIdT ID, GlobalContext *Ctx, | 564 TimerMarker(TimerIdT ID, GlobalContext *Ctx, |
565 TimerStackIdT StackID = GlobalContext::TSK_Default) | 565 TimerStackIdT StackID = GlobalContext::TSK_Default) |
566 : ID(ID), Ctx(Ctx), StackID(StackID) { | 566 : ID(ID), Ctx(Ctx), StackID(StackID) { |
567 if (BuildDefs::dump()) | 567 if (BuildDefs::dump()) |
(...skipping 14 matching lines...) Expand all Loading... |
582 | 582 |
583 private: | 583 private: |
584 void push(); | 584 void push(); |
585 void pushCfg(const Cfg *Func); | 585 void pushCfg(const Cfg *Func); |
586 const TimerIdT ID; | 586 const TimerIdT ID; |
587 GlobalContext *Ctx; | 587 GlobalContext *Ctx; |
588 const TimerStackIdT StackID; | 588 const TimerStackIdT StackID; |
589 bool Active = false; | 589 bool Active = false; |
590 }; | 590 }; |
591 | 591 |
592 /// Helper class for locking the streams and then automatically | 592 /// Helper class for locking the streams and then automatically unlocking them. |
593 /// unlocking them. | |
594 class OstreamLocker { | 593 class OstreamLocker { |
595 private: | 594 private: |
596 OstreamLocker() = delete; | 595 OstreamLocker() = delete; |
597 OstreamLocker(const OstreamLocker &) = delete; | 596 OstreamLocker(const OstreamLocker &) = delete; |
598 OstreamLocker &operator=(const OstreamLocker &) = delete; | 597 OstreamLocker &operator=(const OstreamLocker &) = delete; |
599 | 598 |
600 public: | 599 public: |
601 explicit OstreamLocker(GlobalContext *Ctx) : Ctx(Ctx) { Ctx->lockStr(); } | 600 explicit OstreamLocker(GlobalContext *Ctx) : Ctx(Ctx) { Ctx->lockStr(); } |
602 ~OstreamLocker() { Ctx->unlockStr(); } | 601 ~OstreamLocker() { Ctx->unlockStr(); } |
603 | 602 |
604 private: | 603 private: |
605 GlobalContext *const Ctx; | 604 GlobalContext *const Ctx; |
606 }; | 605 }; |
607 | 606 |
608 } // end of namespace Ice | 607 } // end of namespace Ice |
609 | 608 |
610 #endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H | 609 #endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H |
OLD | NEW |