jansvoboda11 created this revision.
Herald added a subscriber: ributzka.
Herald added a project: All.
jansvoboda11 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D138224

Files:
  clang/include/clang/Basic/SourceLocation.h
  clang/include/clang/Basic/SourceManager.h
  clang/include/clang/Frontend/CompilerInstance.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorOptions.h
  clang/include/clang/Lex/Token.h
  clang/include/clang/Serialization/Simple/ASTReader.h
  clang/include/clang/Serialization/Simple/ASTWriter.h
  clang/include/clang/Serialization/Simple/ModuleCache.h
  clang/include/clang/Serialization/Simple/ModuleFile.h
  clang/include/clang/Serialization/Simple/ModuleManager.h
  clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
  clang/lib/Frontend/CompilerInstance.cpp
  clang/lib/Frontend/FrontendAction.cpp
  clang/lib/Frontend/FrontendActions.cpp
  clang/lib/Lex/Preprocessor.cpp
  clang/lib/Serialization/ASTWriter.cpp
  clang/lib/Serialization/CMakeLists.txt
  clang/lib/Serialization/GeneratePCH.cpp
  clang/lib/Serialization/Simple/ASTReader.cpp
  clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
  clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
  clang/test/ClangScanDeps/modules-basic.c

Index: clang/test/ClangScanDeps/modules-basic.c
===================================================================
--- /dev/null
+++ clang/test/ClangScanDeps/modules-basic.c
@@ -0,0 +1,181 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+//--- include/module.modulemap
+module top { header "top.h" }
+module left { header "left.h" }
+module right { header "right.h" }
+module right_extra { header "right-extra.h" }
+module bottom { header "bottom.h" }
+//--- include/top.h
+//
+#define D1
+//--- include/left.h
+///
+#include "top.h"
+#define D2
+//--- include/right.h
+////
+#include "right-extra.h"
+#include "top.h"
+#define D3
+//--- include/right-extra.h
+/////
+#define D4
+//--- include/bottom.h
+//////
+#include "left.h"
+#include "right.h"
+#define D5
+//--- include/t.h
+
+//--- tu.c
+#include "bottom.h"
+#ifdef D1
+#endif
+#ifdef D2
+#endif
+#ifdef D3
+#endif
+#ifdef D4
+#endif
+#ifdef D5
+#endif
+
+#define D1
+#define D2
+#define D3
+#define D4
+#define D5
+
+//--- cdb.json.template
+[{
+  "file": "DIR/tu.c",
+  "directory": "DIR",
+  "command": "clang -fsyntax-only DIR/tu.c -fmodules -fmodules-cache-path=DIR/cache -fimplicit-module-maps -I DIR/include"
+}]
+
+// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
+
+// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full > %t/result.json
+// RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t
+
+// CHECK:      {
+// CHECK-NEXT:   "modules": [
+// CHECK-NEXT:     {
+// CHECK-NEXT:       "clang-module-deps": [
+// CHECK-NEXT:         {
+// CHECK-NEXT:           "context-hash": "{{.*}}",
+// CHECK-NEXT:           "module-name": "left"
+// CHECK-NEXT:         },
+// CHECK-NEXT:         {
+// CHECK-NEXT:           "context-hash": "{{.*}}",
+// CHECK-NEXT:           "module-name": "right"
+// CHECK-NEXT:         }
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "clang-modulemap-file": "[[PREFIX]]/include/module.modulemap",
+// CHECK-NEXT:       "command-line": [
+// CHECK:              "-fmodule-map-file=[[PREFIX]]/include/module.modulemap",
+// CHECK:              "-fmodule-file=left=[[PREFIX]]/cache/{{.*}}/left-{{.*}}.pcm",
+// CHECK:              "-fmodule-file=right=[[PREFIX]]/cache/{{.*}}/right-{{.*}}.pcm",
+// CHECK:            ],
+// CHECK-NEXT:       "context-hash": "{{.*}}",
+// CHECK-NEXT:       "file-deps": [
+// CHECK-NEXT:         "[[PREFIX]]/include/bottom.h",
+// CHECK-NEXT:         "[[PREFIX]]/include/module.modulemap"
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "name": "bottom"
+// CHECK-NEXT:     },
+// CHECK-NEXT:     {
+// CHECK-NEXT:       "clang-module-deps": [
+// CHECK-NEXT:         {
+// CHECK-NEXT:           "context-hash": "{{.*}}",
+// CHECK-NEXT:           "module-name": "top"
+// CHECK-NEXT:         }
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "clang-modulemap-file": "[[PREFIX]]/include/module.modulemap",
+// CHECK-NEXT:       "command-line": [
+// CHECK:              "-fmodule-map-file=[[PREFIX]]/include/module.modulemap",
+// CHECK:              "-fmodule-file=top=[[PREFIX]]/cache/{{.*}}/top-{{.*}}.pcm",
+// CHECK:            ],
+// CHECK-NEXT:       "context-hash": "{{.*}}",
+// CHECK-NEXT:       "file-deps": [
+// CHECK-NEXT:         "[[PREFIX]]/include/left.h",
+// CHECK-NEXT:         "[[PREFIX]]/include/module.modulemap"
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "name": "left"
+// CHECK-NEXT:     },
+// CHECK-NEXT:     {
+// CHECK-NEXT:       "clang-module-deps": [
+// CHECK-NEXT:         {
+// CHECK-NEXT:           "context-hash": "{{.*}}",
+// CHECK-NEXT:           "module-name": "right_extra"
+// CHECK-NEXT:         },
+// CHECK-NEXT:         {
+// CHECK-NEXT:           "context-hash": "{{.*}}",
+// CHECK-NEXT:           "module-name": "top"
+// CHECK-NEXT:         }
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "clang-modulemap-file": "[[PREFIX]]/include/module.modulemap",
+// CHECK-NEXT:       "command-line": [
+// CHECK:              "-fmodule-map-file=[[PREFIX]]/include/module.modulemap",
+// CHECK:              "-fmodule-file=right_extra=[[PREFIX]]/cache/{{.*}}/right_extra-{{.*}}.pcm",
+// CHECK:              "-fmodule-file=top=[[PREFIX]]/cache/{{.*}}/top-{{.*}}.pcm",
+// CHECK:            ],
+// CHECK-NEXT:       "context-hash": "{{.*}}",
+// CHECK-NEXT:       "file-deps": [
+// CHECK-NEXT:         "[[PREFIX]]/include/module.modulemap",
+// CHECK-NEXT:         "[[PREFIX]]/include/right.h"
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "name": "right"
+// CHECK-NEXT:     },
+// CHECK-NEXT:     {
+// CHECK-NEXT:       "clang-module-deps": [],
+// CHECK-NEXT:       "clang-modulemap-file": "[[PREFIX]]/include/module.modulemap",
+// CHECK-NEXT:       "command-line": [
+// CHECK:            ],
+// CHECK-NEXT:       "context-hash": "{{.*}}",
+// CHECK-NEXT:       "file-deps": [
+// CHECK-NEXT:         "[[PREFIX]]/include/module.modulemap",
+// CHECK-NEXT:         "[[PREFIX]]/include/right-extra.h"
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "name": "right_extra"
+// CHECK-NEXT:     },
+// CHECK-NEXT:     {
+// CHECK-NEXT:       "clang-module-deps": [],
+// CHECK-NEXT:       "clang-modulemap-file": "[[PREFIX]]/include/module.modulemap",
+// CHECK-NEXT:       "command-line": [
+// CHECK:            ],
+// CHECK-NEXT:       "context-hash": "{{.*}}",
+// CHECK-NEXT:       "file-deps": [
+// CHECK-NEXT:         "[[PREFIX]]/include/module.modulemap",
+// CHECK-NEXT:         "[[PREFIX]]/include/top.h"
+// CHECK-NEXT:       ],
+// CHECK-NEXT:       "name": "top"
+// CHECK-NEXT:     }
+// CHECK-NEXT:   ],
+// CHECK-NEXT:   "translation-units": [
+// CHECK-NEXT:     {
+// CHECK-NEXT:       "commands": [
+// CHECK-NEXT:         {
+// CHECK-NEXT:           "clang-context-hash": "{{.*}}",
+// CHECK-NEXT:           "clang-module-deps": [
+// CHECK-NEXT:             {
+// CHECK-NEXT:               "context-hash": "{{.*}}",
+// CHECK-NEXT:               "module-name": "bottom"
+// CHECK-NEXT:             }
+// CHECK-NEXT:           ],
+// CHECK-NEXT:           "command-line": [
+// CHECK:                  "-fmodule-map-file=[[PREFIX]]/include/module.modulemap",
+// CHECK:                  "-fmodule-file=bottom=[[PREFIX]]/cache/{{.*}}/bottom-{{.*}}.pcm",
+// CHECK:                ],
+// CHECK-NEXT:           "executable": "clang",
+// CHECK-NEXT:           "file-deps": [
+// CHECK-NEXT:             "[[PREFIX]]/tu.c"
+// CHECK-NEXT:           ],
+// CHECK-NEXT:           "input-file": "[[PREFIX]]/tu.c"
+// CHECK-NEXT:         }
+// CHECK-NEXT:       ]
+// CHECK-NEXT:     }
+// CHECK-NEXT:   ]
+// CHECK-NEXT: }
Index: clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
===================================================================
--- clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -11,6 +11,9 @@
 #include "clang/Basic/MakeSupport.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Lex/Preprocessor.h"
+#include "clang/Serialization/Simple/ASTReader.h"
+#include "clang/Serialization/Simple/ASTWriter.h"
+#include "clang/Serialization/Simple/ModuleCache.h"
 #include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
 #include "llvm/Support/BLAKE3.h"
 #include "llvm/Support/StringSaver.h"
@@ -20,19 +23,19 @@
 using namespace dependencies;
 
 static void optimizeHeaderSearchOpts(HeaderSearchOptions &Opts,
-                                     ASTReader &Reader,
-                                     const serialization::ModuleFile &MF) {
+                                     SimpleASTReader &Reader,
+                                     const serialization::SimpleModuleFile &MF) {
   // Only preserve search paths that were used during the dependency scan.
   std::vector<HeaderSearchOptions::Entry> Entries = Opts.UserEntries;
   Opts.UserEntries.clear();
 
   llvm::BitVector SearchPathUsage(Entries.size());
-  llvm::DenseSet<const serialization::ModuleFile *> Visited;
-  std::function<void(const serialization::ModuleFile *)> VisitMF =
-      [&](const serialization::ModuleFile *MF) {
+  llvm::DenseSet<const serialization::SimpleModuleFile *> Visited;
+  std::function<void(const serialization::SimpleModuleFile *)> VisitMF =
+      [&](const serialization::SimpleModuleFile *MF) {
         SearchPathUsage |= MF->SearchPathUsage;
         Visited.insert(MF);
-        for (const serialization::ModuleFile *Import : MF->Imports)
+        for (const serialization::SimpleModuleFile *Import : MF->Imports)
           if (!Visited.contains(Import))
             VisitMF(Import);
       };
@@ -380,7 +383,7 @@
     // -fmodule-name is used to compile a translation unit that imports this
     // module. In that case it can be skipped. The appropriate header
     // dependencies will still be reported as expected.
-    if (!M->getASTFile())
+    if (M->getFullModuleName() == MDC.ScanInstance.getLangOpts().ModuleName)
       continue;
     handleTopLevelModule(M);
   }
@@ -410,7 +413,6 @@
 
   MD.ID.ModuleName = M->getFullModuleName();
   MD.ImportedByMainFile = DirectModularDeps.contains(M);
-  MD.ImplicitModulePCMPath = std::string(M->getASTFile()->getName());
   MD.IsSystem = M->IsSystem;
 
   ModuleMap &ModMapInfo =
@@ -424,11 +426,15 @@
     MD.ClangModuleMapFile = std::string(Path);
   }
 
-  serialization::ModuleFile *MF =
-      MDC.ScanInstance.getASTReader()->getModuleManager().lookup(
-          M->getASTFile());
-  MDC.ScanInstance.getASTReader()->visitInputFiles(
-      *MF, true, true, [&](const serialization::InputFile &IF, bool isSystem) {
+  serialization::SimpleModuleFile *MF =
+      MDC.ScanInstance.getSimpleASTReader()->getModuleManager().lookup(
+          M->getFullModuleName());
+  if (!MF) {
+    llvm::errs() << "assert MF null for " << M->getFullModuleName() << "\n";
+    std::abort();
+  }
+  MDC.ScanInstance.getSimpleASTReader()->visitInputFiles(
+      *MF, true, true, [&](const serialization::SimpleInputFile &IF, bool isSystem) {
         // __inferred_module.map is the result of the way in which an implicit
         // module build handles inferred modules. It adds an overlay VFS with
         // this file in the proper directory and relies on the rest of Clang to
@@ -446,7 +452,7 @@
   addAllSubmoduleDeps(M, MD, SeenDeps);
   addAllAffectingClangModules(M, MD, SeenDeps);
 
-  MDC.ScanInstance.getASTReader()->visitTopLevelModuleMaps(
+  MDC.ScanInstance.getSimpleASTReader()->visitTopLevelModuleMaps(
       *MF, [&](const FileEntry *FE) {
         if (FE->getName().endswith("__inferred_module.map"))
           return;
@@ -457,7 +463,7 @@
       MD, [&](CompilerInvocation &BuildInvocation) {
         if (MDC.OptimizeArgs)
           optimizeHeaderSearchOpts(BuildInvocation.getHeaderSearchOpts(),
-                                   *MDC.ScanInstance.getASTReader(), *MF);
+                                   *MDC.ScanInstance.getSimpleASTReader(), *MF);
       });
 
   MDC.associateWithContextHash(CI, MD);
Index: clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
===================================================================
--- clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -19,6 +19,9 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Frontend/Utils.h"
 #include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Serialization/Simple/ASTReader.h"
+#include "clang/Serialization/Simple/ASTWriter.h"
+#include "clang/Serialization/Simple/ModuleCache.h"
 #include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
 #include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
 #include "clang/Tooling/Tooling.h"
@@ -178,6 +181,9 @@
     CompilerInstance &ScanInstance = *ScanInstanceStorage;
     ScanInstance.setInvocation(std::move(Invocation));
 
+    ScanInstance.getFrontendOpts().BuildingImplicitModuleUsesLock = false;
+    ScanInstance.getPreprocessorOpts().ScanningMode = true;
+
     // Create the compiler's actual diagnostics engine.
     sanitizeDiagOpts(ScanInstance.getDiagnosticOpts());
     ScanInstance.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
@@ -199,6 +205,8 @@
 
     ScanInstance.createSourceManager(*FileMgr);
 
+    ScanInstance.setSimpleModuleCache(std::make_shared<SimpleModuleCache>());
+
     llvm::StringSet<> PrebuiltModulesInputFiles;
     // Store the list of prebuilt module files into header search options. This
     // will prevent the implicit build to create duplicate modules and will
Index: clang/lib/Serialization/Simple/ASTReader.cpp
===================================================================
--- /dev/null
+++ clang/lib/Serialization/Simple/ASTReader.cpp
@@ -0,0 +1,708 @@
+#include "clang/Serialization/Simple/ASTReader.h"
+
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+
+/*
+namespace serialization2 {
+  SourceLocation translate(SourceLocation BLoc) {
+    if (BLoc.isInvalid())
+      return {};
+
+auto BOffset = BSM.getFileOffset(BLoc);
+auto AOffset = BOffset;
+
+auto BFileID = BSM.getFileID(BLoc);
+auto AFileID = [&]() {
+  if (BFileID == BPP.getPredefinesFileID())
+    return APP.getPredefinesFileID();
+
+  auto *BSLocEntry = BSM.getSLocEntryForFile(BFileID);
+
+  if (BSLocEntry->isFile()) {
+    if (auto BBuffer =
+            BSLocEntry->getFile().getContentCache().getBufferIfLoaded()) {
+      auto ABuffer = llvm::MemoryBuffer::getMemBuffer(*BBuffer);
+
+      auto BFileCharacteristic = BSM.getFileCharacteristic(BLoc);
+      auto AFileCharacteristic = BFileCharacteristic;
+
+      // TODO: Implement this.
+      int LoadedID = 0;
+      SourceLocation::UIntTy LoadedOffset = 0;
+
+      return ASM.createFileID(std::move(ABuffer), AFileCharacteristic,
+                              LoadedID, LoadedOffset);
+    }
+  }
+
+  auto *BFileEntry = BSM.getFileEntryForID(BFileID);
+  auto *AFileEntry = translate(BFileEntry);
+
+  auto BIncludeLoc = BSM.getIncludeLoc(BFileID);
+  auto AIncludeLoc = translate(BIncludeLoc);
+
+  auto BFileCharacteristic = BSM.getFileCharacteristic(BLoc);
+  auto AFileCharacteristic = BFileCharacteristic;
+
+  // TODO: Implement this.
+  int LoadedID = 0;
+  SourceLocation::UIntTy LoadedOffset = 0;
+
+  return ASM.createFileID(AFileEntry, AIncludeLoc, AFileCharacteristic,
+                          LoadedID, LoadedOffset);
+}();
+
+return ASM.getComposedLoc(AFileID, AOffset);
+}
+};
+
+// TODO: Integrate this properly.
+void foo() {
+  for (const auto &X : Instance.SortedFiles)
+    if (!ImportingInstance.SortedFiles.count(X.getKey()))
+      ImportingInstance.SortedFiles[X.getKey()] = X.getValue();
+
+  auto &SortedFiles = ImportingInstance.SortedFiles[ModuleName];
+
+  std::set<const FileEntry *> AffectingModuleMaps = GetAffectingModuleMaps(
+      Instance.getPreprocessor().getHeaderSearchInfo(),
+      Instance.getPreprocessor().getHeaderSearchInfo().lookupModule(
+          ModuleName));
+
+  SourceManager &SrcMgr = Instance.getPreprocessor().getSourceManager();
+  unsigned N = SrcMgr.local_sloc_entry_size();
+
+  for (unsigned I = 1; I != N; ++I) {
+    const SrcMgr::SLocEntry *SLoc = &SrcMgr.getLocalSLocEntry(I);
+
+    if (!SLoc->isFile())
+      continue;
+    const SrcMgr::FileInfo &File = SLoc->getFile();
+    const SrcMgr::ContentCache *Cache = &File.getContentCache();
+    if (!Cache->OrigEntry)
+      continue;
+
+    if (!isModuleMap(File.getFileCharacteristic()) ||
+        AffectingModuleMaps.empty() ||
+        AffectingModuleMaps.find(Cache->OrigEntry) !=
+            AffectingModuleMaps.end()) {
+      CompilerInstance::EntryStruct Entry{
+          T.translate(Cache->OrigEntry),
+          isSystem(File.getFileCharacteristic()),
+          isModuleMap(File.getFileCharacteristic()) &&
+              File.getIncludeLoc().isInvalid()};
+
+      if (Entry.IsSystemFile)
+        SortedFiles.push_back(Entry);
+      else
+        SortedFiles.push_front(Entry);
+    }
+  }
+}
+} // namespace
+} // namespace serialization2
+*/
+
+/// Mapping from a source location entry to whether it is affecting or not.
+/// Mostly copied from ASTWriter.cpp.
+llvm::BitVector collectNonAffectingInputFiles(Preprocessor &PP, Module *M) {
+  SourceManager &SrcMgr = PP.getSourceManager();
+  unsigned BN = SrcMgr.local_sloc_entry_size();
+
+  llvm::BitVector IsSLocAffecting(BN, true);
+
+  auto AffectingModuleMaps = PP.getAffectingModuleMaps(M);
+
+  for (unsigned I = 1; I != BN; ++I) {
+    const SrcMgr::SLocEntry *SLoc = &SrcMgr.getLocalSLocEntry(I);
+
+    if (!SLoc->isFile())
+      continue;
+    const SrcMgr::FileInfo &File = SLoc->getFile();
+    const SrcMgr::ContentCache *Cache = &File.getContentCache();
+    if (!Cache->OrigEntry)
+      continue;
+
+    if (!isModuleMap(File.getFileCharacteristic()) ||
+        AffectingModuleMaps.empty() ||
+        AffectingModuleMaps.find(Cache->OrigEntry) != AffectingModuleMaps.end())
+      continue;
+
+    IsSLocAffecting[I] = false;
+  }
+
+  return IsSLocAffecting;
+}
+
+bool SimpleASTReader::readAST(StringRef ModuleName, CompilerInstance &CI) {
+  SimplePCM *PCM = Cache->lookup(ModuleName);
+  if (PCM == nullptr)
+    return false;
+
+  llvm::SmallVector<SimpleModuleFile *> LoadedMFs;
+  readASTCore(ModuleName, nullptr, LoadedMFs);
+  for (SimpleModuleFile *LoadedMF : LoadedMFs)
+    readASTBlock(*LoadedMF, CI);
+
+  ASTTransfer T(CI, *PCM->CI, ModuleName);
+  T.translateFileManager();
+  T.translateSourceManager();
+  T.translatePreprocessor();
+  T.translateModule();
+
+  return true;
+}
+
+void SimpleASTReader::readASTCore(
+    StringRef Name, SimpleModuleFile *ImportedBy,
+    llvm::SmallVectorImpl<SimpleModuleFile *> &Loaded) {
+  SimpleModuleFile *M;
+  SimpleModuleManager::AddModuleResult AddResult =
+      ModuleMgr.addModule(Name, ImportedBy, M);
+
+  switch (AddResult) {
+  case SimpleModuleManager::AlreadyLoaded:
+    return;
+  case SimpleModuleManager::NewlyLoaded:
+    break;
+  }
+
+  // ReadControlBlock
+  SimplePCM *PCM = Cache->lookup(Name);
+  if (auto OtherReader = PCM->CI->getSimpleASTReader())
+    for (auto &X : OtherReader->getModuleManager())
+      readASTCore(X->ModuleName, M, Loaded);
+
+  std::vector<bool> SearchPathUsage =
+      PCM->CI->getPreprocessor().getHeaderSearchInfo().computeUserEntryUsage();
+  M->SearchPathUsage.resize(SearchPathUsage.size());
+  for (unsigned I = 0; I < SearchPathUsage.size(); ++I)
+    M->SearchPathUsage[I] = SearchPathUsage[I];
+
+  Loaded.push_back(M);
+}
+
+void SimpleASTReader::readASTBlock(SimpleModuleFile &F, CompilerInstance &CI) {
+  SimplePCM *PCM = Cache->lookup(F.ModuleName);
+  assert(PCM);
+
+  std::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) =
+      CI.getSourceManager().AllocateLoadedSLocEntries(
+          PCM->localValidSLocEntryCount(), PCM->getLastLocalOffset());
+
+  // These would be needed if we implemented the lazy-loading API
+  // (ExternalSLocEntrySource).
+#if 0
+  // Make our entry in the range map. BaseID is negative and growing, so
+  // we invert it. Because we invert it, though, we need the other end of
+  // the range.
+  unsigned RangeStart =
+      unsigned(-F.SLocEntryBaseID) - F.LocalNumSLocEntries + 1;
+  GlobalSLocEntryMap.insert(std::make_pair(RangeStart, &F));
+  F.FirstLoc = SourceLocation::getFromRawEncoding(F.SLocEntryBaseOffset);
+
+  // SLocEntryBaseOffset is lower than MaxLoadedOffset and decreasing.
+  assert((F.SLocEntryBaseOffset & SourceLocation::MacroIDBit) == 0);
+  ImportsInfo.DepRemaps[ModuleName].GlobalSLocOffsetMap.insert(std::make_pair(
+      SourceManager::MaxLoadedOffset - F.SLocEntryBaseOffset - SLocSpaceSize,
+      &F));
+#endif
+
+  // Initialize the remapping table.
+  // Invalid stays invalid.
+  F.SLocRemap.insertOrReplace(std::make_pair(0U, 0));
+  // This module. Base was 2 when being compiled.
+  F.SLocRemap.insertOrReplace(std::make_pair(
+      2U, static_cast<SourceLocation::IntTy>(F.SLocEntryBaseOffset - 2)));
+
+  for (const auto &[Name, SLocOffset] : PCM->SLocEntryBaseOffsets) {
+    SimpleModuleFile *OM = ModuleMgr.lookup(Name);
+
+    // Continuous range maps we may be updating in our module.
+    using SLocRemapBuilder =
+        ContinuousRangeMap<SourceLocation::UIntTy, SourceLocation::IntTy,
+                           2>::Builder;
+    SLocRemapBuilder SLocRemap(F.SLocRemap);
+    SLocRemap.insert({SLocOffset, static_cast<SourceLocation::IntTy>(
+                                      OM->SLocEntryBaseOffset - SLocOffset)});
+  }
+}
+
+void SimpleASTReader::visitInputFiles(SimpleModuleFile &MF, bool IncludeSystem,
+                                      bool Complain,
+                                      InputFileVisitorTy Visitor) {
+  SimplePCM *PCM = Cache->lookup(MF.ModuleName);
+  assert(PCM);
+  SourceManager &SourceMgr = PCM->CI->getSourceManager();
+  unsigned N = PCM->CI->getSourceManager().local_sloc_entry_size();
+  for (unsigned I = 1; I != N; ++I) {
+    SrcMgr::SLocEntry &SLoc = SourceMgr.LocalSLocEntryTable[I];
+    if (!SLoc.isFile())
+      continue;
+    const SrcMgr::FileInfo &FI = SLoc.getFile();
+    if (auto MaybeEntry = FI.getContentCache().OrigEntry)
+      Visitor(*MaybeEntry, false);
+  }
+}
+
+void SimpleASTReader::visitTopLevelModuleMaps(
+    SimpleModuleFile &MF, TopLevelModuleMapVisitorTy Visitor) {
+  SimplePCM *PCM = Cache->lookup(MF.ModuleName);
+  assert(PCM);
+
+  Preprocessor &PP = PCM->CI->getPreprocessor();
+  SourceManager &SourceMgr = PP.getSourceManager();
+
+  llvm::BitVector IsInputFileAffecting =
+      collectNonAffectingInputFiles(PP, PCM->CompiledModule);
+
+  unsigned N = SourceMgr.local_sloc_entry_size();
+  for (unsigned I = 1; I != N; ++I) {
+    SrcMgr::SLocEntry &SLoc = SourceMgr.LocalSLocEntryTable[I];
+    if (!SLoc.isFile())
+      continue;
+    const SrcMgr::FileInfo &FI = SLoc.getFile();
+    if (IsInputFileAffecting[I] &&
+        SrcMgr::isModuleMap(FI.getFileCharacteristic()))
+      if (auto MaybeEntry = FI.getContentCache().OrigEntry)
+        Visitor(*MaybeEntry);
+  }
+}
+
+SimpleASTReader::ASTTransfer::ASTTransfer(CompilerInstance &A,
+                                          CompilerInstance &B,
+                                          StringRef BModuleName)
+    : A(A), APP(A.getPreprocessor()), ASM(A.getSourceManager()),
+      AFM(A.getFileManager()), AHS(A.getPreprocessor().getHeaderSearchInfo()),
+      B(B), BPP(B.getPreprocessor()), BSM(B.getSourceManager()),
+      BFM(B.getFileManager()), BHS(B.getPreprocessor().getHeaderSearchInfo()),
+      BModule(BHS.getModuleMap().findModule(BModuleName)),
+      AModuleFile(
+          A.getSimpleASTReader()->getModuleManager().lookup(BModuleName)) {}
+
+void SimpleASTReader::ASTTransfer::translateFileManager() {
+  //
+}
+
+void SimpleASTReader::ASTTransfer::translateSourceManager() {
+  // We can't translate SLocEntries eagerly. Creating a FileID
+
+  for (const auto &MF : A.getSimpleASTReader()->getModuleManager()) {
+    SimplePCM *PCM = A.getSimpleASTReader()->getCache().lookup(MF->ModuleName);
+    assert(PCM);
+
+    SourceManager &SourceMgr = PCM->CI->getSourceManager();
+    unsigned N = SourceMgr.local_sloc_entry_size();
+    for (unsigned I = 1; I != N; ++I) {
+      SrcMgr::SLocEntry &SLoc = SourceMgr.LocalSLocEntryTable[I];
+
+      int AFileID = translateSLocEntryID(I, MF.get());
+      SourceLocation::UIntTy AOffset = translate(SLoc.getOffset(), MF.get());
+      unsigned Index = -AFileID - 2;
+
+      if (SLoc.isFile()) {
+        const SrcMgr::FileInfo &File = SLoc.getFile();
+        const SrcMgr::ContentCache *Content = &File.getContentCache();
+
+        if (Content->OrigEntry) {
+          if (!ASM.SLocEntryLoaded[Index])
+            ASM.createFileID(translate(*Content->OrigEntry),
+                             translate(File.getIncludeLoc()),
+                             File.getFileCharacteristic(), AFileID, AOffset);
+        } else {
+          llvm::Optional<llvm::MemoryBufferRef> Buffer =
+              Content->getBufferOrNone(PCM->CI->getDiagnostics(),
+                                       PCM->CI->getFileManager());
+          assert(Buffer);
+          if (!ASM.SLocEntryLoaded[Index])
+            ASM.createFileID(*Buffer, File.getFileCharacteristic(), AFileID,
+                             AOffset);
+        }
+      } else {
+        const SrcMgr::ExpansionInfo &Expansion = SLoc.getExpansion();
+
+        if (!ASM.SLocEntryLoaded[Index]) {
+          SourceLocation::UIntTy NextOffset = SourceMgr.getNextLocalOffset();
+          if (I + 1 != N)
+            NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset();
+          unsigned Length = NextOffset - SLoc.getOffset() - 1;
+
+          ASM.createExpansionLoc(translate(Expansion.getSpellingLoc()),
+                                 translate(Expansion.getExpansionLocStart()),
+                                 translate(Expansion.getExpansionLocEnd()),
+                                 Length, Expansion.isExpansionTokenRange(),
+                                 AFileID, AOffset);
+        }
+      }
+      /*
+      // We will detect whether a file changed and return 'Failure' for it, but
+      // we will also try to fail gracefully by setting up the SLocEntry.
+      unsigned InputID = Record[4];
+      InputFile IF = getInputFile(*F, InputID);
+      Optional<FileEntryRef> File = IF.getFile();
+      bool OverriddenBuffer = IF.isOverridden();
+
+      SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
+      if (IncludeLoc.isInvalid() && F->Kind != MK_MainFile) {
+        // This is the module's main file.
+        IncludeLoc = getImportLocation(F);
+      }
+      SrcMgr::CharacteristicKind
+          FileCharacter = (SrcMgr::CharacteristicKind)Record[2];
+      FileID FID = SourceMgr.createFileID(*File, IncludeLoc, FileCharacter, ID,
+                                          BaseOffset + Record[0]);
+      SrcMgr::FileInfo &FileInfo =
+          const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile());
+      FileInfo.NumCreatedFIDs = Record[5];
+      if (Record[3])
+        FileInfo.setHasLineDirectives();
+
+      unsigned NumFileDecls = Record[7];
+      if (NumFileDecls && ContextObj) {
+        const DeclID *FirstDecl = F->FileSortedDecls + Record[6];
+        assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?");
+        FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl,
+                                                               NumFileDecls));
+      }
+
+      const SrcMgr::ContentCache &ContentCache =
+          SourceMgr.getOrCreateContentCache(*File, isSystem(FileCharacter));
+      if (OverriddenBuffer && !ContentCache.BufferOverridden &&
+          ContentCache.ContentsEntry == ContentCache.OrigEntry &&
+          !ContentCache.getBufferIfLoaded()) {
+        auto Buffer = ReadBuffer(SLocEntryCursor, File->getName());
+        if (!Buffer)
+          return true;
+        SourceMgr.overrideFileContents(*File, std::move(Buffer));
+      }
+
+      break;
+    }
+    case SM_SLOC_BUFFER_ENTRY: {
+      const char *Name = Blob.data();
+      unsigned Offset = Record[0];
+      SrcMgr::CharacteristicKind
+          FileCharacter = (SrcMgr::CharacteristicKind)Record[2];
+      SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
+      if (IncludeLoc.isInvalid() && F->isModule()) {
+        IncludeLoc = getImportLocation(F);
+      }
+
+      auto Buffer = ReadBuffer(SLocEntryCursor, Name);
+      if (!Buffer)
+        return true;
+      SourceMgr.createFileID(std::move(Buffer), FileCharacter, ID,
+                             BaseOffset + Offset, IncludeLoc);
+      break;
+    }
+    */
+    }
+  }
+}
+
+SourceLocation
+SimpleASTReader::ASTTransfer::translate(SourceLocation Loc) const {
+  assert(AModuleFile->SLocRemap.find(Loc.getOffset()) !=
+             AModuleFile->SLocRemap.end() &&
+         "Cannot find offset to remap.");
+  SourceLocation::IntTy Remap =
+      AModuleFile->SLocRemap.find(Loc.getOffset())->second;
+  return Loc.getLocWithOffset(Remap);
+}
+
+SourceLocation::UIntTy
+SimpleASTReader::ASTTransfer::translate(SourceLocation::UIntTy Offset,
+                                        const SimpleModuleFile *MF) {
+  if (!MF)
+    MF = AModuleFile;
+  return Offset + MF->SLocRemap.find(Offset)->second;
+}
+
+SrcMgr::ContentCache *
+SimpleASTReader::ASTTransfer::translate(const SrcMgr::ContentCache &BCC) {
+  if (auto AOrigEntry = translate(BCC.OrigEntry))
+    return &ASM.getOrCreateContentCache(*AOrigEntry,
+                                        /*isSystemFile=*/false);
+  return nullptr;
+}
+
+Optional<SrcMgr::FileInfo>
+SimpleASTReader::ASTTransfer::translate(const SrcMgr::FileInfo &BFI) {
+  if (auto *AContentCache = translate(BFI.getContentCache()))
+    return SrcMgr::FileInfo::get(translate(BFI.getIncludeLoc()), *AContentCache,
+                                 BFI.getFileCharacteristic(), BFI.getName());
+  return None;
+}
+
+int SimpleASTReader::ASTTransfer::translateSLocEntryID(
+    int EntryID, const SimpleModuleFile *MF) {
+  if (!MF)
+    MF = AModuleFile;
+  return MF->SLocEntryBaseID + EntryID - 1;
+}
+
+const FileEntry &SimpleASTReader::ASTTransfer::translate(const FileEntry &BFE) {
+  if (auto MaybeAFE = AFM.getFile(BFE.getName()))
+    return **MaybeAFE;
+  return *AFM.getVirtualFile(BFE.getName(), BFE.getSize(),
+                             BFE.getModificationTime());
+}
+
+FileEntryRef SimpleASTReader::ASTTransfer::translate(FileEntryRef BFE) {
+  if (auto AFE = AFM.getOptionalFileRef(BFE.getNameAsRequested()))
+    return *AFE;
+  return AFM.getVirtualFileRef(BFE.getNameAsRequested(), BFE.getSize(),
+                               BFE.getModificationTime());
+}
+
+const DirectoryEntry &
+SimpleASTReader::ASTTransfer::translate(const DirectoryEntry &BDE) {
+  return **AFM.getDirectory(BDE.getName());
+}
+
+Module::Header
+SimpleASTReader::ASTTransfer::translate(const Module::Header &BHeader) {
+  return Module::Header{BHeader.NameAsWritten,
+                        BHeader.PathRelativeToRootModuleDirectory,
+                        translate(BHeader.Entry)};
+}
+
+std::vector<Module *>
+SimpleASTReader::ASTTransfer::translate(Module::submodule_iterator Begin,
+                                        Module::submodule_iterator End) {
+  std::vector<Module *> ASubModules;
+  for (auto It = Begin; It != End; ++It)
+    ASubModules.push_back(translate(*It));
+  return ASubModules;
+}
+
+Module::UnresolvedHeaderDirective SimpleASTReader::ASTTransfer::translate(
+    const Module::UnresolvedHeaderDirective &BD) {
+  return {BD.Kind, //
+          translate(BD.FileNameLoc),
+          BD.FileName,
+          BD.IsUmbrella,
+          BD.HasBuiltinHeader,
+          BD.Size,
+          BD.ModTime};
+}
+
+Module::ExportDecl
+SimpleASTReader::ASTTransfer::translate(const Module::ExportDecl &BED) {
+  return {translate(BED.getPointer()), BED.getInt()};
+}
+
+ModuleId SimpleASTReader::ASTTransfer::translate(const ModuleId &BId) {
+  ModuleId Res;
+  for (const auto &Element : BId)
+    Res.push_back({Element.first, translate(Element.second)});
+  return Res;
+}
+
+Module::UnresolvedExportDecl SimpleASTReader::ASTTransfer::translate(
+    const Module::UnresolvedExportDecl &BUED) {
+  return {translate(BUED.ExportLoc), translate(BUED.Id), BUED.Wildcard};
+}
+
+Module::LinkLibrary
+SimpleASTReader::ASTTransfer::translate(const Module::LinkLibrary &X) {
+  return X;
+}
+
+Module::UnresolvedConflict
+SimpleASTReader::ASTTransfer::translate(const Module::UnresolvedConflict &X) {
+  return {translate(X.Id), X.Message};
+}
+
+Module::Conflict
+SimpleASTReader::ASTTransfer::translate(const Module::Conflict &X) {
+  return {translate(X.Other), X.Message};
+}
+
+const Module &SimpleASTReader::ASTTransfer::translate(const Module &BMod) {
+  return translate(const_cast<Module &>(BMod));
+}
+
+Module &SimpleASTReader::ASTTransfer::translate(Module &BMod) {
+  auto &AModMap = AHS.getModuleMap();
+
+  auto [AMod, New] = AModMap.findOrCreateModule(
+      BMod.Name, translate(BMod.Parent), BMod.IsFramework, BMod.IsExplicit);
+
+  if (!TranslatedModules.insert({BMod.Name}).second)
+    return *AMod;
+
+  AMod->Kind = BMod.Kind;
+  AMod->Directory = translate(BMod.Directory);
+  AMod->PresumedModuleMapFile = BMod.PresumedModuleMapFile;
+  AMod->DefinitionLoc = translate(BMod.DefinitionLoc);
+  AMod->Umbrella = translate(BMod.Umbrella);
+  AMod->UmbrellaAsWritten = BMod.UmbrellaAsWritten;
+  AMod->UmbrellaRelativeToRootModuleDirectory =
+      BMod.UmbrellaRelativeToRootModuleDirectory;
+  AMod->ExportAsModule = BMod.ExportAsModule;
+
+  for (Module *BSubMod : BMod.submodules())
+    translate(BSubMod);
+
+  for (const FileEntry *BTopHeader : BMod.getTopHeaders(B.getFileManager()))
+    AMod->addTopHeader(translate(BTopHeader));
+
+  // TODO: Propagate VisibilityID to other data structures.
+
+  for (auto Kind : {Module::HK_Normal, Module::HK_Textual, Module::HK_Private,
+                    Module::HK_PrivateTextual, Module::HK_Excluded}) {
+    for (const auto &BH : BMod.Headers[Kind]) {
+      const auto &AH = translate(BH);
+      AModMap.addHeader(AMod, AH, ModuleMap::headerKindToRole(Kind),
+                        BHS.getFileInfo(BH.Entry).isModuleHeader);
+    }
+  }
+
+  AMod->UnresolvedHeaders = translate(BMod.UnresolvedHeaders);
+  AMod->MissingHeaders = translate(BMod.MissingHeaders);
+  AMod->Requirements = BMod.Requirements;
+  AMod->ShadowingModule = translate(BMod.ShadowingModule);
+  AMod->IsUnimportable = BMod.IsUnimportable;
+  AMod->HasIncompatibleModuleFile = BMod.HasIncompatibleModuleFile;
+  AMod->IsAvailable = BMod.IsAvailable;
+  AMod->IsFromModuleFile = BMod.IsFromModuleFile;
+  AMod->IsFramework = BMod.IsFramework;
+  AMod->IsExplicit = BMod.IsExplicit;
+  AMod->IsSystem = BMod.IsSystem;
+  AMod->IsExternC = BMod.IsExternC;
+  // This is being dropped by PCM files and propagating it triggers
+  // asserts.
+  // AMod->IsInferred = BMod.IsInferred;
+  AMod->InferSubmodules = BMod.InferSubmodules;
+  AMod->InferExplicitSubmodules = BMod.InferExplicitSubmodules;
+  AMod->InferExportWildcard = BMod.InferExportWildcard;
+  AMod->ConfigMacrosExhaustive = BMod.ConfigMacrosExhaustive;
+  AMod->NoUndeclaredIncludes = BMod.NoUndeclaredIncludes;
+  AMod->ModuleMapIsPrivate = BMod.ModuleMapIsPrivate;
+  AMod->NameVisibility = BMod.NameVisibility;
+  AMod->InferredSubmoduleLoc = translate(BMod.InferredSubmoduleLoc);
+  AMod->Imports = translate(BMod.Imports);
+  AMod->Exports = translate(BMod.Exports);
+  AMod->UnresolvedExports = translate(BMod.UnresolvedExports);
+  AMod->DirectUses = translate(BMod.DirectUses);
+  AMod->UnresolvedDirectUses = translate(BMod.UnresolvedDirectUses);
+  AMod->UndeclaredUses = translate(BMod.UndeclaredUses);
+  AMod->LinkLibraries = translate(BMod.LinkLibraries);
+  AMod->UseExportAsModuleLinkName = BMod.UseExportAsModuleLinkName;
+  AMod->ConfigMacros = BMod.ConfigMacros;
+  AMod->UnresolvedConflicts = BMod.UnresolvedConflicts;
+  AMod->Conflicts = BMod.Conflicts;
+
+  return *AMod;
+}
+
+void SimpleASTReader::ASTTransfer::translateModule() { translate(BModule); }
+
+IdentifierInfo &SimpleASTReader::ASTTransfer::translate(IdentifierInfo &BII) {
+  auto &AII = APP.getIdentifierTable().getOwn(BII.getName());
+
+  AII.setOutOfDate(false);
+
+  // TODO: Check if is interesting.
+
+  if (BII.hasRevertedTokenIDToIdentifier() &&
+      BII.getTokenID() != tok::TokenKind::identifier)
+    AII.revertTokenIDToIdentifier();
+  AII.setObjCOrBuiltinID(BII.getObjCOrBuiltinID());
+  AII.setIsPoisoned(BII.isPoisoned());
+
+  AII.setObjCKeywordID(BII.getObjCKeywordID());
+  AII.setHasMacroDefinition(BII.hasMacroDefinition());
+
+  return AII;
+}
+
+Token SimpleASTReader::ASTTransfer::translate(const Token &BTok) {
+  Token ATok;
+  ATok.startToken();
+  ATok.setLocation(translate(BTok.getLocation()));
+  ATok.setLength(BTok.getLength());
+  ATok.setIdentifierInfo(translate(BTok.getIdentifierInfo()));
+  ATok.setKind(BTok.getKind());
+  ATok.setFlags(BTok.getFlags());
+  return ATok;
+}
+
+MacroInfo &SimpleASTReader::ASTTransfer::translate(MacroInfo &BMI) {
+  auto BLoc = BMI.getDefinitionLoc();
+  auto ALoc = translate(BLoc);
+
+  MacroInfo &AMI = *APP.AllocateMacroInfo(ALoc);
+  AMI.setDefinitionEndLoc(BMI.getDefinitionEndLoc());
+  AMI.setIsUsed(BMI.isUsed());
+  AMI.setUsedForHeaderGuard(BMI.isUsedForHeaderGuard());
+
+  if (BMI.isFunctionLike()) {
+    AMI.setIsFunctionLike();
+    if (BMI.isC99Varargs())
+      AMI.setIsC99Varargs();
+    if (BMI.isGNUVarargs())
+      AMI.setIsGNUVarargs();
+    if (BMI.hasCommaPasting())
+      AMI.setHasCommaPasting();
+    std::vector<IdentifierInfo *> AParams;
+    for (const IdentifierInfo *BParam : BMI.params())
+      AParams.push_back(translate(const_cast<IdentifierInfo *>(BParam)));
+    AMI.setParameterList(AParams, APP.getPreprocessorAllocator());
+  }
+
+  // TODO: Complete preprocessing record.
+
+  std::vector<Token> AToks;
+  for (const Token &BTok : BMI.tokens())
+    AToks.push_back(translate(BTok));
+  AMI.setTokens(AToks, APP.getPreprocessorAllocator());
+
+  return AMI;
+}
+
+void SimpleASTReader::ASTTransfer::translatePreprocessor() {
+  for (const auto &BEntry : BPP.getIdentifierTable()) {
+    IdentifierInfo *BII = BEntry.getValue();
+
+    if (!BII->hadMacroDefinition())
+      continue;
+
+    // Macro directive history is not read for modules.
+
+    IdentifierInfo *BName = BII;
+    IdentifierInfo *AName = translate(BII);
+
+    // TODO: Why does this keep happening to me?
+    //    BName->setOutOfDate(false);
+
+    auto BLeafs = BPP.getLeafModuleMacros(BName);
+    SmallVector<ModuleMacro *, 8> BMacros(BLeafs.begin(), BLeafs.end());
+    llvm::DenseMap<ModuleMacro *, unsigned> Visits;
+    for (unsigned I = 0; I < BMacros.size(); ++I)
+      // Enqueue overridden macros once we've visited all their ancestors.
+      for (auto *BModuleMacro : BMacros[I]->overrides())
+        if (++Visits[BModuleMacro] == BModuleMacro->getNumOverridingMacros())
+          BMacros.push_back(BModuleMacro);
+
+    // Module macros are listed in reverse dependency order.
+    for (const auto *BMacro : llvm::reverse(BMacros)) {
+      auto *AModule = translate(BMacro->getOwningModule());
+      auto *AMacroInfo = translate(BMacro->getMacroInfo());
+
+      std::vector<ModuleMacro *> AOverrides;
+      for (auto *BOverride : BMacro->overrides()) {
+        auto *AOverrideModule = translate(BOverride->getOwningModule());
+        auto *AOverride = APP.getModuleMacro(AOverrideModule, AName);
+        assert(AOverride && "missing definition for overridden macro");
+        AOverrides.push_back(AOverride);
+      }
+
+      bool Inserted = false;
+      APP.addModuleMacro(AModule, AName, AMacroInfo, AOverrides, Inserted);
+    }
+  }
+}
Index: clang/lib/Serialization/GeneratePCH.cpp
===================================================================
--- clang/lib/Serialization/GeneratePCH.cpp
+++ clang/lib/Serialization/GeneratePCH.cpp
@@ -14,6 +14,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Sema/SemaConsumer.h"
 #include "clang/Serialization/ASTWriter.h"
 #include "llvm/Bitstream/BitstreamWriter.h"
@@ -39,6 +40,10 @@
 }
 
 void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
+  // Do not attempt to write the AST file.
+  if (PP.getPreprocessorOpts().ScanningMode)
+    return;
+
   // Don't create a PCH if there were fatal failures during module loading.
   if (PP.getModuleLoader().HadFatalFailure)
     return;
Index: clang/lib/Serialization/CMakeLists.txt
===================================================================
--- clang/lib/Serialization/CMakeLists.txt
+++ clang/lib/Serialization/CMakeLists.txt
@@ -21,6 +21,8 @@
   ModuleManager.cpp
   PCHContainerOperations.cpp
 
+  Simple/ASTReader.cpp
+
   ADDITIONAL_HEADERS
   ASTCommon.h
   ASTReaderInternals.h
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -161,64 +161,6 @@
 
 namespace {
 
-std::set<const FileEntry *> GetAffectingModuleMaps(const HeaderSearch &HS,
-                                                   Module *RootModule) {
-  std::set<const FileEntry *> ModuleMaps{};
-  std::set<const Module *> ProcessedModules;
-  SmallVector<const Module *> ModulesToProcess{RootModule};
-
-  SmallVector<const FileEntry *, 16> FilesByUID;
-  HS.getFileMgr().GetUniqueIDMapping(FilesByUID);
-
-  if (FilesByUID.size() > HS.header_file_size())
-    FilesByUID.resize(HS.header_file_size());
-
-  for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) {
-    const FileEntry *File = FilesByUID[UID];
-    if (!File)
-      continue;
-
-    const HeaderFileInfo *HFI =
-        HS.getExistingFileInfo(File, /*WantExternal*/ false);
-    if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader))
-      continue;
-
-    for (const auto &KH : HS.findAllModulesForHeader(File)) {
-      if (!KH.getModule())
-        continue;
-      ModulesToProcess.push_back(KH.getModule());
-    }
-  }
-
-  while (!ModulesToProcess.empty()) {
-    auto *CurrentModule = ModulesToProcess.pop_back_val();
-    ProcessedModules.insert(CurrentModule);
-
-    Optional<FileEntryRef> ModuleMapFile =
-        HS.getModuleMap().getModuleMapFileForUniquing(CurrentModule);
-    if (!ModuleMapFile) {
-      continue;
-    }
-
-    ModuleMaps.insert(*ModuleMapFile);
-
-    for (auto *ImportedModule : (CurrentModule)->Imports) {
-      if (!ImportedModule ||
-          ProcessedModules.find(ImportedModule) != ProcessedModules.end()) {
-        continue;
-      }
-      ModulesToProcess.push_back(ImportedModule);
-    }
-
-    for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses)
-      if (UndeclaredModule &&
-          ProcessedModules.find(UndeclaredModule) == ProcessedModules.end())
-        ModulesToProcess.push_back(UndeclaredModule);
-  }
-
-  return ModuleMaps;
-}
-
 class ASTTypeWriter {
   ASTWriter &Writer;
   ASTWriter::RecordData Record;
@@ -4519,8 +4461,7 @@
   if (!WritingModule)
     return;
 
-  auto AffectingModuleMaps =
-      GetAffectingModuleMaps(PP->getHeaderSearchInfo(), WritingModule);
+  auto AffectingModuleMaps = PP->getAffectingModuleMaps(WritingModule);
 
   unsigned FileIDAdjustment = 0;
   unsigned OffsetAdjustment = 0;
Index: clang/lib/Lex/Preprocessor.cpp
===================================================================
--- clang/lib/Lex/Preprocessor.cpp
+++ clang/lib/Lex/Preprocessor.cpp
@@ -535,6 +535,66 @@
   return getHeaderSearchInfo().lookupModule(getLangOpts().ModuleName);
 }
 
+std::set<const FileEntry *> Preprocessor::getAffectingModuleMaps(Module *M) {
+  Module *RootModule = M;
+  const HeaderSearch &HS = HeaderInfo;
+
+  std::set<const FileEntry *> ModuleMaps{};
+  std::set<const Module *> ProcessedModules;
+  SmallVector<const Module *> ModulesToProcess{RootModule};
+
+  SmallVector<const FileEntry *, 16> FilesByUID;
+  HS.getFileMgr().GetUniqueIDMapping(FilesByUID);
+
+  if (FilesByUID.size() > HS.header_file_size())
+    FilesByUID.resize(HS.header_file_size());
+
+  for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) {
+    const FileEntry *File = FilesByUID[UID];
+    if (!File)
+      continue;
+
+    const HeaderFileInfo *HFI =
+        HS.getExistingFileInfo(File, /*WantExternal*/ false);
+    if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader))
+      continue;
+
+    for (const auto &KH : HS.findAllModulesForHeader(File)) {
+      if (!KH.getModule())
+        continue;
+      ModulesToProcess.push_back(KH.getModule());
+    }
+  }
+
+  while (!ModulesToProcess.empty()) {
+    auto *CurrentModule = ModulesToProcess.pop_back_val();
+    ProcessedModules.insert(CurrentModule);
+
+    Optional<FileEntryRef> ModuleMapFile =
+        HS.getModuleMap().getModuleMapFileForUniquing(CurrentModule);
+    if (!ModuleMapFile) {
+      continue;
+    }
+
+    ModuleMaps.insert(*ModuleMapFile);
+
+    for (auto *ImportedModule : (CurrentModule)->Imports) {
+      if (!ImportedModule ||
+          ProcessedModules.find(ImportedModule) != ProcessedModules.end()) {
+        continue;
+      }
+      ModulesToProcess.push_back(ImportedModule);
+    }
+
+    for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses)
+      if (UndeclaredModule &&
+          ProcessedModules.find(UndeclaredModule) == ProcessedModules.end())
+        ModulesToProcess.push_back(UndeclaredModule);
+  }
+
+  return ModuleMaps;
+}
+
 //===----------------------------------------------------------------------===//
 // Preprocessor Initialization Methods
 //===----------------------------------------------------------------------===//
Index: clang/lib/Frontend/FrontendActions.cpp
===================================================================
--- clang/lib/Frontend/FrontendActions.cpp
+++ clang/lib/Frontend/FrontendActions.cpp
@@ -120,6 +120,9 @@
 
 std::unique_ptr<ASTConsumer>
 GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
+  if (CI.getPreprocessorOpts().ScanningMode)
+    return std::make_unique<ASTConsumer>();
+
   std::string Sysroot;
   if (!ComputeASTConsumerArguments(CI, /*ref*/ Sysroot))
     return nullptr;
@@ -185,6 +188,9 @@
 std::unique_ptr<ASTConsumer>
 GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
                                         StringRef InFile) {
+  if (CI.getPreprocessorOpts().ScanningMode)
+    return std::make_unique<ASTConsumer>();
+
   std::unique_ptr<raw_pwrite_stream> OS = CreateOutputFile(CI, InFile);
   if (!OS)
     return nullptr;
Index: clang/lib/Frontend/FrontendAction.cpp
===================================================================
--- clang/lib/Frontend/FrontendAction.cpp
+++ clang/lib/Frontend/FrontendAction.cpp
@@ -1129,7 +1129,7 @@
 
   setCompilerInstance(nullptr);
   setCurrentInput(FrontendInputFile());
-  CI.getLangOpts().setCompilingModule(LangOptions::CMK_None);
+//  CI.getLangOpts().setCompilingModule(LangOptions::CMK_None);
 }
 
 bool FrontendAction::shouldEraseOutputFiles() {
Index: clang/lib/Frontend/CompilerInstance.cpp
===================================================================
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -39,6 +39,9 @@
 #include "clang/Serialization/ASTReader.h"
 #include "clang/Serialization/GlobalModuleIndex.h"
 #include "clang/Serialization/InMemoryModuleCache.h"
+#include "clang/Serialization/Simple/ASTReader.h"
+#include "clang/Serialization/Simple/ASTWriter.h"
+#include "clang/Serialization/Simple/ModuleCache.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Config/llvm-config.h"
@@ -209,6 +212,23 @@
   TheASTReader = std::move(Reader);
 }
 
+std::shared_ptr<SimpleASTReader> CompilerInstance::getSimpleASTReader() const {
+  return TheSimpleASTReader;
+}
+
+std::shared_ptr<SimpleASTWriter> CompilerInstance::getSimpleASTWriter() const {
+  return TheSimpleASTWriter;
+}
+
+std::shared_ptr<SimpleModuleCache> CompilerInstance::getSimpleModuleCache() {
+  return TheSimpleModuleCache;
+}
+
+void CompilerInstance::setSimpleModuleCache(
+    std::shared_ptr<SimpleModuleCache> Cache) {
+  TheSimpleModuleCache = std::move(Cache);
+}
+
 std::shared_ptr<ModuleDependencyCollector>
 CompilerInstance::getModuleDepCollector() const {
   return ModuleDepCollector;
@@ -1212,8 +1232,10 @@
   // module.  Since we're sharing an in-memory module cache,
   // CompilerInstance::CompilerInstance is responsible for finalizing the
   // buffers to prevent use-after-frees.
-  CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(),
-                            &ImportingInstance.getModuleCache());
+  auto InstancePtr = std::make_shared<CompilerInstance>(
+      ImportingInstance.getPCHContainerOperations(),
+      &ImportingInstance.getModuleCache());
+  CompilerInstance& Instance = *InstancePtr;
   auto &Inv = *Invocation;
   Instance.setInvocation(std::move(Invocation));
 
@@ -1229,6 +1251,8 @@
   Instance.createSourceManager(Instance.getFileManager());
   SourceManager &SourceMgr = Instance.getSourceManager();
 
+  Instance.setSimpleModuleCache(ImportingInstance.getSimpleModuleCache());
+
   // Note that this module is part of the module build stack, so that we
   // can detect cycles in the module graph.
   SourceMgr.setModuleBuildStack(
@@ -1248,6 +1272,10 @@
 
   PreBuildStep(Instance);
 
+  if (Instance.getPreprocessorOpts().ScanningMode) {
+    llvm::errs() << "{{{{{{{{{{ " << ModuleName << "\n";
+  }
+
   // Execute the action to actually build the module in-place. Use a separate
   // thread so that we get a stack large enough.
   bool Crashed = !llvm::CrashRecoveryContext().RunSafelyOnThread(
@@ -1257,6 +1285,24 @@
       },
       DesiredStackSize);
 
+  if (Instance.getPreprocessorOpts().ScanningMode) {
+    if (!Instance.getSimpleASTReader())
+      Instance.createSimpleASTReader();
+    if (!Instance.getSimpleASTWriter())
+      Instance.createSimpleASTWriter();
+
+    assert(Instance.getLangOpts().isCompilingModule());
+    Module *Module =
+        Instance.getPreprocessor().getHeaderSearchInfo().lookupModule(
+            Instance.getLangOpts().CurrentModule, SourceLocation(),
+            /*AllowSearch=*/false);
+    assert(Module);
+
+    Instance.getSimpleASTWriter()->writeAST(ModuleName, Module, InstancePtr);
+    llvm::errs() << "}}}}}}}}}} " << ModuleName << "\n";
+    ImportingInstance.getSimpleASTReader()->readAST(ModuleName, ImportingInstance);
+  }
+
   PostBuildStep(Instance);
 
   ImportingInstance.getDiagnostics().Report(ImportLoc,
@@ -1364,6 +1410,10 @@
                                       SourceLocation ModuleNameLoc,
                                       Module *Module, StringRef ModuleFileName,
                                       bool *OutOfDate) {
+  // Do not attempt to read the AST file.
+  if (ImportingInstance.getPreprocessorOpts().ScanningMode)
+    return true;
+
   DiagnosticsEngine &Diags = ImportingInstance.getDiagnostics();
 
   unsigned ModuleLoadCapabilities = ASTReader::ARR_Missing;
@@ -1648,6 +1698,21 @@
   }
 }
 
+void CompilerInstance::createSimpleASTReader() {
+  if (TheSimpleASTReader)
+    return;
+
+  TheSimpleASTReader = std::make_shared<SimpleASTReader>(TheSimpleModuleCache);
+}
+
+void CompilerInstance::createSimpleASTWriter() {
+  if (TheSimpleASTWriter)
+    return;
+
+  TheSimpleASTWriter = std::make_shared<SimpleASTWriter>(
+      TheSimpleModuleCache, TheSimpleASTReader.get());
+}
+
 void CompilerInstance::createASTReader() {
   if (TheASTReader)
     return;
@@ -1799,6 +1864,14 @@
   Module *M =
       HS.lookupModule(ModuleName, ImportLoc, true, !IsInclusionDirective);
 
+  if (getPreprocessorOpts().ScanningMode) {
+    // Create an ASTTransfer on demand.
+    if (!getSimpleASTReader())
+      createSimpleASTReader();
+    if (getSimpleASTReader()->readAST(ModuleName, *this))
+      return M;
+  }
+
   // Select the source and filename for loading the named module.
   std::string ModuleFilename;
   ModuleSource Source =
@@ -2092,7 +2165,7 @@
   // Make the named module visible, if it's not already part of the module
   // we are parsing.
   if (ModuleName != getLangOpts().CurrentModule) {
-    if (!Module->IsFromModuleFile && !MapPrivateSubModToTopLevel) {
+    if (!getPreprocessorOpts().ScanningMode && !Module->IsFromModuleFile && !MapPrivateSubModToTopLevel) {
       // We have an umbrella header or directory that doesn't actually include
       // all of the headers within the directory it covers. Complain about
       // this missing submodule and recover by forgetting that we ever saw
Index: clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
===================================================================
--- clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
+++ clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
@@ -87,9 +87,6 @@
   /// additionally appear in \c FileDeps as a dependency.
   std::string ClangModuleMapFile;
 
-  /// The path to where an implicit build would put the PCM for this module.
-  std::string ImplicitModulePCMPath;
-
   /// A collection of absolute paths to files that this module directly depends
   /// on, not including transitive dependencies.
   llvm::StringSet<> FileDeps;
Index: clang/include/clang/Serialization/Simple/ModuleManager.h
===================================================================
--- /dev/null
+++ clang/include/clang/Serialization/Simple/ModuleManager.h
@@ -0,0 +1,57 @@
+#ifndef LLVM_CLANG_SERIALIZATION_SIMPLE_MODULEMANAGER_H
+#define LLVM_CLANG_SERIALIZATION_SIMPLE_MODULEMANAGER_H
+
+#include "clang/Serialization/Simple/ModuleFile.h"
+
+#include "llvm/ADT/SmallVector.h"
+
+#include <memory>
+
+namespace clang {
+namespace serialization {
+class SimpleModuleManager {
+  /// The chain of modules, in the order in which we started to load
+  /// them (this order isn't really useful for anything).
+  SmallVector<std::unique_ptr<SimpleModuleFile>, 2> Chain;
+
+  /// All loaded modules, indexed by name.
+  llvm::StringMap<SimpleModuleFile *> Modules;
+
+public:
+  SimpleModuleFile *lookup(StringRef Name) const {
+    return Modules.lookup(Name);
+  }
+
+  /// The result of attempting to add a new module.
+  enum AddModuleResult {
+    AlreadyLoaded,
+    NewlyLoaded,
+  };
+
+  AddModuleResult addModule(StringRef Name, SimpleModuleFile *ImportedBy,
+                            SimpleModuleFile *&Module) {
+    auto UpdateModuleImports = [&](SimpleModuleFile &MF,
+                                   SimpleModuleFile *ImportedBy) {
+      if (ImportedBy)
+        ImportedBy->Imports.insert(&MF);
+    };
+
+    if (SimpleModuleFile *ModuleEntry = Modules.lookup(Name)) {
+      Module = ModuleEntry;
+      UpdateModuleImports(*ModuleEntry, ImportedBy);
+      return AlreadyLoaded;
+    }
+
+    Chain.push_back(std::make_unique<SimpleModuleFile>(Name));
+    Module = Modules[Name] = Chain.back().get();
+    UpdateModuleImports(*Module, ImportedBy);
+    return NewlyLoaded;
+  }
+
+  auto begin() { return Chain.begin(); }
+  auto end() { return Chain.end(); }
+};
+} // namespace serialization
+} // namespace clang
+
+#endif // LLVM_CLANG_SERIALIZATION_SIMPLE_MODULEMANAGER_H
Index: clang/include/clang/Serialization/Simple/ModuleFile.h
===================================================================
--- /dev/null
+++ clang/include/clang/Serialization/Simple/ModuleFile.h
@@ -0,0 +1,73 @@
+#ifndef LLVM_CLANG_SERIALIZATION_SIMPLE_MODULEFILE_H
+#define LLVM_CLANG_SERIALIZATION_SIMPLE_MODULEFILE_H
+
+#include "clang/Basic/FileEntry.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Serialization/ContinuousRangeMap.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SetVector.h"
+
+namespace clang {
+namespace serialization {
+/// The input file that has been loaded from this AST file, along with
+/// bools indicating whether this was an overridden buffer or if it was
+/// out-of-date or not-found.
+class SimpleInputFile {
+  enum { Overridden = 1, OutOfDate = 2, NotFound = 3 };
+  llvm::PointerIntPair<const FileEntryRef::MapEntry *, 2, unsigned> Val;
+
+public:
+  SimpleInputFile() = default;
+
+  SimpleInputFile(FileEntryRef File, bool isOverridden = false,
+                  bool isOutOfDate = false) {
+    assert(!(isOverridden && isOutOfDate) &&
+           "an overridden cannot be out-of-date");
+    unsigned intVal = 0;
+    if (isOverridden)
+      intVal = Overridden;
+    else if (isOutOfDate)
+      intVal = OutOfDate;
+    Val.setPointerAndInt(&File.getMapEntry(), intVal);
+  }
+
+  static SimpleInputFile getNotFound() {
+    SimpleInputFile File;
+    File.Val.setInt(NotFound);
+    return File;
+  }
+
+  OptionalFileEntryRefDegradesToFileEntryPtr getFile() const {
+    if (auto *P = Val.getPointer())
+      return FileEntryRef(*P);
+    return None;
+  }
+  bool isOverridden() const { return Val.getInt() == Overridden; }
+  bool isOutOfDate() const { return Val.getInt() == OutOfDate; }
+  bool isNotFound() const { return Val.getInt() == NotFound; }
+};
+
+struct SimpleModuleFile {
+  std::string ModuleName;
+
+  llvm::SetVector<SimpleModuleFile *> Imports;
+
+  /// The base ID in the source manager's view of this module.
+  int SLocEntryBaseID = 0;
+
+  /// The base offset in the source manager's view of this module.
+  SourceLocation::UIntTy SLocEntryBaseOffset = 0;
+
+  /// Remapping table for source locations in this module.
+  ContinuousRangeMap<SourceLocation::UIntTy, SourceLocation::IntTy, 2>
+      SLocRemap;
+
+  // TODO: Pull this on-demand from SimpleInMemoryPCM?
+  llvm::BitVector SearchPathUsage;
+
+  SimpleModuleFile(StringRef Name) : ModuleName(Name.str()) {}
+};
+} // namespace serialization
+} // namespace clang
+
+#endif // LLVM_CLANG_SERIALIZATION_SIMPLE_MODULEFILE_H
Index: clang/include/clang/Serialization/Simple/ModuleCache.h
===================================================================
--- /dev/null
+++ clang/include/clang/Serialization/Simple/ModuleCache.h
@@ -0,0 +1,53 @@
+#ifndef LLVM_CLANG_SERIALIZATION_SIMPLE_MODULECACHE_H
+#define LLVM_CLANG_SERIALIZATION_SIMPLE_MODULECACHE_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "llvm/ADT/StringMap.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace clang {
+struct SimplePCM {
+  std::shared_ptr<CompilerInstance> CI;
+
+  Module *CompiledModule;
+
+  std::vector<std::pair<std::string, SourceLocation::UIntTy>>
+      SLocEntryBaseOffsets;
+
+  SimplePCM(std::shared_ptr<CompilerInstance> CI, Module *CompiledModule)
+      : CI(std::move(CI)), CompiledModule(CompiledModule) {}
+
+  unsigned localValidSLocEntryCount() const {
+    // Subtracting 1 to ignore to invalid entry at index 0.
+    return CI->getSourceManager().local_sloc_entry_size() - 1;
+  }
+
+  SourceLocation::UIntTy getLastLocalOffset() const {
+    // Subtracting 1 to get the last local offset.
+    return CI->getSourceManager().getNextLocalOffset() - 1;
+  }
+};
+
+class SimpleModuleCache {
+  llvm::StringMap<SimplePCM> PCMs;
+
+public:
+  SimplePCM &insert(StringRef Name, SimplePCM PCM) {
+    return PCMs.insert({Name, std::move(PCM)}).first->getValue();
+  }
+
+  SimplePCM *lookup(StringRef Name) {
+    auto It = PCMs.find(Name);
+    if (It == PCMs.end())
+      return nullptr;
+    return &It->second;
+  }
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_SERIALIZATION_SIMPLE_MODULECACHE_H
Index: clang/include/clang/Serialization/Simple/ASTWriter.h
===================================================================
--- /dev/null
+++ clang/include/clang/Serialization/Simple/ASTWriter.h
@@ -0,0 +1,36 @@
+#ifndef LLVM_CLANG_SERIALIZATION_SIMPLE_ASTWRITER_H
+#define LLVM_CLANG_SERIALIZATION_SIMPLE_ASTWRITER_H
+
+#include "clang/Serialization/Simple/ModuleCache.h"
+
+namespace clang {
+/// The evil twin of ASTReader.
+class SimpleASTWriter {
+  using SimpleModuleManager = serialization::SimpleModuleManager;
+  using SimpleModuleFile = serialization::SimpleModuleFile;
+
+  std::shared_ptr<SimpleModuleCache> Cache;
+
+  SimpleASTReader *ASTRdr;
+
+public:
+  explicit SimpleASTWriter(std::shared_ptr<SimpleModuleCache> Cache,
+                           SimpleASTReader *ASTRdr)
+      : Cache(std::move(Cache)), ASTRdr(ASTRdr) {}
+
+  void writeAST(StringRef ModuleName, Module *WritingModule,
+                std::shared_ptr<CompilerInstance> CI) {
+    SimplePCM &PCM =
+        Cache->insert(ModuleName, SimplePCM(std::move(CI), WritingModule));
+
+    assert(ASTRdr);
+    SimpleModuleManager &ModuleMgr = ASTRdr->getModuleManager();
+    for (const std::unique_ptr<SimpleModuleFile> &M : ModuleMgr)
+      PCM.SLocEntryBaseOffsets.emplace_back(M->ModuleName,
+                                            M->SLocEntryBaseOffset);
+    //
+  }
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_SERIALIZATION_SIMPLE_ASTWRITER_H
Index: clang/include/clang/Serialization/Simple/ASTReader.h
===================================================================
--- /dev/null
+++ clang/include/clang/Serialization/Simple/ASTReader.h
@@ -0,0 +1,195 @@
+#ifndef LLVM_CLANG_SERIALIZATION_SIMPLE_ASTREADER_H
+#define LLVM_CLANG_SERIALIZATION_SIMPLE_ASTREADER_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Serialization/Simple/ModuleCache.h"
+#include "clang/Serialization/Simple/ModuleFile.h"
+#include "clang/Serialization/Simple/ModuleManager.h"
+
+namespace clang {
+/// The evil twin of ASTReader.
+class SimpleASTReader : public ExternalPreprocessorSource,
+                        public ExternalPreprocessingRecordSource,
+                        public ExternalHeaderFileInfoSource,
+                        public ExternalSemaSource,
+                        public IdentifierInfoLookup,
+                        public ExternalSLocEntrySource {
+  using SimpleModuleManager = serialization::SimpleModuleManager;
+  using SimpleModuleFile = serialization::SimpleModuleFile;
+
+  std::shared_ptr<SimpleModuleCache> Cache;
+
+  SimpleModuleManager ModuleMgr;
+
+public:
+  // Custom {
+  explicit SimpleASTReader(std::shared_ptr<SimpleModuleCache> Cache)
+      : Cache(std::move(Cache)) {}
+
+  SimpleModuleManager &getModuleManager() { return ModuleMgr; }
+
+  SimpleModuleCache &getCache() { return *Cache; }
+
+  bool readAST(StringRef ModuleName, CompilerInstance &CI);
+
+  void readASTCore(StringRef Name, SimpleModuleFile *ImportedBy,
+                   llvm::SmallVectorImpl<SimpleModuleFile *> &Loaded);
+  void readASTBlock(SimpleModuleFile &F, CompilerInstance &CI);
+
+  using InputFileVisitorTy = llvm::function_ref<void(
+      const serialization::SimpleInputFile &IF, bool isSystem)>;
+  using TopLevelModuleMapVisitorTy =
+      llvm::function_ref<void(const FileEntry *)>;
+
+  void visitInputFiles(SimpleModuleFile &MF, bool IncludeSystem, bool Complain,
+                       InputFileVisitorTy Visitor);
+
+  void visitTopLevelModuleMaps(SimpleModuleFile &MF,
+                               TopLevelModuleMapVisitorTy Visitor);
+
+  // Custom }
+
+  // clang-format off
+
+  // ExternalPreprocessorSource {
+  void ReadDefinedMacros() override {}
+  void updateOutOfDateIdentifier(IdentifierInfo &II) override {}
+  IdentifierInfo *GetIdentifier(unsigned int ID) override { return {}; }
+  Module *getModule(unsigned int ModuleID) override { return {}; }
+  // ExternalPreprocessorSource }
+
+  // ExternalPreprocessingRecordSource {
+  PreprocessedEntity *ReadPreprocessedEntity(unsigned int Index) override { return {}; }
+  std::pair<unsigned int, unsigned int> findPreprocessedEntitiesInRange(SourceRange Range) override { return {}; }
+  Optional<bool> isPreprocessedEntityInFileID(unsigned Index, FileID FID) override { return {}; }
+  SourceRange ReadSkippedRange(unsigned int Index) override { return {}; }
+  // ExternalPreprocessingRecordSource }
+
+  // ExternalHeaderFileInfoSource {
+  HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) override { return {}; }
+  // ExternalHeaderFileInfoSource }
+
+  // ExternalSemaSource {
+  // ExternalSemaSource }
+
+  // IdentifierInfoLookup {
+  IdentifierInfo *get(StringRef Name) override { return {}; }
+  IdentifierIterator *getIdentifiers() override { return {}; }
+  // IdentifierInfoLookup }
+
+  // ExternalSLocEntrySource {
+  bool ReadSLocEntry(int ID) override { return false; }
+  std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) override { return {}; }
+  // ExternalSLocEntrySource }
+
+  // clang-format on
+
+  class ASTTransfer {
+    CompilerInstance &A;
+    Preprocessor &APP;
+    SourceManager &ASM;
+    FileManager &AFM;
+    HeaderSearch &AHS;
+
+    CompilerInstance &B;
+    Preprocessor &BPP;
+    SourceManager &BSM;
+    FileManager &BFM;
+    HeaderSearch &BHS;
+
+    const Module *BModule;
+    const SimpleModuleFile *AModuleFile;
+
+    llvm::StringSet<> TranslatedModules;
+
+  public:
+    ASTTransfer(CompilerInstance &A, CompilerInstance &B,
+                StringRef BModuleName);
+
+    void translateFileManager();
+    const FileEntry &translate(const FileEntry &BFE);
+    FileEntryRef translate(FileEntryRef BFE);
+    const DirectoryEntry &translate(const DirectoryEntry &BDE);
+
+    void translateSourceManager();
+    SourceLocation translate(SourceLocation Loc) const;
+    SourceLocation::UIntTy translate(SourceLocation::UIntTy Offset,
+                                     const SimpleModuleFile *MF = nullptr);
+    Optional<SrcMgr::FileInfo> translate(const SrcMgr::FileInfo &BFI);
+    SrcMgr::ContentCache *translate(const SrcMgr::ContentCache &BCC);
+    int translateSLocEntryID(int EntryID, const SimpleModuleFile *MF = nullptr);
+
+    void translatePreprocessor();
+    void translateModule();
+    Module &translate(Module &BMod);
+    const Module &translate(const Module &BMod);
+    Module::Header translate(const Module::Header &BHeader);
+    std::vector<Module *> translate(Module::submodule_iterator Begin,
+                                    Module::submodule_iterator End);
+    Module::UnresolvedHeaderDirective
+    translate(const Module::UnresolvedHeaderDirective &BD);
+    Module::ExportDecl translate(const Module::ExportDecl &BED);
+    ModuleId translate(const ModuleId &BId);
+    Module::UnresolvedExportDecl
+    translate(const Module::UnresolvedExportDecl &BUED);
+    Module::LinkLibrary translate(const Module::LinkLibrary &X);
+    Module::UnresolvedConflict translate(const Module::UnresolvedConflict &X);
+    Module::Conflict translate(const Module::Conflict &X);
+    IdentifierInfo &translate(IdentifierInfo &BII);
+    Token translate(const Token &BTok);
+    MacroInfo &translate(MacroInfo &BMI);
+
+    template <class T> Optional<T> translate(const Optional<T> &BO) {
+      if (!BO)
+        return None;
+      return translate(*BO);
+    }
+
+    template <class T> const T *translate(const T *BP) {
+      if (!BP)
+        return nullptr;
+      return &translate(*BP);
+    }
+
+    template <class T> T *translate(T *BP) {
+      if (!BP)
+        return nullptr;
+      return &translate(*BP);
+    }
+
+    template <class T, class U>
+    llvm::PointerUnion<T, U> translate(llvm::PointerUnion<T, U> BPU) {
+      if (!BPU)
+        return nullptr;
+      if (BPU.template is<T>())
+        return translate(BPU.template get<T>());
+      return translate(BPU.template get<U>());
+    }
+
+    template <class T, unsigned N>
+    SmallVector<T, N> translate(const SmallVector<T, N> &BV) {
+      SmallVector<T, N> AV;
+      AV.reserve(BV.size());
+      for (const T &Entry : BV)
+        AV.push_back(translate(Entry));
+      return AV;
+    }
+
+    template <class T, unsigned N>
+    llvm::SmallSetVector<T, N>
+    translate(const llvm::SmallSetVector<T, N> &BSSV) {
+      llvm::SmallSetVector<T, N> ASSV;
+      for (const auto &Entry : BSSV)
+        ASSV.insert(translate(Entry));
+      return ASSV;
+    }
+  };
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_SERIALIZATION_SIMPLE_ASTREADER_H
Index: clang/include/clang/Lex/Token.h
===================================================================
--- clang/include/clang/Lex/Token.h
+++ clang/include/clang/Lex/Token.h
@@ -246,7 +246,7 @@
     Flags &= ~Flag;
   }
 
-  /// Return the internal represtation of the flags.
+  /// Return the internal representation of the flags.
   ///
   /// This is only intended for low-level operations such as writing tokens to
   /// disk.
@@ -254,6 +254,14 @@
     return Flags;
   }
 
+  /// Set the internal representation of the flags.
+  ///
+  /// This is only intended for low-level operations such as writing tokens to
+  /// disk.
+  void setFlags(unsigned Flags) {
+    this->Flags = Flags;
+  }
+
   /// Set a flag to either true or false.
   void setFlagValue(TokenFlags Flag, bool Val) {
     if (Val)
Index: clang/include/clang/Lex/PreprocessorOptions.h
===================================================================
--- clang/include/clang/Lex/PreprocessorOptions.h
+++ clang/include/clang/Lex/PreprocessorOptions.h
@@ -68,6 +68,8 @@
   std::vector<std::string> Includes;
   std::vector<std::string> MacroIncludes;
 
+  bool ScanningMode = false;
+
   /// Initialize the preprocessor with the compiler and target specific
   /// predefines.
   bool UsePredefines = true;
Index: clang/include/clang/Lex/Preprocessor.h
===================================================================
--- clang/include/clang/Lex/Preprocessor.h
+++ clang/include/clang/Lex/Preprocessor.h
@@ -52,6 +52,7 @@
 #include <cstdint>
 #include <map>
 #include <memory>
+#include <set>
 #include <string>
 #include <utility>
 #include <vector>
@@ -1154,6 +1155,8 @@
   /// Returns the FileID for the preprocessor predefines.
   FileID getPredefinesFileID() const { return PredefinesFileID; }
 
+  std::set<const FileEntry *> getAffectingModuleMaps(Module *M);
+
   /// \{
   /// Accessors for preprocessor callbacks.
   ///
Index: clang/include/clang/Frontend/CompilerInstance.h
===================================================================
--- clang/include/clang/Frontend/CompilerInstance.h
+++ clang/include/clang/Frontend/CompilerInstance.h
@@ -38,6 +38,9 @@
 namespace clang {
 class ASTContext;
 class ASTReader;
+class SimpleASTReader;
+class SimpleASTWriter;
+class SimpleModuleCache;
 class CodeCompleteConsumer;
 class DiagnosticsEngine;
 class DiagnosticConsumer;
@@ -118,6 +121,13 @@
   /// The ASTReader, if one exists.
   IntrusiveRefCntPtr<ASTReader> TheASTReader;
 
+  /// The simple ASTReader, if one exists.
+  std::shared_ptr<SimpleASTReader> TheSimpleASTReader;
+  /// The simple ASTWriter, if one exists.
+  std::shared_ptr<SimpleASTWriter> TheSimpleASTWriter;
+  /// The simple module cache, if one exists.
+  std::shared_ptr<SimpleModuleCache> TheSimpleModuleCache;
+
   /// The module dependency collector for crashdumps
   std::shared_ptr<ModuleDependencyCollector> ModuleDepCollector;
 
@@ -515,6 +525,12 @@
   IntrusiveRefCntPtr<ASTReader> getASTReader() const;
   void setASTReader(IntrusiveRefCntPtr<ASTReader> Reader);
 
+  std::shared_ptr<SimpleASTReader> getSimpleASTReader() const;
+  std::shared_ptr<SimpleASTWriter> getSimpleASTWriter() const;
+
+  std::shared_ptr<SimpleModuleCache> getSimpleModuleCache();
+  void setSimpleModuleCache(std::shared_ptr<SimpleModuleCache> Cache);
+
   std::shared_ptr<ModuleDependencyCollector> getModuleDepCollector() const;
   void setModuleDepCollector(
       std::shared_ptr<ModuleDependencyCollector> Collector);
@@ -769,6 +785,8 @@
   }
 
   void createASTReader();
+  void createSimpleASTReader();
+  void createSimpleASTWriter();
 
   bool loadModuleFile(StringRef FileName);
 
Index: clang/include/clang/Basic/SourceManager.h
===================================================================
--- clang/include/clang/Basic/SourceManager.h
+++ clang/include/clang/Basic/SourceManager.h
@@ -1782,6 +1782,8 @@
 private:
   friend class ASTReader;
   friend class ASTWriter;
+  friend class SimpleASTReader;
+  friend class SimpleASTWriter;
 
   llvm::MemoryBufferRef getFakeBufferForRecovery() const;
   SrcMgr::ContentCache &getFakeContentCacheForRecovery() const;
Index: clang/include/clang/Basic/SourceLocation.h
===================================================================
--- clang/include/clang/Basic/SourceLocation.h
+++ clang/include/clang/Basic/SourceLocation.h
@@ -57,6 +57,8 @@
 private:
   friend class ASTWriter;
   friend class ASTReader;
+  friend class SimpleASTWriter;
+  friend class SimpleASTReader;
   friend class SourceManager;
 
   static FileID get(int V) {
@@ -86,6 +88,7 @@
 class SourceLocation {
   friend class ASTReader;
   friend class ASTWriter;
+  friend class SimpleASTReader;
   friend class SourceManager;
   friend struct llvm::FoldingSetTrait<SourceLocation, void>;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to