From 6227069bdce6b0c3c22f0a0c8f1aef705985125a Mon Sep 17 00:00:00 2001 From: Amy Huang Date: Mon, 11 Jan 2021 16:37:29 -0800 Subject: [PATCH] [DebugInfo][CodeView] Change in line tables only mode to emit type information for function scopes, rather than using the qualified name. In line-tables-only mode, we used to emit qualified names as the display name for functions when using CodeView. This patch changes to emitting the parent scopes instead, with forward declarations for class types. The total object file size ends up being slightly smaller than if we use the full qualified names. Differential Revision: https://reviews.llvm.org/D94639 --- clang/lib/CodeGen/CGDebugInfo.cpp | 32 ++++++++--------- .../debug-info-codeview-display-name.cpp | 40 +++++++--------------- .../test/CodeGenCXX/debug-info-codeview-scopes.cpp | 34 ++++++++++++++++++ 3 files changed, 63 insertions(+), 43 deletions(-) create mode 100644 clang/test/CodeGenCXX/debug-info-codeview-scopes.cpp diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 881ee24546c..00606d3ae50 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -254,24 +254,12 @@ StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) { FunctionTemplateSpecializationInfo *Info = FD->getTemplateSpecializationInfo(); - // Emit the unqualified name in normal operation. LLVM and the debugger can - // compute the fully qualified name from the scope chain. If we're only - // emitting line table info, there won't be any scope chains, so emit the - // fully qualified name here so that stack traces are more accurate. - // FIXME: Do this when emitting DWARF as well as when emitting CodeView after - // evaluating the size impact. - bool UseQualifiedName = DebugKind == codegenoptions::DebugLineTablesOnly && - CGM.getCodeGenOpts().EmitCodeView; - - if (!Info && FII && !UseQualifiedName) + if (!Info && FII) return FII->getName(); SmallString<128> NS; llvm::raw_svector_ostream OS(NS); - if (!UseQualifiedName) - FD->printName(OS); - else - FD->printQualifiedName(OS, getPrintingPolicy()); + FD->printName(OS); // Add any template specialization args. if (Info) { @@ -1058,7 +1046,10 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, Flags |= llvm::DINode::FlagNonTrivial; // Create the type. - SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); + SmallString<256> Identifier; + // Don't include a linkage name in line tables only. + if (CGM.getCodeGenOpts().hasReducedDebugInfo()) + Identifier = getTypeIdentifier(Ty, CGM, TheCU); llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType( getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align, Flags, Identifier); @@ -2326,6 +2317,9 @@ static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind, if (ES->hasExternalDefinitions(RD) == ExternalASTSource::EK_Always) return true; + if (DebugKind == codegenoptions::DebugLineTablesOnly) + return true; + if (DebugKind > codegenoptions::LimitedDebugInfo) return false; @@ -3473,7 +3467,11 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit, DebugKind <= codegenoptions::DebugLineTablesOnly)) LinkageName = StringRef(); - if (CGM.getCodeGenOpts().hasReducedDebugInfo()) { + // Emit the function scope in line tables only mode (if CodeView) to + // differentiate between function names. + if (CGM.getCodeGenOpts().hasReducedDebugInfo() || + (DebugKind == codegenoptions::DebugLineTablesOnly && + CGM.getCodeGenOpts().EmitCodeView)) { if (const NamespaceDecl *NSDecl = dyn_cast_or_null(FD->getDeclContext())) FDContext = getOrCreateNamespace(NSDecl); @@ -3482,6 +3480,8 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit, llvm::DIScope *Mod = getParentModuleOrNull(RDecl); FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU); } + } + if (CGM.getCodeGenOpts().hasReducedDebugInfo()) { // Check if it is a noreturn-marked function if (FD->isNoReturn()) Flags |= llvm::DINode::FlagNoReturn; diff --git a/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp b/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp index 15f625d8832..935fded5e67 100644 --- a/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp +++ b/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp @@ -20,11 +20,9 @@ void freefunc() { } namespace N { int b() { return 0; } -// UNQUAL-DAG: "b" -// QUAL-DAG: "N::b" +// CHECK-DAG: "b" namespace { void func() { } } -// UNQUAL-DAG: "func" -// QUAL-DAG: "N::`anonymous namespace'::func" +// CHECK-DAG: "func" } void _c(void) { @@ -35,24 +33,19 @@ void _c(void) { struct foo { int operator+(int); foo(){} -// UNQUAL-DAG: "foo" -// QUAL-DAG: "foo::foo" +// CHECK-DAG: "foo" ~foo(){} -// UNQUAL-DAG: "~foo" -// QUAL-DAG: "foo::~foo" +// CHECK-DAG: "~foo" foo(int i){} -// UNQUAL-DAG: "foo" -// QUAL-DAG: "foo::foo" +// CHECK-DAG: "foo" foo(char *q){} -// UNQUAL-DAG: "foo" -// QUAL-DAG: "foo::foo" +// CHECK-DAG: "foo" static foo* static_method() { return 0; } -// UNQUAL-DAG: "static_method" -// QUAL-DAG: "foo::static_method" +// CHECK-DAG: "static_method" }; @@ -61,8 +54,7 @@ void use_foo() { foo::static_method(); } -// UNQUAL-DAG: "operator+" -// QUAL-DAG: "foo::operator+" +// CHECK-DAG: "operator+" int foo::operator+(int a) { return a; } // PR17371 @@ -82,17 +74,11 @@ void OverloadedNewDelete::operator delete(void *) { } void OverloadedNewDelete::operator delete[](void *) { } int OverloadedNewDelete::operator+(int x) { return x; }; -// UNQUAL-DAG: "operator new" -// UNQUAL-DAG: "operator new[]" -// UNQUAL-DAG: "operator delete" -// UNQUAL-DAG: "operator delete[]" -// UNQUAL-DAG: "operator+" -// QUAL-DAG: "OverloadedNewDelete::operator new" -// QUAL-DAG: "OverloadedNewDelete::operator new[]" -// QUAL-DAG: "OverloadedNewDelete::operator delete" -// QUAL-DAG: "OverloadedNewDelete::operator delete[]" -// QUAL-DAG: "OverloadedNewDelete::operator+" - +// CHECK-DAG: "operator new" +// CHECK-DAG: "operator new[]" +// CHECK-DAG: "operator delete" +// CHECK-DAG: "operator delete[]" +// CHECK-DAG: "operator+" template void fn_tmpl() {} diff --git a/clang/test/CodeGenCXX/debug-info-codeview-scopes.cpp b/clang/test/CodeGenCXX/debug-info-codeview-scopes.cpp new file mode 100644 index 00000000000..f096e334a15 --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-codeview-scopes.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -debug-info-kind=line-tables-only -S -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix LINUX %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -debug-info-kind=line-tables-only -gcodeview -S -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix MSVC %s + +// Check that we emit type information for function scopes in line tables for +// CodeView. + +namespace A { +void f() {} + +struct S { + static void m() {} +}; +} + +int main() { + A::f(); + A::S::m(); + return 0; + // MSVC: !{{[0-9]+}} = distinct !DISubprogram(name: "f" + // MSVC-SAME: scope: [[SCOPE1:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[SCOPE1]] = !DINamespace(name: "A", {{.*}}) + // MSVC: !{{[0-9]+}} = distinct !DISubprogram(name: "m" + // MSVC-SAME: scope: [[SCOPE2:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[SCOPE2]] = !DICompositeType(tag: DW_TAG_structure_type, + // MSVC-SAME: name: "S", + // MSVC-SAME: scope: [[SCOPE1]] + // MSVC-SAME: ) + + // LINUX-NOT: !DINamespace + // LINUX-NOT: !DICompositeType + return 0; +} -- 2.11.0