Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -187,8 +187,20 @@ // The UDTs we have seen while processing types; each entry is a pair of type // index and type name. - std::vector> LocalUDTs, - GlobalUDTs; + struct UDTRef { + explicit UDTRef(std::string Name, codeview::TypeIndex UnderlyingType) + : Name(std::move(Name)), UnderlyingType(UnderlyingType) {} + + std::string Name; + codeview::TypeIndex UnderlyingType; + bool HasStrongRef = false; + bool IsEmitted = false; + }; + std::vector LocalUDTs; + std::vector GlobalUDTs; + DenseMap> UDTLookup; + codeview::TypeIndex strongRef(const DIVariable *Var); + void strongTypeRef(DITypeRef Type); using FileToFilepathMapTy = std::map; FileToFilepathMapTy FileToFilepathMap; @@ -222,8 +234,7 @@ void emitDebugInfoForRetainedTypes(); - void emitDebugInfoForUDTs( - ArrayRef> UDTs); + void emitDebugInfoForUDTs(ArrayRef UDTs); void emitDebugInfoForGlobal(const DIGlobalVariable *DIGV, const GlobalVariable *GV, MCSymbol *GVSym); Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -20,9 +20,9 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/Triple.h" @@ -66,8 +66,9 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/SMLoc.h" +#include "llvm/Support/ScopedPrinter.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" @@ -1104,6 +1105,10 @@ if (Ty->getName().empty()) return; + // Don't record UDTs that have already been recorded. + if (UDTLookup.find(TI) != UDTLookup.end()) + return; + SmallVector QualifiedNameComponents; const DISubprogram *ClosestSubprogram = getQualifiedNameComponents( Ty->getScope().resolve(), QualifiedNameComponents); @@ -1111,10 +1116,13 @@ std::string FullyQualifiedName = getQualifiedName(QualifiedNameComponents, getPrettyScopeName(Ty)); + auto UDT = llvm::make_unique(std::move(FullyQualifiedName), TI); + UDTRef *PtrUdt = UDT.get(); + UDTLookup[TI] = std::move(UDT); if (ClosestSubprogram == nullptr) - GlobalUDTs.emplace_back(std::move(FullyQualifiedName), TI); + GlobalUDTs.push_back(PtrUdt); else if (ClosestSubprogram == CurrentSubprogram) - LocalUDTs.emplace_back(std::move(FullyQualifiedName), TI); + LocalUDTs.push_back(PtrUdt); // TODO: What if the ClosestSubprogram is neither null or the current // subprogram? Currently, the UDT just gets dropped on the floor. @@ -1124,6 +1132,36 @@ // and then make LocalUDTs a member of FunctionInfo } +codeview::TypeIndex CodeViewDebug::strongRef(const DIVariable *Var) { + // Make sure to call getCompleteTypeIndex first so that the entire type + // hierarchy is lowered. + DITypeRef Ref = Var->getType(); + strongTypeRef(Ref); + + return getCompleteTypeIndex(Ref); +} + +void CodeViewDebug::strongTypeRef(DITypeRef Type) { + TypeIndex Result = getCompleteTypeIndex(Type); + const DIType *Ty = Type.resolve(); + if (!Ty) + return; + + auto Iter = UDTLookup.find(Result); + if (Iter != UDTLookup.end()) + Iter->second->HasStrongRef = true; + + if (auto DT = dyn_cast(Ty)) { + strongTypeRef(DT->getBaseType()); + strongTypeRef(DT->getClassType()); + } else if (auto CT = dyn_cast(Ty)) { + strongTypeRef(CT->getBaseType()); + } else if (auto ST = dyn_cast(Ty)) { + for (DITypeRef Arg : ST->getTypeArray()) + strongTypeRef(Arg); + } +} + TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) { // Generic dispatch for lowering an unknown type. switch (Ty->getTag()) { @@ -2022,7 +2060,6 @@ default: llvm_unreachable("not a record"); } - InsertResult.first->second = TI; return TI; } @@ -2078,8 +2115,7 @@ Flags |= LocalSymFlags::IsOptimizedOut; OS.AddComment("TypeIndex"); - TypeIndex TI = getCompleteTypeIndex(Var.DIVar->getType()); - OS.EmitIntValue(TI.getIndex(), 4); + OS.EmitIntValue(strongRef(Var.DIVar).getIndex(), 4); OS.AddComment("Flags"); OS.EmitIntValue(static_cast(Flags), 2); // Truncate the name so we won't overflow the record length field. @@ -2202,9 +2238,15 @@ OS.EmitValueToAlignment(4); } -void CodeViewDebug::emitDebugInfoForUDTs( - ArrayRef> UDTs) { - for (const std::pair &UDT : UDTs) { +void CodeViewDebug::emitDebugInfoForUDTs(ArrayRef UDTs) { + llvm::DenseSet EmittedUDTs; + for (UDTRef *UDT : UDTs) { + if (!UDT->HasStrongRef) + continue; + + assert(!UDT->IsEmitted); + assert(EmittedUDTs.find(UDT->UnderlyingType) == EmittedUDTs.end()); + MCSymbol *UDTRecordBegin = MMI->getContext().createTempSymbol(), *UDTRecordEnd = MMI->getContext().createTempSymbol(); OS.AddComment("Record length"); @@ -2215,10 +2257,13 @@ OS.EmitIntValue(unsigned(SymbolKind::S_UDT), 2); OS.AddComment("Type"); - OS.EmitIntValue(UDT.second.getIndex(), 4); + OS.EmitIntValue(UDT->UnderlyingType.getIndex(), 4); - emitNullTerminatedSymbolName(OS, UDT.first); + emitNullTerminatedSymbolName(OS, UDT->Name); OS.EmitLabel(UDTRecordEnd); + + EmittedUDTs.insert(UDT->UnderlyingType); + UDT->IsEmitted = true; } } @@ -2314,7 +2359,7 @@ } } OS.AddComment("Type"); - OS.EmitIntValue(getCompleteTypeIndex(DIGV->getType()).getIndex(), 4); + OS.EmitIntValue(strongRef(DIGV).getIndex(), 4); OS.AddComment("DataOffset"); OS.EmitCOFFSecRel32(GVSym, /*Offset=*/0); OS.AddComment("Segment"); Index: llvm/test/DebugInfo/COFF/udts.ll =================================================================== --- llvm/test/DebugInfo/COFF/udts.ll +++ llvm/test/DebugInfo/COFF/udts.ll @@ -5,33 +5,56 @@ ; C++ source to regenerate: ; $ cat t.cpp ; void f() { -; typedef int FOO; +; typedef int FOO; // Referenced by local -> S_UDT +; typedef int BAR; // Unreferenced -> no S_UDT ; FOO f; ; } ; -; struct S { int x; }; -; float g(S *s) { +; struct S { +; typedef int SREF; // Referenced by a member variable -> S_UDT +; typedef int UREF; // Unreferenced -> no S_UDT +; typedef float RREF; // Referenced by function return value -> no S_UDT +; RREF foo() { return 7.0f; } +; SREF x; +; }; +; float g(S *s) { // Referenced by pointer -> S_UDT ; union pun { int x; float f; } p; ; p.x = s->x; -; return p.f; +; return p.f + s->foo(); ; } +; +; // Referenced by global variable -> S_UDT ; typedef struct { int x; } U; ; U u; +; +; // Unreferenced -> no S_UDT +; struct V { +; int x; +; }; +; +; struct W { +; int x; +; }; +; +; typedef W* PTR; +; void h(PTR p) {} +; -; CHECK: {{.*}}Proc{{.*}}Sym { +; CHECK: GlobalProcIdSym { ; CHECK: DisplayName: f ; CHECK: LinkageName: ?f@@YAXXZ ; CHECK: } ; CHECK: UDTSym { +; CHECK-NOT: UDTName: f::BAR ; CHECK-NEXT: Kind: S_UDT (0x1108) ; CHECK-NEXT: Type: int (0x74) ; CHECK-NEXT: UDTName: f::FOO ; CHECK-NEXT: } ; CHECK-NEXT: ProcEnd { -; CHECK: {{.*}}Proc{{.*}}Sym { +; CHECK: GlobalProcIdSym { ; CHECK: DisplayName: g -; CHECK: LinkageName: ?g@@YAMPEAUS@@@Z +; CHECK: LinkageName: ?g@@YAMPAUS@@@Z ; CHECK: } ; CHECK: UDTSym { ; CHECK-NEXT: Kind: S_UDT (0x1108) @@ -41,102 +64,174 @@ ; CHECK-NEXT: ProcEnd { ; CHECK: Subsection +; CHECK: SubSectionType: Symbols +; CHECK: GlobalProcIdSym +; CHECK: LinkageName: ?h@@YAXPAUW@@@Z + ; CHECK-NOT: {{.*}}Proc{{.*}}Sym + +; CHECK: Subsection +; CHECK: SubSectionType: Symbols +; CHECK: GlobalData +; CHECK: LinkageName: ?u@@3UU@@A + +; CHECK: Subsection ; CHECK: UDTSym { ; CHECK-NEXT: Kind: S_UDT (0x1108) -; CHECK-NEXT: Type: S (0x{{[0-9A-F]+}}) -; CHECK-NEXT: UDTName: S -; CHECK: UDTSym { +; CHECK-NEXT: Type: S (0x1009) +; CHECK-NEXT: UDTName: S +; CHECK-NEXT: } +; CHECK-NEXT: UDTSym { +; CHECK-NEXT: Kind: S_UDT (0x1108) +; CHECK-NEXT: Type: W* (0x1013) +; CHECK-NEXT: UDTName: PTR +; CHECK-NEXT: } +; CHECK-NEXT: UDTSym { ; CHECK-NEXT: Kind: S_UDT (0x1108) -; CHECK-NEXT: Type: (0x{{[0-9A-F]+}}) -; CHECK-NEXT: UDTName: U -; CHECK-NOT: UDTSym { +; CHECK-NEXT: Type: U (0x1017) +; CHECK-NEXT: UDTName: U +; CHECK-NEXT: } +; CHECK-NOT: UDTSym + +; 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 = "i686-pc-windows-msvc19.11.25506" %struct.U = type { i32 } %struct.S = type { i32 } %union.pun = type { i32 } +%struct.W = type { i32 } + +$"\01?foo@S@@QAEMXZ" = comdat any @"\01?u@@3UU@@A" = global %struct.U zeroinitializer, align 4, !dbg !0 -; Function Attrs: nounwind uwtable -define void @"\01?f@@YAXXZ"() #0 !dbg !15 { +; Function Attrs: noinline nounwind optnone +define void @"\01?f@@YAXXZ"() #0 !dbg !16 { entry: %f = alloca i32, align 4 - call void @llvm.dbg.declare(metadata i32* %f, metadata !18, metadata !20), !dbg !21 - ret void, !dbg !22 + call void @llvm.dbg.declare(metadata i32* %f, metadata !19, metadata !21), !dbg !22 + ret void, !dbg !23 } -; Function Attrs: nounwind readnone +; Function Attrs: nounwind readnone speculatable declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 -; Function Attrs: nounwind uwtable -define float @"\01?g@@YAMPEAUS@@@Z"(%struct.S* %s) #0 !dbg !23 { +; Function Attrs: noinline optnone +define float @"\01?g@@YAMPAUS@@@Z"(%struct.S* %s) #2 !dbg !24 { entry: - %s.addr = alloca %struct.S*, align 8 + %s.addr = alloca %struct.S*, align 4 %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 !31, metadata !20), !dbg !32 - call void @llvm.dbg.declare(metadata %union.pun* %p, metadata !33, metadata !20), !dbg !38 - %0 = load %struct.S*, %struct.S** %s.addr, align 8, !dbg !39 - %x = getelementptr inbounds %struct.S, %struct.S* %0, i32 0, i32 0, !dbg !40 - %1 = load i32, i32* %x, align 4, !dbg !40 - %x1 = bitcast %union.pun* %p to i32*, !dbg !41 - store i32 %1, i32* %x1, align 4, !dbg !42 - %f = bitcast %union.pun* %p to float*, !dbg !43 - %2 = load float, float* %f, align 4, !dbg !43 - ret float %2, !dbg !44 + store %struct.S* %s, %struct.S** %s.addr, align 4 + call void @llvm.dbg.declare(metadata %struct.S** %s.addr, metadata !39, metadata !21), !dbg !40 + call void @llvm.dbg.declare(metadata %union.pun* %p, metadata !41, metadata !21), !dbg !46 + %0 = load %struct.S*, %struct.S** %s.addr, align 4, !dbg !47 + %x = getelementptr inbounds %struct.S, %struct.S* %0, i32 0, i32 0, !dbg !48 + %1 = load i32, i32* %x, align 4, !dbg !48 + %x1 = bitcast %union.pun* %p to i32*, !dbg !49 + store i32 %1, i32* %x1, align 4, !dbg !50 + %f = bitcast %union.pun* %p to float*, !dbg !51 + %2 = load float, float* %f, align 4, !dbg !51 + %3 = load %struct.S*, %struct.S** %s.addr, align 4, !dbg !52 + %call = call x86_thiscallcc float @"\01?foo@S@@QAEMXZ"(%struct.S* %3), !dbg !53 + %add = fadd float %2, %call, !dbg !54 + ret float %add, !dbg !55 +} + +; Function Attrs: noinline nounwind optnone +define linkonce_odr x86_thiscallcc float @"\01?foo@S@@QAEMXZ"(%struct.S* %this) #0 comdat align 2 !dbg !56 { +entry: + %this.addr = alloca %struct.S*, align 4 + store %struct.S* %this, %struct.S** %this.addr, align 4 + call void @llvm.dbg.declare(metadata %struct.S** %this.addr, metadata !57, metadata !21), !dbg !58 + %this1 = load %struct.S*, %struct.S** %this.addr, align 4 + ret float 7.000000e+00, !dbg !59 +} + +; Function Attrs: noinline nounwind optnone +define void @"\01?h@@YAXPAUW@@@Z"(%struct.W* %p) #0 !dbg !60 { +entry: + %p.addr = alloca %struct.W*, align 4 + store %struct.W* %p, %struct.W** %p.addr, align 4 + call void @llvm.dbg.declare(metadata %struct.W** %p.addr, metadata !66, metadata !21), !dbg !67 + ret void, !dbg !68 } -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 } +attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "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" "no-signed-zeros-fp-math"="false" "no-trapping-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 speculatable } +attributes #2 = { noinline optnone "correctly-rounded-divide-sqrt-fp-math"="false" "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" "no-signed-zeros-fp-math"="false" "no-trapping-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" } !llvm.dbg.cu = !{!2} -!llvm.module.flags = !{!11, !12, !13} -!llvm.ident = !{!14} +!llvm.module.flags = !{!11, !12, !13, !14} +!llvm.ident = !{!15} -!0 = distinct !DIGlobalVariableExpression(var: !1) -!1 = !DIGlobalVariable(name: "u", linkageName: "\01?u@@3UU@@A", scope: !2, file: !3, line: 13, type: !6, isLocal: false, isDefinition: true) -!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 3.9.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) -!3 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild") +!0 = !DIGlobalVariableExpression(var: !1) +!1 = distinct !DIGlobalVariable(name: "u", linkageName: "\01?u@@3UU@@A", scope: !2, file: !3, line: 22, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 6.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) +!3 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvmbuild\5Cninja", checksumkind: CSK_MD5, checksum: "09e294c28bef47c70c41b94dcac823a3") !4 = !{} !5 = !{!0} -!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "U", file: !3, line: 12, baseType: !7) -!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !3, line: 12, size: 32, align: 32, elements: !8, identifier: ".?AUU@@") +!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "U", file: !3, line: 21, baseType: !7) +!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "U", file: !3, line: 21, size: 32, elements: !8, identifier: ".?AUU@@") !8 = !{!9} -!9 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !7, file: !3, line: 12, baseType: !10, size: 32, align: 32) -!10 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) -!11 = !{i32 2, !"CodeView", i32 1} -!12 = !{i32 2, !"Debug Info Version", i32 3} -!13 = !{i32 1, !"PIC Level", i32 2} -!14 = !{!"clang version 3.9.0 "} -!15 = distinct !DISubprogram(name: "f", linkageName: "\01?f@@YAXXZ", scope: !3, file: !3, line: 1, type: !16, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !2, variables: !4) -!16 = !DISubroutineType(types: !17) -!17 = !{null} -!18 = !DILocalVariable(name: "f", scope: !15, file: !3, line: 3, type: !19) -!19 = !DIDerivedType(tag: DW_TAG_typedef, name: "FOO", scope: !15, file: !3, line: 2, baseType: !10) -!20 = !DIExpression() -!21 = !DILocation(line: 3, column: 7, scope: !15) -!22 = !DILocation(line: 4, column: 1, scope: !15) -!23 = distinct !DISubprogram(name: "g", linkageName: "\01?g@@YAMPEAUS@@@Z", scope: !3, file: !3, line: 7, type: !24, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: false, unit: !2, variables: !4) -!24 = !DISubroutineType(types: !25) -!25 = !{!26, !27} -!26 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float) -!27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !28, size: 64, align: 64) -!28 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !3, line: 6, size: 32, align: 32, elements: !29, identifier: ".?AUS@@") -!29 = !{!30} -!30 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !28, file: !3, line: 6, baseType: !10, size: 32, align: 32) -!31 = !DILocalVariable(name: "s", arg: 1, scope: !23, file: !3, line: 7, type: !27) -!32 = !DILocation(line: 7, column: 12, scope: !23) -!33 = !DILocalVariable(name: "p", scope: !23, file: !3, line: 8, type: !34) -!34 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "pun", scope: !23, file: !3, line: 8, size: 32, align: 32, elements: !35) -!35 = !{!36, !37} -!36 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !34, file: !3, line: 8, baseType: !10, size: 32, align: 32) -!37 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !34, file: !3, line: 8, baseType: !26, size: 32, align: 32) -!38 = !DILocation(line: 8, column: 33, scope: !23) -!39 = !DILocation(line: 9, column: 9, scope: !23) -!40 = !DILocation(line: 9, column: 12, scope: !23) -!41 = !DILocation(line: 9, column: 5, scope: !23) -!42 = !DILocation(line: 9, column: 7, scope: !23) -!43 = !DILocation(line: 10, column: 12, scope: !23) -!44 = !DILocation(line: 10, column: 3, scope: !23) - +!9 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !7, file: !3, line: 21, baseType: !10, size: 32) +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{i32 1, !"NumRegisterParameters", i32 0} +!12 = !{i32 2, !"CodeView", i32 1} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"wchar_size", i32 2} +!15 = !{!"clang version 6.0.0 "} +!16 = distinct !DISubprogram(name: "f", linkageName: "\01?f@@YAXXZ", scope: !3, file: !3, line: 1, type: !17, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !2, variables: !4) +!17 = !DISubroutineType(types: !18) +!18 = !{null} +!19 = !DILocalVariable(name: "f", scope: !16, file: !3, line: 4, type: !20) +!20 = !DIDerivedType(tag: DW_TAG_typedef, name: "FOO", scope: !16, file: !3, line: 2, baseType: !10) +!21 = !DIExpression() +!22 = !DILocation(line: 4, column: 7, scope: !16) +!23 = !DILocation(line: 5, column: 1, scope: !16) +!24 = distinct !DISubprogram(name: "g", linkageName: "\01?g@@YAMPAUS@@@Z", scope: !3, file: !3, line: 14, type: !25, isLocal: false, isDefinition: true, scopeLine: 14, flags: DIFlagPrototyped, isOptimized: false, unit: !2, variables: !4) +!25 = !DISubroutineType(types: !26) +!26 = !{!27, !28} +!27 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !29, size: 32) +!29 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !3, line: 7, size: 32, elements: !30, identifier: ".?AUS@@") +!30 = !{!31, !32, !33, !34, !35} +!31 = !DIDerivedType(tag: DW_TAG_typedef, name: "SREF", scope: !29, file: !3, line: 8, baseType: !10) +!32 = !DIDerivedType(tag: DW_TAG_typedef, name: "UREF", scope: !29, file: !3, line: 9, baseType: !10) +!33 = !DIDerivedType(tag: DW_TAG_typedef, name: "RREF", scope: !29, file: !3, line: 10, baseType: !27) +!34 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !29, file: !3, line: 12, baseType: !31, size: 32) +!35 = !DISubprogram(name: "foo", linkageName: "\01?foo@S@@QAEMXZ", scope: !29, file: !3, line: 11, type: !36, isLocal: false, isDefinition: false, scopeLine: 11, flags: DIFlagPrototyped, isOptimized: false) +!36 = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: !37) +!37 = !{!33, !38} +!38 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !29, size: 32, flags: DIFlagArtificial | DIFlagObjectPointer) +!39 = !DILocalVariable(name: "s", arg: 1, scope: !24, file: !3, line: 14, type: !28) +!40 = !DILocation(line: 14, column: 12, scope: !24) +!41 = !DILocalVariable(name: "p", scope: !24, file: !3, line: 15, type: !42) +!42 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "pun", scope: !24, file: !3, line: 15, size: 32, elements: !43) +!43 = !{!44, !45} +!44 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !42, file: !3, line: 15, baseType: !10, size: 32) +!45 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !42, file: !3, line: 15, baseType: !27, size: 32) +!46 = !DILocation(line: 15, column: 33, scope: !24) +!47 = !DILocation(line: 16, column: 9, scope: !24) +!48 = !DILocation(line: 16, column: 12, scope: !24) +!49 = !DILocation(line: 16, column: 5, scope: !24) +!50 = !DILocation(line: 16, column: 7, scope: !24) +!51 = !DILocation(line: 17, column: 12, scope: !24) +!52 = !DILocation(line: 17, column: 16, scope: !24) +!53 = !DILocation(line: 17, column: 19, scope: !24) +!54 = !DILocation(line: 17, column: 14, scope: !24) +!55 = !DILocation(line: 17, column: 3, scope: !24) +!56 = distinct !DISubprogram(name: "foo", linkageName: "\01?foo@S@@QAEMXZ", scope: !29, file: !3, line: 11, type: !36, isLocal: false, isDefinition: true, scopeLine: 11, flags: DIFlagPrototyped, isOptimized: false, unit: !2, declaration: !35, variables: !4) +!57 = !DILocalVariable(name: "this", arg: 1, scope: !56, type: !28, flags: DIFlagArtificial | DIFlagObjectPointer) +!58 = !DILocation(line: 0, scope: !56) +!59 = !DILocation(line: 11, column: 16, scope: !56) +!60 = distinct !DISubprogram(name: "h", linkageName: "\01?h@@YAXPAUW@@@Z", scope: !3, file: !3, line: 35, type: !61, isLocal: false, isDefinition: true, scopeLine: 35, flags: DIFlagPrototyped, isOptimized: false, unit: !2, variables: !4) +!61 = !DISubroutineType(types: !62) +!62 = !{null, !63} +!63 = !DIDerivedType(tag: DW_TAG_typedef, name: "PTR", file: !3, line: 34, baseType: !64) +!64 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !65, size: 32) +!65 = !DICompositeType(tag: DW_TAG_structure_type, name: "W", file: !3, line: 30, flags: DIFlagFwdDecl, identifier: ".?AUW@@") +!66 = !DILocalVariable(name: "p", arg: 1, scope: !60, file: !3, line: 35, type: !63) +!67 = !DILocation(line: 35, column: 12, scope: !60) +!68 = !DILocation(line: 35, column: 16, scope: !60)