Index: lib/CodeGen/AsmPrinter/CodeViewDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -230,6 +230,8 @@ codeview::TypeIndex getScopeIndex(const DIScope *Scope); + void addToUDTs(const DIType *Ty, codeview::TypeIndex TI); + codeview::TypeIndex lowerType(const DIType *Ty, const DIType *ClassTy); codeview::TypeIndex lowerTypeAlias(const DIDerivedType *Ty); codeview::TypeIndex lowerTypeArray(const DICompositeType *Ty); Index: lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -829,6 +829,27 @@ } } +void CodeViewDebug::addToUDTs(const DIType *Ty, TypeIndex TI) { + SmallVector QualifiedNameComponents; + const DISubprogram *ClosestSubprogram = getQualifiedNameComponents( + Ty->getScope().resolve(), QualifiedNameComponents); + + std::string FullyQualifiedName = + getQualifiedName(QualifiedNameComponents, Ty->getName()); + + if (ClosestSubprogram == nullptr) + GlobalUDTs.emplace_back(std::move(FullyQualifiedName), TI); + else if (ClosestSubprogram == CurrentSubprogram) + LocalUDTs.emplace_back(std::move(FullyQualifiedName), TI); + + // TODO: What if the ClosestSubprogram is neither null or the current + // subprogram? Currently, the UDT just gets dropped on the floor. + // + // The current behavior is not desirable. To get maximal fidelity, we would + // need to perform all type translation before beginning emission of .debug$S + // and then make LocalUDTs a member of FunctionInfo +} + TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) { // Generic dispatch for lowering an unknown type. switch (Ty->getTag()) { @@ -873,25 +894,7 @@ TypeIndex UnderlyingTypeIndex = getTypeIndex(UnderlyingTypeRef); StringRef TypeName = Ty->getName(); - SmallVector QualifiedNameComponents; - const DISubprogram *ClosestSubprogram = getQualifiedNameComponents( - Ty->getScope().resolve(), QualifiedNameComponents); - - if (ClosestSubprogram == nullptr) { - std::string FullyQualifiedName = - getQualifiedName(QualifiedNameComponents, TypeName); - GlobalUDTs.emplace_back(std::move(FullyQualifiedName), UnderlyingTypeIndex); - } else if (ClosestSubprogram == CurrentSubprogram) { - std::string FullyQualifiedName = - getQualifiedName(QualifiedNameComponents, TypeName); - LocalUDTs.emplace_back(std::move(FullyQualifiedName), UnderlyingTypeIndex); - } - // TODO: What if the ClosestSubprogram is neither null or the current - // subprogram? Currently, the UDT just gets dropped on the floor. - // - // The current behavior is not desirable. To get maximal fidelity, we would - // need to perform all type translation before beginning emission of .debug$S - // and then make LocalUDTs a member of FunctionInfo + addToUDTs(Ty, UnderlyingTypeIndex); if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) && TypeName == "HRESULT") @@ -899,6 +902,7 @@ if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) && TypeName == "wchar_t") return TypeIndex(SimpleTypeKind::WideCharacter); + return UnderlyingTypeIndex; } @@ -1419,6 +1423,8 @@ TypeIndex(0x0), getFullFilepath(Ty->getFile()))), Ty->getLine())); + addToUDTs(Ty, ClassTI); + return ClassTI; } @@ -1453,6 +1459,8 @@ TypeIndex(0x0), getFullFilepath(Ty->getFile()))), Ty->getLine())); + addToUDTs(Ty, UnionTI); + return UnionTI; } Index: test/DebugInfo/COFF/udts.ll =================================================================== --- test/DebugInfo/COFF/udts.ll +++ test/DebugInfo/COFF/udts.ll @@ -8,6 +8,13 @@ ; typedef int FOO; ; FOO f; ; } +; +; struct S { int x; }; +; float g(S *s) { +; union pun { int x; float f; } p; +; p.x = s->x; +; return p.f; +; } ; CHECK: ProcStart { ; CHECK: DisplayName: f @@ -20,9 +27,29 @@ ; CHECK-NEXT: ProcEnd { ; CHECK-NEXT: } +; CHECK: ProcStart { +; CHECK: DisplayName: g +; CHECK: LinkageName: ?g@@YAMPEAUS@@@Z +; CHECK: } +; CHECK: UDT { +; CHECK-NEXT: Type: g::pun (0x{{[0-9A-F]+}}) +; CHECK-NEXT: UDTName: g::pun +; CHECK-NEXT: } +; CHECK-NEXT: ProcEnd { +; CHECK-NEXT: } + +; CHECK: Subsection +; CHECK-NOT: ProcStart +; CHECK: UDT { +; CHECK-NEXT: Type: S (0x{{[0-9A-F]+}}) +; CHECK-NEXT: UDTName: S + + +%struct.S = type { i32 } +%union.pun = type { i32 } -; Function Attrs: nounwind -define void @"\01?f@@YAXXZ"() #0 !dbg !6 { +; Function Attrs: nounwind uwtable +define void @"\01?f@@YAXXZ"() #0 !dbg !7 { entry: %f = alloca i32, align 4 call void @llvm.dbg.declare(metadata i32* %f, metadata !10, metadata !13), !dbg !14 @@ -32,26 +59,66 @@ ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 -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" } +; Function Attrs: nounwind uwtable +define float @"\01?g@@YAMPEAUS@@@Z"(%struct.S* %s) #0 !dbg !16 { +entry: + %s.addr = alloca %struct.S*, align 8 + %p = alloca %union.pun, align 4 + store %struct.S* %s, %struct.S** %s.addr, align 8 + call void @llvm.dbg.declare(metadata %struct.S** %s.addr, metadata !24, metadata !13), !dbg !25 + call void @llvm.dbg.declare(metadata %union.pun* %p, metadata !26, metadata !13), !dbg !31 + %0 = load %struct.S*, %struct.S** %s.addr, align 8, !dbg !32 + %x = getelementptr inbounds %struct.S, %struct.S* %0, i32 0, i32 0, !dbg !33 + %1 = load i32, i32* %x, align 4, !dbg !33 + %x1 = bitcast %union.pun* %p to i32*, !dbg !34 + store i32 %1, i32* %x1, align 4, !dbg !35 + %f = bitcast %union.pun* %p to float*, !dbg !36 + %2 = load float, float* %f, align 4, !dbg !36 + ret float %2, !dbg !37 +} + +attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "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 = !{!3, !4} -!llvm.ident = !{!5} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 272079) (llvm/trunk 271895)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) -!1 = !DIFile(filename: "-", directory: "/usr/local/src") +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 273566) (llvm/trunk 273570)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "t.cpp", directory: "/usr/local/google/work/llvm/build.release") !2 = !{} !3 = !{i32 2, !"CodeView", i32 1} !4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = !{!"clang version 3.9.0 (trunk 272079) (llvm/trunk 271895)"} -!6 = distinct !DISubprogram(name: "f", linkageName: "\01?f@@YAXXZ", scope: !7, file: !7, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) -!7 = !DIFile(filename: "", directory: "/usr/local/src") +!5 = !{i32 1, !"PIC Level", i32 2} +!6 = !{!"clang version 3.9.0 (trunk 273566) (llvm/trunk 273570)"} +!7 = distinct !DISubprogram(name: "f", linkageName: "\01?f@@YAXXZ", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) !8 = !DISubroutineType(types: !9) !9 = !{null} -!10 = !DILocalVariable(name: "f", scope: !6, file: !7, line: 4, type: !11) -!11 = !DIDerivedType(tag: DW_TAG_typedef, name: "FOO", scope: !6, file: !7, line: 3, baseType: !12) +!10 = !DILocalVariable(name: "f", scope: !7, file: !1, line: 3, type: !11) +!11 = !DIDerivedType(tag: DW_TAG_typedef, name: "FOO", scope: !7, file: !1, line: 2, baseType: !12) !12 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !13 = !DIExpression() -!14 = !DILocation(line: 4, column: 5, scope: !6) -!15 = !DILocation(line: 5, column: 1, scope: !6) +!14 = !DILocation(line: 3, column: 7, scope: !7) +!15 = !DILocation(line: 4, column: 1, scope: !7) +!16 = distinct !DISubprogram(name: "g", linkageName: "\01?g@@YAMPEAUS@@@Z", scope: !1, file: !1, line: 7, type: !17, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!17 = !DISubroutineType(types: !18) +!18 = !{!19, !20} +!19 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float) +!20 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !21, size: 64, align: 64) +!21 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !1, line: 6, size: 32, align: 32, elements: !22, identifier: ".?AUS@@") +!22 = !{!23} +!23 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !21, file: !1, line: 6, baseType: !12, size: 32, align: 32) +!24 = !DILocalVariable(name: "s", arg: 1, scope: !16, file: !1, line: 7, type: !20) +!25 = !DILocation(line: 7, column: 12, scope: !16) +!26 = !DILocalVariable(name: "p", scope: !16, file: !1, line: 8, type: !27) +!27 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "pun", scope: !16, file: !1, line: 8, size: 32, align: 32, elements: !28) +!28 = !{!29, !30} +!29 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !27, file: !1, line: 8, baseType: !12, size: 32, align: 32) +!30 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !27, file: !1, line: 8, baseType: !19, size: 32, align: 32) +!31 = !DILocation(line: 8, column: 33, scope: !16) +!32 = !DILocation(line: 9, column: 9, scope: !16) +!33 = !DILocation(line: 9, column: 12, scope: !16) +!34 = !DILocation(line: 9, column: 5, scope: !16) +!35 = !DILocation(line: 9, column: 7, scope: !16) +!36 = !DILocation(line: 10, column: 12, scope: !16) +!37 = !DILocation(line: 10, column: 3, scope: !16)