diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-11-29 19:06:37 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-11-29 19:06:37 +0000 |
commit | f9e357d8a66c606a86a6e1aef678898b8843bd30 (patch) | |
tree | 7ab77c3935faa49ea645bd0de570bbe875e5d8c9 /lib/Frontend/CompilerInstance.cpp | |
parent | 933e7a61da12400d8971890719cb03d68c1b02eb (diff) |
Teach the module import mechanism how to rebuild modules expressed via
module map, rather than assuming that there is an umbrella
header. This allows us to automatically build umbrella-less modules.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145415 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/CompilerInstance.cpp')
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 72 |
1 files changed, 64 insertions, 8 deletions
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index c6a5583984..433b2cceb7 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -710,6 +710,21 @@ static void doCompileModule(void *UserData) { } namespace { + struct CompileModuleMapData { + CompilerInstance &Instance; + GenerateModuleAction &CreateModuleAction; + }; +} + +/// \brief Helper function that executes the module-generating action under +/// a crash recovery context. +static void doCompileMapModule(void *UserData) { + CompileModuleMapData &Data + = *reinterpret_cast<CompileModuleMapData *>(UserData); + Data.Instance.ExecuteAction(Data.CreateModuleAction); +} + +namespace { /// \brief Class that manages the creation of a lock file to aid /// implicit coordination between different processes. /// @@ -958,17 +973,11 @@ void LockFileManager::waitForUnlock() { // Give up. } -/// \brief Compile a module file for the given module name with the given -/// umbrella header, using the options provided by the importing compiler -/// instance. +/// \brief Compile a module file for the given module, using the options +/// provided by the importing compiler instance. static void compileModule(CompilerInstance &ImportingInstance, ModuleMap::Module *Module, StringRef ModuleFileName) { - // FIXME: Currently, we can only handle modules that have an umbrella - // header. That's lame. - if (!Module->UmbrellaHeader) - return; - LockFileManager Locked(ModuleFileName); switch (Locked) { case LockFileManager::LFS_Error: @@ -985,6 +994,9 @@ static void compileModule(CompilerInstance &ImportingInstance, break; } + ModuleMap &ModMap + = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); + // Construct a compiler invocation for creating this module. llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation (new CompilerInvocation(ImportingInstance.getInvocation())); @@ -1002,6 +1014,50 @@ static void compileModule(CompilerInstance &ImportingInstance, Invocation->getPreprocessorOpts().ModuleBuildPath .push_back(Module->getTopLevelModuleName()); + if (const FileEntry *ModuleMapFile + = ModMap.getContainingModuleMapFile(Module)) { + // If there is a module map file, build the module using the module map. + // Set up the inputs/outputs so that we build the module from its umbrella + // header. + FrontendOptions &FrontendOpts = Invocation->getFrontendOpts(); + FrontendOpts.OutputFile = ModuleFileName.str(); + FrontendOpts.DisableFree = false; + FrontendOpts.Inputs.clear(); + FrontendOpts.Inputs.push_back( + std::make_pair(getSourceInputKindFromOptions(*Invocation->getLangOpts()), + ModuleMapFile->getName())); + + Invocation->getDiagnosticOpts().VerifyDiagnostics = 0; + + + assert(ImportingInstance.getInvocation().getModuleHash() == + Invocation->getModuleHash() && "Module hash mismatch!"); + + // Construct a compiler instance that will be used to actually create the + // module. + CompilerInstance Instance; + Instance.setInvocation(&*Invocation); + Instance.createDiagnostics(/*argc=*/0, /*argv=*/0, + &ImportingInstance.getDiagnosticClient(), + /*ShouldOwnClient=*/true, + /*ShouldCloneClient=*/true); + + // Construct a module-generating action. + GenerateModuleAction CreateModuleAction; + + // Execute the action to actually build the module in-place. Use a separate + // thread so that we get a stack large enough. + const unsigned ThreadStackSize = 8 << 20; + llvm::CrashRecoveryContext CRC; + CompileModuleMapData Data = { Instance, CreateModuleAction }; + CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize); + return; + } + + // FIXME: Temporary fallback: generate the module from the umbrella header. + // This is currently used when we infer a module map from a framework. + assert(Module->UmbrellaHeader && "Inferred module map needs umbrella header"); + // Set up the inputs/outputs so that we build the module from its umbrella // header. FrontendOptions &FrontendOpts = Invocation->getFrontendOpts(); |