diff --git a/clang/docs/PCHInternals.rst b/clang/docs/PCHInternals.rst index a36e65c199c63b23af35539536891962d5cbbccd..d247d3ed0aac77f62fceb46e6dbcea95c1d510a3 100644 --- a/clang/docs/PCHInternals.rst +++ b/clang/docs/PCHInternals.rst @@ -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/clang/include/clang/CodeGen/CodeGenModuleContainer.h b/clang/include/clang/CodeGen/CodeGenModuleContainer.h new file mode 100644 index 0000000000000000000000000000000000000000..3c5456fc18d3d8a5b90c28d69db7584f3803cb4a --- /dev/null +++ b/clang/include/clang/CodeGen/CodeGenModuleContainer.h @@ -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 diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index 850f87c073c5fed2e1dad81e81d8989de85af08b..b96b9f559ec35b127adf3d1a55228e66dc10e283 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -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, diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 27af9995aa9b26161a0e00562e4511c6ee5eb065..754273688b1e39a822d17437ed807f5f9bcf603b 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -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 { diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 1d2fa556e22c34773872d4d84c553816f3f08578..4b8668b3c6f132793855f1d7faee66acd7e0bf67 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -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; } }; diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 18f505d8c5928d70f799f5d823239c89727222e4..dae14bd3b1cd178b12c9cc8c33c17611e6dde583 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -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/clang/lib/CodeGen/CodeGenModuleContainer.cpp b/clang/lib/CodeGen/CodeGenModuleContainer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1162ccf191fcd53900348fb2d3fecdf714e9b52 --- /dev/null +++ b/clang/lib/CodeGen/CodeGenModuleContainer.cpp @@ -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); +} diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index bfb1efe352295618092b5dafa9f83bd9f4f40192..58a5f980085b24de09e00901f5d317ac7e4bc17a 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -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 diff --git a/clang/lib/Frontend/CMakeLists.txt b/clang/lib/Frontend/CMakeLists.txt index 7c5fca54d1e1f61dd2379e712dc5517e36426f45..6c9085d65dc5cf7ae3b2f2a84190fd563b077275 100644 --- a/clang/lib/Frontend/CMakeLists.txt +++ b/clang/lib/Frontend/CMakeLists.txt @@ -45,6 +45,7 @@ add_clang_library(clangFrontend LINK_LIBS clangAST clangBasic + clangCodeGen clangDriver clangEdit clangLex diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp index cb260b4f4c6941a3a8a071d0d3c65572aa7c5e03..1ecc0bfc6b402cc0fe4ffd7fac5d26bd5e66e0ce 100644 --- a/clang/lib/Frontend/ChainedIncludesSource.cpp +++ b/clang/lib/Frontend/ChainedIncludesSource.cpp @@ -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()); } diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index a55a3257851f8e2b81c4fca8c2d6e864b60a7463..3e0f525e65366b05710a71613f6ab7b99bee335f 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -10,10 +10,13 @@ #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> & diff --git a/clang/lib/Frontend/MultiplexConsumer.cpp b/clang/lib/Frontend/MultiplexConsumer.cpp index 3c4fed1d18e31d858a5bb4ce7d8b7f5bc4a5bd47..bb9c907b2e39c7dd2a64c5228dc1737368ad561f 100644 --- a/clang/lib/Frontend/MultiplexConsumer.cpp +++ b/clang/lib/Frontend/MultiplexConsumer.cpp @@ -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, diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 0ee2b2b2215ea2311651f6ab1601b29a9392e0fe..dd73bbae3784a2f9a91bfe88f6f745f93a943b2d 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -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. diff --git a/clang/lib/Serialization/CMakeLists.txt b/clang/lib/Serialization/CMakeLists.txt index d885db22975e38cff8c970c631c900282f00391d..a1a5ad4abe7186b1452807b0224e78ddc1530b9d 100644 --- a/clang/lib/Serialization/CMakeLists.txt +++ b/clang/lib/Serialization/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS BitReader + Object Support ) diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index b5031fdf92a498e613af269b36da6c172098ef59..0cd01dc6f3e72075401017f3b0c0fccc5d06c436 100644 --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -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; } diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp index 4791388045472bc2b4ea7bdf579d88ad99760584..68a23ea870db6504d065a5f8a1b23b898510cdbc 100644 --- a/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -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. diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index ac98ca0b8720306ef6a2f32415187d9c0e35b926..8f1473f3a3a03dbbf0616e4d73cc8a3dcde711af 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -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/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt index 591a9272ae6df21e032c5b2426741a01945d15ca..526f129bab587036456de7ffbdb42d5595144392 100644 --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -58,7 +58,7 @@ set(CLANG_TEST_PARAMS if( NOT CLANG_BUILT_STANDALONE ) list(APPEND CLANG_TEST_DEPS llvm-config - llc opt FileCheck count not llvm-symbolizer llvm-profdata + llc opt FileCheck count not llvm-symbolizer llvm-profdata llvm-objdump ) endif() diff --git a/clang/test/Modules/module_container.m b/clang/test/Modules/module_container.m new file mode 100644 index 0000000000000000000000000000000000000000..348a869ad266508fd3316bc953462d0072e24477 --- /dev/null +++ b/clang/test/Modules/module_container.m @@ -0,0 +1,14 @@ +@import DependsOnModule; +// REQUIRES: x86-registered-target +// 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]+}} diff --git a/clang/test/PCH/floating-literal.c b/clang/test/PCH/floating-literal.c index 738e45a41517f352292acb1c46ab404b25fba8d5..b5ff6fe84b88ced44974a8945d9fd00092e7d7db 100644 --- a/clang/test/PCH/floating-literal.c +++ b/clang/test/PCH/floating-literal.c @@ -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 diff --git a/clang/tools/arcmt-test/Makefile b/clang/tools/arcmt-test/Makefile index d9d44bb05bd262031b70c4e1aeaeeda58d04188a..b0318362c726062262921103517d5933f3d9b2b2 100644 --- a/clang/tools/arcmt-test/Makefile +++ b/clang/tools/arcmt-test/Makefile @@ -17,8 +17,9 @@ TOOL_NO_EXPORTS = 1 NO_INSTALL = 1 include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option -USEDLIBS = clangARCMigrate.a clangRewrite.a \ +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter \ + instrumentation mc objcarcopts option support +USEDLIBS = clangARCMigrate.a clangRewrite.a clangCodeGen.a \ clangFrontend.a clangDriver.a clangSerialization.a clangParse.a \ clangSema.a clangEdit.a clangAnalysis.a clangAST.a clangLex.a \ clangBasic.a diff --git a/clang/tools/c-index-test/Makefile b/clang/tools/c-index-test/Makefile index 62bc9348dbf58c5f5bb01a6b7fdf93a9d94089e3..56a849972525939157049dbda68160bc2b60d81f 100644 --- a/clang/tools/c-index-test/Makefile +++ b/clang/tools/c-index-test/Makefile @@ -22,12 +22,14 @@ TOOL_NO_EXPORTS = 1 # LINK_COMPONENTS before including Makefile.rules include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter \ + instrumentation support mc objcarcopts option # Note that 'USEDLIBS' must include all of the core clang libraries # when -static is given to linker on cygming. USEDLIBS = clang.a \ clangIndex.a clangFormat.a clangRewrite.a \ + clangCodeGen.a \ clangFrontend.a clangDriver.a \ clangTooling.a \ clangToolingCore.a \ diff --git a/clang/tools/clang-check/Makefile b/clang/tools/clang-check/Makefile index e98a131de5a9edd8ce4bfea10940f3fef62c5636..97af69bcc3930b0f628321f2099360cbd7218d99 100644 --- a/clang/tools/clang-check/Makefile +++ b/clang/tools/clang-check/Makefile @@ -15,9 +15,10 @@ TOOLNAME = clang-check TOOL_NO_EXPORTS = 1 include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter \ + instrumentation mc option objcarcopts support USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a \ - clangTooling.a clangParse.a clangSema.a \ + clangCodeGen.a clangTooling.a clangParse.a clangSema.a \ clangStaticAnalyzerFrontend.a clangStaticAnalyzerCheckers.a \ clangStaticAnalyzerCore.a clangAnalysis.a clangRewriteFrontend.a \ clangRewrite.a clangEdit.a clangAST.a clangLex.a clangBasic.a diff --git a/clang/tools/libclang/CMakeLists.txt b/clang/tools/libclang/CMakeLists.txt index 26f88a97c5744af648e54b436171d9b3f4090704..1cc4cb748d3d5d1e1f803b0971ebb95a3ce424ef 100644 --- a/clang/tools/libclang/CMakeLists.txt +++ b/clang/tools/libclang/CMakeLists.txt @@ -40,6 +40,7 @@ set(SOURCES set(LIBS clangAST clangBasic + clangCodeGen clangFrontend clangIndex clangLex diff --git a/clang/tools/libclang/Makefile b/clang/tools/libclang/Makefile index 97f663cde478d6312afd5e77df5eae199c68397d..141a347e9c65c781d6a43d2a15b50f13b3761595 100644 --- a/clang/tools/libclang/Makefile +++ b/clang/tools/libclang/Makefile @@ -16,11 +16,13 @@ LINK_LIBS_IN_SHARED = 1 SHARED_LIBRARY = 1 include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := AsmParser BitReader Core MC MCParser Option Support +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter core \ + instrumentation mc mcparser objcarcopts option support USEDLIBS = clangIndex.a clangARCMigrate.a \ clangRewriteFrontend.a \ clangFormat.a \ clangTooling.a clangToolingCore.a \ + clangCodeGen.a \ clangFrontend.a clangDriver.a \ clangSerialization.a \ clangParse.a clangSema.a \ diff --git a/clang/unittests/AST/Makefile b/clang/unittests/AST/Makefile index e3b3d7dc33e8c35be51f4bec8c30023715eea60c..db6e5010f5670e3bf444a8e07d47acf8ad2455cc 100644 --- a/clang/unittests/AST/Makefile +++ b/clang/unittests/AST/Makefile @@ -10,9 +10,10 @@ CLANG_LEVEL = ../.. TESTNAME = AST include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter \ + instrumentation mc option objcarcopts support USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \ - clangRewrite.a clangRewriteFrontend.a \ + clangCodeGen.a clangRewrite.a clangRewriteFrontend.a \ clangParse.a clangSema.a clangAnalysis.a \ clangEdit.a clangAST.a clangASTMatchers.a clangLex.a clangBasic.a diff --git a/clang/unittests/ASTMatchers/Dynamic/Makefile b/clang/unittests/ASTMatchers/Dynamic/Makefile index dfd0086c883e1a9fff690eb79d23d43ce4fc21b6..dab58be39b7625a0cef5ac291719bb1d166da796 100644 --- a/clang/unittests/ASTMatchers/Dynamic/Makefile +++ b/clang/unittests/ASTMatchers/Dynamic/Makefile @@ -11,10 +11,11 @@ CLANG_LEVEL = ../../.. TESTNAME = DynamicASTMatchers include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option -USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \ - clangRewrite.a clangRewriteFrontend.a clangParse.a clangSema.a \ - clangAnalysis.a clangEdit.a clangAST.a clangASTMatchers.a \ - clangLex.a clangBasic.a clangDynamicASTMatchers.a +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter \ + instrumentation mc option objcarcopts support +USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \ + clangCodeGen.a clangRewrite.a clangRewriteFrontend.a clangParse.a \ + clangSema.a clangAnalysis.a clangEdit.a clangAST.a \ + clangASTMatchers.a clangLex.a clangBasic.a clangDynamicASTMatchers.a include $(CLANG_LEVEL)/unittests/Makefile diff --git a/clang/unittests/ASTMatchers/Makefile b/clang/unittests/ASTMatchers/Makefile index 92f2fa0e5d179f5c973aa30123e42670e755594e..6eacbc261bb5a96afad9d6eaeeca8356c20a2cfe 100644 --- a/clang/unittests/ASTMatchers/Makefile +++ b/clang/unittests/ASTMatchers/Makefile @@ -13,9 +13,10 @@ PARALLEL_DIRS = Dynamic TESTNAME = ASTMatchers include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter \ + instrumentation mc option objcarcopts support USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \ - clangRewrite.a clangRewriteFrontend.a \ + clangCodeGen.a clangRewrite.a clangRewriteFrontend.a \ clangParse.a clangSema.a clangAnalysis.a \ clangEdit.a clangAST.a clangASTMatchers.a clangLex.a clangBasic.a diff --git a/clang/unittests/CodeGen/Makefile b/clang/unittests/CodeGen/Makefile index de347e1afddc943be1acf0fe89f15a1b08e908fa..2c825850c3312422da71b04a1ead3968e35de3dc 100644 --- a/clang/unittests/CodeGen/Makefile +++ b/clang/unittests/CodeGen/Makefile @@ -10,8 +10,8 @@ CLANG_LEVEL = ../.. TESTNAME = CodeGen include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader mc option \ - profiledata support +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter \ + instrumentation mc option objcarcopts profiledata support USEDLIBS = clangCodeGen.a clangFrontend.a clangSerialization.a \ clangDriver.a \ clangParse.a clangSema.a clangAnalysis.a \ diff --git a/clang/unittests/Frontend/Makefile b/clang/unittests/Frontend/Makefile index a63ae18245349fd832fd74504718417966ea9e7f..2604f6e5cc8a44dd916ff7fd2cb6447e8c33016d 100644 --- a/clang/unittests/Frontend/Makefile +++ b/clang/unittests/Frontend/Makefile @@ -10,7 +10,8 @@ CLANG_LEVEL = ../.. TESTNAME = Frontend include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter \ + instrumentation mc option objcarcopts support USEDLIBS = clangFrontendTool.a clangFrontend.a clangDriver.a \ clangSerialization.a clangCodeGen.a clangParse.a clangSema.a \ clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a \ diff --git a/clang/unittests/Sema/Makefile b/clang/unittests/Sema/Makefile index 7fd5c27ad607bae5414114fbd0f6d0fe0f97c942..65ab9bc8dc7b0f20a030cd18499b72c99fc932d4 100644 --- a/clang/unittests/Sema/Makefile +++ b/clang/unittests/Sema/Makefile @@ -10,9 +10,10 @@ CLANG_LEVEL = ../.. TESTNAME = Sema include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter \ + instrumentation mc option objcarcopts support USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \ - clangRewrite.a clangRewriteFrontend.a \ + clangCodeGen.a clangRewrite.a clangRewriteFrontend.a \ clangParse.a clangSema.a clangAnalysis.a \ clangEdit.a clangAST.a clangASTMatchers.a clangLex.a clangBasic.a diff --git a/clang/unittests/Tooling/Makefile b/clang/unittests/Tooling/Makefile index 514e80bd03098746f56c795ab146d229d45adfa1..86c1c34483d8f6c73248f8d4f95de09d5b833278 100644 --- a/clang/unittests/Tooling/Makefile +++ b/clang/unittests/Tooling/Makefile @@ -10,9 +10,10 @@ CLANG_LEVEL = ../.. TESTNAME = Tooling include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter \ + instrumentation mc option objcarcopts support USEDLIBS = clangTooling.a clangToolingCore.a clangFrontend.a \ - clangSerialization.a clangDriver.a \ + clangCodeGen.a clangSerialization.a clangDriver.a \ clangParse.a clangRewrite.a clangRewriteFrontend.a \ clangSema.a clangAnalysis.a clangEdit.a \ clangAST.a clangASTMatchers.a clangLex.a clangBasic.a