diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -54,7 +54,12 @@ static CachedFileSystemEntry createDirectoryEntry(llvm::vfs::Status &&Stat); /// \returns True if the entry is valid. - bool isValid() const { return !MaybeStat || MaybeStat->isStatusKnown(); } + bool isValid() const { return MaybeStat && MaybeStat->isStatusKnown(); } + + std::error_code getErrorCode() const { + assert(!isValid() && "does not have an error code"); + return MaybeStat.getError(); + } /// \returns True if the current entry points to a directory. bool isDirectory() const { return MaybeStat && MaybeStat->isDirectory(); } diff --git a/clang/lib/ASTMatchers/GtestMatchers.cpp b/clang/lib/ASTMatchers/GtestMatchers.cpp --- a/clang/lib/ASTMatchers/GtestMatchers.cpp +++ b/clang/lib/ASTMatchers/GtestMatchers.cpp @@ -53,6 +53,7 @@ case GtestCmp::Lt: return functionDecl(hasName("::testing::internal::CmpHelperLT")); } + llvm_unreachable("Unexpected GtestCmp!"); } static llvm::StringRef getMacroTypeName(MacroType Macro) { @@ -64,6 +65,7 @@ case MacroType::On: return "ON"; } + llvm_unreachable("Unexpected MacroType!"); } static llvm::StringRef getComparisonTypeName(GtestCmp Cmp) { @@ -81,6 +83,7 @@ case GtestCmp::Lt: return "LT"; } + llvm_unreachable("Unexpected GtestCmp!"); } static std::string getMacroName(MacroType Macro, GtestCmp Cmp) { @@ -170,6 +173,7 @@ hasOverloadedOperatorName("()"), argumentCountIs(3), hasArgument(0, ignoringImplicit(MockCall)))))); } + llvm_unreachable("Unexpected MockArgs!"); } static internal::BindableMatcher diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -903,7 +903,9 @@ case Backend_EmitMCNull: return CI.createNullOutputFile(); case Backend_EmitObj: - return CI.createDefaultOutputFile(true, InFile, "o"); + return CI.createDefaultOutputFile(true, InFile, "o", + /*RemoveFileOnSignal=*/true, + /*CreateMissingDirectories=*/true); } llvm_unreachable("Invalid action!"); diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -295,7 +295,8 @@ if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) || (PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) || (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) || - (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) { + (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P)) || + (PhaseArg = DAL.getLastArg(options::OPT_Eonly))) { FinalPhase = phases::Preprocess; // --precompile only runs up to precompilation. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -41,6 +41,7 @@ #include "llvm/Support/Compression.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" +#include "llvm/Support/InitLLVM.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/TargetParser.h" @@ -4632,7 +4633,7 @@ // We normally speed up the clang process a bit by skipping destructors at // exit, but when we're generating diagnostics we can rely on some of the // cleanup. - if (!C.isForDiagnostics()) + if (!C.isForDiagnostics() && !llvm::InitLLVM::RunningInBuildozer()) CmdArgs.push_back("-disable-free"); #ifdef NDEBUG diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -728,6 +728,10 @@ << OF.TempFilename << OF.Filename << EC.message(); llvm::sys::fs::remove(OF.TempFilename); + + // Don't leak file added by RemoveFileOnSignal() in + // CompilerInstance::createOutputFile() + llvm::sys::DontRemoveFileOnSignal(OF.TempFilename); } OutputFiles.clear(); if (DeleteBuiltModules) { diff --git a/clang/lib/Tooling/CommonOptionsParser.cpp b/clang/lib/Tooling/CommonOptionsParser.cpp --- a/clang/lib/Tooling/CommonOptionsParser.cpp +++ b/clang/lib/Tooling/CommonOptionsParser.cpp @@ -86,21 +86,21 @@ static cl::opt BuildPath("p", cl::desc("Build path"), cl::Optional, cl::cat(Category), - cl::sub(*cl::AllSubCommands)); + cl::allSub()); static cl::list SourcePaths( cl::Positional, cl::desc(" [... ]"), OccurrencesFlag, - cl::cat(Category), cl::sub(*cl::AllSubCommands)); + cl::cat(Category), cl::allSub()); static cl::list ArgsAfter( "extra-arg", cl::desc("Additional argument to append to the compiler command line"), - cl::cat(Category), cl::sub(*cl::AllSubCommands)); + cl::cat(Category), cl::allSub()); static cl::list ArgsBefore( "extra-arg-before", cl::desc("Additional argument to prepend to the compiler command line"), - cl::cat(Category), cl::sub(*cl::AllSubCommands)); + cl::cat(Category), cl::allSub()); cl::ResetAllOptionOccurrences(); diff --git a/clang/lib/Tooling/DependencyScanning/CMakeLists.txt b/clang/lib/Tooling/DependencyScanning/CMakeLists.txt --- a/clang/lib/Tooling/DependencyScanning/CMakeLists.txt +++ b/clang/lib/Tooling/DependencyScanning/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + BinaryFormat Core Support ) diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -8,6 +8,7 @@ #include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h" #include "clang/Lex/DependencyDirectivesSourceMinimizer.h" +#include "llvm/BinaryFormat/Magic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Threading.h" @@ -32,12 +33,15 @@ if (!MaybeBuffer) return MaybeBuffer.getError(); + const auto &Buffer = *MaybeBuffer; + llvm::file_magic M = llvm::identify_magic(Buffer->getBuffer()); + llvm::SmallString<1024> MinimizedFileContents; // Minimize the file down to directives that might affect the dependencies. - const auto &Buffer = *MaybeBuffer; SmallVector Tokens; - if (!Minimize || minimizeSourceToDependencyDirectives( - Buffer->getBuffer(), MinimizedFileContents, Tokens)) { + if (!Minimize || M == llvm::file_magic::clang_pch || + minimizeSourceToDependencyDirectives(Buffer->getBuffer(), + MinimizedFileContents, Tokens)) { // Use the original file unless requested otherwise, or // if the minimization failed. // FIXME: Propage the diagnostic if desired by the client. @@ -204,6 +208,8 @@ getOrCreateFileSystemEntry(Filename); if (!Result) return Result.getError(); + if (!(*Result)->isValid()) + return (*Result)->getErrorCode(); return (*Result)->getStatus(); } diff --git a/clang/tools/clang-refactor/ClangRefactor.cpp b/clang/tools/clang-refactor/ClangRefactor.cpp --- a/clang/tools/clang-refactor/ClangRefactor.cpp +++ b/clang/tools/clang-refactor/ClangRefactor.cpp @@ -38,12 +38,10 @@ static cl::OptionCategory CommonRefactorOptions("Refactoring options"); static cl::opt Verbose("v", cl::desc("Use verbose output"), - cl::cat(cl::GeneralCategory), - cl::sub(*cl::AllSubCommands)); + cl::cat(cl::GeneralCategory), cl::allSub()); static cl::opt Inplace("i", cl::desc("Inplace edit s"), - cl::cat(cl::GeneralCategory), - cl::sub(*cl::AllSubCommands)); + cl::cat(cl::GeneralCategory), cl::allSub()); } // end namespace opts diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -33,6 +33,7 @@ #include "llvm/Support/BuryPointer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/CrashRecoveryContext.h" +#include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -50,6 +51,7 @@ #include #include #include +#include using namespace clang; using namespace clang::driver; using namespace llvm::opt; @@ -348,6 +350,8 @@ return 1; } +int ClangDriverMain(SmallVectorImpl &Args); + int main(int Argc, const char **Argv) { noteBottomOfStack(); llvm::InitLLVM X(Argc, Argv); @@ -360,6 +364,18 @@ return 1; llvm::InitializeAllTargets(); + return ClangDriverMain(Args); +} + +int ClangDriverMain(SmallVectorImpl &Args) { + static LLVM_THREAD_LOCAL bool EnterPE = true; + if (EnterPE) { + llvm::sys::DynamicLibrary::AddSymbol("ClangDriverMain", + (void *)(intptr_t)&ClangDriverMain); + EnterPE = false; + } else { + llvm::cl::ResetAllOptionOccurrences(); + } auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(Args[0]); llvm::BumpPtrAllocator A; diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -424,7 +424,7 @@ size_t getSize() const override; void writeTo(uint8_t *buf) const override; - static MergeChunk *instances[Log2MaxSectionAlignment + 1]; + static LLVM_THREAD_LOCAL MergeChunk *instances[Log2MaxSectionAlignment + 1]; std::vector sections; private: diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -938,7 +938,8 @@ } } -MergeChunk *MergeChunk::instances[Log2MaxSectionAlignment + 1] = {}; +LLVM_THREAD_LOCAL MergeChunk + *MergeChunk::instances[Log2MaxSectionAlignment + 1] = {}; MergeChunk::MergeChunk(uint32_t alignment) : builder(StringTableBuilder::RAW, alignment) { diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -275,7 +275,7 @@ bool pseudoRelocs = false; }; -extern Configuration *config; +extern LLVM_THREAD_LOCAL Configuration *config; } // namespace coff } // namespace lld diff --git a/lld/COFF/DebugTypes.h b/lld/COFF/DebugTypes.h --- a/lld/COFF/DebugTypes.h +++ b/lld/COFF/DebugTypes.h @@ -110,15 +110,15 @@ } /// All sources of type information in the program. - static std::vector instances; + static LLVM_THREAD_LOCAL std::vector instances; /// Dependency type sources, such as type servers or PCH object files. These /// must be processed before objects that rely on them. Set by /// TpiSources::sortDependencies. - static ArrayRef dependencySources; + static LLVM_THREAD_LOCAL ArrayRef dependencySources; /// Object file sources. These must be processed after dependencySources. - static ArrayRef objectSources; + static LLVM_THREAD_LOCAL ArrayRef objectSources; /// Sorts the dependencies and reassigns TpiSource indices. static void sortDependencies(); diff --git a/lld/COFF/DebugTypes.cpp b/lld/COFF/DebugTypes.cpp --- a/lld/COFF/DebugTypes.cpp +++ b/lld/COFF/DebugTypes.cpp @@ -160,9 +160,9 @@ }; } // namespace -std::vector TpiSource::instances; -ArrayRef TpiSource::dependencySources; -ArrayRef TpiSource::objectSources; +LLVM_THREAD_LOCAL std::vector TpiSource::instances; +LLVM_THREAD_LOCAL ArrayRef TpiSource::dependencySources; +LLVM_THREAD_LOCAL ArrayRef TpiSource::objectSources; TpiSource::TpiSource(TpiKind k, ObjFile *f) : kind(k), tpiSrcIdx(instances.size()), file(f) { diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -30,7 +30,7 @@ namespace coff { class LinkerDriver; -extern LinkerDriver *driver; +extern LLVM_THREAD_LOCAL LinkerDriver *driver; using llvm::COFF::MachineTypes; using llvm::COFF::WindowsSubsystem; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -59,10 +59,11 @@ namespace lld { namespace coff { -static Timer inputFileTimer("Input File Reading", Timer::root()); +static LLVM_THREAD_LOCAL Timer inputFileTimer("Input File Reading", + Timer::root()); -Configuration *config; -LinkerDriver *driver; +LLVM_THREAD_LOCAL Configuration *config; +LLVM_THREAD_LOCAL LinkerDriver *driver; bool link(ArrayRef args, bool canExitEarly, raw_ostream &stdoutOS, raw_ostream &stderrOS) { @@ -144,7 +145,7 @@ // FIXME: We could open the file in createFutureForFile and avoid needing to // return an error here, but for the moment that would cost us a file descriptor // (a limited resource on Windows) for the duration that the future is pending. -using MBErrPair = std::pair, std::error_code>; +/*using MBErrPair = std::pair, std::error_code>; // Create a std::future that opens and maps a file using the best strategy for // the host platform. @@ -157,13 +158,14 @@ auto strategy = std::launch::deferred; #endif return std::async(strategy, [=]() { - auto mbOrErr = MemoryBuffer::getFile(path, /*IsText=*/false, - /*RequiresNullTerminator=*/false); + auto mbOrErr = MemoryBuffer::getFile(path, + false, //IsText + false); //RequiresNullTerminator if (!mbOrErr) return MBErrPair{nullptr, mbOrErr.getError()}; return MBErrPair{std::move(*mbOrErr), std::error_code()}; }); -} +}*/ // Symbol names are mangled by prepending "_" on x86. static StringRef mangle(StringRef sym) { @@ -247,14 +249,17 @@ } void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy) { - auto future = std::make_shared>( - createFutureForFile(std::string(path))); + /*auto future = std::make_shared>( + createFutureForFile(std::string(path)));*/ std::string pathStr = std::string(path); enqueueTask([=]() { - auto mbOrErr = future->get(); - if (mbOrErr.second) { + // auto mbOrErr = future->get(); + auto mbOrErr = MemoryBuffer::getFile(pathStr, + false, // IsText + false); // RequiresNullTerminator + if (!mbOrErr) { std::string msg = - "could not open '" + pathStr + "': " + mbOrErr.second.message(); + "could not open '" + pathStr + "': " + mbOrErr.getError().message(); // Check if the filename is a typo for an option flag. OptTable thinks // that all args that are not known options and that start with / are // filenames, but e.g. `/nodefaultlibs` is more likely a typo for @@ -266,7 +271,7 @@ else error(msg + "; did you mean '" + nearest + "'"); } else - driver->addBuffer(std::move(mbOrErr.first), wholeArchive, lazy); + driver->addBuffer(std::move(mbOrErr.get()), wholeArchive, lazy); }); } @@ -323,15 +328,16 @@ c.getFullName(), "could not get the filename for the member defining symbol " + toCOFFString(sym)); - auto future = std::make_shared>( - createFutureForFile(childName)); + /*auto future = std::make_shared>( + createFutureForFile(childName));*/ enqueueTask([=]() { - auto mbOrErr = future->get(); - if (mbOrErr.second) - reportBufferError(errorCodeToError(mbOrErr.second), childName); + // auto mbOrErr = future->get(); + auto mbOrErr = MemoryBuffer::getFile(childName, false, false); + if (!mbOrErr) + reportBufferError(errorCodeToError(mbOrErr.getError()), childName); // Pass empty string as archive name so that the original filename is // used as the buffer identifier. - driver->addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), + driver->addArchiveBuffer(takeBuffer(std::move(mbOrErr.get())), toCOFFString(sym), "", /*OffsetInArchive=*/0); }); } diff --git a/lld/COFF/ICF.cpp b/lld/COFF/ICF.cpp --- a/lld/COFF/ICF.cpp +++ b/lld/COFF/ICF.cpp @@ -36,7 +36,7 @@ namespace lld { namespace coff { -static Timer icfTimer("ICF", Timer::root()); +static LLVM_THREAD_LOCAL Timer icfTimer("ICF", Timer::root()); class ICF { public: diff --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h --- a/lld/COFF/InputFiles.h +++ b/lld/COFF/InputFiles.h @@ -173,7 +173,7 @@ bool isResourceObjFile() const { return !resourceChunks.empty(); } - static std::vector instances; + static LLVM_THREAD_LOCAL std::vector instances; // Flags in the absolute @feat.00 symbol if it is present. These usually // indicate if an object was compiled with certain security features enabled @@ -325,7 +325,7 @@ static PDBInputFile *findFromRecordPath(StringRef path, ObjFile *fromFile); - static std::map instances; + static LLVM_THREAD_LOCAL std::map instances; // Record possible errors while opening the PDB file llvm::Optional loadErr; @@ -346,7 +346,7 @@ static bool classof(const InputFile *f) { return f->kind() == ImportKind; } - static std::vector instances; + static LLVM_THREAD_LOCAL std::vector instances; Symbol *impSym = nullptr; Symbol *thunkSym = nullptr; @@ -384,7 +384,7 @@ static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; } ArrayRef getSymbols() { return symbols; } MachineTypes getMachineType() override; - static std::vector instances; + static LLVM_THREAD_LOCAL std::vector instances; std::unique_ptr obj; private: diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -69,10 +69,10 @@ .str(); } -std::vector ObjFile::instances; -std::map PDBInputFile::instances; -std::vector ImportFile::instances; -std::vector BitcodeFile::instances; +LLVM_THREAD_LOCAL std::vector ObjFile::instances; +LLVM_THREAD_LOCAL std::map PDBInputFile::instances; +LLVM_THREAD_LOCAL std::vector ImportFile::instances; +LLVM_THREAD_LOCAL std::vector BitcodeFile::instances; /// Checks that Source is compatible with being a weak alias to Target. /// If Source is Undefined and has no weak alias set, makes it a weak diff --git a/lld/COFF/MarkLive.cpp b/lld/COFF/MarkLive.cpp --- a/lld/COFF/MarkLive.cpp +++ b/lld/COFF/MarkLive.cpp @@ -15,7 +15,7 @@ namespace lld { namespace coff { -static Timer gctimer("GC", Timer::root()); +static LLVM_THREAD_LOCAL Timer gctimer("GC", Timer::root()); // Set live bit on for each reachable chunk. Unmarked (unreachable) // COMDAT chunks will be ignored by Writer, so they will be excluded diff --git a/lld/COFF/PDB.h b/lld/COFF/PDB.h --- a/lld/COFF/PDB.h +++ b/lld/COFF/PDB.h @@ -35,8 +35,8 @@ llvm::Optional> getFileLineCodeView(const SectionChunk *c, uint32_t addr); -extern Timer loadGHashTimer; -extern Timer mergeGHashTimer; +extern LLVM_THREAD_LOCAL Timer loadGHashTimer; +extern LLVM_THREAD_LOCAL Timer mergeGHashTimer; } // namespace coff } // namespace lld diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -66,15 +66,24 @@ static ExitOnError exitOnErr; -static Timer totalPdbLinkTimer("PDB Emission (Cumulative)", Timer::root()); -static Timer addObjectsTimer("Add Objects", totalPdbLinkTimer); -Timer lld::coff::loadGHashTimer("Global Type Hashing", addObjectsTimer); -Timer lld::coff::mergeGHashTimer("GHash Type Merging", addObjectsTimer); -static Timer typeMergingTimer("Type Merging", addObjectsTimer); -static Timer symbolMergingTimer("Symbol Merging", addObjectsTimer); -static Timer publicsLayoutTimer("Publics Stream Layout", totalPdbLinkTimer); -static Timer tpiStreamLayoutTimer("TPI Stream Layout", totalPdbLinkTimer); -static Timer diskCommitTimer("Commit to Disk", totalPdbLinkTimer); +static LLVM_THREAD_LOCAL Timer totalPdbLinkTimer("PDB Emission (Cumulative)", + Timer::root()); +static LLVM_THREAD_LOCAL Timer addObjectsTimer("Add Objects", + totalPdbLinkTimer); +LLVM_THREAD_LOCAL Timer lld::coff::loadGHashTimer("Global Type Hashing", + addObjectsTimer); +LLVM_THREAD_LOCAL Timer lld::coff::mergeGHashTimer("GHash Type Merging", + addObjectsTimer); +static LLVM_THREAD_LOCAL Timer typeMergingTimer("Type Merging", + addObjectsTimer); +static LLVM_THREAD_LOCAL Timer symbolMergingTimer("Symbol Merging", + addObjectsTimer); +static LLVM_THREAD_LOCAL Timer publicsLayoutTimer("Publics Stream Layout", + totalPdbLinkTimer); +static LLVM_THREAD_LOCAL Timer tpiStreamLayoutTimer("TPI Stream Layout", + totalPdbLinkTimer); +static LLVM_THREAD_LOCAL Timer diskCommitTimer("Commit to Disk", + totalPdbLinkTimer); namespace { class DebugSHandler; diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -130,7 +130,7 @@ std::unique_ptr lto; }; -extern SymbolTable *symtab; +extern LLVM_THREAD_LOCAL SymbolTable *symtab; std::vector getSymbolLocations(ObjFile *file, uint32_t symIndex); diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -28,9 +28,9 @@ namespace lld { namespace coff { -static Timer ltoTimer("LTO", Timer::root()); +static LLVM_THREAD_LOCAL Timer ltoTimer("LTO", Timer::root()); -SymbolTable *symtab; +LLVM_THREAD_LOCAL SymbolTable *symtab; void SymbolTable::addFile(InputFile *file) { log("Reading " + toString(file)); diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h --- a/lld/COFF/Symbols.h +++ b/lld/COFF/Symbols.h @@ -257,7 +257,7 @@ // Section index relocations against absolute symbols resolve to // this 16 bit number, and it is the largest valid section index // plus one. This variable keeps it. - static uint16_t numOutputSections; + static LLVM_THREAD_LOCAL uint16_t numOutputSections; private: uint64_t va; diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp --- a/lld/COFF/Symbols.cpp +++ b/lld/COFF/Symbols.cpp @@ -100,7 +100,7 @@ return COFFSymbolRef(reinterpret_cast(sym)); } -uint16_t DefinedAbsolute::numOutputSections; +LLVM_THREAD_LOCAL uint16_t DefinedAbsolute::numOutputSections; static Chunk *makeImportThunk(DefinedImportData *s, uint16_t machine) { if (machine == AMD64) diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -82,7 +82,7 @@ // Global vector of all output sections. After output sections are finalized, // this can be indexed by Chunk::getOutputSection. -static std::vector outputSections; +static LLVM_THREAD_LOCAL std::vector outputSections; OutputSection *Chunk::getOutputSection() const { return osidx == 0 ? nullptr : outputSections[osidx - 1]; @@ -307,8 +307,9 @@ }; } // anonymous namespace -static Timer codeLayoutTimer("Code Layout", Timer::root()); -static Timer diskCommitTimer("Commit Output File", Timer::root()); +static LLVM_THREAD_LOCAL Timer codeLayoutTimer("Code Layout", Timer::root()); +static LLVM_THREAD_LOCAL Timer diskCommitTimer("Commit Output File", + Timer::root()); void lld::coff::writeResult() { Writer().run(); } diff --git a/lld/Common/Memory.cpp b/lld/Common/Memory.cpp --- a/lld/Common/Memory.cpp +++ b/lld/Common/Memory.cpp @@ -11,9 +11,10 @@ using namespace llvm; using namespace lld; -BumpPtrAllocator lld::bAlloc; -StringSaver lld::saver{bAlloc}; -std::vector lld::SpecificAllocBase::instances; +LLVM_THREAD_LOCAL BumpPtrAllocator lld::bAlloc; +LLVM_THREAD_LOCAL StringSaver lld::saver{bAlloc}; +LLVM_THREAD_LOCAL std::vector + lld::SpecificAllocBase::instances; void lld::freeArena() { for (SpecificAllocBase *alloc : SpecificAllocBase::instances) diff --git a/lld/Common/Timer.cpp b/lld/Common/Timer.cpp --- a/lld/Common/Timer.cpp +++ b/lld/Common/Timer.cpp @@ -32,7 +32,7 @@ } Timer &Timer::root() { - static Timer rootTimer("Total Link Time"); + static LLVM_THREAD_LOCAL Timer rootTimer("Total Link Time"); return rootTimer; } diff --git a/lld/include/lld/Common/Memory.h b/lld/include/lld/Common/Memory.h --- a/lld/include/lld/Common/Memory.h +++ b/lld/include/lld/Common/Memory.h @@ -28,8 +28,8 @@ namespace lld { // Use this arena if your object doesn't have a destructor. -extern llvm::BumpPtrAllocator bAlloc; -extern llvm::StringSaver saver; +extern LLVM_THREAD_LOCAL llvm::BumpPtrAllocator bAlloc; +extern LLVM_THREAD_LOCAL llvm::StringSaver saver; void freeArena(); @@ -39,7 +39,7 @@ SpecificAllocBase() { instances.push_back(this); } virtual ~SpecificAllocBase() = default; virtual void reset() = 0; - static std::vector instances; + static LLVM_THREAD_LOCAL std::vector instances; }; template struct SpecificAlloc : public SpecificAllocBase { diff --git a/llvm/include/llvm/ADT/iterator_range.h b/llvm/include/llvm/ADT/iterator_range.h --- a/llvm/include/llvm/ADT/iterator_range.h +++ b/llvm/include/llvm/ADT/iterator_range.h @@ -18,6 +18,7 @@ #ifndef LLVM_ADT_ITERATOR_RANGE_H #define LLVM_ADT_ITERATOR_RANGE_H +#include #include namespace llvm { @@ -29,6 +30,8 @@ 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 @@ -37,27 +40,45 @@ iterator_range(Container &&c) //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; } - bool empty() const { return begin_iterator == 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_iterator == end_iterator; + } }; /// Convenience function for iterating over sub-ranges. /// /// 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); } - } #endif diff --git a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h --- a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h @@ -39,15 +39,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 diff --git a/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h b/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h --- a/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h +++ b/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h @@ -36,7 +36,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. diff --git a/llvm/include/llvm/Analysis/RegionInfo.h b/llvm/include/llvm/Analysis/RegionInfo.h --- a/llvm/include/llvm/Analysis/RegionInfo.h +++ b/llvm/include/llvm/Analysis/RegionInfo.h @@ -799,8 +799,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) diff --git a/llvm/include/llvm/Analysis/RegionInfoImpl.h b/llvm/include/llvm/Analysis/RegionInfoImpl.h --- a/llvm/include/llvm/Analysis/RegionInfoImpl.h +++ b/llvm/include/llvm/Analysis/RegionInfoImpl.h @@ -770,15 +770,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 { diff --git a/llvm/include/llvm/BinaryFormat/Magic.h b/llvm/include/llvm/BinaryFormat/Magic.h --- a/llvm/include/llvm/BinaryFormat/Magic.h +++ b/llvm/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; } diff --git a/llvm/include/llvm/Pass.h b/llvm/include/llvm/Pass.h --- a/llvm/include/llvm/Pass.h +++ b/llvm/include/llvm/Pass.h @@ -28,6 +28,7 @@ #ifndef LLVM_PASS_H #define LLVM_PASS_H +#include "llvm/Support/Compiler.h" #include namespace llvm { @@ -322,13 +323,13 @@ /// 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; /// If TimePassesPerRun is true, there would be one line of report for /// each pass invocation. /// If TimePassesPerRun is false, there would be only one line of /// report for each pass (even there are more than one pass objects). /// (For new pass manager only) -extern bool TimePassesPerRun; +extern LLVM_THREAD_LOCAL bool TimePassesPerRun; } // end namespace llvm diff --git a/llvm/include/llvm/Support/CLData.h b/llvm/include/llvm/Support/CLData.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/Support/CLData.h @@ -0,0 +1,47 @@ +//===- llvm/Support/CLData.h - Command line data storage --------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This is simply a wrapper over a data type, which allows the user to switch, +// in certain cases, from global state to thread-local state. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CLDATA_H +#define LLVM_SUPPORT_CLDATA_H + +namespace llvm { + +/// cl Namespace - This namespace contains all of the command line option +/// processing machinery. It is intentionally a short name to make qualified +/// usage concise. +namespace cl { + +//===----------------------------------------------------------------------===// +// data - A simple data wrapper to be used along with cl::location +// +template class data { +public: + data() = default; + data(const DataType &D) { Val = D; } + template + explicit data(Mods &&... Ms) : Val(std::forward(Ms)...) {} + operator DataType() { return Val; } + data &operator=(const DataType &D) { + Val = D; + return *this; + } + DataType &operator*() { return Val; } + DataType *operator->() { return &Val; } + DataType Val; +}; + +} // end namespace cl + +} // end namespace llvm + +#endif // LLVM_SUPPORT_COMMANDLINE_H diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h --- a/llvm/include/llvm/Support/CommandLine.h +++ b/llvm/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/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" @@ -31,6 +32,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 @@ -238,10 +240,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 @@ -315,11 +317,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 @@ -403,6 +401,10 @@ inline int getNumOccurrences() const { return NumOccurrences; } void reset(); + + virtual unsigned getSize() const = 0; + virtual void duplicateInto(Option *O) = 0; + virtual void postRemap(DenseMap