On Mar 3, 2014, at 7:15 PM, David Blaikie <[email protected]> wrote:
> On Mon, Mar 3, 2014 at 7:05 PM, Pete Cooper <[email protected]> wrote: >> Hey David >> >> We had a failure with this test on our buildbots. Seems Mac OS doesn't >> generate the same debug info for 'c': > > Ah, sorry about that - didn't realize darwin's default of > -fstandalone-debug was built into the frontend (well, I forgot that > was still the darwin default at all). Changed the test to explicitly > specify -fno-standalone-debug. I had no idea we even had that option, nor that it was on by default! Thanks for the quick fix. Pete > >> llvm/tools/clang/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp:22:11: >> error: expected string not found in input >> // CHECK: ; [ DW_TAG_structure_type ] [c<int>] {{.*}} [decl] >> ^ >> <stdin>:27:252: note: scanning from here >> !4 = metadata !{i32 786451, metadata !5, null, metadata !"b<int>", i32 12, >> i64 8, i64 8, i32 0, i32 0, null, metadata !2, i32 0, null, metadata !6, >> metadata !"_ZTS1bIiE"} ; [ DW_TAG_structure_type ] [b<int>] [line 12, size >> 8, align 8, offset 0] [def] [from ] >> >> ^ >> <stdin>:32:170: note: possible intended match here >> !9 = metadata !{i32 786451, metadata !5, null, metadata !"c<int>", i32 20, >> i64 8, i64 8, i32 0, i32 0, null, metadata !10, i32 0, null, metadata !6, >> metadata !"_ZTS1cIiE"} ; [ DW_TAG_structure_type ] [c<int>] [line 20, size >> 8, align 8, offset 0] [def] [from ] >> >> I committed a fix in 202777. Please take a look and see if you think its >> ok. >> >> Thanks, >> Pete >> On Mar 3, 2014, at 3:48 PM, David Blaikie <[email protected]> wrote: >> >> Author: dblaikie >> Date: Mon Mar 3 17:48:23 2014 >> New Revision: 202769 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=202769&view=rev >> Log: >> DebugInfo: Emit only the declaration of a class template that has an >> explicit instantiation declaration (& always emit such a type when there's >> an explicit instantiation definition) >> >> We should only have this optimization fire when the explicit >> instantiation definition would cause at least one member function to be >> emitted, thus ensuring that even a compiler not performing this >> optimization would still emit the full type information elsewhere. >> >> But we should also pessimize output still by always emitting the >> definition when the explicit instantiation definition appears so that at >> some point in the future we can depend on that information even when no >> code had to be emitted in that TU. (this shouldn't happen very often, >> since people mostly use explicit spec decl/defs to reduce code size - >> but perhaps one day they could use it to explicitly reduce debug info >> size too) >> >> This was worth about 2% for Clang and LLVM - so not a huge win, but a >> win. It looks really great for simple STL programs (include <string> and >> just declare a string - 14k -> 1.4k of .dwo) >> >> Added: >> cfe/trunk/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp >> Modified: >> cfe/trunk/lib/CodeGen/CGDebugInfo.cpp >> cfe/trunk/lib/CodeGen/CGDebugInfo.h >> cfe/trunk/lib/CodeGen/CodeGenModule.cpp >> >> Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=202769&r1=202768&r2=202769&view=diff >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original) >> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Mar 3 17:48:23 2014 >> @@ -1458,28 +1458,53 @@ void CGDebugInfo::completeClassData(cons >> TypeCache[TyPtr] = Res; >> } >> >> +static bool hasExplicitMemberDefinition(CXXRecordDecl::method_iterator I, >> + CXXRecordDecl::method_iterator End) >> { >> + for (; I != End; ++I) >> + if (FunctionDecl *Tmpl = I->getInstantiatedFromMemberFunction()) >> + if (!Tmpl->isImplicit() && Tmpl->hasBody()) >> + return true; >> + return false; >> +} >> + >> +static bool shouldOmitDefinition(CodeGenOptions::DebugInfoKind DebugKind, >> + const RecordDecl *RD, >> + const LangOptions &LangOpts) { >> + if (DebugKind > CodeGenOptions::LimitedDebugInfo) >> + return false; >> + >> + if (!LangOpts.CPlusPlus) >> + return false; >> + >> + if (!RD->isCompleteDefinitionRequired()) >> + return true; >> + >> + const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD); >> + >> + if (!CXXDecl) >> + return false; >> + >> + if (CXXDecl->hasDefinition() && CXXDecl->isDynamicClass()) >> + return true; >> + >> + TemplateSpecializationKind Spec = TSK_Undeclared; >> + if (const ClassTemplateSpecializationDecl *SD = >> + dyn_cast<ClassTemplateSpecializationDecl>(RD)) >> + Spec = SD->getSpecializationKind(); >> + >> + if (Spec == TSK_ExplicitInstantiationDeclaration && >> + hasExplicitMemberDefinition(CXXDecl->method_begin(), >> + CXXDecl->method_end())) >> + return true; >> + >> + return false; >> +} >> + >> /// CreateType - get structure or union type. >> llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { >> RecordDecl *RD = Ty->getDecl(); >> - const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD); >> - // Always emit declarations for types that aren't required to be complete >> when >> - // in limit-debug-info mode. If the type is later found to be required to >> be >> - // complete this declaration will be upgraded to a definition by >> - // `completeRequiredType`. >> - // If the type is dynamic, only emit the definition in TUs that require >> class >> - // data. This is handled by `completeClassData`. >> llvm::DICompositeType T(getTypeOrNull(QualType(Ty, 0))); >> - // If we've already emitted the type, just use that, even if it's only a >> - // declaration. The completeType, completeRequiredType, and >> completeClassData >> - // callbacks will handle promoting the declaration to a definition. >> - if (T || >> - // Under -fno-standalone-debug: >> - (DebugKind <= CodeGenOptions::LimitedDebugInfo && >> - // Emit only a forward declaration unless the type is required. >> - ((!RD->isCompleteDefinitionRequired() && >> CGM.getLangOpts().CPlusPlus) || >> - // If the class is dynamic, only emit a declaration. A definition >> will >> - // be emitted whenever the vtable is emitted. >> - (CXXDecl && CXXDecl->hasDefinition() && >> CXXDecl->isDynamicClass())))) { >> + if (T || shouldOmitDefinition(DebugKind, RD, CGM.getLangOpts())) { >> if (!T) >> T = getOrCreateRecordFwdDecl( >> Ty, getContextDescriptor(cast<Decl>(RD->getDeclContext()))); >> @@ -2014,6 +2039,14 @@ llvm::DIType CGDebugInfo::getCompletedTy >> return llvm::DIType(cast_or_null<llvm::MDNode>(V)); >> } >> >> +void CGDebugInfo::completeTemplateDefinition( >> + const ClassTemplateSpecializationDecl &SD) { >> + completeClassData(&SD); >> + // In case this type has no member function definitions being emitted, >> ensure >> + // it is retained >> + >> RetainedTypes.push_back(CGM.getContext().getRecordType(&SD).getAsOpaquePtr()); >> +} >> + >> /// getCachedInterfaceTypeOrNull - Get the type from the interface >> /// cache, unless it needs to regenerated. Otherwise return null. >> llvm::Value *CGDebugInfo::getCachedInterfaceTypeOrNull(QualType Ty) { >> >> Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=202769&r1=202768&r2=202769&view=diff >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original) >> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Mon Mar 3 17:48:23 2014 >> @@ -288,6 +288,8 @@ public: >> void completeRequiredType(const RecordDecl *RD); >> void completeClassData(const RecordDecl *RD); >> >> + void completeTemplateDefinition(const ClassTemplateSpecializationDecl >> &SD); >> + >> private: >> /// EmitDeclare - Emit call to llvm.dbg.declare for a variable >> declaration. >> void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI, >> >> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=202769&r1=202768&r2=202769&view=diff >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original) >> +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Mar 3 17:48:23 2014 >> @@ -3000,7 +3000,15 @@ void CodeGenModule::EmitTopLevelDecl(Dec >> >> ImportedModules.insert(Import->getImportedModule()); >> break; >> - } >> + } >> + >> + case Decl::ClassTemplateSpecialization: { >> + const ClassTemplateSpecializationDecl *Spec = >> + cast<ClassTemplateSpecializationDecl>(D); >> + if (DebugInfo && >> + Spec->getSpecializationKind() == >> TSK_ExplicitInstantiationDefinition) >> + DebugInfo->completeTemplateDefinition(*Spec); >> + } >> >> default: >> // Make sure we handled everything we should, every other kind is a >> >> Added: >> cfe/trunk/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp?rev=202769&view=auto >> ============================================================================== >> --- >> cfe/trunk/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp >> (added) >> +++ >> cfe/trunk/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp >> Mon Mar 3 17:48:23 2014 >> @@ -0,0 +1,72 @@ >> +// RUN: %clang_cc1 -S -emit-llvm -g %s -o - | FileCheck %s >> + >> +template <typename T> >> +struct a { >> +}; >> +extern template class a<int>; >> +// CHECK-NOT: ; [ DW_TAG_structure_type ] [a<int>] >> + >> +template <typename T> >> +struct b { >> +}; >> +extern template class b<int>; >> +b<int> bi; >> +// CHECK: ; [ DW_TAG_structure_type ] [b<int>] {{.*}} [def] >> + >> +template <typename T> >> +struct c { >> + void f() {} >> +}; >> +extern template class c<int>; >> +c<int> ci; >> +// CHECK: ; [ DW_TAG_structure_type ] [c<int>] {{.*}} [decl] >> + >> +template <typename T> >> +struct d { >> + void f(); >> +}; >> +extern template class d<int>; >> +d<int> di; >> +// CHECK: ; [ DW_TAG_structure_type ] [d<int>] {{.*}} [def] >> + >> +template <typename T> >> +struct e { >> + void f(); >> +}; >> +template <typename T> >> +void e<T>::f() { >> +} >> +extern template class e<int>; >> +e<int> ei; >> +// CHECK: ; [ DW_TAG_structure_type ] [e<int>] {{.*}} [decl] >> + >> +template <typename T> >> +struct f { >> + void g(); >> +}; >> +extern template class f<int>; >> +template <typename T> >> +void f<T>::g() { >> +} >> +f<int> fi; >> +// Is this right? We don't seem to emit a def for 'f<int>::g' (even if it >> is >> +// called in this translation unit) so I guess if we're relying on its >> +// definition to be wherever the explicit instantiation definition is, we >> can do >> +// the same for the debug info. >> +// CHECK: ; [ DW_TAG_structure_type ] [f<int>] {{.*}} [decl] >> + >> +template <typename T> >> +struct g { >> + void f(); >> +}; >> +template <> >> +void g<int>::f(); >> +extern template class g<int>; >> +g<int> gi; >> +// CHECK: ; [ DW_TAG_structure_type ] [g<int>] {{.*}} [def] >> + >> +template <typename T> >> +struct h { >> +}; >> +template class h<int>; >> +// CHECK: ; [ DW_TAG_structure_type ] [h<int>] {{.*}} [def] >> >> >> _______________________________________________ >> cfe-commits mailing list >> [email protected] >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> >> _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
