]> granicus.if.org Git - clang/commitdiff
Wrap clang module files in a Mach-O, ELF, or COFF container.
authorAdrian Prantl <aprantl@apple.com>
Fri, 20 Feb 2015 19:44:52 +0000 (19:44 +0000)
committerAdrian Prantl <aprantl@apple.com>
Fri, 20 Feb 2015 19:44:52 +0000 (19:44 +0000)
This is a necessary prerequisite for debugging with modules.
The .pcm files become containers that hold the serialized AST which allows
us to store debug information in the module file that can be shared by all
object files that were built importing the module.

rdar://problem/19104245

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@230044 91177308-0d34-0410-b5e6-96231b3b80d8

20 files changed:
docs/PCHInternals.rst
include/clang/CodeGen/CodeGenModuleContainer.h [new file with mode: 0644]
include/clang/Frontend/FrontendActions.h
include/clang/Serialization/ASTReader.h
include/clang/Serialization/ASTWriter.h
lib/CodeGen/CMakeLists.txt
lib/CodeGen/CodeGenModuleContainer.cpp [new file with mode: 0644]
lib/Frontend/ASTUnit.cpp
lib/Frontend/CMakeLists.txt
lib/Frontend/ChainedIncludesSource.cpp
lib/Frontend/FrontendActions.cpp
lib/Frontend/MultiplexConsumer.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/CMakeLists.txt
lib/Serialization/GeneratePCH.cpp
lib/Serialization/GlobalModuleIndex.cpp
lib/Serialization/ModuleManager.cpp
test/Modules/module_container.m [new file with mode: 0644]
test/PCH/floating-literal.c
tools/libclang/CMakeLists.txt

index a36e65c199c63b23af35539536891962d5cbbccd..d247d3ed0aac77f62fceb46e6dbcea95c1d510a3 100644 (file)
@@ -65,6 +65,9 @@ be included at the beginning of the translation unit.  The extensions to the
 AST file format required for modules are discussed in the section on
 :ref:`modules <pchinternals-modules>`.
 
+Clang's AST files are Mach-O, ELF, or COFF containers that contain a
+``__clangast`` section which holds the AST bitstream.
+
 Clang's AST files are designed with a compact on-disk representation, which
 minimizes both creation time and the time required to initially load the AST
 file.  The AST file itself contains a serialized representation of Clang's
diff --git a/include/clang/CodeGen/CodeGenModuleContainer.h b/include/clang/CodeGen/CodeGenModuleContainer.h
new file mode 100644 (file)
index 0000000..3c5456f
--- /dev/null
@@ -0,0 +1,34 @@
+//===--- CodeGen/ModuleContainerGenerator.h - Emit .pcm files ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGEN_MODULE_CONTAINER_H
+#define LLVM_CLANG_CODEGEN_MODULE_CONTAINER_H
+
+#include "ModuleBuilder.h"
+#include <string>
+
+namespace llvm {
+class raw_ostream;
+}
+
+namespace clang {
+
+class PCHGenerator;
+class TargetOptions;
+
+/// \brief Create a CodeGenerator instance.
+/// It is the responsibility of the caller to call delete on
+/// the allocated CodeGenerator instance.
+CodeGenerator *CreateModuleContainerGenerator(
+    DiagnosticsEngine &Diags, const std::string &ModuleName,
+    const CodeGenOptions &CGO, const TargetOptions &TO, const LangOptions &LO,
+    llvm::raw_ostream *OS, PCHGenerator *PCHGen);
+}
+
+#endif
index 850f87c073c5fed2e1dad81e81d8989de85af08b..b96b9f559ec35b127adf3d1a55228e66dc10e283 100644 (file)
@@ -69,6 +69,14 @@ protected:
                                                  StringRef InFile) override;
 };
 
+/// \brief Emits the output of a GeneratePCHAction or GenerateModuleAction into
+/// a Mach-O/ELF/COFF container.
+class GeneratePCMContainerAction : public FrontendAction {
+protected:
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override;
+};
+
 class GeneratePCHAction : public ASTFrontendAction {
 protected:
   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
index 27af9995aa9b26161a0e00562e4511c6ee5eb065..754273688b1e39a822d17437ed807f5f9bcf603b 100644 (file)
@@ -1127,6 +1127,10 @@ private:
 public:
   void ResolveImportedPath(ModuleFile &M, std::string &Filename);
   static void ResolveImportedPath(std::string &Filename, StringRef Prefix);
+  /// \brief Initialize a BitstreamReader with the `__clangast` section from an
+  /// object file container found in Buffer.
+  static void InitStreamFileWithModule(llvm::MemoryBufferRef Buffer,
+                                       llvm::BitstreamReader &StreamFile);
 
 private:
   struct ImportedModule {
index 1d2fa556e22c34773872d4d84c553816f3f08578..4b8668b3c6f132793855f1d7faee66acd7e0bf67 100644 (file)
@@ -823,10 +823,13 @@ class PCHGenerator : public SemaConsumer {
   std::string OutputFile;
   clang::Module *Module;
   std::string isysroot;
-  raw_ostream *Out;
   Sema *SemaPtr;
-  SmallVector<char, 128> Buffer;
+  // This buffer is always large, but BitstreamWriter really wants a
+  // SmallVectorImpl<char>.
+  SmallVector<char, 0> Buffer;
   llvm::BitstreamWriter Stream;
+  std::function<void(SmallVectorImpl<char>*)>
+    SerializationFinishedCallback;
   ASTWriter Writer;
   bool AllowASTWithErrors;
   bool HasEmittedPCH;
@@ -836,16 +839,21 @@ protected:
   const ASTWriter &getWriter() const { return Writer; }
 
 public:
-  PCHGenerator(const Preprocessor &PP, StringRef OutputFile,
+  PCHGenerator(const Preprocessor &PP,
+               StringRef OutputFile,
                clang::Module *Module,
-               StringRef isysroot, raw_ostream *Out,
+               StringRef isysroot,
                bool AllowASTWithErrors = false);
   ~PCHGenerator();
   void InitializeSema(Sema &S) override { SemaPtr = &S; }
   void HandleTranslationUnit(ASTContext &Ctx) override;
   ASTMutationListener *GetASTMutationListener() override;
   ASTDeserializationListener *GetASTDeserializationListener() override;
-
+  /// \brief Register a callback to be invoked when the serialization is done.
+  void RegisterSerializationFinishedCallback(
+    const std::function<void(SmallVectorImpl<char>*)> Fn) {
+    SerializationFinishedCallback = Fn;
+  }
   bool hasEmittedPCH() const { return HasEmittedPCH; }
 };
 
index 18f505d8c5928d70f799f5d823239c89727222e4..dae14bd3b1cd178b12c9cc8c33c17611e6dde583 100644 (file)
@@ -1,4 +1,5 @@
 set(LLVM_LINK_COMPONENTS
+  ${LLVM_TARGETS_TO_BUILD}
   Analysis
   BitReader
   BitWriter
@@ -63,6 +64,7 @@ add_clang_library(clangCodeGen
   CodeGenAction.cpp
   CodeGenFunction.cpp
   CodeGenModule.cpp
+  CodeGenModuleContainer.cpp
   CodeGenPGO.cpp
   CodeGenTBAA.cpp
   CodeGenTypes.cpp
diff --git a/lib/CodeGen/CodeGenModuleContainer.cpp b/lib/CodeGen/CodeGenModuleContainer.cpp
new file mode 100644 (file)
index 0000000..b1162cc
--- /dev/null
@@ -0,0 +1,150 @@
+//===--- CodeGenModuleContainer.cpp - Emit .pcm files ---------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGen/CodeGenModuleContainer.h"
+#include "CodeGenModule.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGen/BackendUtil.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Serialization/ASTWriter.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/TargetRegistry.h"
+#include <memory>
+using namespace clang;
+
+namespace {
+class ModuleContainerGenerator : public CodeGenerator {
+  DiagnosticsEngine &Diags;
+  std::unique_ptr<const llvm::DataLayout> TD;
+  ASTContext *Ctx;
+  const CodeGenOptions CodeGenOpts;
+  const TargetOptions TargetOpts;
+  const LangOptions LangOpts;
+  llvm::LLVMContext VMContext;
+  std::unique_ptr<llvm::Module> M;
+  std::unique_ptr<CodeGen::CodeGenModule> Builder;
+  raw_ostream *OS;
+  SmallVectorImpl<char> *SerializedASTBuffer;
+
+public:
+  ModuleContainerGenerator(DiagnosticsEngine &diags,
+                           const std::string &ModuleName,
+                           const CodeGenOptions &CGO, const TargetOptions &TO,
+                           const LangOptions &LO, raw_ostream *OS,
+                           PCHGenerator *PCHGen)
+      : Diags(diags), CodeGenOpts(CGO), TargetOpts(TO), LangOpts(LO),
+        M(new llvm::Module(ModuleName, VMContext)), OS(OS) {
+    PCHGen->RegisterSerializationFinishedCallback(
+      [&](SmallVectorImpl<char> *Buf){
+        SerializedASTBuffer = Buf;
+      });
+  }
+
+  virtual ~ModuleContainerGenerator() {}
+  llvm::Module *GetModule() override { return M.get(); }
+  llvm::Module *ReleaseModule() override { return M.release(); }
+
+  /// Lifted from ModuleBuilder.
+  const Decl *GetDeclForMangledName(StringRef MangledName) override {
+    GlobalDecl Result;
+    if (!Builder->lookupRepresentativeDecl(MangledName, Result))
+      return nullptr;
+    const Decl *D = Result.getCanonicalDecl().getDecl();
+    if (auto FD = dyn_cast<FunctionDecl>(D)) {
+      if (FD->hasBody(FD))
+        return FD;
+    } else if (auto TD = dyn_cast<TagDecl>(D)) {
+      if (auto Def = TD->getDefinition())
+        return Def;
+    }
+    return D;
+  }
+
+  void Initialize(ASTContext &Context) override {
+    Ctx = &Context;
+    M->setTargetTriple(Ctx->getTargetInfo().getTriple().getTriple());
+    M->setDataLayout(Ctx->getTargetInfo().getTargetDescription());
+    TD.reset(new llvm::DataLayout(Ctx->getTargetInfo().getTargetDescription()));
+    Builder.reset(
+        new CodeGen::CodeGenModule(Context, CodeGenOpts, *M, *TD, Diags));
+  }
+
+  /// Emit a container holding the serialized AST.
+  void HandleTranslationUnit(ASTContext &Ctx) override {
+    if (Diags.hasErrorOccurred()) {
+      if (Builder)
+        Builder->clear();
+      M.reset();
+      return;
+    }
+
+    // Finalize the Builder.
+    if (Builder)
+      Builder->Release();
+
+    // Initialize the backend if we haven't done so already.
+    LLVMInitializeAllTargetInfos();
+    LLVMInitializeAllTargets();
+    LLVMInitializeAllAsmPrinters();
+    LLVMInitializeAllTargetMCs();
+
+    // Ensure the target exists.
+    std::string Error;
+    auto Triple = Ctx.getTargetInfo().getTriple();
+    if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error))
+      llvm::report_fatal_error(Error);
+
+    // Emit the serialized Clang AST into its own section.
+    auto Size = SerializedASTBuffer->size();
+    auto Int8Ty = llvm::Type::getInt8Ty(VMContext);
+    auto *Ty = llvm::ArrayType::get(Int8Ty, Size);
+    auto *Data = llvm::ConstantDataArray::getString(VMContext,
+        StringRef(SerializedASTBuffer->data(), Size), /*AddNull=*/false);
+    auto *ASTSym = new llvm::GlobalVariable(*M, Ty, /*constant*/ true,
+        llvm::GlobalVariable::InternalLinkage, Data, "__clang_ast");
+    ASTSym->setAlignment(8);
+    if (Triple.isOSBinFormatMachO())
+      // Include Mach-O segment name.
+      ASTSym->setSection("__CLANG,__clangast");
+    else if (Triple.isOSBinFormatCOFF())
+      // Adhere to COFF eight-character limit.
+      ASTSym->setSection("clangast");
+    else
+      ASTSym->setSection("__clangast");
+
+    // Use the LLVM backend to emit the pcm.
+    EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
+                      Ctx.getTargetInfo().getTargetDescription(), M.get(),
+                      BackendAction::Backend_EmitObj, OS);
+
+    // Make sure the module container hits disk now.
+    OS->flush();
+
+    // Free up some memory, in case the process is kept alive.
+    SerializedASTBuffer->clear();
+  }
+};
+}
+
+CodeGenerator *clang::CreateModuleContainerGenerator(
+    DiagnosticsEngine &Diags, const std::string &ModuleName,
+    const CodeGenOptions &CGO, const TargetOptions &TO, const LangOptions &LO,
+    llvm::raw_ostream *OS, PCHGenerator *PCHGen) {
+  return
+    new ModuleContainerGenerator(Diags, ModuleName, CGO, TO, LO, OS, PCHGen);
+}
index bfb1efe352295618092b5dafa9f83bd9f4f40192..58a5f980085b24de09e00901f5d317ac7e4bc17a 100644 (file)
@@ -914,13 +914,20 @@ class PrecompilePreambleConsumer : public PCHGenerator {
   unsigned &Hash;
   std::vector<Decl *> TopLevelDecls;
   PrecompilePreambleAction *Action;
+  raw_ostream *Out;
+  SmallVectorImpl<char> *SerializedASTBuffer;
 
 public:
   PrecompilePreambleConsumer(ASTUnit &Unit, PrecompilePreambleAction *Action,
                              const Preprocessor &PP, StringRef isysroot,
                              raw_ostream *Out)
-    : PCHGenerator(PP, "", nullptr, isysroot, Out, /*AllowASTWithErrors=*/true),
-      Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()), Action(Action) {
+    : PCHGenerator(PP, "", nullptr, isysroot, /*AllowASTWithErrors=*/true),
+      Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()), Action(Action),
+      Out(Out) {
+    RegisterSerializationFinishedCallback(
+      [&](SmallVectorImpl<char> *Buf){
+        SerializedASTBuffer = Buf;
+      });
     Hash = 0;
   }
 
@@ -941,6 +948,13 @@ public:
   void HandleTranslationUnit(ASTContext &Ctx) override {
     PCHGenerator::HandleTranslationUnit(Ctx);
     if (hasEmittedPCH()) {
+      // Write the generated bitstream to "Out".
+      Out->write((char *)&SerializedASTBuffer->front(),
+                 SerializedASTBuffer->size());
+      // Make sure it hits disk now.
+      Out->flush();
+      SerializedASTBuffer->clear();
+
       // Translate the top-level declarations we captured during
       // parsing into declaration IDs in the precompiled
       // preamble. This will allow us to deserialize those top-level
index 7c5fca54d1e1f61dd2379e712dc5517e36426f45..6c9085d65dc5cf7ae3b2f2a84190fd563b077275 100644 (file)
@@ -45,6 +45,7 @@ add_clang_library(clangFrontend
   LINK_LIBS
   clangAST
   clangBasic
+  clangCodeGen
   clangDriver
   clangEdit
   clangLex
index cb260b4f4c6941a3a8a071d0d3c65572aa7c5e03..1ecc0bfc6b402cc0fe4ffd7fac5d26bd5e66e0ce 100644 (file)
@@ -156,11 +156,13 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
                                                  &Clang->getPreprocessor());
     Clang->createASTContext();
 
-    SmallVector<char, 256> serialAST;
-    llvm::raw_svector_ostream OS(serialAST);
-    auto consumer =
-        llvm::make_unique<PCHGenerator>(Clang->getPreprocessor(), "-", nullptr,
-                                        /*isysroot=*/"", &OS);
+    auto consumer = llvm::make_unique<PCHGenerator>(Clang->getPreprocessor(),
+                                       "-", nullptr, /*isysroot=*/"");
+    SmallVectorImpl<char> *serialAST;
+    consumer->RegisterSerializationFinishedCallback(
+      [&](SmallVectorImpl<char> *Buf){
+        serialAST = Buf;
+      });
     Clang->getASTContext().setASTMutationListener(
                                             consumer->GetASTMutationListener());
     Clang->setASTConsumer(std::move(consumer));
@@ -197,7 +199,9 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
 
     ParseAST(Clang->getSema());
     Clang->getDiagnosticClient().EndSourceFile();
-    SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(OS.str()));
+    SerialBufs.push_back(llvm::MemoryBuffer::
+        getMemBufferCopy(StringRef(serialAST->data(), serialAST->size())));
+    serialAST->clear();
     source->CIs.push_back(Clang.release());
   }
 
index a55a3257851f8e2b81c4fca8c2d6e864b60a7463..3e0f525e65366b05710a71613f6ab7b99bee335f 100644 (file)
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/Basic/FileManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGen/CodeGenModuleContainer.h"
 #include "clang/Frontend/ASTConsumers.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/MultiplexConsumer.h"
 #include "clang/Frontend/Utils.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/Pragma.h"
@@ -85,8 +88,23 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
 
   if (!CI.getFrontendOpts().RelocatablePCH)
     Sysroot.clear();
-  return llvm::make_unique<PCHGenerator>(CI.getPreprocessor(), OutputFile,
-                                         nullptr, Sysroot, OS);
+
+  std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+  Consumers.push_back(llvm::make_unique<PCHGenerator>(CI.getPreprocessor(),
+                                                      OutputFile, nullptr,
+                                                      Sysroot));
+
+  auto CGOpts = CI.getCodeGenOpts();
+  // The debug info emitted by ModuleContainerGenerator is not affected by the
+  // optimization level.
+  CGOpts.OptimizationLevel = 0;
+  CGOpts.setDebugInfo(CodeGenOptions::LimitedDebugInfo);
+  Consumers.push_back(std::unique_ptr<ASTConsumer>(
+      CreateModuleContainerGenerator(CI.getDiagnostics(), "PCH", CGOpts,
+                                     CI.getTargetOpts(), CI.getLangOpts(), OS,
+                                     cast<PCHGenerator>(Consumers[0].get()))));
+
+  return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
 }
 
 bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
@@ -122,8 +140,22 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
   if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS))
     return nullptr;
 
-  return llvm::make_unique<PCHGenerator>(CI.getPreprocessor(), OutputFile,
-                                         Module, Sysroot, OS);
+  std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+  Consumers.push_back(llvm::make_unique<PCHGenerator>(CI.getPreprocessor(),
+                                                      OutputFile, Module,
+                                                      Sysroot));
+
+  auto CGOpts = CI.getCodeGenOpts();
+  // The debug info emitted by ModuleContainerGenerator is not affected by the
+  // optimization level.
+  CGOpts.OptimizationLevel = 0;
+  CGOpts.setDebugInfo(CodeGenOptions::LimitedDebugInfo);
+  Consumers.push_back(
+      std::unique_ptr<ASTConsumer>(CreateModuleContainerGenerator(
+          CI.getDiagnostics(), Module->getFullModuleName(), CGOpts,
+          CI.getTargetOpts(), CI.getLangOpts(), OS,
+          cast<PCHGenerator>(Consumers[0].get()))));
+  return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
 }
 
 static SmallVectorImpl<char> &
index 3c4fed1d18e31d858a5bb4ce7d8b7f5bc4a5bd47..bb9c907b2e39c7dd2a64c5228dc1737368ad561f 100644 (file)
@@ -33,11 +33,14 @@ public:
   void ReaderInitialized(ASTReader *Reader) override;
   void IdentifierRead(serialization::IdentID ID,
                       IdentifierInfo *II) override;
+  void MacroRead(serialization::MacroID ID, MacroInfo *MI) override;
   void TypeRead(serialization::TypeIdx Idx, QualType T) override;
   void DeclRead(serialization::DeclID ID, const Decl *D) override;
   void SelectorRead(serialization::SelectorID iD, Selector Sel) override;
   void MacroDefinitionRead(serialization::PreprocessedEntityID,
                            MacroDefinition *MD) override;
+  void ModuleRead(serialization::SubmoduleID ID, Module *Mod) override;
+
 private:
   std::vector<ASTDeserializationListener*> Listeners;
 };
@@ -59,6 +62,12 @@ void MultiplexASTDeserializationListener::IdentifierRead(
     Listeners[i]->IdentifierRead(ID, II);
 }
 
+void MultiplexASTDeserializationListener::MacroRead(
+    serialization::MacroID ID, MacroInfo *MI) {
+  for (auto &Listener : Listeners)
+    Listener->MacroRead(ID, MI);
+}
+
 void MultiplexASTDeserializationListener::TypeRead(
     serialization::TypeIdx Idx, QualType T) {
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)
@@ -83,6 +92,12 @@ void MultiplexASTDeserializationListener::MacroDefinitionRead(
     Listeners[i]->MacroDefinitionRead(ID, MD);
 }
 
+void MultiplexASTDeserializationListener::ModuleRead(
+    serialization::SubmoduleID ID, Module *Mod) {
+  for (auto &Listener : Listeners)
+    Listener->ModuleRead(ID, Mod);
+}
+
 // This ASTMutationListener forwards its notifications to a set of
 // child listeners.
 class MultiplexASTMutationListener : public ASTMutationListener {
@@ -98,11 +113,13 @@ public:
                                const VarTemplateSpecializationDecl *D) override;
   void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                       const FunctionDecl *D) override;
+  void ResolvedExceptionSpec(const FunctionDecl *FD) override;
   void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override;
   void CompletedImplicitDefinition(const FunctionDecl *D) override;
   void StaticDataMemberInstantiated(const VarDecl *D) override;
   void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
                                     const ObjCInterfaceDecl *IFD) override;
+  void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
   void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
                                     const ObjCPropertyDecl *OrigProp,
                                     const ObjCCategoryDecl *ClassExt) override;
@@ -149,6 +166,11 @@ void MultiplexASTMutationListener::AddedCXXTemplateSpecialization(
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)
     Listeners[i]->AddedCXXTemplateSpecialization(TD, D);
 }
+void MultiplexASTMutationListener::ResolvedExceptionSpec(
+    const FunctionDecl *FD) {
+  for (auto &Listener : Listeners)
+    Listener->ResolvedExceptionSpec(FD);
+}
 void MultiplexASTMutationListener::DeducedReturnType(const FunctionDecl *FD,
                                                      QualType ReturnType) {
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)
@@ -170,6 +192,11 @@ void MultiplexASTMutationListener::AddedObjCCategoryToInterface(
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)
     Listeners[i]->AddedObjCCategoryToInterface(CatD, IFD);
 }
+void MultiplexASTMutationListener::FunctionDefinitionInstantiated(
+    const FunctionDecl *D) {
+  for (auto &Listener : Listeners)
+    Listener->FunctionDefinitionInstantiated(D);
+} 
 void MultiplexASTMutationListener::AddedObjCPropertyInClassExtension(
                                              const ObjCPropertyDecl *Prop,
                                              const ObjCPropertyDecl *OrigProp,
index bb6a450222d3163a4737bbb7609a613f7c8b5e7d..69d8f117cb99380c80dd45821e4a16dcfcd8d61e 100644 (file)
@@ -46,6 +46,8 @@
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -632,6 +634,27 @@ void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) {
 // AST reader implementation
 //===----------------------------------------------------------------------===//
 
+void ASTReader::InitStreamFileWithModule(llvm::MemoryBufferRef Buffer,
+                                         llvm::BitstreamReader &StreamFile) {
+  if (auto OF = llvm::object::ObjectFile::createObjectFile(Buffer)) {
+    bool IsCOFF = isa<llvm::object::COFFObjectFile>(OF.get().get());
+    // Find the clang AST section in the container.
+    for (auto &Section : OF->get()->sections()) {
+      StringRef Name;
+      Section.getName(Name);
+      if ((!IsCOFF && Name == "__clangast") ||
+          ( IsCOFF && Name ==   "clangast")) {
+        StringRef Buf;
+        Section.getContents(Buf);
+        return StreamFile.init((const unsigned char*)Buf.begin(),
+                               (const unsigned char*)Buf.end());
+      }
+    }
+  }
+  StreamFile.init((const unsigned char *)Buffer.getBufferStart(),
+                  (const unsigned char *)Buffer.getBufferEnd());
+}
+
 void ASTReader::setDeserializationListener(ASTDeserializationListener *Listener,
                                            bool TakeOwnership) {
   DeserializationListener = Listener;
@@ -3883,9 +3906,10 @@ ASTReader::ReadASTCore(StringRef FileName,
 
   ModuleFile &F = *M;
   BitstreamCursor &Stream = F.Stream;
+  InitStreamFileWithModule(F.Buffer->getMemBufferRef(), F.StreamFile);
   Stream.init(&F.StreamFile);
-  F.SizeInBits = F.Buffer->getBufferSize() * 8;
-  
+  F.SizeInBits = F.StreamFile.getBitcodeBytes().getExtent() * 8;
+
   // Sniff for the signature.
   if (Stream.Read(8) != 'C' ||
       Stream.Read(8) != 'P' ||
@@ -4174,8 +4198,7 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
 
   // Initialize the stream
   llvm::BitstreamReader StreamFile;
-  StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
-                  (const unsigned char *)(*Buffer)->getBufferEnd());
+  InitStreamFileWithModule((*Buffer)->getMemBufferRef(), StreamFile);
   BitstreamCursor Stream(StreamFile);
 
   // Sniff for the signature.
@@ -4270,8 +4293,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
 
   // Initialize the stream
   llvm::BitstreamReader StreamFile;
-  StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
-                  (const unsigned char *)(*Buffer)->getBufferEnd());
+  InitStreamFileWithModule((*Buffer)->getMemBufferRef(), StreamFile);
   BitstreamCursor Stream(StreamFile);
 
   // Sniff for the signature.
index d885db22975e38cff8c970c631c900282f00391d..a1a5ad4abe7186b1452807b0224e78ddc1530b9d 100644 (file)
@@ -1,5 +1,6 @@
 set(LLVM_LINK_COMPONENTS
   BitReader
+  Object
   Support
   )
 
index b5031fdf92a498e613af269b36da6c172098ef59..0cd01dc6f3e72075401017f3b0c0fccc5d06c436 100644 (file)
@@ -19,7 +19,6 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/SemaConsumer.h"
 #include "llvm/Bitcode/BitstreamWriter.h"
-#include "llvm/Support/raw_ostream.h"
 #include <string>
 
 using namespace clang;
@@ -28,10 +27,11 @@ PCHGenerator::PCHGenerator(const Preprocessor &PP,
                            StringRef OutputFile,
                            clang::Module *Module,
                            StringRef isysroot,
-                           raw_ostream *OS, bool AllowASTWithErrors)
+                           bool AllowASTWithErrors)
   : PP(PP), OutputFile(OutputFile), Module(Module), 
-    isysroot(isysroot.str()), Out(OS), 
-    SemaPtr(nullptr), Stream(Buffer), Writer(Stream),
+    isysroot(isysroot.str()),
+    SemaPtr(nullptr), Stream(Buffer),
+    Writer(Stream),
     AllowASTWithErrors(AllowASTWithErrors),
     HasEmittedPCH(false) {
 }
@@ -52,14 +52,8 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
   assert(SemaPtr && "No Sema?");
   Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot, hasErrors);
 
-  // Write the generated bitstream to "Out".
-  Out->write((char *)&Buffer.front(), Buffer.size());
-
-  // Make sure it hits disk now.
-  Out->flush();
-
-  // Free up some memory, in case the process is kept alive.
-  Buffer.clear();
+  if (SerializationFinishedCallback)
+    SerializationFinishedCallback(&Buffer);
 
   HasEmittedPCH = true;
 }
index 4791388045472bc2b4ea7bdf579d88ad99760584..68a23ea870db6504d065a5f8a1b23b898510cdbc 100644 (file)
@@ -15,6 +15,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ASTReader.h"
 #include "clang/Serialization/GlobalModuleIndex.h"
 #include "clang/Serialization/Module.h"
 #include "llvm/ADT/DenseMap.h"
@@ -501,8 +502,8 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
 
   // Initialize the input stream
   llvm::BitstreamReader InStreamFile;
-  InStreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
-                    (const unsigned char *)(*Buffer)->getBufferEnd());
+  ASTReader::InitStreamFileWithModule((*Buffer)->getMemBufferRef(),
+                                      InStreamFile);
   llvm::BitstreamCursor InStream(InStreamFile);
 
   // Sniff for the signature.
index ac98ca0b8720306ef6a2f32415187d9c0e35b926..8f1473f3a3a03dbbf0616e4d73cc8a3dcde711af 100644 (file)
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/ModuleMap.h"
+#include "clang/Serialization/ASTReader.h"
 #include "clang/Serialization/GlobalModuleIndex.h"
 #include "clang/Serialization/ModuleManager.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -135,10 +136,10 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
 
       New->Buffer = std::move(*Buf);
     }
-    
-    // Initialize the stream
-    New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(),
-                         (const unsigned char *)New->Buffer->getBufferEnd());
+
+    // Initialize the stream.
+    ASTReader::InitStreamFileWithModule(New->Buffer->getMemBufferRef(),
+                                        New->StreamFile);
   }
 
   if (ExpectedSignature) {
diff --git a/test/Modules/module_container.m b/test/Modules/module_container.m
new file mode 100644 (file)
index 0000000..98a662a
--- /dev/null
@@ -0,0 +1,14 @@
+@import DependsOnModule;
+
+// RUN: rm -rf %t-MachO %t-ELF %t-COFF
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin -fmodules -fdisable-module-hash -fmodules-cache-path=%t-MachO -F %S/Inputs %s
+// RUN: %clang_cc1 -triple=x86_64-linux-elf -fmodules -fdisable-module-hash -fmodules-cache-path=%t-ELF -F %S/Inputs %s
+// RUN: %clang_cc1 -triple=x86_64-windows-coff -fmodules -fdisable-module-hash -fmodules-cache-path=%t-COFF -F %S/Inputs %s
+
+// RUN: llvm-objdump -section-headers %t-MachO/DependsOnModule.pcm %t-ELF/DependsOnModule.pcm %t-COFF/DependsOnModule.pcm | FileCheck %s
+// CHECK: file format Mach-O 64-bit x86-64
+// CHECK: __clangast   {{[0-9a-f]+}} {{[0-9a-f]+}} DATA
+// CHECK: file format ELF64-x86-64
+// CHECK: __clangast   {{[0-9a-f]+}} {{[0-9a-f]+}} DATA
+// CHECK: file format COFF-x86-64
+// CHECK: clangast   {{[0-9a-f]+}} {{[0-9a-f]+}}
index 738e45a41517f352292acb1c46ab404b25fba8d5..b5ff6fe84b88ced44974a8945d9fd00092e7d7db 100644 (file)
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -triple mips64-none-linux-gnu -emit-pch -o %t %s
+// REQUIRES: mips-registered-target
 // RUN: %clang_cc1 -x ast -ast-print %t | FileCheck %s
 
 // Make sure the semantics of FloatingLiterals are stored correctly in
index 26f88a97c5744af648e54b436171d9b3f4090704..1cc4cb748d3d5d1e1f803b0971ebb95a3ce424ef 100644 (file)
@@ -40,6 +40,7 @@ set(SOURCES
 set(LIBS
   clangAST
   clangBasic
+  clangCodeGen
   clangFrontend
   clangIndex
   clangLex