aboutsummaryrefslogtreecommitdiff
path: root/llvm/test/DebugInfo/Generic/no-empty-child-vars.ll
blob: 2b533968e33002178ba6127fea1a3a828fa25a7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
; RUN: %llc_dwarf %s -o - -filetype=obj | llvm-dwarfdump - | FileCheck %s -implicit-check-not=DW_TAG
;
; Issue #46473
; XFAIL: target=sparc{{.*}}
;
; This tests that we do not create concrete variable DIEs for variables that
; have no location -- for both ways that LLVM-IR can express a variable with
; no location. It's possible to:
;   1) Omit all dbg.values and place the variable in the subprograms retained
;      nodes list,
;   2) Have a dbg.value with an undef operand, and none with "real" operands.
; Both of these should produce the same DWARF. In the two functions below
; (qux and croix) I've modified the IR to represent both scenarios.
;
; Original C, LLVM-IR modified afterwards:
;
; int foo(int bar) {
;   int baz = 12 + bar;
;   return baz;
; }
;
; int qux(int quux) {
;   int xyzzy = foo(quux);
;   return xyzzy;
; }
;
; int croix(int quux) {
;   int xyzzy = foo(quux);
;   return xyzzy;
; }
;
;; Note the implicit DW_TAG check-not in the FileCheck command line.
; CHECK: DW_TAG_compile_unit
;;
;; First subprogram is attached to the plain "foo" function in the output
;; object. It should have locations for the two variables in the function,
;; let's be non-specific as to how.
; CHECK:     DW_TAG_subprogram
; CHECK:       DW_AT_abstract_origin (0x{{[0-9a-f]*}} "foo")
; CHECK:       DW_TAG_formal_parameter
; CHECK:         DW_AT_location
; CHECK:       DW_TAG_variable
; CHECK:         DW_AT_location
;
;; Abstract subprogram; should have plain variable declarations
; CHECK:     DW_TAG_subprogram
; CHECK:       DW_AT_name ("foo")
; CHECK:       DW_TAG_formal_parameter
; CHECK:         DW_AT_name ("bar")
; CHECK:       DW_TAG_variable
; CHECK:         DW_AT_name ("baz")
;
; CHECK:     DW_TAG_base_type
;
;; The copy of "foo" inlined into "qux" should have no children.
; CHECK:     DW_TAG_subprogram
; CHECK:       DW_AT_name ("qux")
; CHECK:       DW_TAG_formal_parameter
; CHECK:       DW_TAG_variable
; CHECK:       DW_TAG_inlined_subroutine
; CHECK:     NULL
;
;; Same for the copy of foo inlined into "croix"
; CHECK:     DW_TAG_subprogram
; CHECK:       DW_AT_name ("croix")
; CHECK:       DW_TAG_formal_parameter
; CHECK:       DW_TAG_variable
; CHECK:       DW_TAG_inlined_subroutine
; CHECK:     NULL

; NOTE: Instructions below changed from `add` to `mul` to make them more expensive
; and unlikely to be sunk to replace COPYs into a return value register.

; Function Attrs: norecurse nounwind readnone uwtable willreturn
define dso_local i32 @foo(i32 %bar) local_unnamed_addr !dbg !7 {
entry:
  call void @llvm.dbg.value(metadata i32 %bar, metadata !12, metadata !DIExpression()), !dbg !14
  %add = mul nsw i32 %bar, 12, !dbg !15
  call void @llvm.dbg.value(metadata i32 %add, metadata !13, metadata !DIExpression()), !dbg !14
  ret i32 %add, !dbg !16
}

; Function Attrs: norecurse nounwind readnone uwtable willreturn
define dso_local i32 @qux(i32 %quux) local_unnamed_addr !dbg !17 {
entry:
  %add.i = mul nsw i32 %quux, 12, !dbg !24
  ret i32 %add.i, !dbg !25
}

; Function Attrs: norecurse nounwind readnone uwtable willreturn
define dso_local i32 @croix(i32 %quux) local_unnamed_addr !dbg !26 {
entry:
  call void @llvm.dbg.value(metadata i32 undef, metadata !28, metadata !DIExpression()), !dbg !30
  call void @llvm.dbg.value(metadata i32 undef, metadata !12, metadata !DIExpression()), !dbg !31
  %add.i = mul nsw i32 %quux, 12, !dbg !33
  call void @llvm.dbg.value(metadata i32 undef, metadata !13, metadata !DIExpression()), !dbg !31
  call void @llvm.dbg.value(metadata i32 undef, metadata !29, metadata !DIExpression()), !dbg !30
  ret i32 %add.i, !dbg !34
}

; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
declare void @llvm.dbg.value(metadata, metadata, metadata)

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5}
!llvm.ident = !{!6}

!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "test.c", directory: ".")
!2 = !{}
!3 = !{i32 7, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 4}
!6 = !{!"clang"}
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
!8 = !DISubroutineType(types: !9)
!9 = !{!10, !10}
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!11 = !{!12, !13}
!12 = !DILocalVariable(name: "bar", arg: 1, scope: !7, file: !1, line: 1, type: !10)
!13 = !DILocalVariable(name: "baz", scope: !7, file: !1, line: 2, type: !10)
!14 = !DILocation(line: 0, scope: !7)
!15 = !DILocation(line: 2, column: 16, scope: !7)
!16 = !DILocation(line: 3, column: 3, scope: !7)
!17 = distinct !DISubprogram(name: "qux", scope: !1, file: !1, line: 6, type: !8, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !18)
!18 = !{!19, !20}
!19 = !DILocalVariable(name: "quux", arg: 1, scope: !17, file: !1, line: 6, type: !10)
!20 = !DILocalVariable(name: "xyzzy", scope: !17, file: !1, line: 7, type: !10)
!21 = !DILocation(line: 0, scope: !17)
!22 = !DILocation(line: 0, scope: !7, inlinedAt: !23)
!23 = distinct !DILocation(line: 7, column: 15, scope: !17)
!24 = !DILocation(line: 2, column: 16, scope: !7, inlinedAt: !23)
!25 = !DILocation(line: 8, column: 3, scope: !17)
!26 = distinct !DISubprogram(name: "croix", scope: !1, file: !1, line: 11, type: !8, scopeLine: 11, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !27)
!27 = !{!28, !29}
!28 = !DILocalVariable(name: "quux", arg: 1, scope: !26, file: !1, line: 11, type: !10)
!29 = !DILocalVariable(name: "xyzzy", scope: !26, file: !1, line: 12, type: !10)
!30 = !DILocation(line: 0, scope: !26)
!31 = !DILocation(line: 0, scope: !7, inlinedAt: !32)
!32 = distinct !DILocation(line: 12, column: 15, scope: !26)
!33 = !DILocation(line: 2, column: 16, scope: !7, inlinedAt: !32)
!34 = !DILocation(line: 13, column: 3, scope: !26)