[llvm] r273009 - [codeview] Make function names more consistent with MSVC

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 17 09:11:20 PDT 2016


Author: rnk
Date: Fri Jun 17 11:11:20 2016
New Revision: 273009

URL: http://llvm.org/viewvc/llvm-project?rev=273009&view=rev
Log:
[codeview] Make function names more consistent with MSVC

Names in function id records don't include nested name specifiers or
template arguments, but names in the symbol stream include both.

For the symbol stream, instead of having Clang put the fully qualified
name in the subprogram display name, recreate it from the subprogram
scope chain. For the type stream, take the unqualified name and chop of
any template arguments.

This makes it so that CodeView DI metadata is more similar to DWARF DI
metadata.

Modified:
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/test/DebugInfo/COFF/cpp-mangling.ll

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=273009&r1=273008&r2=273009&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Fri Jun 17 11:11:20 2016
@@ -135,7 +135,9 @@ TypeIndex CodeViewDebug::getFuncIdForSub
     return I->second;
 
   TypeIndex ParentScope = TypeIndex(0);
-  StringRef DisplayName = SP->getDisplayName();
+  // The display name includes function template arguments. Drop them to match
+  // MSVC.
+  StringRef DisplayName = SP->getDisplayName().split('<').first;
   FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName);
   TypeIndex TI = TypeTable.writeFuncId(FuncId);
 
@@ -453,6 +455,31 @@ void CodeViewDebug::switchToDebugSection
     emitCodeViewMagicVersion();
 }
 
+static const DISubprogram *getQualifiedNameComponents(
+    const DIScope *Scope, SmallVectorImpl<StringRef> &QualifiedNameComponents) {
+  const DISubprogram *ClosestSubprogram = nullptr;
+  while (Scope != nullptr) {
+    if (ClosestSubprogram == nullptr)
+      ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
+    StringRef ScopeName = Scope->getName();
+    if (!ScopeName.empty())
+      QualifiedNameComponents.push_back(ScopeName);
+    Scope = Scope->getScope().resolve();
+  }
+  return ClosestSubprogram;
+}
+
+static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents,
+                                    StringRef TypeName) {
+  std::string FullyQualifiedName;
+  for (StringRef QualifiedNameComponent : reverse(QualifiedNameComponents)) {
+    FullyQualifiedName.append(QualifiedNameComponent);
+    FullyQualifiedName.append("::");
+  }
+  FullyQualifiedName.append(TypeName);
+  return FullyQualifiedName;
+}
+
 void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
                                              FunctionInfo &FI) {
   // For each function there is a separate subsection
@@ -463,11 +490,18 @@ void CodeViewDebug::emitDebugInfoForFunc
   // Switch to the to a comdat section, if appropriate.
   switchToDebugSectionForSymbol(Fn);
 
-  StringRef FuncName;
+  std::string FuncName;
   auto *SP = GV->getSubprogram();
   setCurrentSubprogram(SP);
-  if (SP != nullptr)
-    FuncName = SP->getDisplayName();
+
+  // If we have a display name, build the fully qualified name by walking the
+  // chain of scopes.
+  if (SP != nullptr && !SP->getDisplayName().empty()) {
+    SmallVector<StringRef, 5> QualifiedNameComponents;
+    getQualifiedNameComponents(SP->getScope().resolve(),
+                               QualifiedNameComponents);
+    FuncName = getQualifiedName(QualifiedNameComponents, SP->getDisplayName());
+  }
 
   // If our DISubprogram name is empty, use the mangled name.
   if (FuncName.empty())
@@ -769,31 +803,6 @@ TypeIndex CodeViewDebug::lowerType(const
   }
 }
 
-static const DISubprogram *getQualifiedNameComponents(
-    const DIScope *Scope, SmallVectorImpl<StringRef> &QualifiedNameComponents) {
-  const DISubprogram *ClosestSubprogram = nullptr;
-  while (Scope != nullptr) {
-    if (ClosestSubprogram == nullptr)
-      ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
-    StringRef ScopeName = Scope->getName();
-    if (!ScopeName.empty())
-      QualifiedNameComponents.push_back(ScopeName);
-    Scope = Scope->getScope().resolve();
-  }
-  return ClosestSubprogram;
-}
-
-static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents,
-                                    StringRef TypeName) {
-  std::string FullyQualifiedName;
-  for (StringRef QualifiedNameComponent : reverse(QualifiedNameComponents)) {
-    FullyQualifiedName.append(QualifiedNameComponent);
-    FullyQualifiedName.append("::");
-  }
-  FullyQualifiedName.append(TypeName);
-  return FullyQualifiedName;
-}
-
 TypeIndex CodeViewDebug::lowerTypeAlias(const DIDerivedType *Ty) {
   DITypeRef UnderlyingTypeRef = Ty->getBaseType();
   TypeIndex UnderlyingTypeIndex = getTypeIndex(UnderlyingTypeRef);

Modified: llvm/trunk/test/DebugInfo/COFF/cpp-mangling.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/cpp-mangling.ll?rev=273009&r1=273008&r2=273009&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/cpp-mangling.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/cpp-mangling.ll Fri Jun 17 11:11:20 2016
@@ -1,55 +1,83 @@
-; RUN: llc -mcpu=core2 -mtriple=i686-pc-win32 -o - -O0 < %s \
-; RUN:   | llvm-mc -triple=i686-pc-win32 -filetype=obj \
-; RUN:   | llvm-readobj -s -sr -codeview -section-symbols | FileCheck %s
-
-; This LL file was generated by running clang on the following code:
-; D:\src.cpp:
-;  1 namespace foo {
-;  2 int bar(int x) {
-;  3   return x * 2;
-;  4 }
-;  5 }
+; RUN: llc -mcpu=core2 -mtriple=i686-pc-win32 -o - -O0 -filetype=obj < %s \
+; RUN:   | llvm-readobj -codeview | FileCheck %s
+
+; C++ source to regenerate:
+; namespace foo {
+; int bar(int x) { return x * 2; }
+; }
+; template <typename T, int (*)(int)>
+; void fn_tmpl() {}
+; template void fn_tmpl<int, foo::bar>();
+; void f() {
+;   fn_tmpl<int, foo::bar>();
+; }
+
+; CHECK:        ProcStart {
+; CHECK:         FunctionType: bar ({{.*}})
+; CHECK:         DisplayName: foo::bar{{$}}
+; CHECK-NEXT:    LinkageName: ?bar at foo@@YAHH at Z
 
 ; CHECK:        ProcStart {
-; CHECK:     DisplayName: foo::bar
-; CHECK-NEXT:     LinkageName: ?bar at foo@@YAHH at Z
+; CHECK:         FunctionType: fn_tmpl ({{.*}})
+; CHECK:         DisplayName: foo::fn_tmpl<int,&foo::bar>
+; CHECK-NEXT:    LinkageName: ??$fn_tmpl at H$1?bar at foo@@YAHH at Z@foo@@YAXXZ
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i386-pc-windows-msvc19.0.23918"
+
+$"\01??$fn_tmpl at H$1?bar at foo@@YAHH at Z@foo@@YAXXZ" = comdat any
 
-; Function Attrs: nounwind uwtable
-define i32 @"\01?bar at foo@@YAHH at Z"(i32 %x) #0 !dbg !4 {
+; Function Attrs: nounwind
+define i32 @"\01?bar at foo@@YAHH at Z"(i32 %x) #0 !dbg !6 {
 entry:
   %x.addr = alloca i32, align 4
   store i32 %x, i32* %x.addr, align 4
-  call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !13, metadata !14), !dbg !15
-  %0 = load i32, i32* %x.addr, align 4, !dbg !16
-  %mul = mul nsw i32 %0, 2, !dbg !17
-  ret i32 %mul, !dbg !18
+  call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !11, metadata !12), !dbg !13
+  %0 = load i32, i32* %x.addr, align 4, !dbg !14
+  %mul = mul nsw i32 %0, 2, !dbg !15
+  ret i32 %mul, !dbg !16
 }
 
 ; Function Attrs: nounwind readnone
 declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
 
-attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+; Function Attrs: nounwind
+define weak_odr void @"\01??$fn_tmpl at H$1?bar at foo@@YAHH at Z@foo@@YAXXZ"() #0 comdat !dbg !17 {
+entry:
+  ret void, !dbg !24
+}
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
 attributes #1 = { nounwind readnone }
 
 !llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!9, !10, !11}
-!llvm.ident = !{!12}
+!llvm.module.flags = !{!3, !4}
+!llvm.ident = !{!5}
 
-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 257652)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "t2.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
 !2 = !{}
-!4 = distinct !DISubprogram(name: "foo::bar", linkageName: "\01?bar at foo@@YAHH at Z", scope: !5, file: !1, line: 2, type: !6, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
-!5 = !DINamespace(name: "foo", scope: null, file: !1, line: 1)
-!6 = !DISubroutineType(types: !7)
-!7 = !{!8, !8}
-!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
-!9 = !{i32 2, !"CodeView", i32 1}
-!10 = !{i32 2, !"Debug Info Version", i32 3}
-!11 = !{i32 1, !"PIC Level", i32 2}
-!12 = !{!"clang version 3.9.0 (trunk 257652)"}
-!13 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !1, line: 2, type: !8)
-!14 = !DIExpression()
-!15 = !DILocation(line: 2, column: 13, scope: !4)
-!16 = !DILocation(line: 3, column: 10, scope: !4)
-!17 = !DILocation(line: 3, column: 12, scope: !4)
-!18 = !DILocation(line: 3, column: 3, scope: !4)
+!3 = !{i32 2, !"CodeView", i32 1}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{!"clang version 3.9.0 "}
+!6 = distinct !DISubprogram(name: "bar", linkageName: "\01?bar at foo@@YAHH at Z", scope: !7, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
+!7 = !DINamespace(name: "foo", scope: null, file: !1, line: 1)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !10}
+!10 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!11 = !DILocalVariable(name: "x", arg: 1, scope: !6, file: !1, line: 2, type: !10)
+!12 = !DIExpression()
+!13 = !DILocation(line: 2, column: 13, scope: !6)
+!14 = !DILocation(line: 2, column: 25, scope: !6)
+!15 = !DILocation(line: 2, column: 27, scope: !6)
+!16 = !DILocation(line: 2, column: 18, scope: !6)
+!17 = distinct !DISubprogram(name: "fn_tmpl<int,&foo::bar>", linkageName: "\01??$fn_tmpl at H$1?bar at foo@@YAHH at Z@foo@@YAXXZ", scope: !7, file: !1, line: 4, type: !18, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false, unit: !0, templateParams: !20, variables: !2)
+!18 = !DISubroutineType(types: !19)
+!19 = !{null}
+!20 = !{!21, !22}
+!21 = !DITemplateTypeParameter(name: "T", type: !10)
+!22 = !DITemplateValueParameter(type: !23, value: i32 (i32)* @"\01?bar at foo@@YAHH at Z")
+!23 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 32, align: 32)
+!24 = !DILocation(line: 4, column: 17, scope: !17)




More information about the llvm-commits mailing list