r247369 - Module Debugging: Emit forward declarations for types that are defined in

David Blaikie via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 10 18:40:35 PDT 2015


On Thu, Sep 10, 2015 at 6:03 PM, Adrian Prantl via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> 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.
>

This change seems to have a lot more code in it than I was expecting...

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.

Why the extra complexity?

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)?)


>
> 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
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150910/4b76b5c4/attachment-0001.html>


More information about the cfe-commits mailing list