mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +00:00
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 r202185. rdar://problem/13690847 This re-applies r202184 + a bugfix in DwarfDebug's argument handling. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202188 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9791b3f9ae
commit
dbaa6ab8b5
@ -442,7 +442,7 @@ namespace llvm {
|
|||||||
/// through debug info anchors.
|
/// through debug info anchors.
|
||||||
void retainType(DIType T);
|
void retainType(DIType T);
|
||||||
|
|
||||||
/// createUnspecifiedParameter - Create unspeicified type descriptor
|
/// createUnspecifiedParameter - Create unspecified type descriptor
|
||||||
/// for a subroutine type.
|
/// for a subroutine type.
|
||||||
DIDescriptor createUnspecifiedParameter();
|
DIDescriptor createUnspecifiedParameter();
|
||||||
|
|
||||||
|
@ -403,16 +403,22 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit *SPCU,
|
|||||||
DIArray Args = SPTy.getTypeArray();
|
DIArray Args = SPTy.getTypeArray();
|
||||||
uint16_t SPTag = SPTy.getTag();
|
uint16_t SPTag = SPTy.getTag();
|
||||||
if (SPTag == dwarf::DW_TAG_subroutine_type)
|
if (SPTag == dwarf::DW_TAG_subroutine_type)
|
||||||
|
// FIXME: Use DwarfUnit::constructSubprogramArguments() here.
|
||||||
for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
|
for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
|
||||||
|
DIType ATy(Args.getElement(i));
|
||||||
|
if (ATy.isUnspecifiedParameter()) {
|
||||||
|
assert(i == N-1 && "ellipsis must be the last argument");
|
||||||
|
SPCU->createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, *SPDie);
|
||||||
|
} else {
|
||||||
DIE *Arg =
|
DIE *Arg =
|
||||||
SPCU->createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie);
|
SPCU->createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie);
|
||||||
DIType ATy(Args.getElement(i));
|
|
||||||
SPCU->addType(Arg, ATy);
|
SPCU->addType(Arg, ATy);
|
||||||
if (ATy.isArtificial())
|
if (ATy.isArtificial())
|
||||||
SPCU->addFlag(Arg, dwarf::DW_AT_artificial);
|
SPCU->addFlag(Arg, dwarf::DW_AT_artificial);
|
||||||
if (ATy.isObjectPointer())
|
if (ATy.isObjectPointer())
|
||||||
SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer, Arg);
|
SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer, Arg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
DIE *SPDeclDie = SPDie;
|
DIE *SPDeclDie = SPDie;
|
||||||
SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram,
|
SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram,
|
||||||
*SPCU->getUnitDie());
|
*SPCU->getUnitDie());
|
||||||
@ -582,7 +588,7 @@ DIE *DwarfDebug::createScopeChildrenDIE(DwarfCompileUnit *TheCU,
|
|||||||
DIE *ObjectPointer = NULL;
|
DIE *ObjectPointer = NULL;
|
||||||
|
|
||||||
// Collect arguments for current function.
|
// Collect arguments for current function.
|
||||||
if (LScopes.isCurrentFunctionScope(Scope))
|
if (LScopes.isCurrentFunctionScope(Scope)) {
|
||||||
for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i)
|
for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i)
|
||||||
if (DbgVariable *ArgDV = CurrentFnArguments[i])
|
if (DbgVariable *ArgDV = CurrentFnArguments[i])
|
||||||
if (DIE *Arg =
|
if (DIE *Arg =
|
||||||
@ -592,6 +598,16 @@ DIE *DwarfDebug::createScopeChildrenDIE(DwarfCompileUnit *TheCU,
|
|||||||
ObjectPointer = Arg;
|
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.
|
// Collect lexical scope children first.
|
||||||
const SmallVectorImpl<DbgVariable *> &Variables =
|
const SmallVectorImpl<DbgVariable *> &Variables =
|
||||||
ScopeVariables.lookup(Scope);
|
ScopeVariables.lookup(Scope);
|
||||||
|
@ -1139,6 +1139,22 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) {
|
|||||||
addSourceLine(&Buffer, 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.
|
/// constructTypeDIE - Construct type DIE from DICompositeType.
|
||||||
void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
|
void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
|
||||||
// Add name if not anonymous or intermediate type.
|
// Add name if not anonymous or intermediate type.
|
||||||
@ -1162,19 +1178,12 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
|
|||||||
addType(&Buffer, RTy);
|
addType(&Buffer, RTy);
|
||||||
|
|
||||||
bool isPrototyped = true;
|
bool isPrototyped = true;
|
||||||
// Add arguments.
|
if (Elements.getNumElements() == 2 &&
|
||||||
for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) {
|
Elements.getElement(1).isUnspecifiedParameter())
|
||||||
DIDescriptor Ty = Elements.getElement(i);
|
|
||||||
if (Ty.isUnspecifiedParameter()) {
|
|
||||||
createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer);
|
|
||||||
isPrototyped = false;
|
isPrototyped = false;
|
||||||
} else {
|
|
||||||
DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer);
|
constructSubprogramArguments(Buffer, Elements);
|
||||||
addType(Arg, DIType(Ty));
|
|
||||||
if (DIType(Ty).isArtificial())
|
|
||||||
addFlag(Arg, dwarf::DW_AT_artificial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Add prototype flag if we're dealing with a C language and the
|
// Add prototype flag if we're dealing with a C language and the
|
||||||
// function has been prototyped.
|
// function has been prototyped.
|
||||||
uint16_t Language = getLanguage();
|
uint16_t Language = getLanguage();
|
||||||
@ -1457,13 +1466,7 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
|
|||||||
|
|
||||||
// Add arguments. Do not add arguments for subprogram definition. They will
|
// Add arguments. Do not add arguments for subprogram definition. They will
|
||||||
// be handled while processing variables.
|
// be handled while processing variables.
|
||||||
for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
|
constructSubprogramArguments(*SPDie, Args);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SP.isArtificial())
|
if (SP.isArtificial())
|
||||||
|
@ -476,6 +476,9 @@ protected:
|
|||||||
DIE *getOrCreateStaticMemberDIE(DIDerivedType DT);
|
DIE *getOrCreateStaticMemberDIE(DIDerivedType DT);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// constructSubprogramArguments - Construct function argument DIEs.
|
||||||
|
void constructSubprogramArguments(DIE &Buffer, DIArray Args);
|
||||||
|
|
||||||
/// constructTypeDIE - Construct basic type die from DIBasicType.
|
/// constructTypeDIE - Construct basic type die from DIBasicType.
|
||||||
void constructTypeDIE(DIE &Buffer, DIBasicType BTy);
|
void constructTypeDIE(DIE &Buffer, DIBasicType BTy);
|
||||||
|
|
||||||
|
90
test/DebugInfo/X86/varargs.ll
Normal file
90
test/DebugInfo/X86/varargs.ll
Normal file
@ -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}
|
Loading…
Reference in New Issue
Block a user