From 643dd83661d46f69d5f7a6dd0ec0e4df764ba6e3 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 22 Jun 2016 17:15:28 +0000 Subject: [PATCH] [codeview] Defer emission of all referenced complete records This is the motivating example: struct B { int b; }; struct A { B *b; }; int f(A *p) { return p->b->b; } Clang emits complete types for both A and B because they are required to be complete, but our CodeView emission would only emit forward declarations of A and B. This was a consequence of the fact that the A* type must reference the forward declaration of A, which doesn't reference B at all. We can't eagerly emit complete definitions of A and B when we request the forward declaration's type index because of recursive types like linked lists. If we did that, our stack usage could get out of hand, and it would be possible to lower a type while attempting to lower a type, and we would need to double check if our type is already present in the TypeIndexMap after all recursive getTypeIndex calls. Instead, defer complete type emission until after all type lowering has completed. This ensures that all referenced complete types are emitted, and that type lowering is not re-entrant. llvm-svn: 273443 --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 40 +++- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h | 11 + .../DebugInfo/COFF/defer-complete-type.ll | 193 ++++++++++++++++++ llvm/test/DebugInfo/COFF/types-basic.ll | 69 +++++-- .../test/DebugInfo/COFF/types-calling-conv.ll | 63 ++++-- 5 files changed, 331 insertions(+), 45 deletions(-) create mode 100644 llvm/test/DebugInfo/COFF/defer-complete-type.ll diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 31f0872a3010..da69f8b6ab67 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1400,6 +1400,8 @@ TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) { TypeIndex FwdDeclTI = TypeTable.writeClass(ClassRecord( Kind, 0, CO, HfaKind::None, WindowsRTClassKind::None, TypeIndex(), TypeIndex(), TypeIndex(), 0, FullName, Ty->getIdentifier())); + if (!Ty->isForwardDecl()) + DeferredCompleteTypes.push_back(Ty); return FwdDeclTI; } @@ -1431,6 +1433,8 @@ TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) { TypeIndex FwdDeclTI = TypeTable.writeUnion(UnionRecord(0, CO, HfaKind::None, TypeIndex(), 0, FullName, Ty->getIdentifier())); + if (!Ty->isForwardDecl()) + DeferredCompleteTypes.push_back(Ty); return FwdDeclTI; } @@ -1518,6 +1522,18 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) { return std::make_tuple(FieldTI, TypeIndex(), MemberCount); } +struct CodeViewDebug::TypeLoweringScope { + TypeLoweringScope(CodeViewDebug &CVD) : CVD(CVD) { ++CVD.TypeEmissionLevel; } + ~TypeLoweringScope() { + // Don't decrement TypeEmissionLevel until after emitting deferred types, so + // inner TypeLoweringScopes don't attempt to emit deferred types. + if (CVD.TypeEmissionLevel == 1) + CVD.emitDeferredCompleteTypes(); + --CVD.TypeEmissionLevel; + } + CodeViewDebug &CVD; +}; + TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) { const DIType *Ty = TypeRef.resolve(); const DIType *ClassTy = ClassTyRef.resolve(); @@ -1533,9 +1549,14 @@ TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) { if (I != TypeIndices.end()) return I->second; - TypeIndex TI = lowerType(Ty, ClassTy); + TypeIndex TI; + { + TypeLoweringScope S(*this); + TI = lowerType(Ty, ClassTy); + recordTypeIndexForDINode(Ty, TI, ClassTy); + } - return recordTypeIndexForDINode(Ty, TI, ClassTy); + return TI; } TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) { @@ -1564,6 +1585,8 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) { if (!InsertResult.second) return InsertResult.first->second; + TypeLoweringScope S(*this); + // Make sure the forward declaration is emitted first. It's unclear if this // is necessary, but MSVC does it, and we should follow suit until we can show // otherwise. @@ -1592,6 +1615,19 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) { return TI; } +/// Emit all the deferred complete record types. Try to do this in FIFO order, +/// and do this until fixpoint, as each complete record type typically references +/// many other record types. +void CodeViewDebug::emitDeferredCompleteTypes() { + SmallVector TypesToEmit; + while (!DeferredCompleteTypes.empty()) { + std::swap(DeferredCompleteTypes, TypesToEmit); + for (const DICompositeType *RecordTy : TypesToEmit) + getCompleteTypeIndex(RecordTy); + TypesToEmit.clear(); + } +} + void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) { // LocalSym record, see SymbolRecord.h for more info. MCSymbol *LocalBegin = MMI->getContext().createTempSymbol(), diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index be8d6cea024c..a7976d8d2acd 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -150,6 +150,13 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { /// always looked up in the normal TypeIndices map. DenseMap CompleteTypeIndices; + /// Complete record types to emit after all active type lowerings are + /// finished. + SmallVector DeferredCompleteTypes; + + /// Number of type lowering frames active on the stack. + unsigned TypeEmissionLevel = 0; + const DISubprogram *CurrentSubprogram = nullptr; // The UDTs we have seen while processing types; each entry is a pair of type @@ -246,6 +253,10 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { codeview::TypeIndex lowerCompleteTypeClass(const DICompositeType *Ty); codeview::TypeIndex lowerCompleteTypeUnion(const DICompositeType *Ty); + struct TypeLoweringScope; + + void emitDeferredCompleteTypes(); + void collectMemberInfo(ClassInfo &Info, const DIDerivedType *DDTy); ClassInfo collectClassInfo(const DICompositeType *Ty); diff --git a/llvm/test/DebugInfo/COFF/defer-complete-type.ll b/llvm/test/DebugInfo/COFF/defer-complete-type.ll new file mode 100644 index 000000000000..d3ec61842b48 --- /dev/null +++ b/llvm/test/DebugInfo/COFF/defer-complete-type.ll @@ -0,0 +1,193 @@ +; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s + +; Both A and B should get forward declarations and complete definitions for this +; example. + +; C++ source to regenerate: +; $ cat t.cpp +; struct B { int b; }; +; struct A { B *b; }; +; int f(A *p) { return p->b->b; } +; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll + +; CHECK: CodeViewTypes [ +; CHECK: Section: .debug$T (6) +; CHECK: Magic: 0x4 +; CHECK: Struct (0x1000) { +; 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: A +; CHECK: LinkageName: .?AUA@@ +; CHECK: } +; CHECK: Pointer (0x1001) { +; CHECK: TypeLeafKind: LF_POINTER (0x1002) +; CHECK: PointeeType: A (0x1000) +; CHECK: PointerAttributes: 0x1000C +; CHECK: PtrType: Near64 (0xC) +; CHECK: PtrMode: Pointer (0x0) +; CHECK: IsFlat: 0 +; CHECK: IsConst: 0 +; CHECK: IsVolatile: 0 +; CHECK: IsUnaligned: 0 +; CHECK: SizeOf: 8 +; CHECK: } +; CHECK: ArgList (0x1002) { +; CHECK: TypeLeafKind: LF_ARGLIST (0x1201) +; CHECK: NumArgs: 1 +; CHECK: Arguments [ +; CHECK: ArgType: A* (0x1001) +; CHECK: ] +; CHECK: } +; CHECK: Procedure (0x1003) { +; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008) +; CHECK: ReturnType: int (0x74) +; CHECK: CallingConvention: NearC (0x0) +; CHECK: FunctionOptions [ (0x0) +; CHECK: ] +; CHECK: NumParameters: 1 +; CHECK: ArgListType: (A*) (0x1002) +; CHECK: } +; CHECK: Struct (0x1004) { +; 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: B +; CHECK: LinkageName: .?AUB@@ +; CHECK: } +; CHECK: Pointer (0x1005) { +; CHECK: TypeLeafKind: LF_POINTER (0x1002) +; CHECK: PointeeType: B (0x1004) +; CHECK: PointerAttributes: 0x1000C +; CHECK: PtrType: Near64 (0xC) +; CHECK: PtrMode: Pointer (0x0) +; CHECK: IsFlat: 0 +; CHECK: IsConst: 0 +; CHECK: IsVolatile: 0 +; CHECK: IsUnaligned: 0 +; CHECK: SizeOf: 8 +; CHECK: } +; CHECK: FieldList (0x1006) { +; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203) +; CHECK: DataMember { +; CHECK: AccessSpecifier: Public (0x3) +; CHECK: Type: B* (0x1005) +; CHECK: FieldOffset: 0x0 +; CHECK: Name: b +; CHECK: } +; CHECK: } +; CHECK: Struct (0x1007) { +; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) +; CHECK: MemberCount: 1 +; CHECK: Properties [ (0x200) +; CHECK: HasUniqueName (0x200) +; CHECK: ] +; CHECK: FieldList: (0x1006) +; CHECK: DerivedFrom: 0x0 +; CHECK: VShape: 0x0 +; CHECK: SizeOf: 8 +; CHECK: Name: A +; CHECK: LinkageName: .?AUA@@ +; CHECK: } +; CHECK: FieldList (0x1008) { +; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203) +; CHECK: DataMember { +; CHECK: AccessSpecifier: Public (0x3) +; CHECK: Type: int (0x74) +; CHECK: FieldOffset: 0x0 +; CHECK: Name: b +; CHECK: } +; CHECK: } +; CHECK: Struct (0x1009) { +; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) +; CHECK: MemberCount: 1 +; CHECK: Properties [ (0x200) +; CHECK: HasUniqueName (0x200) +; CHECK: ] +; CHECK: FieldList: (0x1008) +; CHECK: DerivedFrom: 0x0 +; CHECK: VShape: 0x0 +; CHECK: SizeOf: 4 +; CHECK: Name: B +; CHECK: LinkageName: .?AUB@@ +; CHECK: } +; CHECK: FuncId (0x100A) { +; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) +; CHECK: ParentScope: 0x0 +; CHECK: FunctionType: int (A*) (0x1003) +; CHECK: Name: f +; CHECK: } +; CHECK: ] + +; 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.A = type { %struct.B* } +%struct.B = type { i32 } + +; Function Attrs: nounwind uwtable +define i32 @"\01?f@@YAHPEAUA@@@Z"(%struct.A* %p) #0 !dbg !7 { +entry: + %p.addr = alloca %struct.A*, align 8 + store %struct.A* %p, %struct.A** %p.addr, align 8 + call void @llvm.dbg.declare(metadata %struct.A** %p.addr, metadata !19, metadata !20), !dbg !21 + %0 = load %struct.A*, %struct.A** %p.addr, align 8, !dbg !22 + %b = getelementptr inbounds %struct.A, %struct.A* %0, i32 0, i32 0, !dbg !23 + %1 = load %struct.B*, %struct.B** %b, align 8, !dbg !23 + %b1 = getelementptr inbounds %struct.B, %struct.B* %1, i32 0, i32 0, !dbg !24 + %2 = load i32, i32* %b1, align 4, !dbg !24 + ret i32 %2, !dbg !25 +} + +; 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-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, !5} +!llvm.ident = !{!6} + +!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 = !{} +!3 = !{i32 2, !"CodeView", i32 1} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"PIC Level", i32 2} +!6 = !{!"clang version 3.9.0 "} +!7 = distinct !DISubprogram(name: "f", linkageName: "\01?f@@YAHPEAUA@@@Z", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !11} +!10 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64, align: 64) +!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !1, line: 2, size: 64, align: 64, elements: !13, identifier: ".?AUA@@") +!13 = !{!14} +!14 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !12, file: !1, line: 2, baseType: !15, size: 64, align: 64) +!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 64, align: 64) +!16 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B", file: !1, line: 1, size: 32, align: 32, elements: !17, identifier: ".?AUB@@") +!17 = !{!18} +!18 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !16, file: !1, line: 1, baseType: !10, size: 32, align: 32) +!19 = !DILocalVariable(name: "p", arg: 1, scope: !7, file: !1, line: 3, type: !11) +!20 = !DIExpression() +!21 = !DILocation(line: 3, column: 10, scope: !7) +!22 = !DILocation(line: 3, column: 22, scope: !7) +!23 = !DILocation(line: 3, column: 25, scope: !7) +!24 = !DILocation(line: 3, column: 28, scope: !7) +!25 = !DILocation(line: 3, column: 15, scope: !7) diff --git a/llvm/test/DebugInfo/COFF/types-basic.ll b/llvm/test/DebugInfo/COFF/types-basic.ll index e621424b838d..b5c241b7ab1b 100644 --- a/llvm/test/DebugInfo/COFF/types-basic.ll +++ b/llvm/test/DebugInfo/COFF/types-basic.ll @@ -119,19 +119,44 @@ ; CHECK: Arguments [ ; CHECK: ] ; CHECK: } -; CHECK: MemberFunction (0x1009) { -; CHECK: TypeLeafKind: LF_MFUNCTION (0x1009) -; CHECK: ReturnType: void (0x3) -; CHECK: ClassType: A (0x1005) -; CHECK: ThisType: A* (0x1007) -; CHECK: CallingConvention: NearC (0x0) -; CHECK: FunctionOptions [ (0x0) -; CHECK: ] -; CHECK: NumParameters: 0 -; CHECK: ArgListType: () (0x1008) -; CHECK: ThisAdjustment: 0 -; CHECK: } -; CHECK: Pointer (0x100A) { +; CHECK: MemberFunction (0x1009) { +; CHECK: TypeLeafKind: LF_MFUNCTION (0x1009) +; CHECK: ReturnType: void (0x3) +; CHECK: ClassType: A (0x1005) +; CHECK: ThisType: A* (0x1007) +; CHECK: CallingConvention: NearC (0x0) +; CHECK: FunctionOptions [ (0x0) +; CHECK: ] +; CHECK: NumParameters: 0 +; CHECK: ArgListType: () (0x1008) +; CHECK: ThisAdjustment: 0 +; CHECK: } +; CHECK: FieldList (0x100A) { +; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203) +; CHECK: DataMember { +; CHECK: AccessSpecifier: Public (0x3) +; CHECK: Type: int (0x74) +; CHECK: FieldOffset: 0x0 +; CHECK: Name: a +; CHECK: } +; CHECK: OneMethod { +; CHECK: AccessSpecifier: Public (0x3) +; CHECK: Type: void A::() (0x1009) +; CHECK: Name: A::f +; CHECK: } +; CHECK: } +; CHECK: Struct (0x100B) { +; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) +; CHECK: MemberCount: 2 +; CHECK: Properties [ (0x0) +; CHECK: ] +; CHECK: FieldList: (0x100A) +; CHECK: DerivedFrom: 0x0 +; CHECK: VShape: 0x0 +; CHECK: SizeOf: 4 +; CHECK: Name: A +; CHECK: } +; CHECK: Pointer (0x100C) { ; CHECK: TypeLeafKind: LF_POINTER (0x1002) ; CHECK: PointeeType: void A::() (0x1009) ; CHECK: PointerAttributes: 0x1006C @@ -144,16 +169,16 @@ ; CHECK: ClassType: A (0x1005) ; CHECK: Representation: GeneralFunction (0x8) ; CHECK: } -; CHECK: Modifier (0x100B) { +; CHECK: Modifier (0x100D) { ; CHECK: TypeLeafKind: LF_MODIFIER (0x1001) ; CHECK: ModifiedType: void (0x3) ; CHECK: Modifiers [ (0x1) ; CHECK: Const (0x1) ; CHECK: ] ; CHECK: } -; CHECK: Pointer (0x100C) { +; CHECK: Pointer (0x100E) { ; CHECK: TypeLeafKind: LF_POINTER (0x1002) -; CHECK: PointeeType: const void (0x100B) +; CHECK: PointeeType: const void (0x100D) ; CHECK: PointerAttributes: 0x1000C ; CHECK: PtrType: Near64 (0xC) ; CHECK: PtrMode: Pointer (0x0) @@ -162,7 +187,7 @@ ; CHECK: IsVolatile: 0 ; CHECK: IsUnaligned: 0 ; CHECK: } -; CHECK: Procedure (0x100D) { +; CHECK: Procedure (0x100F) { ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008) ; CHECK: ReturnType: void (0x3) ; CHECK: CallingConvention: NearC (0x0) @@ -171,10 +196,10 @@ ; CHECK: NumParameters: 0 ; CHECK: ArgListType: () (0x1008) ; CHECK: } -; CHECK: FuncId (0x100E) { +; CHECK: FuncId (0x1010) { ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) ; CHECK: ParentScope: 0x0 -; CHECK: FunctionType: void () (0x100D) +; CHECK: FunctionType: void () (0x100F) ; CHECK: Name: CharTypes ; CHECK: } ; CHECK: ] @@ -235,7 +260,7 @@ ; CHECK: VarName: v4 ; CHECK: } ; CHECK: Local { -; CHECK: Type: void A::() A::* (0x100A) +; CHECK: Type: void A::() A::* (0x100C) ; CHECK: VarName: v5 ; CHECK: } ; CHECK: Local { @@ -255,7 +280,7 @@ ; CHECK: VarName: l4 ; CHECK: } ; CHECK: Local { -; CHECK: Type: const void* (0x100C) +; CHECK: Type: const void* (0x100E) ; CHECK: VarName: v6 ; CHECK: } ; CHECK: ProcEnd { @@ -263,7 +288,7 @@ ; CHECK: ] ; CHECK: Subsection [ ; CHECK: ProcStart { -; CHECK: Type: CharTypes (0x100E) +; CHECK: Type: CharTypes (0x1010) ; CHECK: DisplayName: CharTypes ; CHECK: LinkageName: ?CharTypes@@YAXXZ ; CHECK: } diff --git a/llvm/test/DebugInfo/COFF/types-calling-conv.ll b/llvm/test/DebugInfo/COFF/types-calling-conv.ll index f7ecb25d4584..3a8f6beac93f 100644 --- a/llvm/test/DebugInfo/COFF/types-calling-conv.ll +++ b/llvm/test/DebugInfo/COFF/types-calling-conv.ll @@ -37,6 +37,7 @@ ; CHECK: IsConst: 0 ; CHECK: IsVolatile: 0 ; CHECK: IsUnaligned: 0 +; CHECK: SizeOf: 4 ; CHECK: } ; CHECK: ArgList (0x1002) { ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201) @@ -54,32 +55,37 @@ ; CHECK: ] ; CHECK: NumParameters: 0 ; CHECK: ArgListType: () (0x1002) +; CHECK: ThisAdjustment: 0 ; CHECK: } -; CHECK: FuncId (0x1004) { +; CHECK: FieldList (0x1004) { +; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203) +; CHECK: OneMethod { +; CHECK: AccessSpecifier: Public (0x3) +; CHECK: Type: void A::() (0x1003) +; CHECK: Name: A::thiscallcc +; CHECK: } +; CHECK: } +; CHECK: Struct (0x1005) { +; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) +; CHECK: MemberCount: 1 +; CHECK: Properties [ (0x0) +; CHECK: ] +; CHECK: FieldList: (0x1004) +; CHECK: DerivedFrom: 0x0 +; CHECK: VShape: 0x0 +; CHECK: SizeOf: 1 +; CHECK: Name: A +; CHECK: } +; CHECK: MemberFuncId (0x1006) { ; CHECK: TypeLeafKind: LF_MFUNC_ID (0x1602) ; CHECK: ClassType: A (0x1000) ; CHECK: FunctionType: void A::() (0x1003) ; CHECK: Name: A::thiscallcc ; CHECK: } -; CHECK: Procedure (0x1005) { -; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008) -; CHECK: ReturnType: void (0x3) -; CHECK: CallingConvention: NearC (0x0) -; CHECK: FunctionOptions [ (0x0) -; CHECK: ] -; CHECK: NumParameters: 0 -; CHECK: ArgListType: () (0x1002) -; CHECK: } -; CHECK: FuncId (0x1006) { -; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) -; CHECK: ParentScope: 0x0 -; CHECK: FunctionType: void () (0x1005) -; CHECK: Name: cdeclcc -; CHECK: } ; CHECK: Procedure (0x1007) { ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008) ; CHECK: ReturnType: void (0x3) -; CHECK: CallingConvention: NearFast (0x4) +; CHECK: CallingConvention: NearC (0x0) ; CHECK: FunctionOptions [ (0x0) ; CHECK: ] ; CHECK: NumParameters: 0 @@ -89,12 +95,12 @@ ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) ; CHECK: ParentScope: 0x0 ; CHECK: FunctionType: void () (0x1007) -; CHECK: Name: fastcallcc +; CHECK: Name: cdeclcc ; CHECK: } ; CHECK: Procedure (0x1009) { ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008) ; CHECK: ReturnType: void (0x3) -; CHECK: CallingConvention: NearStdCall (0x7) +; CHECK: CallingConvention: NearFast (0x4) ; CHECK: FunctionOptions [ (0x0) ; CHECK: ] ; CHECK: NumParameters: 0 @@ -104,12 +110,12 @@ ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) ; CHECK: ParentScope: 0x0 ; CHECK: FunctionType: void () (0x1009) -; CHECK: Name: stdcallcc +; CHECK: Name: fastcallcc ; CHECK: } ; CHECK: Procedure (0x100B) { ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008) ; CHECK: ReturnType: void (0x3) -; CHECK: CallingConvention: NearVector (0x18) +; CHECK: CallingConvention: NearStdCall (0x7) ; CHECK: FunctionOptions [ (0x0) ; CHECK: ] ; CHECK: NumParameters: 0 @@ -119,6 +125,21 @@ ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) ; CHECK: ParentScope: 0x0 ; CHECK: FunctionType: void () (0x100B) +; CHECK: Name: stdcallcc +; CHECK: } +; CHECK: Procedure (0x100D) { +; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008) +; CHECK: ReturnType: void (0x3) +; CHECK: CallingConvention: NearVector (0x18) +; CHECK: FunctionOptions [ (0x0) +; CHECK: ] +; CHECK: NumParameters: 0 +; CHECK: ArgListType: () (0x1002) +; CHECK: } +; CHECK: FuncId (0x100E) { +; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) +; CHECK: ParentScope: 0x0 +; CHECK: FunctionType: void () (0x100D) ; CHECK: Name: vectorcallcc ; CHECK: } ; CHECK: ]