diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-09-13 23:15:45 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-09-13 23:15:45 +0000 |
commit | 6e975c4517958bcc11c834336d340797356058db (patch) | |
tree | e3b9b3a30636d52d700d5e48004d86f24dc7f70a /lib/Frontend | |
parent | 7ea51d5f0b4a8fc5768d1b4744a556dc756f1b3b (diff) |
For modules, use a hash of the compiler version, language options, and
target triple to separate modules built under different
conditions. The hash is used to create a subdirectory in the module
cache path where other invocations of the compiler (with the same
version, language options, etc.) can find the precompiled modules.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139662 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 26 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 82 | ||||
-rw-r--r-- | lib/Frontend/InitHeaderSearch.cpp | 2 |
3 files changed, 96 insertions, 14 deletions
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index ece9cd8406..720f7bb582 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -221,6 +221,15 @@ void CompilerInstance::createPreprocessor() { InitializePreprocessor(*PP, PPOpts, getHeaderSearchOpts(), getFrontendOpts()); + // Set up the module path, including the hash for the + // module-creation options. + llvm::SmallString<256> SpecificModuleCache( + getHeaderSearchOpts().ModuleCachePath); + if (!getHeaderSearchOpts().DisableModuleHash) + llvm::sys::path::append(SpecificModuleCache, + getInvocation().getModuleHash()); + PP->getHeaderSearchInfo().setModuleCachePath(SpecificModuleCache); + // Handle generating dependencies, if requested. const DependencyOutputOptions &DepOpts = getDependencyOutputOpts(); if (!DepOpts.OutputFile.empty()) @@ -644,13 +653,8 @@ static InputKind getSourceInputKindFromOptions(const LangOptions &LangOpts) { /// instance. static void compileModule(CompilerInstance &ImportingInstance, StringRef ModuleName, + StringRef ModuleFileName, StringRef UmbrellaHeader) { - // Determine the file that we'll be writing to. - llvm::SmallString<128> ModuleFile; - ModuleFile += - ImportingInstance.getInvocation().getHeaderSearchOpts().ModuleCachePath; - llvm::sys::path::append(ModuleFile, ModuleName + ".pcm"); - // Construct a compiler invocation for creating this module. llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation (new CompilerInvocation(ImportingInstance.getInvocation())); @@ -658,7 +662,7 @@ static void compileModule(CompilerInstance &ImportingInstance, Invocation->getPreprocessorOpts().resetNonModularOptions(); FrontendOptions &FrontendOpts = Invocation->getFrontendOpts(); - FrontendOpts.OutputFile = ModuleFile.str(); + FrontendOpts.OutputFile = ModuleFileName.str(); FrontendOpts.DisableFree = false; FrontendOpts.Inputs.clear(); FrontendOpts.Inputs.push_back( @@ -686,10 +690,6 @@ static void compileModule(CompilerInstance &ImportingInstance, // FIXME: Need to synchronize when multiple processes do this. Instance.ExecuteAction(CreateModuleAction); - // Tell the importing instance's file manager to forget about the module - // file, since we've just created it. - ImportingInstance.getFileManager().forgetFile(ModuleFile); - // Tell the diagnostic client that it's (re-)starting to process a source // file. ImportingInstance.getDiagnosticClient() @@ -710,8 +710,10 @@ ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc, // Search for a module with the given name. std::string UmbrellaHeader; + std::string ModuleFileName; const FileEntry *ModuleFile = PP->getHeaderSearchInfo().lookupModule(ModuleName.getName(), + &ModuleFileName, &UmbrellaHeader); bool BuildingModule = false; @@ -720,7 +722,7 @@ ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc, // can be used to create the module file. Create a separate compilation // module to do so. BuildingModule = true; - compileModule(*this, ModuleName.getName(), UmbrellaHeader); + compileModule(*this, ModuleName.getName(), ModuleFileName, UmbrellaHeader); ModuleFile = PP->getHeaderSearchInfo().lookupModule(ModuleName.getName()); } diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 6c999caf24..6c47d7b114 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1383,6 +1383,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { Opts.UseLibcxx = (strcmp(A->getValue(Args), "libc++") == 0); Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir); Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodule_cache_path); + Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash); // Add -I..., -F..., and -index-header-map options in order. bool IsIndexHeaderMap = false; @@ -1914,3 +1915,84 @@ void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args); ParseTargetArgs(Res.getTargetOpts(), *Args); } + +namespace { + + class ModuleSignature { + llvm::SmallVector<uint64_t, 16> Data; + unsigned CurBit; + uint64_t CurValue; + + public: + ModuleSignature() : CurBit(0), CurValue(0) { } + + void add(uint64_t Value, unsigned Bits); + void add(StringRef Value); + void flush(); + + llvm::APInt getAsInteger() const; + }; +} + +void ModuleSignature::add(uint64_t Value, unsigned int NumBits) { + CurValue |= Value << CurBit; + if (CurBit + NumBits < 64) { + CurBit += NumBits; + return; + } + + // Add the current word. + Data.push_back(CurValue); + + if (CurBit) + CurValue = Value >> (64-CurBit); + else + CurValue = 0; + CurBit = (CurBit+NumBits) & 63; +} + +void ModuleSignature::flush() { + if (CurBit == 0) + return; + + Data.push_back(CurValue); + CurBit = 0; + CurValue = 0; +} + +void ModuleSignature::add(StringRef Value) { + for (StringRef::iterator I = Value.begin(), IEnd = Value.end(); I != IEnd;++I) + add(*I, 8); +} + +llvm::APInt ModuleSignature::getAsInteger() const { + return llvm::APInt(Data.size() * 64, Data); +} + +std::string CompilerInvocation::getModuleHash() const { + ModuleSignature Signature; + + // Start the signature with the compiler version. + Signature.add(getClangFullRepositoryVersion()); + + // Extend the signature with the language options +#define LANGOPT(Name, Bits, Default, Description) \ + Signature.add(LangOpts.Name, Bits); +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ + Signature.add(static_cast<unsigned>(LangOpts.get##Name()), Bits); +#define BENIGN_LANGOPT(Name, Bits, Default, Description) +#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) +#include "clang/Basic/LangOptions.def" + + // Extend the signature with the target triple + llvm::Triple T(TargetOpts.Triple); + Signature.add((unsigned)T.getArch(), 5); + Signature.add((unsigned)T.getVendor(), 4); + Signature.add((unsigned)T.getOS(), 5); + Signature.add((unsigned)T.getEnvironment(), 4); + + // We've generated the signature. Treat it as one large APInt that we'll + // encode as hex and return. + Signature.flush(); + return Signature.getAsInteger().toString(16, /*Signed=*/false); +} diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 05152a77b2..08af532267 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -1161,7 +1161,5 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS, if (HSOpts.UseStandardIncludes) Init.AddDefaultSystemIncludePaths(Lang, Triple, HSOpts); - HS.setModuleCachePath(HSOpts.ModuleCachePath); - Init.Realize(Lang); } |