From: Reid Kleckner Date: Wed, 22 Jun 2016 01:32:56 +0000 (+0000) Subject: [codeview] Improve names of types in scopes and member function ids X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=41bcea90ec2d7ccd0360b4f03f9766b62189d1ab;p=llvm [codeview] Improve names of types in scopes and member function ids We now include namespace scope info in LF_FUNC_ID records and we emit LF_MFUNC_ID records for member functions as we should. Class names are now fully qualified, which is what MSVC does. Add a little bit of scaffolding to handle ThisAdjustment when it arrives in DISubprogram. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@273358 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 62509b6ebb2..9163e3b4c15 100644 --- a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -123,6 +123,57 @@ CodeViewDebug::getInlineSite(const DILocation *InlinedAt, return *Site; } +static const DISubprogram *getQualifiedNameComponents( + const DIScope *Scope, SmallVectorImpl &QualifiedNameComponents) { + const DISubprogram *ClosestSubprogram = nullptr; + while (Scope != nullptr) { + if (ClosestSubprogram == nullptr) + ClosestSubprogram = dyn_cast(Scope); + StringRef ScopeName = Scope->getName(); + if (!ScopeName.empty()) + QualifiedNameComponents.push_back(ScopeName); + Scope = Scope->getScope().resolve(); + } + return ClosestSubprogram; +} + +static std::string getQualifiedName(ArrayRef QualifiedNameComponents, + StringRef TypeName) { + std::string FullyQualifiedName; + for (StringRef QualifiedNameComponent : reverse(QualifiedNameComponents)) { + FullyQualifiedName.append(QualifiedNameComponent); + FullyQualifiedName.append("::"); + } + FullyQualifiedName.append(TypeName); + return FullyQualifiedName; +} + +static std::string getFullyQualifiedName(const DIScope *Scope, StringRef Name) { + SmallVector QualifiedNameComponents; + getQualifiedNameComponents(Scope, QualifiedNameComponents); + return getQualifiedName(QualifiedNameComponents, Name); +} + +TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) { + // No scope means global scope and that uses the zero index. + if (!Scope || isa(Scope)) + return TypeIndex(); + + assert(!isa(Scope) && "shouldn't make a namespace scope for a type"); + + // Check if we've already translated this scope. + auto I = TypeIndices.find({Scope, nullptr}); + if (I != TypeIndices.end()) + return I->second; + + // Build the fully qualified name of the scope. + std::string ScopeName = + getFullyQualifiedName(Scope->getScope().resolve(), Scope->getName()); + TypeIndex TI = + TypeTable.writeStringId(StringIdRecord(TypeIndex(), ScopeName)); + return recordTypeIndexForDINode(Scope, TI); +} + TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) { // It's possible to ask for the FuncId of a function which doesn't have a // subprogram: inlining a function with debug info into a function with none. @@ -134,22 +185,51 @@ TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) { if (I != TypeIndices.end()) return I->second; - TypeIndex ParentScope = TypeIndex(0); // The display name includes function template arguments. Drop them to match // MSVC. StringRef DisplayName = SP->getDisplayName().split('<').first; - FuncIdRecord FuncId(ParentScope, lowerSubprogramType(SP), DisplayName); - TypeIndex TI = TypeTable.writeFuncId(FuncId); - recordTypeIndexForDINode(SP, TI); - return TI; + const DIScope *Scope = SP->getScope().resolve(); + TypeIndex TI; + if (const auto *Class = dyn_cast_or_null(Scope)) { + // If the scope is a DICompositeType, then this must be a method. Member + // function types take some special handling, and require access to the + // subprogram. + TypeIndex ClassType = getTypeIndex(Class); + MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class), + DisplayName); + TI = TypeTable.writeMemberFuncId(MFuncId); + } else { + // Otherwise, this must be a free function. + TypeIndex ParentScope = getScopeIndex(Scope); + FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName); + TI = TypeTable.writeFuncId(FuncId); + } + + return recordTypeIndexForDINode(SP, TI); } -void CodeViewDebug::recordTypeIndexForDINode(const DINode *Node, TypeIndex TI, +TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP, + const DICompositeType *Class) { + // Key the MemberFunctionRecord into the map as {SP, Class}. It won't collide + // with the MemberFuncIdRecord, which is keyed in as {SP, nullptr}. + auto I = TypeIndices.find({SP, nullptr}); + if (I != TypeIndices.end()) + return I->second; + + // FIXME: Get the ThisAdjustment off of SP when it is available. + TypeIndex TI = + lowerTypeMemberFunction(SP->getType(), Class, /*ThisAdjustment=*/0); + + return recordTypeIndexForDINode(SP, TI, Class); +} + +TypeIndex CodeViewDebug::recordTypeIndexForDINode(const DINode *Node, TypeIndex TI, const DIType *ClassTy) { auto InsertResult = TypeIndices.insert({{Node, ClassTy}, TI}); (void)InsertResult; assert(InsertResult.second && "DINode was already assigned a type index"); + return TI; } unsigned CodeViewDebug::getPointerSizeInBytes() { @@ -458,31 +538,6 @@ void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) { emitCodeViewMagicVersion(); } -static const DISubprogram *getQualifiedNameComponents( - const DIScope *Scope, SmallVectorImpl &QualifiedNameComponents) { - const DISubprogram *ClosestSubprogram = nullptr; - while (Scope != nullptr) { - if (ClosestSubprogram == nullptr) - ClosestSubprogram = dyn_cast(Scope); - StringRef ScopeName = Scope->getName(); - if (!ScopeName.empty()) - QualifiedNameComponents.push_back(ScopeName); - Scope = Scope->getScope().resolve(); - } - return ClosestSubprogram; -} - -static std::string getQualifiedName(ArrayRef 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 @@ -499,12 +554,9 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, // If we have a display name, build the fully qualified name by walking the // chain of scopes. - if (SP != nullptr && !SP->getDisplayName().empty()) { - SmallVector QualifiedNameComponents; - getQualifiedNameComponents(SP->getScope().resolve(), - QualifiedNameComponents); - FuncName = getQualifiedName(QualifiedNameComponents, SP->getDisplayName()); - } + if (SP != nullptr && !SP->getDisplayName().empty()) + FuncName = + getFullyQualifiedName(SP->getScope().resolve(), SP->getDisplayName()); // If our DISubprogram name is empty, use the mangled name. if (FuncName.empty()) @@ -792,8 +844,12 @@ TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) { case dwarf::DW_TAG_volatile_type: return lowerTypeModifier(cast(Ty)); case dwarf::DW_TAG_subroutine_type: - if (ClassTy) - return lowerTypeMemberFunction(cast(Ty), ClassTy); + if (ClassTy) { + // The member function type of a member function pointer has no + // ThisAdjustment. + return lowerTypeMemberFunction(cast(Ty), ClassTy, + /*ThisAdjustment=*/0); + } return lowerTypeFunction(cast(Ty)); case dwarf::DW_TAG_enumeration_type: return lowerTypeEnum(cast(Ty)); @@ -1113,7 +1169,8 @@ TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) { } TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty, - const DIType *ClassTy) { + const DIType *ClassTy, + int ThisAdjustment) { // Lower the containing class type. TypeIndex ClassType = getTypeIndex(ClassTy); @@ -1150,14 +1207,7 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty, // ThisPointerAdjustment. TypeIndex TI = TypeTable.writeMemberFunction(MemberFunctionRecord( ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FunctionOptions::None, - ArgTypeIndices.size(), ArgListIndex, 0)); - - return TI; -} - -TypeIndex CodeViewDebug::lowerSubprogramType(const DISubprogram *SP) { - auto ClassType = dyn_cast_or_null(SP->getScope().resolve()); - TypeIndex TI = getTypeIndex(SP->getType(), ClassType); + ArgTypeIndices.size(), ArgListIndex, ThisAdjustment)); return TI; } @@ -1243,7 +1293,10 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) { FTI = TypeTable.writeFieldList(Fields); } - return TypeTable.writeEnum(EnumRecord(EnumeratorCount, CO, FTI, Ty->getName(), + std::string FullName = + getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName()); + + return TypeTable.writeEnum(EnumRecord(EnumeratorCount, CO, FTI, FullName, Ty->getIdentifier(), getTypeIndex(Ty->getBaseType()))); } @@ -1353,9 +1406,11 @@ TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) { TypeRecordKind Kind = getRecordKind(Ty); ClassOptions CO = ClassOptions::ForwardReference | getRecordUniqueNameOption(Ty); + std::string FullName = + getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName()); TypeIndex FwdDeclTI = TypeTable.writeClass(ClassRecord( Kind, 0, CO, HfaKind::None, WindowsRTClassKind::None, TypeIndex(), - TypeIndex(), TypeIndex(), 0, Ty->getName(), Ty->getIdentifier())); + TypeIndex(), TypeIndex(), 0, FullName, Ty->getIdentifier())); return FwdDeclTI; } @@ -1369,19 +1424,24 @@ TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) { unsigned FieldCount; std::tie(FieldTI, VShapeTI, FieldCount) = lowerRecordFieldList(Ty); + std::string FullName = + getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName()); + uint64_t SizeInBytes = Ty->getSizeInBits() / 8; return TypeTable.writeClass(ClassRecord( Kind, FieldCount, CO, HfaKind::None, WindowsRTClassKind::None, FieldTI, - TypeIndex(), VShapeTI, SizeInBytes, Ty->getName(), Ty->getIdentifier())); + TypeIndex(), VShapeTI, SizeInBytes, FullName, Ty->getIdentifier())); // FIXME: Make an LF_UDT_SRC_LINE record. } TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) { ClassOptions CO = ClassOptions::ForwardReference | getRecordUniqueNameOption(Ty); + std::string FullName = + getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName()); TypeIndex FwdDeclTI = TypeTable.writeUnion(UnionRecord(0, CO, HfaKind::None, TypeIndex(), 0, - Ty->getName(), Ty->getIdentifier())); + FullName, Ty->getIdentifier())); return FwdDeclTI; } @@ -1391,8 +1451,10 @@ TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) { unsigned FieldCount; std::tie(FieldTI, std::ignore, FieldCount) = lowerRecordFieldList(Ty); uint64_t SizeInBytes = Ty->getSizeInBits() / 8; + std::string FullName = + getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName()); return TypeTable.writeUnion(UnionRecord(FieldCount, CO, HfaKind::None, - FieldTI, SizeInBytes, Ty->getName(), + FieldTI, SizeInBytes, FullName, Ty->getIdentifier())); // FIXME: Make an LF_UDT_SRC_LINE record. } @@ -1484,8 +1546,7 @@ TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) { TypeIndex TI = lowerType(Ty, ClassTy); - recordTypeIndexForDINode(Ty, TI, ClassTy); - return TI; + return recordTypeIndexForDINode(Ty, TI, ClassTy); } TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) { diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/lib/CodeGen/AsmPrinter/CodeViewDebug.h index b54463dfe1d..98499b934af 100644 --- a/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -218,6 +218,11 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { codeview::TypeIndex getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef = DITypeRef()); + codeview::TypeIndex getMemberFunctionType(const DISubprogram *SP, + const DICompositeType *Class); + + codeview::TypeIndex getScopeIndex(const DIScope *Scope); + codeview::TypeIndex lowerType(const DIType *Ty, const DIType *ClassTy); codeview::TypeIndex lowerTypeAlias(const DIDerivedType *Ty); codeview::TypeIndex lowerTypeArray(const DICompositeType *Ty); @@ -227,7 +232,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty); codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty); codeview::TypeIndex lowerTypeMemberFunction(const DISubroutineType *Ty, - const DIType *ClassTy); + const DIType *ClassTy, + int ThisAdjustment); codeview::TypeIndex lowerTypeEnum(const DICompositeType *Ty); codeview::TypeIndex lowerTypeClass(const DICompositeType *Ty); codeview::TypeIndex lowerTypeUnion(const DICompositeType *Ty); @@ -242,8 +248,6 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { codeview::TypeIndex lowerCompleteTypeClass(const DICompositeType *Ty); codeview::TypeIndex lowerCompleteTypeUnion(const DICompositeType *Ty); - codeview::TypeIndex lowerSubprogramType(const DISubprogram *SP); - void collectMemberInfo(ClassInfo &Info, const DIDerivedType *DDTy); ClassInfo &collectClassInfo(const DICompositeType *Ty); @@ -254,8 +258,9 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { lowerRecordFieldList(const DICompositeType *Ty); /// Inserts {{Node, ClassTy}, TI} into TypeIndices and checks for duplicates. - void recordTypeIndexForDINode(const DINode *Node, codeview::TypeIndex TI, - const DIType *ClassTy = nullptr); + codeview::TypeIndex recordTypeIndexForDINode(const DINode *Node, + codeview::TypeIndex TI, + const DIType *ClassTy = nullptr); unsigned getPointerSizeInBytes(); diff --git a/test/DebugInfo/COFF/scopes.ll b/test/DebugInfo/COFF/scopes.ll new file mode 100644 index 00000000000..e07e92ddb7d --- /dev/null +++ b/test/DebugInfo/COFF/scopes.ll @@ -0,0 +1,143 @@ +; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s + +; Check that we keep namespace scopes around the same way MSVC does. +; We do function scopes slightly differently, but everything should be alright. + +; C++ source to regenerate: +; namespace foo { +; namespace bar { +; void baz() { +; struct LocalRecord { +; int x; +; } l; +; }; +; struct GlobalRecord { +; int x; +; void method(); +; } g; +; void GlobalRecord::method() {} +; } +; } + +; CHECK-LABEL: FuncId ({{.*}}) { +; CHECK-NEXT: TypeLeafKind: LF_FUNC_ID (0x1601) +; CHECK-NEXT: ParentScope: foo::bar ({{.*}}) +; CHECK-NEXT: FunctionType: void () ({{.*}}) +; CHECK-NEXT: Name: baz +; CHECK-NEXT: } + +; CHECK: Struct ({{.*}}) { +; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) +; CHECK: MemberCount: 0 +; CHECK: Properties [ (0x80) +; CHECK: ForwardReference (0x80) +; CHECK: ] +; CHECK: FieldList: 0x0 +; CHECK: DerivedFrom: 0x0 +; CHECK: VShape: 0x0 +; CHECK: SizeOf: 0 +; CHECK: Name: foo::bar::baz::LocalRecord +; CHECK: } + +; CHECK: Struct ({{.*}}) { +; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) +; CHECK: MemberCount: 1 +; CHECK: Properties [ (0x0) +; CHECK: ] +; CHECK: Name: foo::bar::baz::LocalRecord +; CHECK: } + +; CHECK: Struct ({{.*}}) { +; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) +; CHECK: MemberCount: 0 +; CHECK: Properties [ (0x280) +; CHECK: ForwardReference (0x80) +; CHECK: HasUniqueName (0x200) +; CHECK: ] +; CHECK: FieldList: 0x0 +; CHECK: DerivedFrom: 0x0 +; CHECK: VShape: 0x0 +; CHECK: SizeOf: 0 +; CHECK: Name: foo::bar::GlobalRecord +; CHECK: } + +; CHECK-LABEL: MemberFuncId ({{.*}}) { +; CHECK-NEXT: TypeLeafKind: LF_MFUNC_ID (0x1602) +; CHECK-NEXT: ClassType: foo::bar::GlobalRecord ({{.*}}) +; CHECK-NEXT: FunctionType: void foo::bar::GlobalRecord::() ({{.*}}) +; CHECK-NEXT: Name: method +; CHECK-NEXT: } + + +; ModuleID = 't.cpp' +source_filename = "t.cpp" +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.0.23918" + +%"struct.foo::bar::GlobalRecord" = type { i32 } +%struct.LocalRecord = type { i32 } + +@"\01?g@bar@foo@@3UGlobalRecord@12@A" = global %"struct.foo::bar::GlobalRecord" zeroinitializer, align 4 + +; Function Attrs: nounwind uwtable +define void @"\01?baz@bar@foo@@YAXXZ"() #0 !dbg !19 { +entry: + %l = alloca %struct.LocalRecord, align 4 + call void @llvm.dbg.declare(metadata %struct.LocalRecord* %l, metadata !22, metadata !26), !dbg !27 + ret void, !dbg !28 +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: nounwind uwtable +define void @"\01?method@GlobalRecord@bar@foo@@QEAAXXZ"(%"struct.foo::bar::GlobalRecord"* %this) #0 align 2 !dbg !29 { +entry: + %this.addr = alloca %"struct.foo::bar::GlobalRecord"*, align 8 + store %"struct.foo::bar::GlobalRecord"* %this, %"struct.foo::bar::GlobalRecord"** %this.addr, align 8 + call void @llvm.dbg.declare(metadata %"struct.foo::bar::GlobalRecord"** %this.addr, metadata !30, metadata !26), !dbg !32 + %this1 = load %"struct.foo::bar::GlobalRecord"*, %"struct.foo::bar::GlobalRecord"** %this.addr, align 8 + ret void, !dbg !33 +} + +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 = !{!15, !16, !17} +!llvm.ident = !{!18} + +!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, globals: !3) +!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild") +!2 = !{} +!3 = !{!4} +!4 = distinct !DIGlobalVariable(name: "g", linkageName: "\01?g@bar@foo@@3UGlobalRecord@12@A", scope: !5, file: !1, line: 12, type: !7, isLocal: false, isDefinition: true, variable: %"struct.foo::bar::GlobalRecord"* @"\01?g@bar@foo@@3UGlobalRecord@12@A") +!5 = !DINamespace(name: "bar", scope: !6, file: !1, line: 2) +!6 = !DINamespace(name: "foo", scope: null, file: !1, line: 1) +!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "GlobalRecord", scope: !5, file: !1, line: 9, size: 32, align: 32, elements: !8, identifier: ".?AUGlobalRecord@bar@foo@@") +!8 = !{!9, !11} +!9 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !7, file: !1, line: 10, baseType: !10, size: 32, align: 32) +!10 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!11 = !DISubprogram(name: "method", linkageName: "\01?method@GlobalRecord@bar@foo@@QEAAXXZ", scope: !7, file: !1, line: 11, type: !12, isLocal: false, isDefinition: false, scopeLine: 11, flags: DIFlagPrototyped, isOptimized: false) +!12 = !DISubroutineType(types: !13) +!13 = !{null, !14} +!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!15 = !{i32 2, !"CodeView", i32 1} +!16 = !{i32 2, !"Debug Info Version", i32 3} +!17 = !{i32 1, !"PIC Level", i32 2} +!18 = !{!"clang version 3.9.0 "} +!19 = distinct !DISubprogram(name: "baz", linkageName: "\01?baz@bar@foo@@YAXXZ", scope: !5, file: !1, line: 3, type: !20, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!20 = !DISubroutineType(types: !21) +!21 = !{null} +!22 = !DILocalVariable(name: "l", scope: !19, file: !1, line: 6, type: !23) +!23 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "LocalRecord", scope: !19, file: !1, line: 4, size: 32, align: 32, elements: !24) +!24 = !{!25} +!25 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !23, file: !1, line: 5, baseType: !10, size: 32, align: 32) +!26 = !DIExpression() +!27 = !DILocation(line: 6, column: 5, scope: !19) +!28 = !DILocation(line: 7, column: 1, scope: !19) +!29 = distinct !DISubprogram(name: "method", linkageName: "\01?method@GlobalRecord@bar@foo@@QEAAXXZ", scope: !7, file: !1, line: 13, type: !12, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !11, variables: !2) +!30 = !DILocalVariable(name: "this", arg: 1, scope: !29, type: !31, flags: DIFlagArtificial | DIFlagObjectPointer) +!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, align: 64) +!32 = !DILocation(line: 0, scope: !29) +!33 = !DILocation(line: 13, column: 30, scope: !29) diff --git a/test/DebugInfo/COFF/types-calling-conv.ll b/test/DebugInfo/COFF/types-calling-conv.ll index 96dbe000245..f7ecb25d458 100644 --- a/test/DebugInfo/COFF/types-calling-conv.ll +++ b/test/DebugInfo/COFF/types-calling-conv.ll @@ -56,8 +56,8 @@ ; CHECK: ArgListType: () (0x1002) ; CHECK: } ; CHECK: FuncId (0x1004) { -; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) -; CHECK: ParentScope: 0x0 +; CHECK: TypeLeafKind: LF_MFUNC_ID (0x1602) +; CHECK: ClassType: A (0x1000) ; CHECK: FunctionType: void A::() (0x1003) ; CHECK: Name: A::thiscallcc ; CHECK: } diff --git a/test/DebugInfo/COFF/types-data-members.ll b/test/DebugInfo/COFF/types-data-members.ll index 963c74454d5..ba3ef7bb2e5 100644 --- a/test/DebugInfo/COFF/types-data-members.ll +++ b/test/DebugInfo/COFF/types-data-members.ll @@ -288,7 +288,7 @@ ; CHECK: DerivedFrom: 0x0 ; CHECK: VShape: 0x0 ; CHECK: SizeOf: 0 -; CHECK: Name: Nested +; CHECK: Name: Class::Nested ; CHECK: LinkageName: .?AUNested@Class@@ ; CHECK: } ; CHECK: FieldList (0x1014) { @@ -310,7 +310,7 @@ ; CHECK: DerivedFrom: 0x0 ; CHECK: VShape: 0x0 ; CHECK: SizeOf: 4 -; CHECK: Name: Nested +; CHECK: Name: Class::Nested ; CHECK: LinkageName: .?AUNested@Class@@ ; CHECK: } ; CHECK: Pointer (0x1016) { @@ -337,8 +337,8 @@ ; CHECK: ThisAdjustment: 0 ; CHECK: } ; CHECK: FuncId (0x1018) { -; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) -; CHECK: ParentScope: 0x0 +; CHECK: TypeLeafKind: LF_MFUNC_ID (0x1602) +; CHECK: ClassType: DerivedClass (0x100D) ; CHECK: FunctionType: void DerivedClass::() (0x1017) ; CHECK: Name: DerivedClass::DerivedClass ; CHECK: }