Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -395,6 +395,10 @@ option(LLVM_ENABLE_PEDANTIC "Compile with pedantic enabled." ON) option(LLVM_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF) +if (MSVC) + option(LLVM_ENABLE_INCREMENTAL_LINK "Link incrementally. Enabling it might produce slower executables." OFF) +endif() + option(LLVM_ENABLE_DUMP "Enable dump functions even when assertions are disabled" OFF) if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" ) Index: cmake/modules/ChooseMSVCCRT.cmake =================================================================== --- cmake/modules/ChooseMSVCCRT.cmake +++ cmake/modules/ChooseMSVCCRT.cmake @@ -50,6 +50,17 @@ set(${flagsvar} "${${flagsvar}}" CACHE STRING "${flagsvar_docs}" FORCE) endmacro(set_flag_in_var) +macro(disable_MT_if_LLDB build message) + if (LLVM_TOOL_LLDB_BUILD) + if ((NOT ${build} STREQUAL "DEBUG") AND (LLVM_USE_CRT_${build} STREQUAL "MT")) + if (LLVM_TOOL_CLANG_BUILD OR LLVM_TOOL_LLD_BUILD) + set(performance " This might impact runtime performance for Clang or LLD. Preferably build them separately.") + endif() + message(WARNING "${message}.${performance}") + set(LLVM_USE_CRT_${build} "MD") + endif() + endif() +endmacro(disable_MT_if_LLDB) macro(choose_msvc_crt MSVC_CRT) if(LLVM_USE_CRT) @@ -66,6 +77,20 @@ get_current_crt(LLVM_USE_CRT_${build} MSVC_CRT_REGEX CMAKE_CXX_FLAGS_${build}) + + # Make /MT the default in Release builds to make them faster + # and avoid the DLL function thunking. + if ((${build} STREQUAL "MINSIZEREL") OR + (${build} STREQUAL "RELEASE") OR + (${build} STREQUAL "RELWITHDEBINFO")) + set(LLVM_USE_CRT_${build} "MT") + endif() + if (${build} STREQUAL "DEBUG") + set(LLVM_USE_CRT_${build} "MTd") + endif() + + disable_MT_if_LLDB(${build} "Using /MD as required by LLDB") + set(LLVM_USE_CRT_${build} "${LLVM_USE_CRT_${build}}" CACHE STRING "Specify VC++ CRT to use for ${build_type} configurations." @@ -72,7 +97,9 @@ FORCE) set_property(CACHE LLVM_USE_CRT_${build} PROPERTY STRINGS ;${${MSVC_CRT}}) - endif(NOT LLVM_USE_CRT_${build}) + else() + disable_MT_if_LLDB(${build} "Disabling /MT as required by LLDB") + endif() endforeach(build_type) foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE}) Index: cmake/modules/HandleLLVMOptions.cmake =================================================================== --- cmake/modules/HandleLLVMOptions.cmake +++ cmake/modules/HandleLLVMOptions.cmake @@ -403,6 +403,14 @@ # "Enforce type conversion rules". append("/Zc:rvalueCast" CMAKE_CXX_FLAGS) + if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC" AND NOT LLVM_ENABLE_INCREMENTAL_LINK) + foreach(CONFIG RELEASE RELWITHDEBINFO MINSIZEREL) + foreach(FLAG EXE MODULE SHARED STATIC) + string(REGEX REPLACE "[-/](INCREMENTAL:YES|INCREMENTAL:NO|INCREMENTAL)" "/INCREMENTAL:NO" CMAKE_${FLAG}_LINKER_FLAGS_${CONFIG} "${CMAKE_${FLAG}_LINKER_FLAGS_${CONFIG}}") + endforeach() + endforeach() + endif() + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT LLVM_ENABLE_LTO) # clang-cl and cl by default produce non-deterministic binaries because # link.exe /incremental requires a timestamp in the .obj file. clang-cl Index: include/llvm/ADT/GlobalTypeDenseMap.h =================================================================== --- include/llvm/ADT/GlobalTypeDenseMap.h +++ include/llvm/ADT/GlobalTypeDenseMap.h @@ -0,0 +1,354 @@ +//===- llvm/ADT/GlobalTypeDenseMap.h - Dense probed hash table ------------*- +// C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the GlobalTypeDenseMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_GLOBALTYPEDENSEMAP_H +#define LLVM_DEBUGINFO_CODEVIEW_GLOBALTYPEDENSEMAP_H + +#include "llvm/DebugInfo/CodeView/TypeHashing.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Memory.h" +#include "llvm/Support/ReverseIteration.h" +#include "llvm/Support/type_traits.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace llvm { +namespace codeview { + +struct GloballyHashedInfo { + static unsigned getHash(uint64_t Key, unsigned BucketMask) { + return (Key >> 32) & BucketMask; + } + void packKeyValue(uint64_t Key, uint32_t Value, + unsigned BucketNo, unsigned BucketMask) { + KV = (Key & ~((uint64_t)BucketMask << 32)) | ((uint64_t)(Value & BucketMask) << 32); + //auto T = extractKeyValue(BucketNo, BucketMask); + //assert((T == std::pair(Key, Value))); + } + std::pair extractKeyValue(unsigned BucketNo, + unsigned BucketMask) const { + uint64_t K = + (KV & ~((uint64_t)BucketMask << 32)) | ((uint64_t)BucketNo << 32); + uint32_t V = (KV >> 32) & BucketMask; + return {K, V}; + } + bool isEmpty() const { return !KV; } + unsigned isEqualOrEmpty(const uint64_t Other, unsigned BucketNo, + unsigned BucketMask) const { + if (!KV) + return 2; // empty + auto Extracted = extractKeyValue(BucketNo, BucketMask); + if (Extracted.first == Other) + return 1; // equal + return 0; + } + uint64_t KV; +}; + +template +class GlobalTypeDenseMap { +public: + LLVM_NODISCARD bool empty() const { return getNumEntries() == 0; } + unsigned size() const { return getNumEntries(); } + + uint64_t getBucketsMask() const { return getNumBuckets() - 1; } + + struct iterator { + iterator(unsigned O, BucketT *B, unsigned M) + : Offset(O), Bucket(B), Mask(M) {} + + unsigned Offset; /*hashed location (offset)*/ + BucketT *Bucket; /*real key-value location (with collisions)*/ + unsigned Mask; + + ValueT getValue() { + auto KV = Bucket->extractKeyValue(Offset, Mask); + return KV.second; + } + void setValue(ValueT V) { + auto KV = Bucket->extractKeyValue(Offset, Mask); + Bucket->packKeyValue(KV.first, V, Offset, Mask); + } + }; + + // Inserts key,value pair into the map if the key isn't already in the map. + // The value is constructed in-place if the key is not in the map, otherwise + // it is not moved. + template + std::pair + try_emplace(const KeyT &Key, const uint32_t &Value, + RehashFunc Rehash) { + uint64_t InsertKey = *(uint64_t *)&Key; + + auto R = LookupBucketFor(InsertKey); + if (std::get<2>(R) /*already there*/) + return {{std::get<0>(R), std::get<1>(R), (unsigned)getBucketsMask()}, + false /*not inserted*/}; + + // Otherwise, insert the new element. + auto I = InsertIntoBucket({std::get<0>(R), std::get<1>(R)}, InsertKey, Value, Rehash); + return {{std::get<0>(I), std::get<1>(I), (unsigned)getBucketsMask()}, + true /*inserted*/}; + } + +protected: + + /// Returns the number of buckets to allocate to ensure that the + /// GlobalTypeDenseMap can accommodate \p NumEntries without need to grow(). + unsigned getMinBucketToReserveForEntries(unsigned NumEntries) { + // Ensure that "NumEntries * 4 < NumBuckets * 3" + if (NumEntries == 0) + return 0; + // +1 is required because of the strict equality. + // For example if NumEntries is 48, we need to return 401. + return NextPowerOf2(NumEntries * 4 / 3 + 1); + } + +private: + + void incrementNumEntries() { setNumEntries(getNumEntries() + 1); } + + void decrementNumEntries() { setNumEntries(getNumEntries() - 1); } + + BucketT *getBucketsEnd() { return getBuckets() + getNumBuckets(); } + + const BucketT *getBucketsEnd() const { + return getBuckets() + getNumBuckets(); + } + + template + std::pair + InsertIntoBucket(std::pair TheBucket, + const uint64_t &Key, const uint32_t &Value, + RehashFunc Rehash) { + // If the load of the hash table is more than 3/4, grow the table. + // + // The later case is tricky. For example, if we had one empty bucket with + // tons of tombstones, failing lookups (e.g. for insertion) would have to + // probe almost the entire table until it found the empty bucket. If the + // table completely filled with tombstones, no lookup would ever succeed, + // causing infinite loops in lookup. + unsigned NewNumEntries = getNumEntries() + 1; + unsigned NumBuckets = getNumBuckets(); + if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) { + NumEntries = 0; + grow(NumBuckets * 2, Rehash); + auto R = LookupBucketFor(Key); + assert(!std::get<2>(R)); + TheBucket = {std::get<0>(R), std::get<1>(R)}; + } + assert(std::get<1>(TheBucket)); + + // Only update the state after we've grown our bucket space appropriately + // so that when growing buckets we have self-consistent entry count. + incrementNumEntries(); + + std::get<1>(TheBucket)->packKeyValue(Key, Value, std::get<0>(TheBucket), + getBucketsMask()); + return TheBucket; + } + + /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in + /// FoundBucket. If the bucket contains the key and a value, this returns + /// true, otherwise it returns a bucket with an empty marker or tombstone and + /// returns false. + std::tuple + LookupBucketFor(const uint64_t &Key) { + if (getNumBuckets() == 0) + return {0, nullptr, false}; + + assert(Key && "Empty value shouldn't be inserted into map!"); + + BucketT *BucketsPtr = getBuckets(); + const unsigned BucketsMask = getBucketsMask(); + unsigned BucketNo = BucketT::getHash(Key, BucketsMask); + unsigned InitialBucketNo = BucketNo; + unsigned ProbeAmt = 1; + //BucketT *LastBucket = nullptr; + //unsigned CacheLines = 0; + HashTableStats::State S; + while (true) { + BucketT *ThisBucket = BucketsPtr + BucketNo; + + /*if (ProbeAmt > MaxProbes) + MaxProbes = ProbeAmt; + if (ProbeAmt <= MAX_PROBES) + Probes[ProbeAmt - 1]++; + if (((size_t)ThisBucket & ~63) != ((size_t)LastBucket & ~63)) { + CacheLines++; + if (CacheLines > MaxCacheProbes) + MaxCacheProbes = CacheLines; + } + if (CacheLines <= MAX_CACHE_PROBES) + CacheProbes[CacheLines - 1]++;*/ + Stats.updateOnAccess(S, ProbeAmt, ThisBucket); + + auto R = ThisBucket->isEqualOrEmpty(Key, InitialBucketNo, BucketsMask); + if (LLVM_LIKELY(R)) { + return {InitialBucketNo, ThisBucket, + R == 1 ? true /*bucket equals provided Key*/ + : false /*bucket empty*/}; + } + + //LastBucket = ThisBucket; + // Otherwise, it's a hash collision, continue quadratic probing. + BucketNo += ProbeAmt++; + BucketNo &= BucketsMask; + } + } + +public: + /// Return the approximate size (in bytes) of the actual map. + /// This is just the raw memory used by GlobalTypeDenseMap. + /// If entries are pointers to objects, the size of the referenced objects + /// are not included. + size_t getMemorySize() const { return getNumBuckets() * sizeof(BucketT); } + +private: + + struct HashTableStats { + struct State { + unsigned CacheLines{}; + void *PrevBucket{}; + }; + void updateOnAccess(State &S, unsigned ProbeAmt, void *Bucket) { + if (ProbeAmt > MaxProbes) + MaxProbes = ProbeAmt; + if (ProbeAmt <= MAX_PROBES) + Probes[ProbeAmt - 1]++; + if (((size_t)Bucket & ~63) != ((size_t)S.PrevBucket & ~63)) { + S.CacheLines++; + if (S.CacheLines > MaxCacheProbes) + MaxCacheProbes = S.CacheLines; + } + if (S.CacheLines <= MAX_CACHE_PROBES) + CacheProbes[S.CacheLines - 1]++; + S.PrevBucket = Bucket; + } + + unsigned MaxProbes = 0; + enum { MAX_PROBES = 256 }; + unsigned Probes[MAX_PROBES]{}; + unsigned MaxCacheProbes = 0; + enum { MAX_CACHE_PROBES = 128 }; + unsigned CacheProbes[MAX_CACHE_PROBES]{}; + }; + + BucketT *Buckets = nullptr; + unsigned NumEntries = 0; + unsigned NumBuckets = 0; + llvm::sys::MemoryBlock MB; + HashTableStats Stats; + + /*unsigned MaxProbes = 0; + enum { MAX_PROBES = 256 }; + unsigned Probes[MAX_PROBES]{}; + unsigned MaxCacheProbes = 0; + enum { MAX_CACHE_PROBES = 128 }; + unsigned CacheProbes[MAX_CACHE_PROBES]{};*/ + +public: + GlobalTypeDenseMap() { init(0); } + + ~GlobalTypeDenseMap() { + deleteBuckets(MB); + Buckets = nullptr; + NumBuckets = 0; + NumEntries = 0; + } + + void init(unsigned InitNumEntries) { + auto InitBuckets = getMinBucketToReserveForEntries(InitNumEntries); + allocateBuckets(InitBuckets); + } + + template + void grow(unsigned AtLeast, RehashFunc Rehash) { + BucketT *OldBuckets = Buckets; + unsigned NewNumBuckets = std::max( + 64, static_cast(NextPowerOf2(AtLeast - 1))); + allocateBuckets(NewNumBuckets); + assert(Buckets); + if (OldBuckets) + Rehash(); + } + +private: + unsigned getNumEntries() const { return NumEntries; } + + void setNumEntries(unsigned Num) { NumEntries = Num; } + + BucketT *getBuckets() const { return Buckets; } + + unsigned getNumBuckets() const { return NumBuckets; } + + bool allocateBuckets(unsigned Num) { + if (Num == 0) + return false; + + size_t BlockSize = sizeof(BucketT) * Num; + + if (MB.allocatedSize()) { + BucketT *MBEnd = (BucketT *)((uint8_t *)MB.base() + MB.allocatedSize()); + if ((Buckets + NumBuckets + Num) <= MBEnd) { + Buckets += NumBuckets; + NumBuckets = Num; + return true; + } + if (BlockSize <= MB.allocatedSize()) { + ::memset(MB.base(), 0, BlockSize); + Buckets = (BucketT *)MB.base(); + NumBuckets = Num; + return true; + } + } + + deleteBuckets(MB); + + const unsigned TwoMegs = 1 << 21; + const unsigned Nb2MegPages = (BlockSize + TwoMegs - 1) / TwoMegs; + + const unsigned Flags = + sys::Memory::MF_READ | sys::Memory::MF_WRITE | sys::Memory::MF_HUGE_HINT; + + std::error_code EC; + MB = llvm::sys::Memory::allocateMappedMemory(Nb2MegPages * TwoMegs, nullptr, + Flags, EC); + Buckets = static_cast(MB.base()); + assert(Buckets); + NumBuckets = Num; + return true; + } + static void deleteBuckets(llvm::sys::MemoryBlock &MB) { + if (MB.allocatedSize()) { + llvm::sys::Memory::releaseMappedMemory(MB); + } + } +}; +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_GLOBALTYPEDENSEMAP_H Index: include/llvm/ADT/StringMap.h =================================================================== --- include/llvm/ADT/StringMap.h +++ include/llvm/ADT/StringMap.h @@ -30,6 +30,34 @@ namespace llvm { +struct HashTableStats { + struct State { + unsigned CacheLines{}; + void* PrevBucket{}; + }; + void updateOnAccess(State& S, unsigned ProbeAmt, void* Bucket) { + if (ProbeAmt > MaxProbes) + MaxProbes = ProbeAmt; + if (ProbeAmt <= MAX_PROBES) + Probes[ProbeAmt - 1]++; + if (((size_t)Bucket & ~63) != ((size_t)S.PrevBucket & ~63)) { + S.CacheLines++; + if (S.CacheLines > MaxCacheProbes) + MaxCacheProbes = S.CacheLines; + } + if (S.CacheLines <= MAX_CACHE_PROBES) + CacheProbes[S.CacheLines - 1]++; + S.PrevBucket = Bucket; + } + + unsigned MaxProbes = 0; + enum { MAX_PROBES = 256 }; + unsigned Probes[MAX_PROBES]{}; + unsigned MaxCacheProbes = 0; + enum { MAX_CACHE_PROBES = 128 }; + unsigned CacheProbes[MAX_CACHE_PROBES]{}; +}; + template class StringMapConstIterator; template class StringMapIterator; template class StringMapKeyIterator; @@ -56,6 +84,7 @@ unsigned NumItems = 0; unsigned NumTombstones = 0; unsigned ItemSize; + static HashTableStats Stats; protected: explicit StringMapImpl(unsigned itemSize) Index: include/llvm/ADT/iterator_range.h =================================================================== --- include/llvm/ADT/iterator_range.h +++ include/llvm/ADT/iterator_range.h @@ -18,6 +18,7 @@ #ifndef LLVM_ADT_ITERATOR_RANGE_H #define LLVM_ADT_ITERATOR_RANGE_H +#include #include #include @@ -27,23 +28,41 @@ /// /// This just wraps two iterators into a range-compatible interface. Nothing /// fancy at all. -template -class iterator_range { +template class iterator_range { IteratorT begin_iterator, end_iterator; + size_t Length{}; + bool LengthSet{false}; public: - //TODO: Add SFINAE to test that the Container's iterators match the range's + // TODO: Add SFINAE to test that the Container's iterators match the range's // iterators. template iterator_range(Container &&c) - //TODO: Consider ADL/non-member begin/end calls. + // TODO: Consider ADL/non-member begin/end calls. : begin_iterator(c.begin()), end_iterator(c.end()) {} - iterator_range(IteratorT begin_iterator, IteratorT end_iterator) + iterator_range(IteratorT begin_iterator, IteratorT end_iterator, + Optional RangeLength = None) : begin_iterator(std::move(begin_iterator)), - end_iterator(std::move(end_iterator)) {} + end_iterator(std::move(end_iterator)) { + if (RangeLength) { + Length = *RangeLength; + LengthSet = true; + } + } IteratorT begin() const { return begin_iterator; } IteratorT end() const { return end_iterator; } + + size_t size() const { + assert(LengthSet && "Range length not set for this iterator! Use iteration " + "instead to determine the size!"); + return Length; + } + bool empty() const { + if (LengthSet) + return !Length; + return begin() == end(); + } }; /// Convenience function for iterating over sub-ranges. @@ -50,12 +69,16 @@ /// /// This provides a bit of syntactic sugar to make using sub-ranges /// in for loops a bit easier. Analogous to std::make_pair(). -template iterator_range make_range(T x, T y) { - return iterator_range(std::move(x), std::move(y)); +template +iterator_range make_range(T x, T y, Optional RangeLength = None) { + return iterator_range(std::move(x), std::move(y), RangeLength); } -template iterator_range make_range(std::pair p) { - return iterator_range(std::move(p.first), std::move(p.second)); +template +iterator_range make_range(std::pair p, + Optional RangeLength = None) { + return iterator_range(std::move(p.first), std::move(p.second), + RangeLength); } template @@ -63,6 +86,6 @@ int n) { return make_range(std::next(adl_begin(t), n), adl_end(t)); } -} +} // namespace llvm #endif Index: include/llvm/Analysis/LoopAccessAnalysis.h =================================================================== --- include/llvm/Analysis/LoopAccessAnalysis.h +++ include/llvm/Analysis/LoopAccessAnalysis.h @@ -44,15 +44,15 @@ static const unsigned MaxVectorWidth; /// VF as overridden by the user. - static unsigned VectorizationFactor; + static LLVM_THREAD_LOCAL unsigned VectorizationFactor; /// Interleave factor as overridden by the user. - static unsigned VectorizationInterleave; + static LLVM_THREAD_LOCAL unsigned VectorizationInterleave; /// True if force-vector-interleave was specified by the user. static bool isInterleaveForced(); /// \When performing memory disambiguation checks at runtime do not /// make more than this number of comparisons. - static unsigned RuntimeMemoryCheckThreshold; + static LLVM_THREAD_LOCAL unsigned RuntimeMemoryCheckThreshold; }; /// Checks memory dependences among accesses to the same underlying Index: include/llvm/Analysis/ObjCARCAnalysisUtils.h =================================================================== --- include/llvm/Analysis/ObjCARCAnalysisUtils.h +++ include/llvm/Analysis/ObjCARCAnalysisUtils.h @@ -44,7 +44,7 @@ namespace objcarc { /// A handy option to enable/disable all ARC Optimizations. -extern bool EnableARCOpts; +extern LLVM_THREAD_LOCAL bool EnableARCOpts; /// Test if the given module looks interesting to run ARC optimization /// on. Index: include/llvm/Analysis/RegionInfo.h =================================================================== --- include/llvm/Analysis/RegionInfo.h +++ include/llvm/Analysis/RegionInfo.h @@ -801,8 +801,8 @@ RegionInfoBase(const RegionInfoBase &) = delete; RegionInfoBase &operator=(const RegionInfoBase &) = delete; - static bool VerifyRegionInfo; - static typename RegionT::PrintStyle printStyle; + static LLVM_THREAD_LOCAL bool VerifyRegionInfo; + static LLVM_THREAD_LOCAL typename RegionT::PrintStyle printStyle; void print(raw_ostream &OS) const; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) Index: include/llvm/Analysis/RegionInfoImpl.h =================================================================== --- include/llvm/Analysis/RegionInfoImpl.h +++ include/llvm/Analysis/RegionInfoImpl.h @@ -772,15 +772,16 @@ #ifdef EXPENSIVE_CHECKS template -bool RegionInfoBase::VerifyRegionInfo = true; +LLVM_THREAD_LOCAL bool RegionInfoBase::VerifyRegionInfo = true; #else template -bool RegionInfoBase::VerifyRegionInfo = false; +LLVM_THREAD_LOCAL bool RegionInfoBase::VerifyRegionInfo = false; #endif template -typename Tr::RegionT::PrintStyle RegionInfoBase::printStyle = - RegionBase::PrintNone; +LLVM_THREAD_LOCAL + typename Tr::RegionT::PrintStyle RegionInfoBase::printStyle = + RegionBase::PrintNone; template void RegionInfoBase::print(raw_ostream &OS) const { Index: include/llvm/BinaryFormat/Magic.h =================================================================== --- include/llvm/BinaryFormat/Magic.h +++ include/llvm/BinaryFormat/Magic.h @@ -50,6 +50,7 @@ wasm_object, ///< WebAssembly Object file pdb, ///< Windows PDB debug info file tapi_file, ///< Text-based Dynamic Library Stub file + clang_pch, ///< Clang PCH precompiled headers file }; bool is_object() const { return V != unknown; } Index: include/llvm/DebugInfo/CodeView/DebugHashesSection.h =================================================================== --- include/llvm/DebugInfo/CodeView/DebugHashesSection.h +++ include/llvm/DebugInfo/CodeView/DebugHashesSection.h @@ -0,0 +1,18 @@ +//===- DebugHashesSection.h -------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGHASHESSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGHASHESSECTION_H + +namespace llvm { +namespace codeview { + +} // namespace codeview +} // namespace llvm + +#endif Index: include/llvm/IR/PassTimingInfo.h =================================================================== --- include/llvm/IR/PassTimingInfo.h +++ include/llvm/IR/PassTimingInfo.h @@ -39,7 +39,7 @@ /// If the user specifies the -time-passes argument on an LLVM tool command line /// then the value of this boolean will be true, otherwise false. /// This is the storage for the -time-passes option. -extern bool TimePassesIsEnabled; +extern LLVM_THREAD_LOCAL bool TimePassesIsEnabled; /// This class implements -time-passes functionality for new pass manager. /// It provides the pass-instrumentation callbacks that measure the pass Index: include/llvm/Pass.h =================================================================== --- include/llvm/Pass.h +++ include/llvm/Pass.h @@ -353,7 +353,7 @@ /// If the user specifies the -time-passes argument on an LLVM tool command line /// then the value of this boolean will be true, otherwise false. /// This is the storage for the -time-passes option. -extern bool TimePassesIsEnabled; +extern LLVM_THREAD_LOCAL bool TimePassesIsEnabled; } // end namespace llvm Index: include/llvm/Support/CommandLine.h =================================================================== --- include/llvm/Support/CommandLine.h +++ include/llvm/Support/CommandLine.h @@ -20,6 +20,7 @@ #define LLVM_SUPPORT_COMMANDLINE_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" @@ -29,6 +30,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -240,10 +242,10 @@ }; // A special subcommand representing no subcommand -extern ManagedStatic TopLevelSubCommand; +//extern ManagedStatic TopLevelSubCommand; // A special subcommand that can be used to put an option into all subcommands. -extern ManagedStatic AllSubCommands; +//extern ManagedStatic AllSubCommands; //===----------------------------------------------------------------------===// // Option Base class @@ -317,11 +319,7 @@ return getNumOccurrencesFlag() == cl::ConsumeAfter; } - bool isInAllSubCommands() const { - return any_of(Subs, [](const SubCommand *SC) { - return SC == &*AllSubCommands; - }); - } + bool isInAllSubCommands() const; //-------------------------------------------------------------------------=== // Accessor functions set by OptionModifiers @@ -392,6 +390,10 @@ inline int getNumOccurrences() const { return NumOccurrences; } void reset(); + + virtual unsigned getSize() const = 0; + virtual void duplicateInto(Option *O) = 0; + virtual void postRemap(DenseMap