From a83de9f778387b6a561a0fe98c733a2777fc3ac4 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Sun, 20 Sep 2015 16:51:35 +0000 Subject: [PATCH] Module debugging: Support submodules in the PCM/PCH debug info. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@248127 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDebugInfo.cpp | 38 ++++++++++++++----- lib/CodeGen/CGDebugInfo.h | 13 +++++-- .../ObjectFilePCHContainerOperations.cpp | 5 +++ test/Modules/DebugInfoSubmodules.c | 15 ++++++++ test/Modules/Inputs/DebugSubmoduleA.h | 3 ++ test/Modules/Inputs/DebugSubmoduleB.h | 3 ++ test/Modules/Inputs/module.map | 11 ++++++ 7 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 test/Modules/DebugInfoSubmodules.c create mode 100644 test/Modules/Inputs/DebugSubmoduleA.h create mode 100644 test/Modules/Inputs/DebugSubmoduleB.h diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index c0a3db4d61..6af8d6626b 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/Version.h" #include "clang/Frontend/CodeGenOptions.h" #include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessorOptions.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -2159,17 +2160,34 @@ ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) { } llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) { - if (!DebugTypeExtRefs || !D->isFromASTFile()) - return nullptr; + ExternalASTSource::ASTSourceDescriptor Info; + if (ClangModuleMap) { + // We are building a clang module or a precompiled header. + // + // TODO: When D is a CXXRecordDecl or a C++ Enum, the ODR applies + // and it wouldn't be necessary to specify the parent scope + // because the type is already unique by definition (it would look + // like the output of -fno-standalone-debug). On the other hand, + // the parent scope helps a consumer to quickly locate the object + // file where the type's definition is located, so it might be + // best to make this behavior a command line or debugger tuning + // option. + FullSourceLoc Loc(D->getLocation(), CGM.getContext().getSourceManager()); + if (Module *M = ClangModuleMap->inferModuleFromLocation(Loc)) { + auto Info = ExternalASTSource::ASTSourceDescriptor(*M); + return getOrCreateModuleRef(Info, /*SkeletonCU=*/false); + } + } - // Record a reference to an imported clang module or precompiled header. - llvm::DIModule *ModuleRef = nullptr; - auto *Reader = CGM.getContext().getExternalSource(); - auto Idx = D->getOwningModuleID(); - auto Info = Reader->getSourceDescriptor(Idx); - if (Info) - ModuleRef = getOrCreateModuleRef(*Info, true); - return ModuleRef; + if (DebugTypeExtRefs && D->isFromASTFile()) { + // Record a reference to an imported clang module or precompiled header. + auto *Reader = CGM.getContext().getExternalSource(); + auto Idx = D->getOwningModuleID(); + auto Info = Reader->getSourceDescriptor(Idx); + if (Info) + return getOrCreateModuleRef(*Info, /*SkeletonCU=*/true); + } + return nullptr; } llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 8d42f57a3e..8cad0c16b7 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -32,12 +32,13 @@ class MDNode; namespace clang { class CXXMethodDecl; -class VarDecl; -class ObjCInterfaceDecl; -class ObjCIvarDecl; class ClassTemplateSpecializationDecl; class GlobalDecl; +class ModuleMap; +class ObjCInterfaceDecl; +class ObjCIvarDecl; class UsingDecl; +class VarDecl; namespace CodeGen { class CodeGenModule; @@ -55,6 +56,7 @@ class CGDebugInfo { bool DebugTypeExtRefs; llvm::DIBuilder DBuilder; llvm::DICompileUnit *TheCU = nullptr; + ModuleMap *ClangModuleMap = nullptr; SourceLocation CurLoc; llvm::DIType *VTablePtrType = nullptr; llvm::DIType *ClassTy = nullptr; @@ -274,6 +276,11 @@ public: void finalize(); + /// When generating debug information for a clang module or + /// precompiled header, this module map will be used to determine + /// the module of origin of each Decl. + void setModuleMap(ModuleMap &MMap) { ClangModuleMap = &MMap; } + /// Update the current source location. If \arg loc is invalid it is /// ignored. void setLocation(SourceLocation Loc); diff --git a/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp index 147d198d9b..1673340a49 100644 --- a/lib/CodeGen/ObjectFilePCHContainerOperations.cpp +++ b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp @@ -19,6 +19,8 @@ #include "clang/CodeGen/BackendUtil.h" #include "clang/Frontend/CodeGenOptions.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/HeaderSearch.h" #include "clang/Serialization/ASTWriter.h" #include "llvm/ADT/StringRef.h" #include "llvm/Bitcode/BitstreamReader.h" @@ -41,6 +43,7 @@ class PCHContainerGenerator : public ASTConsumer { DiagnosticsEngine &Diags; const std::string MainFileName; ASTContext *Ctx; + ModuleMap &MMap; const HeaderSearchOptions &HeaderSearchOpts; const PreprocessorOptions &PreprocessorOpts; CodeGenOptions CodeGenOpts; @@ -121,6 +124,7 @@ public: raw_pwrite_stream *OS, std::shared_ptr Buffer) : Diags(CI.getDiagnostics()), Ctx(nullptr), + MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()), HeaderSearchOpts(CI.getHeaderSearchOpts()), PreprocessorOpts(CI.getPreprocessorOpts()), TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()), OS(OS), @@ -145,6 +149,7 @@ public: M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString()); Builder.reset(new CodeGen::CodeGenModule( *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags)); + Builder->getModuleDebugInfo()->setModuleMap(MMap); } bool HandleTopLevelDecl(DeclGroupRef D) override { diff --git a/test/Modules/DebugInfoSubmodules.c b/test/Modules/DebugInfoSubmodules.c new file mode 100644 index 0000000000..1cba00dc7c --- /dev/null +++ b/test/Modules/DebugInfoSubmodules.c @@ -0,0 +1,15 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fmodule-format=obj -g -dwarf-ext-refs \ +// RUN: -fimplicit-module-maps -x c -fmodules-cache-path=%t -I %S/Inputs \ +// RUN: %s -mllvm -debug-only=pchcontainer 2>&1 | FileCheck %s +#include "DebugSubmoduleA.h" + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A", +// CHECK-SAME: scope: ![[SUBMODULEA:[0-9]+]] +// CHECK: ![[SUBMODULEA]] = !DIModule( +// CHECK-SAME: name: "DebugSubmodules.DebugSubmoduleA", + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "B", +// CHECK-SAME: scope: ![[SUBMODULEB:[0-9]+]] +// CHECK: ![[SUBMODULEB]] = !DIModule( +// CHECK-SAME: name: "DebugSubmodules.DebugSubmoduleB", diff --git a/test/Modules/Inputs/DebugSubmoduleA.h b/test/Modules/Inputs/DebugSubmoduleA.h new file mode 100644 index 0000000000..1403a7d156 --- /dev/null +++ b/test/Modules/Inputs/DebugSubmoduleA.h @@ -0,0 +1,3 @@ +struct A { + int a; +}; diff --git a/test/Modules/Inputs/DebugSubmoduleB.h b/test/Modules/Inputs/DebugSubmoduleB.h new file mode 100644 index 0000000000..b06ae6a230 --- /dev/null +++ b/test/Modules/Inputs/DebugSubmoduleB.h @@ -0,0 +1,3 @@ +struct B { + int b; +}; diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map index 79a9a47e58..27751d8fd5 100644 --- a/test/Modules/Inputs/module.map +++ b/test/Modules/Inputs/module.map @@ -364,3 +364,14 @@ module TargetFeatures { module x86_64 { requires x86_64 } } } + +module DebugSubmodules { + module DebugSubmoduleA { + header "DebugSubmoduleA.h" + export * + } + module DebugSubmoduleB { + header "DebugSubmoduleB.h" + export * + } +} -- 2.50.1