r247369 - Module Debugging: Emit forward declarations for types that are defined in
Adrian Prantl via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 10 18:03:26 PDT 2015
Author: adrian
Date: Thu Sep 10 20:03:26 2015
New Revision: 247369
URL: http://llvm.org/viewvc/llvm-project?rev=247369&view=rev
Log:
Module Debugging: Emit forward declarations for types that are defined in
clang modules, if -dwarf-ext-refs (DebugTypesExtRefs) is specified.
Added:
cfe/trunk/test/Modules/ExtDebugInfo.cpp
cfe/trunk/test/Modules/ExtDebugInfo.m
Modified:
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.h
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=247369&r1=247368&r2=247369&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Thu Sep 10 20:03:26 2015
@@ -148,7 +148,9 @@ void CGDebugInfo::setLocation(SourceLoca
}
llvm::DIScope *CGDebugInfo::getDeclContextDescriptor(const Decl *D) {
- return getContextDescriptor(cast<Decl>(D->getDeclContext()), TheCU);
+ llvm::DIScope *Mod = getParentModuleOrNull(D);
+ return getContextDescriptor(cast<Decl>(D->getDeclContext()),
+ Mod ? Mod : TheCU);
}
llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context,
@@ -1448,6 +1450,9 @@ void CGDebugInfo::completeRequiredType(c
if (CXXDecl->isDynamicClass())
return;
+ if (DebugTypeExtRefs && RD->isFromASTFile())
+ return;
+
QualType Ty = CGM.getContext().getRecordType(RD);
llvm::DIType *T = getTypeOrNull(Ty);
if (T && T->isForwardDecl())
@@ -1669,9 +1674,9 @@ CGDebugInfo::getOrCreateModuleRef(Extern
TheCU->getSourceLanguage(), internString(Mod.ModuleName),
internString(Mod.Path), TheCU->getProducer(), true, StringRef(), 0,
internString(Mod.ASTFile), llvm::DIBuilder::FullDebug, Mod.Signature);
- llvm::DIModule *M =
- DIB.createModule(CU, Mod.ModuleName, ConfigMacros, internString(Mod.Path),
- internString(CGM.getHeaderSearchOpts().Sysroot));
+ llvm::DIModule *M = DIB.createModule(
+ CU, Mod.ModuleName, ConfigMacros, internString(Mod.Path),
+ internString(CGM.getHeaderSearchOpts().Sysroot));
DIB.finalize();
ModRef.reset(M);
return M;
@@ -2081,9 +2086,16 @@ llvm::DIType *CGDebugInfo::getOrCreateTy
if (auto *T = getTypeOrNull(Ty))
return T;
+ llvm::DIType *Res = nullptr;
+ if (DebugTypeExtRefs)
+ // Make a forward declaration of an external type.
+ Res = getTypeExtRefOrNull(Ty, Unit);
+
// Otherwise create the type.
- llvm::DIType *Res = CreateTypeNode(Ty, Unit);
- void *TyPtr = Ty.getAsOpaquePtr();
+ if (!Res)
+ Res = CreateTypeNode(Ty, Unit);
+
+ void* TyPtr = Ty.getAsOpaquePtr();
// And update the type cache.
TypeCache[TyPtr].reset(Res);
@@ -2115,6 +2127,123 @@ ObjCInterfaceDecl *CGDebugInfo::getObjCI
}
}
+llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) {
+ if (!DebugTypeExtRefs || !D || !D->isFromASTFile())
+ return nullptr;
+
+ llvm::DIModule *ModuleRef = nullptr;
+ auto *Reader = CGM.getContext().getExternalSource();
+ auto Idx = D->getOwningModuleID();
+ auto Info = Reader->getSourceDescriptor(Idx);
+ if (Info)
+ ModuleRef = getOrCreateModuleRef(*Info);
+ return ModuleRef;
+}
+
+llvm::DIType *CGDebugInfo::getTypeExtRefOrNull(QualType Ty, llvm::DIFile *F,
+ bool Anchored) {
+ assert(DebugTypeExtRefs && "module debugging only");
+ Decl *TyDecl = nullptr;
+ StringRef Name;
+ SmallString<256> UID;
+ unsigned Tag = 0;
+
+ // Handle all types that have a declaration.
+ switch (Ty->getTypeClass()) {
+ case Type::Typedef: {
+ TyDecl = cast<TypedefType>(Ty)->getDecl();
+ if (!TyDecl->isFromASTFile())
+ return nullptr;
+
+ // A typedef will anchor a type in the module.
+ if (auto *TD = dyn_cast<TypedefDecl>(TyDecl)) {
+ // This is a working around the fact that LLVM does not allow
+ // typedefs to be forward declarations.
+ QualType Ty = TD->getUnderlyingType();
+ Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
+ if (auto *AnchoredTy = getTypeExtRefOrNull(Ty, F, /*Anchored=*/true)) {
+ TypeCache[Ty.getAsOpaquePtr()].reset(AnchoredTy);
+ SourceLocation Loc = TD->getLocation();
+ return DBuilder.createTypedef(AnchoredTy, TD->getName(),
+ getOrCreateFile(Loc), getLineNumber(Loc),
+ getDeclContextDescriptor(TD));
+ }
+ }
+ break;
+ }
+
+ case Type::Record: {
+ TyDecl = cast<RecordType>(Ty)->getDecl();
+ if (!TyDecl->isFromASTFile())
+ return nullptr;
+
+ if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TyDecl))
+ if (!CTSD->isExplicitInstantiationOrSpecialization() && !Anchored)
+ // We may not assume that this type made it into the module.
+ return nullptr;
+ // C++ classes and template instantiations.
+ if (auto *RD = dyn_cast<CXXRecordDecl>(TyDecl)) {
+ if (!RD->getDefinition())
+ return nullptr;
+ Tag = getTagForRecord(RD);
+ UID =
+ getUniqueTagTypeName(cast<TagType>(RD->getTypeForDecl()), CGM, TheCU);
+ Name = getClassName(RD);
+ } else if (auto *RD = dyn_cast<RecordDecl>(TyDecl)) {
+ // C-style structs.
+ if (!RD->getDefinition())
+ return nullptr;
+ Tag = getTagForRecord(RD);
+ Name = getClassName(RD);
+ }
+ break;
+ }
+
+ case Type::Enum: {
+ TyDecl = cast<EnumType>(Ty)->getDecl();
+ if (!TyDecl->isFromASTFile())
+ return nullptr;
+
+ if (auto *ED = dyn_cast<EnumDecl>(TyDecl)) {
+ if (!ED->getDefinition())
+ return nullptr;
+ Tag = llvm::dwarf::DW_TAG_enumeration_type;
+ if ((TheCU->getSourceLanguage() == llvm::dwarf::DW_LANG_C_plus_plus) ||
+ (TheCU->getSourceLanguage() == llvm::dwarf::DW_LANG_ObjC_plus_plus)) {
+ UID = getUniqueTagTypeName(cast<TagType>(ED->getTypeForDecl()), CGM,
+ TheCU);
+ Name = ED->getName();
+ }
+ }
+ break;
+ }
+
+ case Type::ObjCInterface: {
+ TyDecl = cast<ObjCInterfaceType>(Ty)->getDecl();
+ if (!TyDecl->isFromASTFile())
+ return nullptr;
+
+ if (auto *ID = dyn_cast<ObjCInterfaceDecl>(TyDecl)) {
+ if (!ID->getDefinition())
+ return nullptr;
+ Tag = llvm::dwarf::DW_TAG_structure_type;
+ Name = ID->getName();
+ }
+ break;
+ }
+
+ default:
+ return nullptr;
+ }
+
+ if (Tag && !Name.empty()) {
+ assert(TyDecl);
+ auto *Ctx = getDeclContextDescriptor(TyDecl);
+ return DBuilder.createForwardDecl(Tag, Name, Ctx, F, 0, 0, 0, 0, UID);
+ } else
+ return nullptr;
+}
+
llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
// Handle qualifiers, which recursively handles what they refer to.
if (Ty.hasLocalQualifiers())
@@ -2325,8 +2454,10 @@ void CGDebugInfo::collectFunctionDeclPro
dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
FDContext = getOrCreateNameSpace(NSDecl);
else if (const RecordDecl *RDecl =
- dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))
- FDContext = getContextDescriptor(RDecl, TheCU);
+ dyn_cast_or_null<RecordDecl>(FD->getDeclContext())) {
+ llvm::DIScope *Mod = getParentModuleOrNull(RDecl);
+ FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU);
+ }
// Collect template parameters.
TParamsArray = CollectFunctionTemplateParams(FD, Unit);
}
@@ -2374,7 +2505,9 @@ void CGDebugInfo::collectVarDeclProps(co
// outside the class by putting it in the global scope.
if (DC->isRecord())
DC = CGM.getContext().getTranslationUnitDecl();
- VDContext = getContextDescriptor(cast<Decl>(DC), TheCU);
+
+ llvm::DIScope *Mod = getParentModuleOrNull(VD);
+ VDContext = getContextDescriptor(cast<Decl>(DC), Mod ? Mod : TheCU);
}
llvm::DISubprogram *
@@ -3299,7 +3432,8 @@ void CGDebugInfo::EmitGlobalVariable(con
llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
if (!LexicalBlockStack.empty())
return LexicalBlockStack.back();
- return getContextDescriptor(D, TheCU);
+ llvm::DIScope *Mod = getParentModuleOrNull(D);
+ return getContextDescriptor(D, Mod ? Mod : TheCU);
}
void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) {
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=247369&r1=247368&r2=247369&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Thu Sep 10 20:03:26 2015
@@ -397,6 +397,15 @@ private:
llvm::DIModule *
getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod);
+ /// DebugTypeExtRefs: If \p D originated in a clang module, return it.
+ llvm::DIModule *getParentModuleOrNull(const Decl *D);
+
+ /// Return a forward declaration of an external type, if this type
+ /// came from a clang module. If \p Anchored is true, template
+ /// types will be assumed to have been instantiated in the module.
+ llvm::DIType *getTypeExtRefOrNull(QualType Ty, llvm::DIFile *F,
+ bool Anchored = false);
+
/// Get the type from the cache or create a new partial type if
/// necessary.
llvm::DICompositeType *getOrCreateLimitedType(const RecordType *Ty,
Added: cfe/trunk/test/Modules/ExtDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ExtDebugInfo.cpp?rev=247369&view=auto
==============================================================================
--- cfe/trunk/test/Modules/ExtDebugInfo.cpp (added)
+++ cfe/trunk/test/Modules/ExtDebugInfo.cpp Thu Sep 10 20:03:26 2015
@@ -0,0 +1,74 @@
+// RUN: rm -rf %t
+// Test that only forward declarations are emitted for types dfined in modules.
+
+// Modules:
+// RUN: %clang_cc1 -x objective-c++ -std=c++11 -g -dwarf-ext-refs -fmodules \
+// RUN: -fmodule-format=obj -fimplicit-module-maps -DMODULES \
+// RUN: -fmodules-cache-path=%t %s -I %S/Inputs -I %t -emit-llvm -o %t-mod.ll
+// RUN: cat %t-mod.ll | FileCheck %s
+
+// PCH:
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodule-format=obj -emit-pch -I%S/Inputs \
+// RUN: -o %t.pch %S/Inputs/DebugCXX.h
+// RUN: %clang_cc1 -std=c++11 -g -dwarf-ext-refs -fmodule-format=obj \
+// RUN: -include-pch %t.pch %s -emit-llvm -o %t-pch.ll %s
+// RUN: cat %t-pch.ll | FileCheck %s
+
+#ifdef MODULES
+ at import DebugCXX;
+#endif
+
+using DebugCXX::Struct;
+
+Struct s;
+DebugCXX::Enum e;
+DebugCXX::Template<long> implicitTemplate;
+DebugCXX::Template<int> explicitTemplate;
+DebugCXX::FloatInstatiation typedefTemplate;
+int Struct::static_member = -1;
+enum {
+ e3 = -1
+} conflicting_uid = e3;
+auto anon_enum = DebugCXX::e2;
+char _anchor = anon_enum + conflicting_uid;
+
+// CHECK: ![[ANON_ENUM:[0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type
+// CHECK-SAME: scope: ![[MOD:[0-9]+]],
+// CHECK-SAME: {{.*}}line: 16, {{.*}}, elements: ![[EE:[0-9]+]])
+
+// CHECK: ![[NS:.*]] = !DINamespace(name: "DebugCXX", scope: ![[MOD:[0-9]+]],
+// CHECK: ![[MOD]] = !DIModule(scope: null, name: {{.*}}DebugCXX
+
+// CHECK: ![[EE]] = !{![[E2:[0-9]+]]}
+// CHECK: ![[E2]] = !DIEnumerator(name: "e2", value: 50)
+
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Struct",
+// CHECK-SAME: scope: ![[NS]],
+// CHECK-SAME: flags: DIFlagFwdDecl,
+// CHECK-SAME: identifier: "_ZTSN8DebugCXX6StructE")
+
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum",
+// CHECK-SAME: scope: ![[NS]],
+// CHECK-SAME: flags: DIFlagFwdDecl,
+// CHECK-SAME: identifier: "_ZTSN8DebugCXX4EnumE")
+
+// CHECK: !DICompositeType(tag: DW_TAG_class_type,
+
+// CHECK: !DICompositeType(tag: DW_TAG_class_type,
+// CHECK-SAME: name: "Template<int, DebugCXX::traits<int> >",
+// CHECK-SAME: scope: ![[NS]],
+// CHECK-SAME: flags: DIFlagFwdDecl,
+// CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIiNS_6traitsIiEEEE")
+
+// CHECK: !DICompositeType(tag: DW_TAG_class_type,
+// CHECK-SAME: name: "Template<float, DebugCXX::traits<float> >",
+// CHECK-SAME: scope: ![[NS]],
+// CHECK-SAME: flags: DIFlagFwdDecl,
+// CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIfNS_6traitsIfEEEE")
+
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_member",
+// CHECK-SAME: scope: !"_ZTSN8DebugCXX6StructE"
+
+// CHECK: !DIGlobalVariable(name: "anon_enum", {{.*}}, type: ![[ANON_ENUM]]
+
+// CHECK: !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !"_ZTSN8DebugCXX6StructE", line: 21)
Added: cfe/trunk/test/Modules/ExtDebugInfo.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ExtDebugInfo.m?rev=247369&view=auto
==============================================================================
--- cfe/trunk/test/Modules/ExtDebugInfo.m (added)
+++ cfe/trunk/test/Modules/ExtDebugInfo.m Thu Sep 10 20:03:26 2015
@@ -0,0 +1,29 @@
+// RUN: rm -rf %t
+// Test that only forward declarations are emitted for types dfined in modules.
+
+// Modules:
+// RUN: %clang_cc1 -x objective-c -g -dwarf-ext-refs -fmodules \
+// RUN: -fmodule-format=obj -fimplicit-module-maps -DMODULES \
+// RUN: -fmodules-cache-path=%t %s -I %S/Inputs -I %t -emit-llvm -o %t-mod.ll
+// RUN: cat %t-mod.ll | FileCheck %s
+
+// PCH:
+// RUN: %clang_cc1 -x objective-c -fmodule-format=obj -emit-pch -I%S/Inputs \
+// RUN: -o %t.pch %S/Inputs/DebugObjC.h
+// RUN: %clang_cc1 -x objective-c -g -dwarf-ext-refs -fmodule-format=obj \
+// RUN: -include-pch %t.pch %s -emit-llvm -o %t-pch.ll %s
+// RUN: cat %t-pch.ll | FileCheck %s
+
+#ifdef MODULES
+ at import DebugObjC;
+#endif
+
+int foo(ObjCClass *c) {
+ [c instanceMethodWithInt: 0];
+ return [c property];
+}
+
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type,
+// CHECK-SAME: scope: ![[MOD:[0-9]+]],
+// CHECK-SAME: flags: DIFlagFwdDecl)
+// CHECK: ![[MOD]] = !DIModule(scope: null, name: {{.*}}DebugObjC
More information about the cfe-commits
mailing list