Index: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -117,15 +117,10 @@ /// to be confused with type indices for LF_FUNC_ID records. unsigned NextFuncId = 0; - codeview::TypeIndex VoidFnTyIdx; - - /// Get a type index for a generic void function type. - codeview::TypeIndex getGenericFunctionTypeIndex(); - InlineSite &getInlineSite(const DILocation *InlinedAt, const DISubprogram *Inlinee); - void recordFuncIdForSubprogram(const DISubprogram *SP); + codeview::TypeIndex getFuncIdForSubprogram(const DISubprogram *SP); static void collectInlineSiteChildren(SmallVectorImpl &Children, const FunctionInfo &FI, @@ -195,6 +190,7 @@ codeview::TypeIndex lowerTypePointer(const DIDerivedType *Ty); codeview::TypeIndex lowerTypeMemberPointer(const DIDerivedType *Ty); codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty); + codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty); public: CodeViewDebug(AsmPrinter *Asm); Index: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -117,31 +117,31 @@ Site->SiteFuncId = NextFuncId++; Site->Inlinee = Inlinee; InlinedSubprograms.insert(Inlinee); - recordFuncIdForSubprogram(Inlinee); + getFuncIdForSubprogram(Inlinee); } return *Site; } -TypeIndex CodeViewDebug::getGenericFunctionTypeIndex() { - if (VoidFnTyIdx.getIndex() != 0) - return VoidFnTyIdx; - - ArrayRef NoArgs; - ArgListRecord ArgListRec(TypeRecordKind::ArgList, NoArgs); - TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec); +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. + if (!SP) + return TypeIndex::Void(); - ProcedureRecord Procedure(TypeIndex::Void(), CallingConvention::NearC, - FunctionOptions::None, 0, ArgListIndex); - VoidFnTyIdx = TypeTable.writeProcedure(Procedure); - return VoidFnTyIdx; -} + // Check if we've already translated this subprogram. + auto I = TypeIndices.find(SP); + if (I != TypeIndices.end()) + return I->second; -void CodeViewDebug::recordFuncIdForSubprogram(const DISubprogram *SP) { TypeIndex ParentScope = TypeIndex(0); StringRef DisplayName = SP->getDisplayName(); - FuncIdRecord FuncId(ParentScope, getGenericFunctionTypeIndex(), DisplayName); + FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName); TypeIndex TI = TypeTable.writeFuncId(FuncId); - TypeIndices[SP] = TI; + + auto InsertResult = TypeIndices.insert({SP, TI}); + (void)InsertResult; + assert(InsertResult.second && "DISubprogram lowered twice"); + return TI; } void CodeViewDebug::recordLocalVariable(LocalVariable &&Var, @@ -495,7 +495,7 @@ OS.AddComment("Offset before epilogue"); OS.EmitIntValue(0, 4); OS.AddComment("Function type index"); - OS.EmitIntValue(0, 4); + OS.EmitIntValue(getFuncIdForSubprogram(GV->getSubprogram()).getIndex(), 4); OS.AddComment("Function section relative address"); OS.EmitCOFFSecRel32(Fn); OS.AddComment("Function section index"); @@ -744,6 +744,8 @@ case dwarf::DW_TAG_const_type: case dwarf::DW_TAG_volatile_type: return lowerTypeModifier(cast(Ty)); + case dwarf::DW_TAG_subroutine_type: + return lowerTypeFunction(cast(Ty)); default: // Use the null type index. return TypeIndex(); @@ -934,6 +936,32 @@ return TypeTable.writeModifier(MR); } +TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) { + SmallVector ReturnAndArgTypeIndices; + for (DITypeRef ArgTypeRef : Ty->getTypeArray()) + ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgTypeRef)); + + TypeIndex ReturnTypeIndex = TypeIndex::Void(); + ArrayRef ArgTypeIndices = None; + if (!ReturnAndArgTypeIndices.empty()) { + auto ReturnAndArgTypesRef = makeArrayRef(ReturnAndArgTypeIndices); + ReturnTypeIndex = ReturnAndArgTypesRef.front(); + ArgTypeIndices = ReturnAndArgTypesRef.drop_front(); + } + + ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices); + TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec); + + // TODO: We should use DW_AT_calling_convention to determine what CC this + // procedure record should have. + // TODO: Some functions are member functions, we should use a more appropriate + // record for those. + ProcedureRecord Procedure(ReturnTypeIndex, CallingConvention::NearC, + FunctionOptions::None, ArgTypeIndices.size(), + ArgListIndex); + return TypeTable.writeProcedure(Procedure); +} + TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef) { const DIType *Ty = TypeRef.resolve(); Index: llvm/trunk/test/DebugInfo/COFF/asm.ll =================================================================== --- llvm/trunk/test/DebugInfo/COFF/asm.ll +++ llvm/trunk/test/DebugInfo/COFF/asm.ll @@ -37,7 +37,7 @@ ; X86-NEXT: .long [[END_OF_F]]-_f ; X86-NEXT: .long 0 ; X86-NEXT: .long 0 -; X86-NEXT: .long 0 +; X86-NEXT: .long 4098 ; X86-NEXT: .secrel32 _f ; X86-NEXT: .secidx _f ; X86-NEXT: .byte 0 @@ -130,7 +130,7 @@ ; X64-NEXT: .long [[END_OF_F]]-f ; X64-NEXT: .long 0 ; X64-NEXT: .long 0 -; X64-NEXT: .long 0 +; X64-NEXT: .long 4098 ; X64-NEXT: .secrel32 f ; X64-NEXT: .secidx f ; X64-NEXT: .byte 0 Index: llvm/trunk/test/DebugInfo/COFF/inlining.ll =================================================================== --- llvm/trunk/test/DebugInfo/COFF/inlining.ll +++ llvm/trunk/test/DebugInfo/COFF/inlining.ll @@ -138,6 +138,12 @@ ; OBJ: FunctionType: void () (0x1001) ; OBJ: Name: foo ; OBJ: } +; OBJ: FuncId (0x1004) { +; OBJ: TypeLeafKind: LF_FUNC_ID (0x1601) +; OBJ: ParentScope: 0x0 +; OBJ: FunctionType: void () (0x1001) +; OBJ: Name: baz +; OBJ: } ; OBJ-NOT: TypeLeafKind: LF_FUNC_ID ; OBJ: ] @@ -164,7 +170,7 @@ ; OBJ: CodeSize: 0x3D ; OBJ: DbgStart: 0x0 ; OBJ: DbgEnd: 0x0 -; OBJ: FunctionType: 0x0 +; OBJ: FunctionType: baz (0x1004) ; OBJ: CodeOffset: ?baz@@YAXXZ+0x0 ; OBJ: Segment: 0x0 ; OBJ: Flags [ (0x0) Index: llvm/trunk/test/DebugInfo/COFF/multifile.ll =================================================================== --- llvm/trunk/test/DebugInfo/COFF/multifile.ll +++ llvm/trunk/test/DebugInfo/COFF/multifile.ll @@ -46,7 +46,7 @@ ; X86-NEXT: .long [[END_OF_F]]-_f ; X86-NEXT: .long 0 ; X86-NEXT: .long 0 -; X86-NEXT: .long 0 +; X86-NEXT: .long 4098 ; X86-NEXT: .secrel32 _f ; X86-NEXT: .secidx _f ; X86-NEXT: .byte 0 @@ -154,7 +154,7 @@ ; X64-NEXT: .long [[END_OF_F]]-f ; X64-NEXT: .long 0 ; X64-NEXT: .long 0 -; X64-NEXT: .long 0 +; X64-NEXT: .long 4098 ; X64-NEXT: .secrel32 f ; X64-NEXT: .secidx f ; X64-NEXT: .byte 0 Index: llvm/trunk/test/DebugInfo/COFF/multifunction.ll =================================================================== --- llvm/trunk/test/DebugInfo/COFF/multifunction.ll +++ llvm/trunk/test/DebugInfo/COFF/multifunction.ll @@ -67,7 +67,7 @@ ; X86-NEXT: .long [[END_OF_X]]-_x ; X86-NEXT: .long 0 ; X86-NEXT: .long 0 -; X86-NEXT: .long 0 +; X86-NEXT: .long 4098 ; X86-NEXT: .secrel32 _x ; X86-NEXT: .secidx _x ; X86-NEXT: .byte 0 @@ -92,7 +92,7 @@ ; X86-NEXT: .long [[END_OF_Y]]-_y ; X86-NEXT: .long 0 ; X86-NEXT: .long 0 -; X86-NEXT: .long 0 +; X86-NEXT: .long 4099 ; X86-NEXT: .secrel32 _y ; X86-NEXT: .secidx _y ; X86-NEXT: .byte 0 @@ -117,7 +117,7 @@ ; X86-NEXT: .long [[END_OF_F]]-_f ; X86-NEXT: .long 0 ; X86-NEXT: .long 0 -; X86-NEXT: .long 0 +; X86-NEXT: .long 4100 ; X86-NEXT: .secrel32 _f ; X86-NEXT: .secidx _f ; X86-NEXT: .byte 0 @@ -331,7 +331,7 @@ ; X64-NEXT: .long [[END_OF_X]]-x ; X64-NEXT: .long 0 ; X64-NEXT: .long 0 -; X64-NEXT: .long 0 +; X64-NEXT: .long 4098 ; X64-NEXT: .secrel32 x ; X64-NEXT: .secidx x ; X64-NEXT: .byte 0 @@ -356,7 +356,7 @@ ; X64-NEXT: .long [[END_OF_Y]]-y ; X64-NEXT: .long 0 ; X64-NEXT: .long 0 -; X64-NEXT: .long 0 +; X64-NEXT: .long 4099 ; X64-NEXT: .secrel32 y ; X64-NEXT: .secidx y ; X64-NEXT: .byte 0 @@ -381,7 +381,7 @@ ; X64-NEXT: .long [[END_OF_F]]-f ; X64-NEXT: .long 0 ; X64-NEXT: .long 0 -; X64-NEXT: .long 0 +; X64-NEXT: .long 4100 ; X64-NEXT: .secrel32 f ; X64-NEXT: .secidx f ; X64-NEXT: .byte 0 Index: llvm/trunk/test/DebugInfo/COFF/simple.ll =================================================================== --- llvm/trunk/test/DebugInfo/COFF/simple.ll +++ llvm/trunk/test/DebugInfo/COFF/simple.ll @@ -36,7 +36,7 @@ ; X86-NEXT: .long [[END_OF_F]]-_f ; X86-NEXT: .long 0 ; X86-NEXT: .long 0 -; X86-NEXT: .long 0 +; X86-NEXT: .long 4098 ; X86-NEXT: .secrel32 _f ; X86-NEXT: .secidx _f ; X86-NEXT: .byte 0 @@ -126,7 +126,7 @@ ; X64-NEXT: .long [[END_OF_F]]-f ; X64-NEXT: .long 0 ; X64-NEXT: .long 0 -; X64-NEXT: .long 0 +; X64-NEXT: .long 4098 ; X64-NEXT: .secrel32 f ; X64-NEXT: .secidx f ; X64-NEXT: .byte 0 Index: llvm/trunk/test/DebugInfo/COFF/types-basic.ll =================================================================== --- llvm/trunk/test/DebugInfo/COFF/types-basic.ll +++ llvm/trunk/test/DebugInfo/COFF/types-basic.ll @@ -32,16 +32,40 @@ ; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll ; CHECK: CodeViewTypes [ -; CHECK: Modifier (0x1000) { +; CHECK: ArgList (0x1000) { +; CHECK: TypeLeafKind: LF_ARGLIST (0x1201) +; CHECK: NumArgs: 3 +; CHECK: Arguments [ +; CHECK: ArgType: float (0x40) +; CHECK: ArgType: double (0x41) +; CHECK: ArgType: __int64 (0x13) +; CHECK: ] +; CHECK: } +; CHECK: Procedure (0x1001) { +; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008) +; CHECK: ReturnType: void (0x3) +; CHECK: CallingConvention: NearC (0x0) +; CHECK: FunctionOptions [ (0x0) +; CHECK: ] +; CHECK: NumParameters: 3 +; CHECK: ArgListType: (float, double, __int64) (0x1000) +; CHECK: } +; CHECK: FuncId (0x1002) { +; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) +; CHECK: ParentScope: 0x0 +; CHECK: FunctionType: void (float, double, __int64) (0x1001) +; CHECK: Name: f +; CHECK: } +; CHECK: Modifier (0x1003) { ; CHECK: TypeLeafKind: LF_MODIFIER (0x1001) ; CHECK: ModifiedType: int (0x74) ; CHECK: Modifiers [ (0x1) ; CHECK: Const (0x1) ; CHECK: ] ; CHECK: } -; CHECK: Pointer (0x1001) { +; CHECK: Pointer (0x1004) { ; CHECK: TypeLeafKind: LF_POINTER (0x1002) -; CHECK: PointeeType: const int (0x1000) +; CHECK: PointeeType: const int (0x1003) ; CHECK: PointerAttributes: 0x1000C ; CHECK: PtrType: Near64 (0xC) ; CHECK: PtrMode: Pointer (0x0) @@ -50,7 +74,7 @@ ; CHECK: IsVolatile: 0 ; CHECK: IsUnaligned: 0 ; CHECK: } -; CHECK: Pointer (0x1002) { +; CHECK: Pointer (0x1005) { ; CHECK: TypeLeafKind: LF_POINTER (0x1002) ; CHECK: PointeeType: int (0x74) ; CHECK: PointerAttributes: 0x804C @@ -63,9 +87,25 @@ ; CHECK: ClassType: 0x0 ; CHECK: Representation: Unknown (0x0) ; CHECK: } -; CHECK: Pointer (0x1003) { +; CHECK: ArgList (0x1006) { +; CHECK: TypeLeafKind: LF_ARGLIST (0x1201) +; CHECK: NumArgs: 1 +; CHECK: Arguments [ +; CHECK: ArgType: (0x600) +; CHECK: ] +; CHECK: } +; CHECK: Procedure (0x1007) { +; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008) +; CHECK: ReturnType: void (0x3) +; CHECK: CallingConvention: NearC (0x0) +; CHECK: FunctionOptions [ (0x0) +; CHECK: ] +; CHECK: NumParameters: 1 +; CHECK: ArgListType: () (0x1006) +; CHECK: } +; CHECK: Pointer (0x1008) { ; CHECK: TypeLeafKind: LF_POINTER (0x1002) -; CHECK: PointeeType: 0x0 +; CHECK: PointeeType: void () (0x1007) ; CHECK: PointerAttributes: 0x1006C ; CHECK: PtrType: Near64 (0xC) ; CHECK: PtrMode: PointerToMemberFunction (0x3) @@ -83,7 +123,7 @@ ; CHECK: ProcStart { ; CHECK: DbgStart: 0x0 ; CHECK: DbgEnd: 0x0 -; CHECK: FunctionType: 0x0 +; CHECK: FunctionType: f (0x1002) ; CHECK: CodeOffset: ?f@@YAXMN_J@Z+0x0 ; CHECK: Segment: 0x0 ; CHECK: Flags [ (0x0) @@ -121,7 +161,7 @@ ; CHECK: VarName: v2 ; CHECK: } ; CHECK: Local { -; CHECK: Type: const int* (0x1001) +; CHECK: Type: const int* (0x1004) ; CHECK: VarName: v21 ; CHECK: } ; CHECK: Local { @@ -129,11 +169,11 @@ ; CHECK: VarName: v3 ; CHECK: } ; CHECK: Local { -; CHECK: Type: int ::* (0x1002) +; CHECK: Type: int ::* (0x1005) ; CHECK: VarName: v4 ; CHECK: } ; CHECK: Local { -; CHECK: Type: ::* (0x1003) +; CHECK: Type: void () ::* (0x1008) ; CHECK: VarName: v5 ; CHECK: } ; CHECK: Local {