[cfe-commits] r145436 - in /cfe/trunk/lib: Frontend/CompilerInstance.cpp Lex/ModuleMap.cpp

Douglas Gregor dgregor at apple.com
Tue Nov 29 13:59:16 PST 2011


Author: dgregor
Date: Tue Nov 29 15:59:16 2011
New Revision: 145436

URL: http://llvm.org/viewvc/llvm-project?rev=145436&view=rev
Log:
Switch on-demand module building over to use module maps, always. When
we infer the module map, we'll just print the module map to a
temporary file and generate the module using that.


Modified:
    cfe/trunk/lib/Frontend/CompilerInstance.cpp
    cfe/trunk/lib/Lex/ModuleMap.cpp

Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=145436&r1=145435&r2=145436&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Tue Nov 29 15:59:16 2011
@@ -696,20 +696,6 @@
 }
 
 namespace {
-  struct CompileModuleData {
-    CompilerInstance &Instance;
-    GeneratePCHAction &CreateModuleAction;
-  };
-}
-
-/// \brief Helper function that executes the module-generating action under
-/// a crash recovery context.
-static void doCompileModule(void *UserData) {
-  CompileModuleData &Data = *reinterpret_cast<CompileModuleData *>(UserData);
-  Data.Instance.ExecuteAction(Data.CreateModuleAction);
-}
-
-namespace {
   struct CompileModuleMapData {
     CompilerInstance &Instance;
     GenerateModuleAction &CreateModuleAction;
@@ -1001,79 +987,60 @@
   llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation
     (new CompilerInvocation(ImportingInstance.getInvocation()));
 
+  PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
+  
   // For any options that aren't intended to affect how a module is built,
   // reset them to their default values.
   Invocation->getLangOpts()->resetNonModularOptions();
-  Invocation->getPreprocessorOpts().resetNonModularOptions();
+  PPOpts.resetNonModularOptions();
 
   // Note the name of the module we're building.
   Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName();
 
   // Note that this module is part of the module build path, so that we
   // can detect cycles in the module graph.
-  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");
+  PPOpts.ModuleBuildPath.push_back(Module->getTopLevelModuleName());
 
+  // 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()),
-                                           Module->UmbrellaHeader->getName()));
+  InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts());
 
-  Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
+  // Get or create the module map that we'll use to build this module.
+  llvm::SmallString<128> TempModuleMapFileName;
+  if (const FileEntry *ModuleMapFile
+                                  = ModMap.getContainingModuleMapFile(Module)) {
+    // Use the module map where this module resides.
+    FrontendOpts.Inputs.push_back(std::make_pair(IK, ModuleMapFile->getName()));
+  } else {
+    // Create a temporary module map file.
+    TempModuleMapFileName = Module->Name;
+    TempModuleMapFileName += "-%%%%%%%%.map";
+    int FD;
+    if (llvm::sys::fs::unique_file(TempModuleMapFileName.str(), FD, 
+                                   TempModuleMapFileName,
+                                   /*makeAbsolute=*/false)
+          != llvm::errc::success)
+      return;
 
+    // Print the module map to this file.
+    llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true);
+    Module->print(OS);
+    FrontendOpts.Inputs.push_back(
+      std::make_pair(IK, TempModuleMapFileName.str().str()));
+  }
 
+  // Don't free the remapped file buffers; they are owned by our caller.
+  PPOpts.RetainRemappedFileBuffers = true;
+    
+  Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
   assert(ImportingInstance.getInvocation().getModuleHash() ==
-           Invocation->getModuleHash() && "Module hash mismatch!");
-
+         Invocation->getModuleHash() && "Module hash mismatch!");
+  
   // Construct a compiler instance that will be used to actually create the
   // module.
   CompilerInstance Instance;
@@ -1082,16 +1049,23 @@
                              &ImportingInstance.getDiagnosticClient(),
                              /*ShouldOwnClient=*/true,
                              /*ShouldCloneClient=*/true);
-
+  
   // Construct a module-generating action.
-  GeneratePCHAction CreateModuleAction(true);
-
+  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;
-  CompileModuleData Data = { Instance, CreateModuleAction };
-  CRC.RunSafelyOnThread(&doCompileModule, &Data, ThreadStackSize);
+  CompileModuleMapData Data = { Instance, CreateModuleAction };
+  CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize);
+  
+  // Delete the temporary module map file.
+  // FIXME: Even though we're executing under crash protection, it would still
+  // be nice to do this with RemoveFileOnSignal when we can. However, that
+  // doesn't make sense for all clients, so clean this up manually.
+  if (!TempModuleMapFileName.empty())
+    llvm::sys::Path(TempModuleMapFileName).eraseFromDisk();
 }
 
 ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=145436&r1=145435&r2=145436&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Tue Nov 29 15:59:16 2011
@@ -69,7 +69,7 @@
 }
 
 static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
-  OS << std::string(' ', Spaces);
+  OS << std::string(Spaces, ' ');
 }
 
 void ModuleMap::Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
@@ -78,7 +78,7 @@
     OS << "framework ";
   if (IsExplicit)
     OS << "explicit ";
-  OS << Name << " {\n";
+  OS << "module " << Name << " {\n";
   
   if (UmbrellaHeader) {
     indent(OS, Indent + 2);
@@ -586,28 +586,35 @@
   
   // Look for this file.
   llvm::SmallString<128> PathName;
-  PathName += Directory->getName();
-  unsigned PathLength = PathName.size();
   const FileEntry *File = 0;
-  if (ActiveModule->isPartOfFramework()) {
-    // Check whether this file is in the public headers.
-    llvm::sys::path::append(PathName, "Headers");
-    llvm::sys::path::append(PathName, FileName);
+  
+  if (llvm::sys::path::is_absolute(FileName)) {
+    PathName = FileName;
     File = SourceMgr.getFileManager().getFile(PathName);
+  } else {
+    // Search for the header file within the search directory.
+    PathName += Directory->getName();
+    unsigned PathLength = PathName.size();
+    if (ActiveModule->isPartOfFramework()) {
+      // Check whether this file is in the public headers.
+      llvm::sys::path::append(PathName, "Headers");
+      llvm::sys::path::append(PathName, FileName);
+      File = SourceMgr.getFileManager().getFile(PathName);
 
-    if (!File) {
-      // Check whether this file is in the private headers.
-      PathName.resize(PathLength);
-      llvm::sys::path::append(PathName, "PrivateHeaders");
+      if (!File) {
+        // Check whether this file is in the private headers.
+        PathName.resize(PathLength);
+        llvm::sys::path::append(PathName, "PrivateHeaders");
+        llvm::sys::path::append(PathName, FileName);
+        File = SourceMgr.getFileManager().getFile(PathName);
+      }
+      
+      // FIXME: Deal with subframeworks.
+    } else {
+      // Lookup for normal headers.
       llvm::sys::path::append(PathName, FileName);
       File = SourceMgr.getFileManager().getFile(PathName);
     }
-    
-    // FIXME: Deal with subframeworks.
-  } else {
-    // Lookup for normal headers.
-    llvm::sys::path::append(PathName, FileName);
-    File = SourceMgr.getFileManager().getFile(PathName);
   }
   
   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
@@ -654,11 +661,14 @@
   
   // Look for this file.
   llvm::SmallString<128> PathName;
-  PathName += Directory->getName();
+  if (llvm::sys::path::is_relative(FileName)) {
+    // FIXME: Change this search to also look for private headers!
+    PathName += Directory->getName();
+    
+    if (ActiveModule->isPartOfFramework())
+      llvm::sys::path::append(PathName, "Headers");
+  }
   
-  if (ActiveModule->isPartOfFramework())
-    llvm::sys::path::append(PathName, "Headers");
-
   llvm::sys::path::append(PathName, FileName);
   
   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.





More information about the cfe-commits mailing list