From cbc9d22e49b434b6ceb2eb94b67079d02e0a7b74 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Sun, 3 Nov 2019 21:15:03 +0100 Subject: [PATCH] make -fmodules-codegen and -fmodules-debuginfo work also with PCHs Allow to build PCH's (with -building-pch-with-obj and the extra .o file) with -fmodules-codegen -fmodules-debuginfo to allow emitting shared code into the extra .o file, similarly to how it works with modules. A bit of a misnomer, but the underlying functionality is the same. This saves up to 20% of build time here. Differential Revision: https://reviews.llvm.org/D69778 --- clang/lib/Serialization/ASTReader.cpp | 3 ++- clang/lib/Serialization/ASTReaderDecl.cpp | 18 +++++++++++++--- clang/lib/Serialization/ASTWriter.cpp | 4 ++-- clang/lib/Serialization/ASTWriterDecl.cpp | 13 +++++++----- clang/test/Modules/Inputs/codegen-flags/foo.h | 3 +++ clang/test/PCH/codegen.cpp | 30 +++++++++++++++++++++++++++ 6 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 clang/test/PCH/codegen.cpp diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index a9f433b..6c8bc7d 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3224,7 +3224,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { case MODULAR_CODEGEN_DECLS: // FIXME: Skip reading this record if our ASTConsumer doesn't care about // them (ie: if we're not codegenerating this module). - if (F.Kind == MK_MainFile) + if (F.Kind == MK_MainFile || + getContext().getLangOpts().BuildingPCHWithObjectFile) for (unsigned I = 0, N = Record.size(); I != N; ++I) EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); break; diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index a132164..3bcc9ad 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -501,8 +501,12 @@ uint64_t ASTDeclReader::GetCurrentCursorOffset() { } void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) { - if (Record.readInt()) + if (Record.readInt()) { Reader.DefinitionSource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile; + if (Reader.getContext().getLangOpts().BuildingPCHWithObjectFile && + Reader.DeclIsFromPCHWithObjectFile(FD)) + Reader.DefinitionSource[FD] = true; + } if (auto *CD = dyn_cast(FD)) { CD->setNumCtorInitializers(Record.readInt()); if (CD->getNumCtorInitializers()) @@ -1417,8 +1421,12 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { Reader.getContext().setBlockVarCopyInit(VD, CopyExpr, Record.readInt()); } - if (VD->getStorageDuration() == SD_Static && Record.readInt()) + if (VD->getStorageDuration() == SD_Static && Record.readInt()) { Reader.DefinitionSource[VD] = Loc.F->Kind == ModuleKind::MK_MainFile; + if (Reader.getContext().getLangOpts().BuildingPCHWithObjectFile && + Reader.DeclIsFromPCHWithObjectFile(VD)) + Reader.DefinitionSource[VD] = true; + } enum VarKind { VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization @@ -1677,8 +1685,12 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.ODRHash = Record.readInt(); Data.HasODRHash = true; - if (Record.readInt()) + if (Record.readInt()) { Reader.DefinitionSource[D] = Loc.F->Kind == ModuleKind::MK_MainFile; + if (Reader.getContext().getLangOpts().BuildingPCHWithObjectFile && + Reader.DeclIsFromPCHWithObjectFile(D)) + Reader.DefinitionSource[D] = true; + } Data.NumBases = Record.readInt(); if (Data.NumBases) diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index aebdfa9..6eba48a 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5583,8 +5583,8 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { // getODRHash will compute the ODRHash if it has not been previously computed. Record->push_back(D->getODRHash()); - bool ModulesDebugInfo = Writer->Context->getLangOpts().ModulesDebugInfo && - Writer->WritingModule && !D->isDependentType(); + bool ModulesDebugInfo = + Writer->Context->getLangOpts().ModulesDebugInfo && !D->isDependentType(); Record->push_back(ModulesDebugInfo); if (ModulesDebugInfo) Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(D)); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 74a49fa..6b8a9d9 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1010,15 +1010,16 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { if (D->getStorageDuration() == SD_Static) { bool ModulesCodegen = false; - if (Writer.WritingModule && - !D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo() && + if (!D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo() && !isa(D)) { // When building a C++ Modules TS module interface unit, a strong // definition in the module interface is provided by the compilation of // that module interface unit, not by its users. (Inline variables are // still emitted in module users.) ModulesCodegen = - (Writer.WritingModule->Kind == Module::ModuleInterfaceUnit && + (((Writer.WritingModule && + Writer.WritingModule->Kind == Module::ModuleInterfaceUnit) || + Writer.Context->getLangOpts().BuildingPCHWithObjectFile) && Writer.Context->GetGVALinkageForVariable(D) == GVA_StrongExternal); } Record.push_back(ModulesCodegen); @@ -2425,9 +2426,11 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { assert(FD->doesThisDeclarationHaveABody()); bool ModulesCodegen = false; - if (Writer->WritingModule && !FD->isDependentContext()) { + if (!FD->isDependentContext()) { Optional Linkage; - if (Writer->WritingModule->Kind == Module::ModuleInterfaceUnit) { + if ((Writer->WritingModule && + Writer->WritingModule->Kind == Module::ModuleInterfaceUnit) || + Writer->Context->getLangOpts().BuildingPCHWithObjectFile) { // When building a C++ Modules TS module interface unit, a strong // definition in the module interface is provided by the compilation of // that module interface unit, not by its users. (Inline functions are diff --git a/clang/test/Modules/Inputs/codegen-flags/foo.h b/clang/test/Modules/Inputs/codegen-flags/foo.h index 7b9c1cd..74cfab1 100644 --- a/clang/test/Modules/Inputs/codegen-flags/foo.h +++ b/clang/test/Modules/Inputs/codegen-flags/foo.h @@ -1,4 +1,7 @@ +#ifndef FOO_H +#define FOO_H struct foo { }; inline void f1() { } +#endif diff --git a/clang/test/PCH/codegen.cpp b/clang/test/PCH/codegen.cpp new file mode 100644 index 0000000..120db0e --- /dev/null +++ b/clang/test/PCH/codegen.cpp @@ -0,0 +1,30 @@ +// This test is the PCH version of Modules/codegen-flags.test . It uses its inputs. +// The purpose of this test is just verify that the codegen options work with PCH as well. +// All the codegen functionality should be tested in Modules/. + +// RUN: rm -rf %t +// RUN: mkdir -p %t +// REQUIRES: x86-registered-target + +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -x c++-header -building-pch-with-obj -emit-pch %S/../Modules/Inputs/codegen-flags/foo.h -o %t/foo-cg.pch +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-debuginfo -x c++-header -building-pch-with-obj -emit-pch %S/../Modules/Inputs/codegen-flags/foo.h -o %t/foo-di.pch + +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - %s -include-pch %t/foo-cg.pch -building-pch-with-obj -fmodules-codegen | FileCheck --check-prefix=CG %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - %s -include-pch %t/foo-di.pch -building-pch-with-obj -fmodules-debuginfo | FileCheck --check-prefix=DI %s + +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - -include-pch %t/foo-cg.pch %S/../Modules/Inputs/codegen-flags/use.cpp | FileCheck --check-prefix=CG-USE %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - -include-pch %t/foo-di.pch %S/../Modules/Inputs/codegen-flags/use.cpp | FileCheck --check-prefix=DI-USE %s + +// CG: define weak_odr void @_Z2f1v +// CG: DICompileUnit +// CG-NOT: DICompositeType + +// CG-USE: declare void @_Z2f1v +// CG-USE: DICompileUnit +// CG-USE: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo" + +// DI-NOT: define +// DI: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo" + +// DI-USE: define linkonce_odr void @_Z2f1v +// DI-USE: = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", {{.*}}, flags: DIFlagFwdDecl -- 2.7.4