| 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 /// This file defines aspects of the compilation that persist across | 11 /// This file defines aspects of the compilation that persist across multiple |
| 12 /// multiple 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 "IceDefs.h" | 21 #include "IceDefs.h" |
| 22 #include "IceELFObjectWriter.h" | 22 #include "IceELFObjectWriter.h" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 41 return hash<Ice::IceString>()(Key.Name) + | 41 return hash<Ice::IceString>()(Key.Name) + |
| 42 hash<Ice::RelocOffsetT>()(Key.Offset); | 42 hash<Ice::RelocOffsetT>()(Key.Offset); |
| 43 } | 43 } |
| 44 }; | 44 }; |
| 45 } // end of namespace std | 45 } // end of namespace std |
| 46 | 46 |
| 47 namespace Ice { | 47 namespace Ice { |
| 48 | 48 |
| 49 namespace { | 49 namespace { |
| 50 | 50 |
| 51 // Define the key comparison function for the constant pool's | 51 // Define the key comparison function for the constant pool's unordered_map, |
| 52 // unordered_map, but only for key types of interest: integer types, | 52 // but only for key types of interest: integer types, floating point types, and |
| 53 // floating point types, and the special RelocatableTuple. | 53 // the special RelocatableTuple. |
| 54 template <typename KeyType, class Enable = void> struct KeyCompare {}; | 54 template <typename KeyType, class Enable = void> struct KeyCompare {}; |
| 55 | 55 |
| 56 template <typename KeyType> | 56 template <typename KeyType> |
| 57 struct KeyCompare<KeyType, | 57 struct KeyCompare<KeyType, |
| 58 typename std::enable_if< | 58 typename std::enable_if< |
| 59 std::is_integral<KeyType>::value || | 59 std::is_integral<KeyType>::value || |
| 60 std::is_same<KeyType, RelocatableTuple>::value>::type> { | 60 std::is_same<KeyType, RelocatableTuple>::value>::type> { |
| 61 bool operator()(const KeyType &Value1, const KeyType &Value2) const { | 61 bool operator()(const KeyType &Value1, const KeyType &Value2) const { |
| 62 return Value1 == Value2; | 62 return Value1 == Value2; |
| 63 } | 63 } |
| 64 }; | 64 }; |
| 65 template <typename KeyType> | 65 template <typename KeyType> |
| 66 struct KeyCompare<KeyType, typename std::enable_if< | 66 struct KeyCompare<KeyType, typename std::enable_if< |
| 67 std::is_floating_point<KeyType>::value>::type> { | 67 std::is_floating_point<KeyType>::value>::type> { |
| 68 bool operator()(const KeyType &Value1, const KeyType &Value2) const { | 68 bool operator()(const KeyType &Value1, const KeyType &Value2) const { |
| 69 return !memcmp(&Value1, &Value2, sizeof(KeyType)); | 69 return !memcmp(&Value1, &Value2, sizeof(KeyType)); |
| 70 } | 70 } |
| 71 }; | 71 }; |
| 72 | 72 |
| 73 // Define a key comparison function for sorting the constant pool's | 73 // Define a key comparison function for sorting the constant pool's values |
| 74 // values after they are dumped to a vector. This covers integer | 74 // after they are dumped to a vector. This covers integer types, floating point |
| 75 // types, floating point types, and ConstantRelocatable values. | 75 // types, and ConstantRelocatable values. |
| 76 template <typename ValueType, class Enable = void> struct KeyCompareLess {}; | 76 template <typename ValueType, class Enable = void> struct KeyCompareLess {}; |
| 77 | 77 |
| 78 template <typename ValueType> | 78 template <typename ValueType> |
| 79 struct KeyCompareLess<ValueType, | 79 struct KeyCompareLess<ValueType, |
| 80 typename std::enable_if<std::is_floating_point< | 80 typename std::enable_if<std::is_floating_point< |
| 81 typename ValueType::PrimType>::value>::type> { | 81 typename ValueType::PrimType>::value>::type> { |
| 82 bool operator()(const Constant *Const1, const Constant *Const2) const { | 82 bool operator()(const Constant *Const1, const Constant *Const2) const { |
| 83 using CompareType = uint64_t; | 83 using CompareType = uint64_t; |
| 84 static_assert(sizeof(typename ValueType::PrimType) <= sizeof(CompareType), | 84 static_assert(sizeof(typename ValueType::PrimType) <= sizeof(CompareType), |
| 85 "Expected floating-point type of width 64-bit or less"); | 85 "Expected floating-point type of width 64-bit or less"); |
| (...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 } | 594 } |
| 595 } | 595 } |
| 596 if (Found) { | 596 if (Found) { |
| 597 NewName[NewPos++] = OldName[OldPos++]; // 'S' | 597 NewName[NewPos++] = OldName[OldPos++]; // 'S' |
| 598 size_t Length = Last - OldPos; | 598 size_t Length = Last - OldPos; |
| 599 // NewPos and OldPos point just past the 'S'. | 599 // NewPos and OldPos point just past the 'S'. |
| 600 assert(NewName[NewPos - 1] == 'S'); | 600 assert(NewName[NewPos - 1] == 'S'); |
| 601 assert(OldName[OldPos - 1] == 'S'); | 601 assert(OldName[OldPos - 1] == 'S'); |
| 602 assert(OldName[OldPos + Length] == '_'); | 602 assert(OldName[OldPos + Length] == '_'); |
| 603 if (AllZs) { | 603 if (AllZs) { |
| 604 // Replace N 'Z' characters with a '0' (if N=0) or '1' (if | 604 // Replace N 'Z' characters with a '0' (if N=0) or '1' (if N>0) |
| 605 // N>0) followed by N '0' characters. | 605 // followed by N '0' characters. |
| 606 NewName[NewPos++] = (Length ? '1' : '0'); | 606 NewName[NewPos++] = (Length ? '1' : '0'); |
| 607 for (size_t i = 0; i < Length; ++i) { | 607 for (size_t i = 0; i < Length; ++i) { |
| 608 NewName[NewPos++] = '0'; | 608 NewName[NewPos++] = '0'; |
| 609 } | 609 } |
| 610 } else { | 610 } else { |
| 611 // Iterate right-to-left and increment the base-36 number. | 611 // Iterate right-to-left and increment the base-36 number. |
| 612 bool Carry = true; | 612 bool Carry = true; |
| 613 for (size_t i = 0; i < Length; ++i) { | 613 for (size_t i = 0; i < Length; ++i) { |
| 614 size_t Offset = Length - 1 - i; | 614 size_t Offset = Length - 1 - i; |
| 615 char Ch = OldName[OldPos + Offset]; | 615 char Ch = OldName[OldPos + Offset]; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 635 OldPos = Last; | 635 OldPos = Last; |
| 636 // Fall through and let the '_' be copied across. | 636 // Fall through and let the '_' be copied across. |
| 637 } | 637 } |
| 638 } | 638 } |
| 639 NewName[NewPos] = OldName[OldPos]; | 639 NewName[NewPos] = OldName[OldPos]; |
| 640 } | 640 } |
| 641 assert(NewName[NewPos] == '\0'); | 641 assert(NewName[NewPos] == '\0'); |
| 642 OldName = NewName; | 642 OldName = NewName; |
| 643 } | 643 } |
| 644 | 644 |
| 645 // In this context, name mangling means to rewrite a symbol using a | 645 // In this context, name mangling means to rewrite a symbol using a given |
| 646 // given prefix. For a C++ symbol, nest the original symbol inside | 646 // prefix. For a C++ symbol, nest the original symbol inside the "prefix" |
| 647 // the "prefix" namespace. For other symbols, just prepend the | 647 // namespace. For other symbols, just prepend the prefix. |
| 648 // prefix. | |
| 649 IceString GlobalContext::mangleName(const IceString &Name) const { | 648 IceString GlobalContext::mangleName(const IceString &Name) const { |
| 650 // An already-nested name like foo::bar() gets pushed down one | 649 // An already-nested name like foo::bar() gets pushed down one level, making |
| 651 // level, making it equivalent to Prefix::foo::bar(). | 650 // it equivalent to Prefix::foo::bar(). |
| 652 // _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz | 651 // _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz |
| 653 // A non-nested but mangled name like bar() gets nested, making it | 652 // A non-nested but mangled name like bar() gets nested, making it equivalent |
| 654 // equivalent to Prefix::bar(). | 653 // to Prefix::bar(). |
| 655 // _Z3barxyz ==> ZN6Prefix3barExyz | 654 // _Z3barxyz ==> ZN6Prefix3barExyz |
| 656 // An unmangled, extern "C" style name, gets a simple prefix: | 655 // An unmangled, extern "C" style name, gets a simple prefix: |
| 657 // bar ==> Prefixbar | 656 // bar ==> Prefixbar |
| 658 if (!BuildDefs::dump() || getFlags().getTestPrefix().empty()) | 657 if (!BuildDefs::dump() || getFlags().getTestPrefix().empty()) |
| 659 return Name; | 658 return Name; |
| 660 | 659 |
| 661 const IceString &TestPrefix = getFlags().getTestPrefix(); | 660 const IceString &TestPrefix = getFlags().getTestPrefix(); |
| 662 unsigned PrefixLength = TestPrefix.length(); | 661 unsigned PrefixLength = TestPrefix.length(); |
| 663 ManglerVector NameBase(1 + Name.length()); | 662 ManglerVector NameBase(1 + Name.length()); |
| 664 const size_t BufLen = 30 + Name.length() + PrefixLength; | 663 const size_t BufLen = 30 + Name.length() + PrefixLength; |
| 665 ManglerVector NewName(BufLen); | 664 ManglerVector NewName(BufLen); |
| 666 uint32_t BaseLength = 0; // using uint32_t due to sscanf format string | 665 uint32_t BaseLength = 0; // using uint32_t due to sscanf format string |
| 667 | 666 |
| 668 int ItemsParsed = sscanf(Name.c_str(), "_ZN%s", NameBase.data()); | 667 int ItemsParsed = sscanf(Name.c_str(), "_ZN%s", NameBase.data()); |
| 669 if (ItemsParsed == 1) { | 668 if (ItemsParsed == 1) { |
| 670 // Transform _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz | 669 // Transform _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz |
| 671 // (splice in "6Prefix") ^^^^^^^ | 670 // (splice in "6Prefix") ^^^^^^^ |
| 672 snprintf(NewName.data(), BufLen, "_ZN%u%s%s", PrefixLength, | 671 snprintf(NewName.data(), BufLen, "_ZN%u%s%s", PrefixLength, |
| 673 TestPrefix.c_str(), NameBase.data()); | 672 TestPrefix.c_str(), NameBase.data()); |
| 674 // We ignore the snprintf return value (here and below). If we | 673 // We ignore the snprintf return value (here and below). If we somehow |
| 675 // somehow miscalculated the output buffer length, the output will | 674 // miscalculated the output buffer length, the output will be truncated, |
| 676 // be truncated, but it will be truncated consistently for all | 675 // but it will be truncated consistently for all mangleName() calls on the |
| 677 // mangleName() calls on the same input string. | 676 // same input string. |
| 678 incrementSubstitutions(NewName); | 677 incrementSubstitutions(NewName); |
| 679 return NewName.data(); | 678 return NewName.data(); |
| 680 } | 679 } |
| 681 | 680 |
| 682 // Artificially limit BaseLength to 9 digits (less than 1 billion) | 681 // Artificially limit BaseLength to 9 digits (less than 1 billion) because |
| 683 // because sscanf behavior is undefined on integer overflow. If | 682 // sscanf behavior is undefined on integer overflow. If there are more than 9 |
| 684 // there are more than 9 digits (which we test by looking at the | 683 // digits (which we test by looking at the beginning of NameBase), then we |
| 685 // beginning of NameBase), then we consider this a failure to parse | 684 // consider this a failure to parse a namespace mangling, and fall back to |
| 686 // a namespace mangling, and fall back to the simple prefixing. | 685 // the simple prefixing. |
| 687 ItemsParsed = sscanf(Name.c_str(), "_Z%9u%s", &BaseLength, NameBase.data()); | 686 ItemsParsed = sscanf(Name.c_str(), "_Z%9u%s", &BaseLength, NameBase.data()); |
| 688 if (ItemsParsed == 2 && BaseLength <= strlen(NameBase.data()) && | 687 if (ItemsParsed == 2 && BaseLength <= strlen(NameBase.data()) && |
| 689 !isdigit(NameBase[0])) { | 688 !isdigit(NameBase[0])) { |
| 690 // Transform _Z3barxyz ==> _ZN6Prefix3barExyz | 689 // Transform _Z3barxyz ==> _ZN6Prefix3barExyz |
| 691 // ^^^^^^^^ ^ | 690 // ^^^^^^^^ ^ |
| 692 // (splice in "N6Prefix", and insert "E" after "3bar") | 691 // (splice in "N6Prefix", and insert "E" after "3bar") But an "I" after the |
| 693 // But an "I" after the identifier indicates a template argument | 692 // identifier indicates a template argument list terminated with "E"; |
| 694 // list terminated with "E"; insert the new "E" before/after the | 693 // insert the new "E" before/after the old "E". E.g.: |
| 695 // old "E". E.g.: | |
| 696 // Transform _Z3barIabcExyz ==> _ZN6Prefix3barIabcEExyz | 694 // Transform _Z3barIabcExyz ==> _ZN6Prefix3barIabcEExyz |
| 697 // ^^^^^^^^ ^ | 695 // ^^^^^^^^ ^ |
| 698 // (splice in "N6Prefix", and insert "E" after "3barIabcE") | 696 // (splice in "N6Prefix", and insert "E" after "3barIabcE") |
| 699 ManglerVector OrigName(Name.length()); | 697 ManglerVector OrigName(Name.length()); |
| 700 ManglerVector OrigSuffix(Name.length()); | 698 ManglerVector OrigSuffix(Name.length()); |
| 701 uint32_t ActualBaseLength = BaseLength; | 699 uint32_t ActualBaseLength = BaseLength; |
| 702 if (NameBase[ActualBaseLength] == 'I') { | 700 if (NameBase[ActualBaseLength] == 'I') { |
| 703 ++ActualBaseLength; | 701 ++ActualBaseLength; |
| 704 while (NameBase[ActualBaseLength] != 'E' && | 702 while (NameBase[ActualBaseLength] != 'E' && |
| 705 NameBase[ActualBaseLength] != '\0') | 703 NameBase[ActualBaseLength] != '\0') |
| (...skipping 17 matching lines...) Expand all Loading... |
| 723 GlobalContext::~GlobalContext() { | 721 GlobalContext::~GlobalContext() { |
| 724 llvm::DeleteContainerPointers(AllThreadContexts); | 722 llvm::DeleteContainerPointers(AllThreadContexts); |
| 725 LockedPtr<DestructorArray> Dtors = getDestructors(); | 723 LockedPtr<DestructorArray> Dtors = getDestructors(); |
| 726 // Destructors are invoked in the opposite object construction order. | 724 // Destructors are invoked in the opposite object construction order. |
| 727 for (auto DtorIter = Dtors->crbegin(); DtorIter != Dtors->crend(); | 725 for (auto DtorIter = Dtors->crbegin(); DtorIter != Dtors->crend(); |
| 728 ++DtorIter) { | 726 ++DtorIter) { |
| 729 (*DtorIter)(); | 727 (*DtorIter)(); |
| 730 } | 728 } |
| 731 } | 729 } |
| 732 | 730 |
| 733 // TODO(stichnot): Consider adding thread-local caches of constant | 731 // TODO(stichnot): Consider adding thread-local caches of constant pool entries |
| 734 // pool entries to reduce contention. | 732 // to reduce contention. |
| 735 | 733 |
| 736 // All locking is done by the getConstantInt[0-9]+() target function. | 734 // All locking is done by the getConstantInt[0-9]+() target function. |
| 737 Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) { | 735 Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) { |
| 738 switch (Ty) { | 736 switch (Ty) { |
| 739 case IceType_i1: | 737 case IceType_i1: |
| 740 return getConstantInt1(Value); | 738 return getConstantInt1(Value); |
| 741 case IceType_i8: | 739 case IceType_i8: |
| 742 return getConstantInt8(Value); | 740 return getConstantInt8(Value); |
| 743 case IceType_i16: | 741 case IceType_i16: |
| 744 return getConstantInt16(Value); | 742 return getConstantInt16(Value); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 868 } | 866 } |
| 869 llvm_unreachable("Unknown type"); | 867 llvm_unreachable("Unknown type"); |
| 870 } | 868 } |
| 871 | 869 |
| 872 ConstantList GlobalContext::getConstantExternSyms() { | 870 ConstantList GlobalContext::getConstantExternSyms() { |
| 873 return getConstPool()->ExternRelocatables.getConstantPool(); | 871 return getConstPool()->ExternRelocatables.getConstantPool(); |
| 874 } | 872 } |
| 875 | 873 |
| 876 JumpTableDataList GlobalContext::getJumpTables() { | 874 JumpTableDataList GlobalContext::getJumpTables() { |
| 877 JumpTableDataList JumpTables(*getJumpTableList()); | 875 JumpTableDataList JumpTables(*getJumpTableList()); |
| 878 // Make order deterministic by sorting into functions and then ID of the | 876 // Make order deterministic by sorting into functions and then ID of the jump |
| 879 // jump table within that function. | 877 // table within that function. |
| 880 std::sort(JumpTables.begin(), JumpTables.end(), | 878 std::sort(JumpTables.begin(), JumpTables.end(), |
| 881 [](const JumpTableData &A, const JumpTableData &B) { | 879 [](const JumpTableData &A, const JumpTableData &B) { |
| 882 if (A.getFunctionName() != B.getFunctionName()) | 880 if (A.getFunctionName() != B.getFunctionName()) |
| 883 return A.getFunctionName() < B.getFunctionName(); | 881 return A.getFunctionName() < B.getFunctionName(); |
| 884 return A.getId() < B.getId(); | 882 return A.getId() < B.getId(); |
| 885 }); | 883 }); |
| 886 | 884 |
| 887 if (getFlags().shouldReorderPooledConstants()) { | 885 if (getFlags().shouldReorderPooledConstants()) { |
| 888 // If reorder-pooled-constants option is set to true, we also shuffle the | 886 // If reorder-pooled-constants option is set to true, we also shuffle the |
| 889 // jump tables before emitting them. | 887 // jump tables before emitting them. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 939 Timers->at(StackID).reset(); | 937 Timers->at(StackID).reset(); |
| 940 } | 938 } |
| 941 | 939 |
| 942 void GlobalContext::setTimerName(TimerStackIdT StackID, | 940 void GlobalContext::setTimerName(TimerStackIdT StackID, |
| 943 const IceString &NewName) { | 941 const IceString &NewName) { |
| 944 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers; | 942 auto Timers = &ICE_TLS_GET_FIELD(TLS)->Timers; |
| 945 assert(StackID < Timers->size()); | 943 assert(StackID < Timers->size()); |
| 946 Timers->at(StackID).setName(NewName); | 944 Timers->at(StackID).setName(NewName); |
| 947 } | 945 } |
| 948 | 946 |
| 949 // Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr | 947 // Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr at the |
| 950 // at the interface to take and transfer ownership, but they | 948 // interface to take and transfer ownership, but they internally store the raw |
| 951 // internally store the raw Cfg pointer in the work queue. This | 949 // Cfg pointer in the work queue. This allows e.g. future queue optimizations |
| 952 // allows e.g. future queue optimizations such as the use of atomics | 950 // such as the use of atomics to modify queue elements. |
| 953 // to modify queue elements. | |
| 954 void GlobalContext::optQueueBlockingPush(std::unique_ptr<Cfg> Func) { | 951 void GlobalContext::optQueueBlockingPush(std::unique_ptr<Cfg> Func) { |
| 955 assert(Func); | 952 assert(Func); |
| 956 OptQ.blockingPush(Func.release()); | 953 OptQ.blockingPush(Func.release()); |
| 957 if (getFlags().isSequential()) | 954 if (getFlags().isSequential()) |
| 958 translateFunctions(); | 955 translateFunctions(); |
| 959 } | 956 } |
| 960 | 957 |
| 961 std::unique_ptr<Cfg> GlobalContext::optQueueBlockingPop() { | 958 std::unique_ptr<Cfg> GlobalContext::optQueueBlockingPop() { |
| 962 return std::unique_ptr<Cfg>(OptQ.blockingPop()); | 959 return std::unique_ptr<Cfg>(OptQ.blockingPop()); |
| 963 } | 960 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 Ctx = Func->getContext(); | 1009 Ctx = Func->getContext(); |
| 1013 Active = | 1010 Active = |
| 1014 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); | 1011 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); |
| 1015 if (Active) | 1012 if (Active) |
| 1016 Ctx->pushTimer(ID, StackID); | 1013 Ctx->pushTimer(ID, StackID); |
| 1017 } | 1014 } |
| 1018 | 1015 |
| 1019 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); | 1016 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); |
| 1020 | 1017 |
| 1021 } // end of namespace Ice | 1018 } // end of namespace Ice |
| OLD | NEW |