| OLD | NEW |
| 1 //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===// | 1 //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===// |
| 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 /// \brief Defines aspects of the compilation that persist across multiple | 11 /// \brief Defines aspects of the compilation that persist across multiple |
| 12 /// functions. | 12 /// functions. |
| 13 /// | 13 /// |
| 14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
| 15 | 15 |
| 16 #include "IceGlobalContext.h" | 16 #include "IceGlobalContext.h" |
| 17 | 17 |
| 18 #include "IceCfg.h" | 18 #include "IceCfg.h" |
| 19 #include "IceCfgNode.h" | 19 #include "IceCfgNode.h" |
| 20 #include "IceClFlags.h" | 20 #include "IceClFlags.h" |
| 21 #include "IceClFlagsExtra.h" |
| 21 #include "IceDefs.h" | 22 #include "IceDefs.h" |
| 22 #include "IceELFObjectWriter.h" | 23 #include "IceELFObjectWriter.h" |
| 23 #include "IceGlobalInits.h" | 24 #include "IceGlobalInits.h" |
| 24 #include "IceOperand.h" | 25 #include "IceOperand.h" |
| 25 #include "IceTargetLowering.h" | 26 #include "IceTargetLowering.h" |
| 26 #include "IceTimerTree.h" | 27 #include "IceTimerTree.h" |
| 27 #include "IceTypes.h" | 28 #include "IceTypes.h" |
| 28 | 29 |
| 29 #ifdef __clang__ | 30 #ifdef __clang__ |
| 30 #pragma clang diagnostic push | 31 #pragma clang diagnostic push |
| 31 #pragma clang diagnostic ignored "-Wunused-parameter" | 32 #pragma clang diagnostic ignored "-Wunused-parameter" |
| 32 #endif // __clang__ | 33 #endif // __clang__ |
| 33 | 34 |
| 34 #include "llvm/Support/Timer.h" | 35 #include "llvm/Support/Timer.h" |
| 35 | 36 |
| 36 #ifdef __clang__ | 37 #ifdef __clang__ |
| 37 #pragma clang diagnostic pop | 38 #pragma clang diagnostic pop |
| 38 #endif // __clang__ | 39 #endif // __clang__ |
| 39 | 40 |
| 40 #include <algorithm> // max() | 41 #include <algorithm> // max() |
| 41 #include <cctype> // isdigit(), isupper() | |
| 42 #include <locale> // locale | |
| 43 | 42 |
| 44 namespace std { | 43 namespace std { |
| 45 template <> struct hash<Ice::RelocatableTuple> { | 44 template <> struct hash<Ice::RelocatableTuple> { |
| 46 size_t operator()(const Ice::RelocatableTuple &Key) const { | 45 size_t operator()(const Ice::RelocatableTuple &Key) const { |
| 47 if (!Key.EmitString.empty()) { | 46 if (!Key.EmitString.empty()) { |
| 48 return hash<Ice::IceString>()(Key.EmitString); | 47 return hash<Ice::IceString>()(Key.EmitString); |
| 49 } | 48 } |
| 50 | 49 |
| 51 // If there's no emit string, then we use the relocatable's name, plus the | 50 // If there's no emit string, then we use the relocatable's name, plus the |
| 52 // hash of a combination of the number of OffsetExprs and the known, fixed | 51 // hash of a combination of the number of OffsetExprs and the known, fixed |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 Str << "|i16=" << Pool->Integers16.size(); | 242 Str << "|i16=" << Pool->Integers16.size(); |
| 244 Str << "|i32=" << Pool->Integers32.size(); | 243 Str << "|i32=" << Pool->Integers32.size(); |
| 245 Str << "|i64=" << Pool->Integers64.size(); | 244 Str << "|i64=" << Pool->Integers64.size(); |
| 246 Str << "|Rel=" << Pool->Relocatables.size(); | 245 Str << "|Rel=" << Pool->Relocatables.size(); |
| 247 Str << "|ExtRel=" << Pool->ExternRelocatables.size(); | 246 Str << "|ExtRel=" << Pool->ExternRelocatables.size(); |
| 248 } | 247 } |
| 249 Str << "\n"; | 248 Str << "\n"; |
| 250 } | 249 } |
| 251 | 250 |
| 252 GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError, | 251 GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError, |
| 253 ELFStreamer *ELFStr, const ClFlags &Flags) | 252 ELFStreamer *ELFStr) |
| 254 : ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump), | 253 : ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump), |
| 255 StrEmit(OsEmit), StrError(OsError), Flags(Flags), ObjectWriter(), | 254 StrEmit(OsEmit), StrError(OsError), ObjectWriter(), |
| 256 OptQ(/*Sequential=*/Flags.isSequential(), | 255 OptQ(/*Sequential=*/Flags.isSequential(), |
| 257 /*MaxSize=*/Flags.getNumTranslationThreads()), | 256 /*MaxSize=*/Flags.getNumTranslationThreads()), |
| 258 // EmitQ is allowed unlimited size. | 257 // EmitQ is allowed unlimited size. |
| 259 EmitQ(/*Sequential=*/Flags.isSequential()), | 258 EmitQ(/*Sequential=*/Flags.isSequential()), |
| 260 DataLowering(TargetDataLowering::createLowering(this)) { | 259 DataLowering(TargetDataLowering::createLowering(this)) { |
| 261 assert(OsDump && "OsDump is not defined for GlobalContext"); | 260 assert(OsDump && "OsDump is not defined for GlobalContext"); |
| 262 assert(OsEmit && "OsEmit is not defined for GlobalContext"); | 261 assert(OsEmit && "OsEmit is not defined for GlobalContext"); |
| 263 assert(OsError && "OsError is not defined for GlobalContext"); | 262 assert(OsError && "OsError is not defined for GlobalContext"); |
| 264 // Make sure thread_local fields are properly initialized before any | 263 // Make sure thread_local fields are properly initialized before any |
| 265 // accesses are made. Do this here instead of at the start of | 264 // accesses are made. Do this here instead of at the start of |
| (...skipping 20 matching lines...) Expand all Loading... |
| 286 ObjectWriter.reset(new ELFObjectWriter(*this, *ELFStr)); | 285 ObjectWriter.reset(new ELFObjectWriter(*this, *ELFStr)); |
| 287 break; | 286 break; |
| 288 case FT_Asm: | 287 case FT_Asm: |
| 289 case FT_Iasm: | 288 case FT_Iasm: |
| 290 break; | 289 break; |
| 291 } | 290 } |
| 292 | 291 |
| 293 // ProfileBlockInfoVarDecl is initialized here because it takes this as a | 292 // ProfileBlockInfoVarDecl is initialized here because it takes this as a |
| 294 // parameter -- we want to | 293 // parameter -- we want to |
| 295 // ensure that at least this' member variables are initialized. | 294 // ensure that at least this' member variables are initialized. |
| 296 ProfileBlockInfoVarDecl = VariableDeclaration::create(this); | 295 ProfileBlockInfoVarDecl = VariableDeclaration::createExternal(this); |
| 297 ProfileBlockInfoVarDecl->setAlignment(typeWidthInBytes(IceType_i64)); | 296 ProfileBlockInfoVarDecl->setAlignment(typeWidthInBytes(IceType_i64)); |
| 298 ProfileBlockInfoVarDecl->setIsConstant(true); | 297 ProfileBlockInfoVarDecl->setIsConstant(true); |
| 299 | 298 |
| 300 // Note: if you change this symbol, make sure to update | 299 // Note: if you change this symbol, make sure to update |
| 301 // runtime/szrt_profiler.c as well. | 300 // runtime/szrt_profiler.c as well. |
| 302 ProfileBlockInfoVarDecl->setName("__Sz_block_profile_info"); | 301 ProfileBlockInfoVarDecl->setName("__Sz_block_profile_info"); |
| 303 ProfileBlockInfoVarDecl->setSuppressMangling(); | |
| 304 ProfileBlockInfoVarDecl->setLinkage(llvm::GlobalValue::ExternalLinkage); | |
| 305 | 302 |
| 306 TargetLowering::staticInit(this); | 303 TargetLowering::staticInit(this); |
| 307 } | 304 } |
| 308 | 305 |
| 309 void GlobalContext::translateFunctions() { | 306 void GlobalContext::translateFunctions() { |
| 310 while (std::unique_ptr<Cfg> Func = optQueueBlockingPop()) { | 307 while (std::unique_ptr<Cfg> Func = optQueueBlockingPop()) { |
| 311 // Install Func in TLS for Cfg-specific container allocators. | 308 // Install Func in TLS for Cfg-specific container allocators. |
| 312 CfgLocalAllocatorScope _(Func.get()); | 309 CfgLocalAllocatorScope _(Func.get()); |
| 313 // Reset per-function stats being accumulated in TLS. | 310 // Reset per-function stats being accumulated in TLS. |
| 314 resetStats(); | 311 resetStats(); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 void GlobalContext::lowerGlobals(const IceString &SectionSuffix) { | 408 void GlobalContext::lowerGlobals(const IceString &SectionSuffix) { |
| 412 TimerMarker T(TimerStack::TT_emitGlobalInitializers, this); | 409 TimerMarker T(TimerStack::TT_emitGlobalInitializers, this); |
| 413 const bool DumpGlobalVariables = | 410 const bool DumpGlobalVariables = |
| 414 BuildDefs::dump() && | 411 BuildDefs::dump() && |
| 415 (Flags.getVerbose() & IceV_GlobalInit & Cfg::defaultVerboseMask()) && | 412 (Flags.getVerbose() & IceV_GlobalInit & Cfg::defaultVerboseMask()) && |
| 416 Flags.getVerboseFocusOn().empty(); | 413 Flags.getVerboseFocusOn().empty(); |
| 417 if (DumpGlobalVariables) { | 414 if (DumpGlobalVariables) { |
| 418 OstreamLocker L(this); | 415 OstreamLocker L(this); |
| 419 Ostream &Stream = getStrDump(); | 416 Ostream &Stream = getStrDump(); |
| 420 for (const Ice::VariableDeclaration *Global : Globals) { | 417 for (const Ice::VariableDeclaration *Global : Globals) { |
| 421 Global->dump(this, Stream); | 418 Global->dump(Stream); |
| 422 } | 419 } |
| 423 } | 420 } |
| 424 if (Flags.getDisableTranslation()) | 421 if (Flags.getDisableTranslation()) |
| 425 return; | 422 return; |
| 426 | 423 |
| 427 addBlockInfoPtrs(ProfileBlockInfoVarDecl); | 424 addBlockInfoPtrs(ProfileBlockInfoVarDecl); |
| 428 // If we need to shuffle the layout of global variables, shuffle them now. | 425 // If we need to shuffle the layout of global variables, shuffle them now. |
| 429 if (getFlags().shouldReorderGlobalVariables()) { | 426 if (getFlags().shouldReorderGlobalVariables()) { |
| 430 // Create a random number generator for global variable reordering. | 427 // Create a random number generator for global variable reordering. |
| 431 RandomNumberGenerator RNG(getFlags().getRandomSeed(), | 428 RandomNumberGenerator RNG(getFlags().getRandomSeed(), |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 break; | 535 break; |
| 539 case EmitterWorkItem::WI_GlobalInits: { | 536 case EmitterWorkItem::WI_GlobalInits: { |
| 540 accumulateGlobals(Item->getGlobalInits()); | 537 accumulateGlobals(Item->getGlobalInits()); |
| 541 } break; | 538 } break; |
| 542 case EmitterWorkItem::WI_Asm: { | 539 case EmitterWorkItem::WI_Asm: { |
| 543 lowerGlobalsIfNoCodeHasBeenSeen(); | 540 lowerGlobalsIfNoCodeHasBeenSeen(); |
| 544 accumulateGlobals(Item->getGlobalInits()); | 541 accumulateGlobals(Item->getGlobalInits()); |
| 545 | 542 |
| 546 std::unique_ptr<Assembler> Asm = Item->getAsm(); | 543 std::unique_ptr<Assembler> Asm = Item->getAsm(); |
| 547 Asm->alignFunction(); | 544 Asm->alignFunction(); |
| 548 IceString MangledName = mangleName(Asm->getFunctionName()); | 545 const IceString &Name = Asm->getFunctionName(); |
| 549 switch (getFlags().getOutFileType()) { | 546 switch (getFlags().getOutFileType()) { |
| 550 case FT_Elf: | 547 case FT_Elf: |
| 551 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(), | 548 getObjectWriter()->writeFunctionCode(Name, Asm->getInternal(), |
| 552 Asm.get()); | 549 Asm.get()); |
| 553 break; | 550 break; |
| 554 case FT_Iasm: { | 551 case FT_Iasm: { |
| 555 OstreamLocker L(this); | 552 OstreamLocker L(this); |
| 556 Cfg::emitTextHeader(MangledName, this, Asm.get()); | 553 Cfg::emitTextHeader(Name, this, Asm.get()); |
| 557 Asm->emitIASBytes(this); | 554 Asm->emitIASBytes(this); |
| 558 } break; | 555 } break; |
| 559 case FT_Asm: | 556 case FT_Asm: |
| 560 llvm::report_fatal_error("Unexpected FT_Asm"); | 557 llvm::report_fatal_error("Unexpected FT_Asm"); |
| 561 break; | 558 break; |
| 562 } | 559 } |
| 563 } break; | 560 } break; |
| 564 case EmitterWorkItem::WI_Cfg: { | 561 case EmitterWorkItem::WI_Cfg: { |
| 565 if (!BuildDefs::dump()) | 562 if (!BuildDefs::dump()) |
| 566 llvm::report_fatal_error("WI_Cfg work item created inappropriately"); | 563 llvm::report_fatal_error("WI_Cfg work item created inappropriately"); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 580 } | 577 } |
| 581 // Update the start index for next shuffling queue | 578 // Update the start index for next shuffling queue |
| 582 ShuffleStartIndex = ShuffleEndIndex; | 579 ShuffleStartIndex = ShuffleEndIndex; |
| 583 } | 580 } |
| 584 | 581 |
| 585 // In case there are no code to be generated, we invoke the conditional | 582 // In case there are no code to be generated, we invoke the conditional |
| 586 // lowerGlobals again -- this is a no-op if code has been emitted. | 583 // lowerGlobals again -- this is a no-op if code has been emitted. |
| 587 lowerGlobalsIfNoCodeHasBeenSeen(); | 584 lowerGlobalsIfNoCodeHasBeenSeen(); |
| 588 } | 585 } |
| 589 | 586 |
| 590 // Scan a string for S[0-9A-Z]*_ patterns and replace them with | |
| 591 // S<num>_ where <num> is the next base-36 value. If a type name | |
| 592 // legitimately contains that pattern, then the substitution will be | |
| 593 // made in error and most likely the link will fail. In this case, | |
| 594 // the test classes can be rewritten not to use that pattern, which is | |
| 595 // much simpler and more reliable than implementing a full demangling | |
| 596 // parser. Another substitution-in-error may occur if a type | |
| 597 // identifier ends with the pattern S[0-9A-Z]*, because an immediately | |
| 598 // following substitution string like "S1_" or "PS1_" may be combined | |
| 599 // with the previous type. | |
| 600 void GlobalContext::incrementSubstitutions(ManglerVector &OldName) const { | |
| 601 const std::locale CLocale("C"); | |
| 602 // Provide extra space in case the length of <num> increases. | |
| 603 ManglerVector NewName(OldName.size() * 2); | |
| 604 size_t OldPos = 0; | |
| 605 size_t NewPos = 0; | |
| 606 size_t OldLen = OldName.size(); | |
| 607 for (; OldPos < OldLen; ++OldPos, ++NewPos) { | |
| 608 if (OldName[OldPos] == '\0') | |
| 609 break; | |
| 610 if (OldName[OldPos] == 'S') { | |
| 611 // Search forward until we find _ or invalid character (including \0). | |
| 612 bool AllZs = true; | |
| 613 bool Found = false; | |
| 614 size_t Last; | |
| 615 for (Last = OldPos + 1; Last < OldLen; ++Last) { | |
| 616 char Ch = OldName[Last]; | |
| 617 if (Ch == '_') { | |
| 618 Found = true; | |
| 619 break; | |
| 620 } else if (std::isdigit(Ch) || std::isupper(Ch, CLocale)) { | |
| 621 if (Ch != 'Z') | |
| 622 AllZs = false; | |
| 623 } else { | |
| 624 // Invalid character, stop searching. | |
| 625 break; | |
| 626 } | |
| 627 } | |
| 628 if (Found) { | |
| 629 NewName[NewPos++] = OldName[OldPos++]; // 'S' | |
| 630 size_t Length = Last - OldPos; | |
| 631 // NewPos and OldPos point just past the 'S'. | |
| 632 assert(NewName[NewPos - 1] == 'S'); | |
| 633 assert(OldName[OldPos - 1] == 'S'); | |
| 634 assert(OldName[OldPos + Length] == '_'); | |
| 635 if (AllZs) { | |
| 636 // Replace N 'Z' characters with a '0' (if N=0) or '1' (if N>0) | |
| 637 // followed by N '0' characters. | |
| 638 NewName[NewPos++] = (Length ? '1' : '0'); | |
| 639 for (size_t i = 0; i < Length; ++i) { | |
| 640 NewName[NewPos++] = '0'; | |
| 641 } | |
| 642 } else { | |
| 643 // Iterate right-to-left and increment the base-36 number. | |
| 644 bool Carry = true; | |
| 645 for (size_t i = 0; i < Length; ++i) { | |
| 646 size_t Offset = Length - 1 - i; | |
| 647 char Ch = OldName[OldPos + Offset]; | |
| 648 if (Carry) { | |
| 649 Carry = false; | |
| 650 switch (Ch) { | |
| 651 case '9': | |
| 652 Ch = 'A'; | |
| 653 break; | |
| 654 case 'Z': | |
| 655 Ch = '0'; | |
| 656 Carry = true; | |
| 657 break; | |
| 658 default: | |
| 659 ++Ch; | |
| 660 break; | |
| 661 } | |
| 662 } | |
| 663 NewName[NewPos + Offset] = Ch; | |
| 664 } | |
| 665 NewPos += Length; | |
| 666 } | |
| 667 OldPos = Last; | |
| 668 // Fall through and let the '_' be copied across. | |
| 669 } | |
| 670 } | |
| 671 NewName[NewPos] = OldName[OldPos]; | |
| 672 } | |
| 673 assert(NewName[NewPos] == '\0'); | |
| 674 OldName = NewName; | |
| 675 } | |
| 676 | |
| 677 // In this context, name mangling means to rewrite a symbol using a given | |
| 678 // prefix. For a C++ symbol, nest the original symbol inside the "prefix" | |
| 679 // namespace. For other symbols, just prepend the prefix. | |
| 680 IceString GlobalContext::mangleName(const IceString &Name) const { | |
| 681 // An already-nested name like foo::bar() gets pushed down one level, making | |
| 682 // it equivalent to Prefix::foo::bar(). | |
| 683 // _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz | |
| 684 // A non-nested but mangled name like bar() gets nested, making it equivalent | |
| 685 // to Prefix::bar(). | |
| 686 // _Z3barxyz ==> ZN6Prefix3barExyz | |
| 687 // An unmangled, extern "C" style name, gets a simple prefix: | |
| 688 // bar ==> Prefixbar | |
| 689 if (!BuildDefs::dump() || getFlags().getTestPrefix().empty()) | |
| 690 return Name; | |
| 691 | |
| 692 const IceString &TestPrefix = getFlags().getTestPrefix(); | |
| 693 unsigned PrefixLength = TestPrefix.length(); | |
| 694 ManglerVector NameBase(1 + Name.length()); | |
| 695 const size_t BufLen = 30 + Name.length() + PrefixLength; | |
| 696 ManglerVector NewName(BufLen); | |
| 697 uint32_t BaseLength = 0; // using uint32_t due to sscanf format string | |
| 698 | |
| 699 int ItemsParsed = sscanf(Name.c_str(), "_ZN%s", NameBase.data()); | |
| 700 if (ItemsParsed == 1) { | |
| 701 // Transform _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz | |
| 702 // (splice in "6Prefix") ^^^^^^^ | |
| 703 snprintf(NewName.data(), BufLen, "_ZN%u%s%s", PrefixLength, | |
| 704 TestPrefix.c_str(), NameBase.data()); | |
| 705 // We ignore the snprintf return value (here and below). If we somehow | |
| 706 // miscalculated the output buffer length, the output will be truncated, | |
| 707 // but it will be truncated consistently for all mangleName() calls on the | |
| 708 // same input string. | |
| 709 incrementSubstitutions(NewName); | |
| 710 return NewName.data(); | |
| 711 } | |
| 712 | |
| 713 // Artificially limit BaseLength to 9 digits (less than 1 billion) because | |
| 714 // sscanf behavior is undefined on integer overflow. If there are more than 9 | |
| 715 // digits (which we test by looking at the beginning of NameBase), then we | |
| 716 // consider this a failure to parse a namespace mangling, and fall back to | |
| 717 // the simple prefixing. | |
| 718 ItemsParsed = sscanf(Name.c_str(), "_Z%9u%s", &BaseLength, NameBase.data()); | |
| 719 if (ItemsParsed == 2 && BaseLength <= strlen(NameBase.data()) && | |
| 720 !isdigit(NameBase[0])) { | |
| 721 // Transform _Z3barxyz ==> _ZN6Prefix3barExyz | |
| 722 // ^^^^^^^^ ^ | |
| 723 // (splice in "N6Prefix", and insert "E" after "3bar") But an "I" after the | |
| 724 // identifier indicates a template argument list terminated with "E"; | |
| 725 // insert the new "E" before/after the old "E". E.g.: | |
| 726 // Transform _Z3barIabcExyz ==> _ZN6Prefix3barIabcEExyz | |
| 727 // ^^^^^^^^ ^ | |
| 728 // (splice in "N6Prefix", and insert "E" after "3barIabcE") | |
| 729 ManglerVector OrigName(Name.length()); | |
| 730 ManglerVector OrigSuffix(Name.length()); | |
| 731 uint32_t ActualBaseLength = BaseLength; | |
| 732 if (NameBase[ActualBaseLength] == 'I') { | |
| 733 ++ActualBaseLength; | |
| 734 while (NameBase[ActualBaseLength] != 'E' && | |
| 735 NameBase[ActualBaseLength] != '\0') | |
| 736 ++ActualBaseLength; | |
| 737 } | |
| 738 strncpy(OrigName.data(), NameBase.data(), ActualBaseLength); | |
| 739 OrigName[ActualBaseLength] = '\0'; | |
| 740 strcpy(OrigSuffix.data(), NameBase.data() + ActualBaseLength); | |
| 741 snprintf(NewName.data(), BufLen, "_ZN%u%s%u%sE%s", PrefixLength, | |
| 742 TestPrefix.c_str(), BaseLength, OrigName.data(), | |
| 743 OrigSuffix.data()); | |
| 744 incrementSubstitutions(NewName); | |
| 745 return NewName.data(); | |
| 746 } | |
| 747 | |
| 748 // Transform bar ==> Prefixbar | |
| 749 // ^^^^^^ | |
| 750 return TestPrefix + Name; | |
| 751 } | |
| 752 | |
| 753 GlobalContext::~GlobalContext() { | 587 GlobalContext::~GlobalContext() { |
| 754 llvm::DeleteContainerPointers(AllThreadContexts); | 588 llvm::DeleteContainerPointers(AllThreadContexts); |
| 755 LockedPtr<DestructorArray> Dtors = getDestructors(); | 589 LockedPtr<DestructorArray> Dtors = getDestructors(); |
| 756 // Destructors are invoked in the opposite object construction order. | 590 // Destructors are invoked in the opposite object construction order. |
| 757 for (const auto &Dtor : reverse_range(*Dtors)) | 591 for (const auto &Dtor : reverse_range(*Dtors)) |
| 758 Dtor(); | 592 Dtor(); |
| 759 } | 593 } |
| 760 | 594 |
| 761 // TODO(stichnot): Consider adding thread-local caches of constant pool entries | 595 // TODO(stichnot): Consider adding thread-local caches of constant pool entries |
| 762 // to reduce contention. | 596 // to reduce contention. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 805 return getConstPool()->Floats.getOrAdd(this, ConstantFloat); | 639 return getConstPool()->Floats.getOrAdd(this, ConstantFloat); |
| 806 } | 640 } |
| 807 | 641 |
| 808 Constant *GlobalContext::getConstantDouble(double ConstantDouble) { | 642 Constant *GlobalContext::getConstantDouble(double ConstantDouble) { |
| 809 return getConstPool()->Doubles.getOrAdd(this, ConstantDouble); | 643 return getConstPool()->Doubles.getOrAdd(this, ConstantDouble); |
| 810 } | 644 } |
| 811 | 645 |
| 812 Constant *GlobalContext::getConstantSym(const RelocOffsetT Offset, | 646 Constant *GlobalContext::getConstantSym(const RelocOffsetT Offset, |
| 813 const RelocOffsetArray &OffsetExpr, | 647 const RelocOffsetArray &OffsetExpr, |
| 814 const IceString &Name, | 648 const IceString &Name, |
| 815 const IceString &EmitString, | 649 const IceString &EmitString) { |
| 816 bool SuppressMangling) { | |
| 817 return getConstPool()->Relocatables.getOrAdd( | 650 return getConstPool()->Relocatables.getOrAdd( |
| 818 this, | 651 this, RelocatableTuple(Offset, OffsetExpr, Name, EmitString)); |
| 819 RelocatableTuple(Offset, OffsetExpr, Name, EmitString, SuppressMangling)); | |
| 820 } | 652 } |
| 821 | 653 |
| 822 Constant *GlobalContext::getConstantSym(RelocOffsetT Offset, | 654 Constant *GlobalContext::getConstantSym(RelocOffsetT Offset, |
| 823 const IceString &Name, | 655 const IceString &Name) { |
| 824 bool SuppressMangling) { | |
| 825 constexpr char EmptyEmitString[] = ""; | 656 constexpr char EmptyEmitString[] = ""; |
| 826 return getConstantSym(Offset, {}, Name, EmptyEmitString, SuppressMangling); | 657 return getConstantSym(Offset, {}, Name, EmptyEmitString); |
| 827 } | 658 } |
| 828 | 659 |
| 829 Constant *GlobalContext::getConstantExternSym(const IceString &Name) { | 660 Constant *GlobalContext::getConstantExternSym(const IceString &Name) { |
| 830 constexpr RelocOffsetT Offset = 0; | 661 constexpr RelocOffsetT Offset = 0; |
| 831 constexpr bool SuppressMangling = true; | |
| 832 return getConstPool()->ExternRelocatables.getOrAdd( | 662 return getConstPool()->ExternRelocatables.getOrAdd( |
| 833 this, RelocatableTuple(Offset, {}, Name, SuppressMangling)); | 663 this, RelocatableTuple(Offset, {}, Name)); |
| 834 } | 664 } |
| 835 | 665 |
| 836 Constant *GlobalContext::getConstantUndef(Type Ty) { | 666 Constant *GlobalContext::getConstantUndef(Type Ty) { |
| 837 return getConstPool()->Undefs.getOrAdd(this, Ty); | 667 return getConstPool()->Undefs.getOrAdd(this, Ty); |
| 838 } | 668 } |
| 839 | 669 |
| 840 // All locking is done by the getConstant*() target function. | 670 // All locking is done by the getConstant*() target function. |
| 841 Constant *GlobalContext::getConstantZero(Type Ty) { | 671 Constant *GlobalContext::getConstantZero(Type Ty) { |
| 842 switch (Ty) { | 672 switch (Ty) { |
| 843 case IceType_i1: | 673 case IceType_i1: |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 // jump tables as pooled constants. | 760 // jump tables as pooled constants. |
| 931 RandomNumberGenerator RNG(getFlags().getRandomSeed(), | 761 RandomNumberGenerator RNG(getFlags().getRandomSeed(), |
| 932 RPE_PooledConstantReordering); | 762 RPE_PooledConstantReordering); |
| 933 RandomShuffle(JumpTables.begin(), JumpTables.end(), | 763 RandomShuffle(JumpTables.begin(), JumpTables.end(), |
| 934 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); | 764 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); |
| 935 } | 765 } |
| 936 return JumpTables; | 766 return JumpTables; |
| 937 } | 767 } |
| 938 | 768 |
| 939 JumpTableData & | 769 JumpTableData & |
| 940 GlobalContext::addJumpTable(IceString FuncName, SizeT Id, | 770 GlobalContext::addJumpTable(const IceString &FuncName, SizeT Id, |
| 941 const JumpTableData::TargetList &TargetList) { | 771 const JumpTableData::TargetList &TargetList) { |
| 942 auto JumpTableList = getJumpTableList(); | 772 auto JumpTableList = getJumpTableList(); |
| 943 JumpTableList->emplace_back(FuncName, Id, TargetList); | 773 JumpTableList->emplace_back(FuncName, Id, TargetList); |
| 944 return JumpTableList->back(); | 774 return JumpTableList->back(); |
| 945 } | 775 } |
| 946 | 776 |
| 947 TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) { | 777 TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) { |
| 948 if (!BuildDefs::dump()) | 778 if (!BuildDefs::dump()) |
| 949 return 0; | 779 return 0; |
| 950 auto Timers = getTimers(); | 780 auto Timers = getTimers(); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1023 | 853 |
| 1024 void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) { | 854 void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) { |
| 1025 if (!BuildDefs::dump()) | 855 if (!BuildDefs::dump()) |
| 1026 return; | 856 return; |
| 1027 auto Timers = getTimers(); | 857 auto Timers = getTimers(); |
| 1028 assert(Timers->size() > StackID); | 858 assert(Timers->size() > StackID); |
| 1029 OstreamLocker L(this); | 859 OstreamLocker L(this); |
| 1030 Timers->at(StackID).dump(getStrDump(), DumpCumulative); | 860 Timers->at(StackID).dump(getStrDump(), DumpCumulative); |
| 1031 } | 861 } |
| 1032 | 862 |
| 863 ClFlags GlobalContext::Flags; |
| 864 ClFlagsExtra GlobalContext::ExtraFlags; |
| 865 |
| 1033 void TimerMarker::push() { | 866 void TimerMarker::push() { |
| 1034 switch (StackID) { | 867 switch (StackID) { |
| 1035 case GlobalContext::TSK_Default: | 868 case GlobalContext::TSK_Default: |
| 1036 Active = Ctx->getFlags().getSubzeroTimingEnabled(); | 869 Active = Ctx->getFlags().getSubzeroTimingEnabled(); |
| 1037 break; | 870 break; |
| 1038 case GlobalContext::TSK_Funcs: | 871 case GlobalContext::TSK_Funcs: |
| 1039 Active = Ctx->getFlags().getTimeEachFunction(); | 872 Active = Ctx->getFlags().getTimeEachFunction(); |
| 1040 break; | 873 break; |
| 1041 default: | 874 default: |
| 1042 break; | 875 break; |
| 1043 } | 876 } |
| 1044 if (Active) | 877 if (Active) |
| 1045 Ctx->pushTimer(ID, StackID); | 878 Ctx->pushTimer(ID, StackID); |
| 1046 } | 879 } |
| 1047 | 880 |
| 1048 void TimerMarker::pushCfg(const Cfg *Func) { | 881 void TimerMarker::pushCfg(const Cfg *Func) { |
| 1049 Ctx = Func->getContext(); | 882 Ctx = Func->getContext(); |
| 1050 Active = | 883 Active = |
| 1051 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); | 884 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); |
| 1052 if (Active) | 885 if (Active) |
| 1053 Ctx->pushTimer(ID, StackID); | 886 Ctx->pushTimer(ID, StackID); |
| 1054 } | 887 } |
| 1055 | 888 |
| 1056 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); | 889 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); |
| 1057 | 890 |
| 1058 } // end of namespace Ice | 891 } // end of namespace Ice |
| OLD | NEW |