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