From c6d0a14a788cd602766b005afa03f54019a9e298 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 25 Feb 2014 19:38:07 +0000 Subject: [PATCH] Debug info: Support variadic functions. Variadic functions have an unspecified parameter tag after the last argument. In IR this is represented as an unspecified parameter in the subroutine type. Paired commit with CFE. rdar://problem/13690847 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202184 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DIBuilder.h | 2 +- lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 12 +++- lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 43 +++++++------ lib/CodeGen/AsmPrinter/DwarfUnit.h | 3 + test/DebugInfo/X86/varargs.ll | 90 +++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 22 deletions(-) create mode 100644 test/DebugInfo/X86/varargs.ll diff --git a/include/llvm/DIBuilder.h b/include/llvm/DIBuilder.h index c8595a02f1..7cd5a1bcf0 100644 --- a/include/llvm/DIBuilder.h +++ b/include/llvm/DIBuilder.h @@ -442,7 +442,7 @@ namespace llvm { /// through debug info anchors. void retainType(DIType T); - /// createUnspecifiedParameter - Create unspeicified type descriptor + /// createUnspecifiedParameter - Create unspecified type descriptor /// for a subroutine type. DIDescriptor createUnspecifiedParameter(); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 2425948ae9..f9ee2705a3 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -582,7 +582,7 @@ DIE *DwarfDebug::createScopeChildrenDIE(DwarfCompileUnit *TheCU, DIE *ObjectPointer = NULL; // Collect arguments for current function. - if (LScopes.isCurrentFunctionScope(Scope)) + if (LScopes.isCurrentFunctionScope(Scope)) { for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i) if (DbgVariable *ArgDV = CurrentFnArguments[i]) if (DIE *Arg = @@ -592,6 +592,16 @@ DIE *DwarfDebug::createScopeChildrenDIE(DwarfCompileUnit *TheCU, ObjectPointer = Arg; } + // Create the unspecified parameter that marks a function as variadic. + DISubprogram SP(Scope->getScopeNode()); + assert(SP.Verify()); + DIArray FnArgs = SP.getType().getTypeArray(); + if (FnArgs.getElement(FnArgs.getNumElements()-1).isUnspecifiedParameter()) { + DIE *Ellipsis = new DIE(dwarf::DW_TAG_unspecified_parameters); + Children.push_back(Ellipsis); + } + } + // Collect lexical scope children first. const SmallVectorImpl &Variables = ScopeVariables.lookup(Scope); diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 81dbfc505a..4626c43f56 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1139,6 +1139,22 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { addSourceLine(&Buffer, DTy); } +/// constructSubprogramArguments - Construct function argument DIEs. +void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DIArray Args) { + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIDescriptor Ty = Args.getElement(i); + if (Ty.isUnspecifiedParameter()) { + assert(i == N-1 && "ellipsis must be the last argument"); + createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer); + } else { + DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer); + addType(Arg, DIType(Ty)); + if (DIType(Ty).isArtificial()) + addFlag(Arg, dwarf::DW_AT_artificial); + } + } +} + /// constructTypeDIE - Construct type DIE from DICompositeType. void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { // Add name if not anonymous or intermediate type. @@ -1162,19 +1178,12 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { addType(&Buffer, RTy); bool isPrototyped = true; - // Add arguments. - for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { - DIDescriptor Ty = Elements.getElement(i); - if (Ty.isUnspecifiedParameter()) { - createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer); - isPrototyped = false; - } else { - DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer); - addType(Arg, DIType(Ty)); - if (DIType(Ty).isArtificial()) - addFlag(Arg, dwarf::DW_AT_artificial); - } - } + if (Elements.getNumElements() == 2 && + Elements.getElement(1).isUnspecifiedParameter()) + isPrototyped = false; + + constructSubprogramArguments(Buffer, Elements); + // Add prototype flag if we're dealing with a C language and the // function has been prototyped. uint16_t Language = getLanguage(); @@ -1457,13 +1466,7 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) { // Add arguments. Do not add arguments for subprogram definition. They will // be handled while processing variables. - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie); - DIType ATy(Args.getElement(i)); - addType(Arg, ATy); - if (ATy.isArtificial()) - addFlag(Arg, dwarf::DW_AT_artificial); - } + constructSubprogramArguments(*SPDie, Args); } if (SP.isArtificial()) diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.h b/lib/CodeGen/AsmPrinter/DwarfUnit.h index 370ecbf831..bf77272b8a 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -476,6 +476,9 @@ protected: DIE *getOrCreateStaticMemberDIE(DIDerivedType DT); private: + /// constructSubprogramArguments - Construct function argument DIEs. + void constructSubprogramArguments(DIE &Buffer, DIArray Args); + /// constructTypeDIE - Construct basic type die from DIBasicType. void constructTypeDIE(DIE &Buffer, DIBasicType BTy); diff --git a/test/DebugInfo/X86/varargs.ll b/test/DebugInfo/X86/varargs.ll new file mode 100644 index 0000000000..e724d75445 --- /dev/null +++ b/test/DebugInfo/X86/varargs.ll @@ -0,0 +1,90 @@ +; RUN: llc -O0 -filetype=obj -o %t.o %s +; RUN: llvm-dwarfdump -debug-dump=info %t.o | FileCheck %s +; +; Normal variadic function. +; +; CHECK: DW_TAG_subprogram +; CHECK-NOT: DW_TAG +; CHECK: DW_TAG_formal_parameter +; CHECK-NOT: DW_TAG +; CHECK: DW_TAG_unspecified_parameters +; +; Variadic C++ member function. +; +; CHECK: DW_TAG_subprogram +; CHECK-NOT: DW_TAG +; CHECK: DW_TAG_formal_parameter +; CHECK-NOT: DW_TAG +; CHECK: DW_TAG_formal_parameter +; CHECK-NOT: DW_TAG +; CHECK: DW_TAG_unspecified_parameters +; +; Variadic function pointer. +; +; CHECK: DW_TAG_subroutine_type +; CHECK-NOT: DW_TAG +; CHECK: DW_TAG_formal_parameter +; CHECK-NOT: DW_TAG +; CHECK: DW_TAG_unspecified_parameters +; +; Test debug info for variadic function arguments. +; Created from tools/clang/tests/CodeGenCXX/debug-info-varargs.cpp +; +; ModuleID = 'llvm/tools/clang/test/CodeGenCXX/debug-info-varargs.cpp' +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.9.0" + +%struct.A = type { i8 } + +; Function Attrs: nounwind ssp uwtable +define void @_Z1biz(i32 %c, ...) #0 { + %1 = alloca i32, align 4 + %a = alloca %struct.A, align 1 + %fptr = alloca void (i32, ...)*, align 8 + store i32 %c, i32* %1, align 4 + call void @llvm.dbg.declare(metadata !{i32* %1}, metadata !21), !dbg !22 + call void @llvm.dbg.declare(metadata !{%struct.A* %a}, metadata !23), !dbg !24 + call void @llvm.dbg.declare(metadata !{void (i32, ...)** %fptr}, metadata !25), !dbg !27 + store void (i32, ...)* @_Z1biz, void (i32, ...)** %fptr, align 8, !dbg !27 + ret void, !dbg !28 +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata) #1 + +attributes #0 = { nounwind ssp uwtable } +attributes #1 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!18, !19} +!llvm.ident = !{!20} + +!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.5 ", i1 false, metadata !"", i32 0, metadata !2, metadata !3, metadata !13, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [llvm/tools/clang/test/CodeGenCXX/debug-info-varargs.cpp] [DW_LANG_C_plus_plus] +!1 = metadata !{metadata !"llvm/tools/clang/test/CodeGenCXX/debug-info-varargs.cpp", metadata !"radar/13690847"} +!2 = metadata !{} +!3 = metadata !{metadata !4} +!4 = metadata !{i32 786451, metadata !1, null, metadata !"A", i32 3, i64 8, i64 8, i32 0, i32 0, null, metadata !5, i32 0, null, null, metadata !"_ZTS1A"} ; [ DW_TAG_structure_type ] [A] [line 3, size 8, align 8, offset 0] [def] [from ] +!5 = metadata !{metadata !6} +!6 = metadata !{i32 786478, metadata !1, metadata !"_ZTS1A", metadata !"a", metadata !"a", metadata !"_ZN1A1aEiz", i32 6, metadata !7, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null, i32 0, metadata !12, i32 6} ; [ DW_TAG_subprogram ] [line 6] [a] +!7 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!8 = metadata !{null, metadata !9, metadata !10, metadata !11} +!9 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 1088, metadata !"_ZTS1A"} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [artificial] [from _ZTS1A] +!10 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!11 = metadata !{i32 786456} +!12 = metadata !{i32 786468} +!13 = metadata !{metadata !14} +!14 = metadata !{i32 786478, metadata !1, metadata !15, metadata !"b", metadata !"b", metadata !"_Z1biz", i32 13, metadata !16, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i32, ...)* @_Z1biz, null, null, metadata !2, i32 13} ; [ DW_TAG_subprogram ] [line 13] [def] [b] +!15 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [llvm/tools/clang/test/CodeGenCXX/debug-info-varargs.cpp] +!16 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !17, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!17 = metadata !{null, metadata !10, metadata !11} +!18 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} +!19 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!20 = metadata !{metadata !"clang version 3.5 "} +!21 = metadata !{i32 786689, metadata !14, metadata !"c", metadata !15, i32 16777229, metadata !10, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [c] [line 13] +!22 = metadata !{i32 13, i32 0, metadata !14, null} +!23 = metadata !{i32 786688, metadata !14, metadata !"a", metadata !15, i32 16, metadata !4, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [a] [line 16] +!24 = metadata !{i32 16, i32 0, metadata !14, null} +!25 = metadata !{i32 786688, metadata !14, metadata !"fptr", metadata !15, i32 18, metadata !26, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [fptr] [line 18] +!26 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !16} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ] +!27 = metadata !{i32 18, i32 0, metadata !14, null} +!28 = metadata !{i32 22, i32 0, metadata !14, null} -- 2.39.2