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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
| # RUN: llc -debug-entry-values -start-after=machineverifier -filetype=obj %s -o -| llvm-dwarfdump -| FileCheck %s
#
# CHECK: DW_TAG_GNU_call_site
# CHECK-NEXT: DW_AT_abstract_origin {{.*}} "foo"
# CHECK-NEXT: DW_AT_low_pc
# CHECK-EMPTY:
# CHECK-NEXT: DW_TAG_GNU_call_site_parameter
# CHECK-NEXT: DW_AT_location (DW_OP_reg2 RCX)
# CHECK-NEXT: DW_AT_GNU_call_site_value (DW_OP_breg14 R14+0)
# CHECK-EMPTY:
# CHECK-NEXT: DW_TAG_GNU_call_site_parameter
# CHECK-NEXT: DW_AT_location (DW_OP_reg1 RDX)
# CHECK-NEXT: DW_AT_GNU_call_site_value (DW_OP_fbreg +8)
# CHECK-EMPTY:
# CHECK-NEXT: DW_TAG_GNU_call_site_parameter
# CHECK-NEXT: DW_AT_location (DW_OP_reg5 RDI)
# CHECK-NEXT: DW_AT_GNU_call_site_value (DW_OP_GNU_entry_value(DW_OP_reg4 RSI))
# CHECK-EMPTY:
# CHECK: DW_TAG_GNU_call_site
# CHECK-NEXT: DW_AT_abstract_origin {{.*}}"foo"
# CHECK-NEXT: DW_AT_low_pc
# CHECK-EMPTY:
# CHECK-NEXT: DW_TAG_GNU_call_site_parameter
# RCX loads memory location. We can't rely that memory location won't be changed.
# CHECK-NOT: DW_AT_location (DW_OP_reg2 RCX)
# CHECK-NEXT: DW_AT_location (DW_OP_reg4 RSI)
# CHECK-NEXT: DW_AT_GNU_call_site_value (DW_OP_lit4)
# CHECK-EMPTY:
# CHECK-NOT: DW_TAG_GNU_call_site_parameter
#
# Check that call site interpretation analysis can interpret instructions such
# as move immediate, register to register moves, stack loading and LEA
# instructions. Last negative check should verify that we are not producing
# interpretation for RDX register since its loaded value is call clobberable.
# Also check that we are generating proper call site debug entities.
--- |
; ModuleID = 'dbgcall-site-interpretation.c'
source_filename = "dbgcall-site-interpretation.c"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: nounwind uwtable
define dso_local i32 @baa(i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) local_unnamed_addr !dbg !9 {
entry:
%arg3.addr = alloca i32, align 4
%local2 = alloca i32, align 4
call void @llvm.dbg.value(metadata i32 %arg1, metadata !14, metadata !DIExpression()), !dbg !21
call void @llvm.dbg.value(metadata i32 %arg2, metadata !15, metadata !DIExpression()), !dbg !21
call void @llvm.dbg.value(metadata i32 %arg3, metadata !16, metadata !DIExpression()), !dbg !21
store i32 %arg3, i32* %arg3.addr, align 4
call void @llvm.dbg.value(metadata i32 %arg4, metadata !17, metadata !DIExpression()), !dbg !21
%0 = bitcast i32* %local2 to i8*, !dbg !21
call void @llvm.dbg.value(metadata i32* %arg3.addr, metadata !16, metadata !DIExpression(DW_OP_deref)), !dbg !21
%call = call i32 @foo(i32 %arg1, i32 %arg2, i32* nonnull %arg3.addr, i32 %arg4), !dbg !21
call void @llvm.dbg.value(metadata i32 %call, metadata !18, metadata !DIExpression()), !dbg !21
%cmp = icmp sgt i32 %arg1, %arg2, !dbg !21
%1 = load i32, i32* %arg3.addr, align 4, !dbg !21
call void @llvm.dbg.value(metadata i32 %1, metadata !16, metadata !DIExpression()), !dbg !21
%add = add nsw i32 %1, %arg1, !dbg !21
%add1 = add nsw i32 %arg4, %arg2, !dbg !21
%local1.0 = select i1 %cmp, i32 %add, i32 %add1, !dbg !21
call void @llvm.dbg.value(metadata i32 %local1.0, metadata !18, metadata !DIExpression()), !dbg !21
%rem = srem i32 %1, %arg1, !dbg !21
%tobool = icmp eq i32 %rem, 0, !dbg !21
%mul = mul nsw i32 %1, %arg1, !dbg !21
%add3 = add nsw i32 %1, %arg4, !dbg !21
%storemerge = select i1 %tobool, i32 %mul, i32 %add3, !dbg !21
call void @llvm.dbg.value(metadata i32 %storemerge, metadata !19, metadata !DIExpression()), !dbg !21
store i32 %storemerge, i32* %local2, align 4, !dbg !21
%cmp6 = icmp slt i32 %storemerge, %arg4, !dbg !21
%local3.0.v = select i1 %cmp6, i32 %local1.0, i32 %arg1, !dbg !21
%local3.0 = mul nsw i32 %local3.0.v, %storemerge, !dbg !21
call void @llvm.dbg.value(metadata i32 %local3.0, metadata !20, metadata !DIExpression()), !dbg !21
call void @llvm.dbg.value(metadata i32* %local2, metadata !19, metadata !DIExpression(DW_OP_deref)), !dbg !21
%call12 = call i32 @foo(i32 %local1.0, i32 4, i32* nonnull %local2, i32 %local3.0), !dbg !21
call void @llvm.dbg.value(metadata i32 %call12, metadata !14, metadata !DIExpression()), !dbg !21
%add13 = add nsw i32 %call12, 4, !dbg !21
ret i32 %add13, !dbg !21
}
declare !dbg !4 dso_local i32 @foo(i32, i32, i32*, i32) local_unnamed_addr
; Function Attrs: nounwind readnone speculatable
declare void @llvm.dbg.value(metadata, metadata, metadata)
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!5, !6, !7}
!llvm.ident = !{!8}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
!1 = !DIFile(filename: "dbgcall-site-interpretation.c", directory: "/dir")
!2 = !{}
!3 = !{!4}
!4 = !DISubprogram(name: "foo", scope: !1, file: !1, line: 9, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
!5 = !{i32 2, !"Dwarf Version", i32 4}
!6 = !{i32 2, !"Debug Info Version", i32 3}
!7 = !{i32 1, !"wchar_size", i32 4}
!8 = !{!"clang version 9.0.0"}
!9 = distinct !DISubprogram(name: "baa", scope: !1, file: !1, line: 10, type: !10, scopeLine: 10, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13)
!10 = !DISubroutineType(types: !11)
!11 = !{!12, !12, !12, !12, !12}
!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!13 = !{!14, !15, !16, !17, !18, !19, !20}
!14 = !DILocalVariable(name: "arg1", arg: 1, scope: !9, file: !1, line: 10, type: !12)
!15 = !DILocalVariable(name: "arg2", arg: 2, scope: !9, file: !1, line: 10, type: !12, flags: DIFlagArgumentNotModified)
!16 = !DILocalVariable(name: "arg3", arg: 3, scope: !9, file: !1, line: 10, type: !12)
!17 = !DILocalVariable(name: "arg4", arg: 4, scope: !9, file: !1, line: 10, type: !12, flags: DIFlagArgumentNotModified)
!18 = !DILocalVariable(name: "local1", scope: !9, file: !1, line: 11, type: !12)
!19 = !DILocalVariable(name: "local2", scope: !9, file: !1, line: 11, type: !12)
!20 = !DILocalVariable(name: "local3", scope: !9, file: !1, line: 11, type: !12)
!21 = !DILocation(line: 10, column: 13, scope: !9)
...
---
name: baa
liveins:
- { reg: '$edi', virtual-reg: '' }
- { reg: '$esi', virtual-reg: '' }
- { reg: '$edx', virtual-reg: '' }
- { reg: '$ecx', virtual-reg: '' }
callSites:
- { bb: 0, offset: 23, fwdArgRegs:
- { arg: 0, reg: '$edi' }
- { arg: 1, reg: '$esi' }
- { arg: 2, reg: '$rdx' }
- { arg: 3, reg: '$ecx' } }
- { bb: 0, offset: 49, fwdArgRegs:
- { arg: 0, reg: '$edi' }
- { arg: 1, reg: '$esi' }
- { arg: 2, reg: '$rdx' }
- { arg: 3, reg: '$ecx' } }
body: |
bb.0.entry:
liveins: $ecx, $edi, $edx, $esi, $r15, $r14, $rbx
DBG_VALUE $edi, $noreg, !14, !DIExpression(), debug-location !21
DBG_VALUE $esi, $noreg, !15, !DIExpression(), debug-location !21
DBG_VALUE $edx, $noreg, !16, !DIExpression(), debug-location !21
DBG_VALUE $ecx, $noreg, !17, !DIExpression(), debug-location !21
frame-setup PUSH64r killed $r15, implicit-def $rsp, implicit $rsp
CFI_INSTRUCTION def_cfa_offset 16
frame-setup PUSH64r killed $r14, implicit-def $rsp, implicit $rsp
CFI_INSTRUCTION def_cfa_offset 24
frame-setup PUSH64r killed $rbx, implicit-def $rsp, implicit $rsp
CFI_INSTRUCTION def_cfa_offset 32
$rsp = frame-setup SUB64ri8 $rsp, 16, implicit-def dead $eflags
CFI_INSTRUCTION def_cfa_offset 48
CFI_INSTRUCTION offset $rbx, -32
CFI_INSTRUCTION offset $r14, -24
CFI_INSTRUCTION offset $r15, -16
$r14d = MOV32rr $ecx, implicit-def $r14
DBG_VALUE $edx, $noreg, !16, !DIExpression(), debug-location !21
$r15d = MOV32rr $esi, implicit-def $r15
$ebx = MOV32rr $edi, implicit-def $rbx
$edi = MOV32rr $esi
MOV32mr $rsp, 1, $noreg, 8, $noreg, killed renamable $edx :: (store 4 into %ir.arg3.addr)
renamable $rdx = LEA64r $rsp, 1, $noreg, 8, $noreg
renamable $ecx = MOV32rr $r14d,
CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit $rdx, implicit $ecx, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, implicit-def $rax, debug-location !21
DBG_VALUE $noreg, $noreg, !18, !DIExpression(), debug-location !21
$rdx = MOV64rr renamable $rax
$ecx = KILL renamable $ecx, implicit-def $rcx
renamable $eax = LEA64_32r renamable $rcx, 1, renamable $rbx, 0, $noreg, debug-location !21
renamable $edi = LEA64_32r renamable $r14, 1, renamable $r15, 0, $noreg, debug-location !21
CMP32rr renamable $ebx, renamable $r15d, implicit-def $eflags, implicit killed $r15, debug-location !21
renamable $edi = CMOV32rr killed renamable $edi, killed renamable $eax, 15, implicit killed $eflags, debug-location !21
DBG_VALUE $edi, $noreg, !18, !DIExpression(), debug-location !21
$eax = MOV32rr $ecx, debug-location !21
CDQ implicit-def $eax, implicit-def $edx, implicit $eax, debug-location !21
IDIV32r renamable $ebx, implicit-def dead $eax, implicit-def $edx, implicit-def dead $eflags, implicit $eax, implicit $edx, debug-location !21
$eax = MOV32rr $ecx, debug-location !21
renamable $eax = nsw IMUL32rr killed renamable $eax, renamable $ebx, implicit-def dead $eflags, debug-location !21
renamable $ecx = nsw ADD32rr renamable $ecx, renamable $r14d, implicit-def dead $eflags, implicit killed $rcx, implicit-def $rcx, debug-location !21
TEST32rr killed renamable $edx, renamable $edx, implicit-def $eflags, debug-location !21
renamable $ecx = CMOV32rr renamable $ecx, killed renamable $eax, 4, implicit killed $eflags, implicit killed $rcx, implicit-def $rcx, debug-location !21
DBG_VALUE $ecx, $noreg, !19, !DIExpression(), debug-location !21
MOV32mr $rsp, 1, $noreg, 12, $noreg, renamable $ecx, debug-location !21 :: (store 4 into %ir.local2)
CMP32rr renamable $ecx, renamable $r14d, implicit-def $eflags, implicit killed $r14, debug-location !21
renamable $ebx = CMOV32rr renamable $ebx, renamable $edi, 12, implicit killed $eflags, implicit killed $rbx, implicit-def $rbx, debug-location !21
renamable $ecx = nsw IMUL32rr renamable $ecx, renamable $ebx, implicit-def dead $eflags, implicit killed $rbx, implicit killed $rcx, implicit-def $rcx, debug-location !21
DBG_VALUE $rsp, $noreg, !19, !DIExpression(DW_OP_plus_uconst, 12, DW_OP_deref), debug-location !21
DBG_VALUE $ecx, $noreg, !20, !DIExpression(), debug-location !21
$esi = MOV32ri 4, debug-location !21
renamable $ecx = MOV32rm $rsp, 1, $noreg, 8, $noreg, implicit-def $rcx, debug-location !21 :: (dereferenceable load 4 from %ir.arg3.addr)
CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit $rdx, implicit $ecx, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, implicit-def $rax, debug-location !21
DBG_VALUE $eax, $noreg, !14, !DIExpression(), debug-location !21
renamable $eax = nsw ADD32ri8 killed renamable $eax, 4, implicit-def dead $eflags, debug-location !21
$rsp = frame-destroy ADD64ri8 $rsp, 16, implicit-def dead $eflags, debug-location !21
CFI_INSTRUCTION def_cfa_offset 32, debug-location !21
$rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !21
CFI_INSTRUCTION def_cfa_offset 24, debug-location !21
$r14 = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !21
DBG_VALUE $ecx, $noreg, !17, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !21
CFI_INSTRUCTION def_cfa_offset 16, debug-location !21
$r15 = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !21
DBG_VALUE $esi, $noreg, !15, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !21
CFI_INSTRUCTION def_cfa_offset 8, debug-location !21
RETQ $eax, debug-location !21
...
|