Module debugging: Support submodules in the PCM/PCH debug info.

llvm-svn: 248127
This commit is contained in:
Adrian Prantl 2015-09-20 16:51:35 +00:00
parent 707a406078
commit 9402cef0ae
7 changed files with 75 additions and 13 deletions

View File

@ -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) {

View File

@ -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);

View File

@ -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<PCHBuffer> 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 {

View File

@ -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",

View File

@ -0,0 +1,3 @@
struct A {
int a;
};

View File

@ -0,0 +1,3 @@
struct B {
int b;
};

View File

@ -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 *
}
}