From f9e357d8a66c606a86a6e1aef678898b8843bd30 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 29 Nov 2011 19:06:37 +0000 Subject: 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 --- lib/Frontend/CompilerInstance.cpp | 72 ++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 8 deletions(-) (limited to 'lib/Frontend/CompilerInstance.cpp') 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 @@ -709,6 +709,21 @@ static void doCompileModule(void *UserData) { Data.Instance.ExecuteAction(Data.CreateModuleAction); } +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(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 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(); -- cgit v1.2.3-18-g5258