Skip to content

Commit b21a6ca

Browse files
committed
Fix crash at translation of invalid debug value instruction
1 parent 8ce6443 commit b21a6ca

File tree

2 files changed

+211
-3
lines changed

2 files changed

+211
-3
lines changed

lib/SPIRV/LLVMToSPIRVDbgTran.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,15 @@ void LLVMToSPIRVDbgTran::transLocationInfo() {
162162
unsigned LineNo = 0;
163163
unsigned Col = 0;
164164
for (const Instruction &I : BB) {
165+
V = SPIRVWriter->getTranslatedValue(&I);
166+
// If instruction was not translated, just skip it.
167+
if (!V)
168+
continue;
165169
const DebugLoc &DL = I.getDebugLoc();
166170
if (!DL.get()) {
167171
if (DbgScope || InlinedAt) { // Emit DebugNoScope
168172
DbgScope = nullptr;
169173
InlinedAt = nullptr;
170-
V = SPIRVWriter->getTranslatedValue(&I);
171174
transDebugLoc(DL, SBB, static_cast<SPIRVInstruction *>(V));
172175
}
173176
continue;
@@ -176,7 +179,6 @@ void LLVMToSPIRVDbgTran::transLocationInfo() {
176179
if (DL.getScope() != DbgScope || DL.getInlinedAt() != InlinedAt) {
177180
DbgScope = DL.getScope();
178181
InlinedAt = DL.getInlinedAt();
179-
V = SPIRVWriter->getTranslatedValue(&I);
180182
transDebugLoc(DL, SBB, static_cast<SPIRVInstruction *>(V));
181183
}
182184
// If any component of OpLine has changed emit another OpLine
@@ -186,7 +188,6 @@ void LLVMToSPIRVDbgTran::transLocationInfo() {
186188
File = DirAndFile;
187189
LineNo = DL.getLine();
188190
Col = DL.getCol();
189-
V = SPIRVWriter->getTranslatedValue(&I);
190191
BM->addLine(V, File ? File->getId() : getDebugInfoNone()->getId(),
191192
LineNo, Col);
192193
}
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
; Source:
2+
; __kernel void kernel_fn(__global int *res) {}
3+
;
4+
; __kernel void testKernel(__global int *res) {
5+
; ndrange_t ndrange;
6+
; void (^kernelBlock)(void) = ^{ kernel_fn(res); };
7+
; enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, kernelBlock);
8+
; }
9+
10+
; Command:
11+
; clang-7 -cc1 -triple spir -cl-std=cl2.0 -finclude-default-header -disable-llvm-passes /work/tmp/tmp.cl -debug-info-kind=limited -dwarf-column-info -emit-llvm -o - | opt-7 -mem2reg -S -o test/DebugInfo/DebugValueInvalid.ll
12+
13+
; RUN: llvm-as < %s | llvm-spirv -spirv-text -o %t
14+
; RUN: FileCheck < %t %s
15+
16+
; ModuleID = '<stdin>'
17+
source_filename = "/work/tmp/tmp.cl"
18+
target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
19+
target triple = "spir"
20+
21+
%struct.ndrange_t = type { i32, [3 x i32], [3 x i32], [3 x i32] }
22+
%opencl.queue_t = type opaque
23+
24+
; Function Attrs: convergent nounwind
25+
define spir_kernel void @kernel_fn(i32 addrspace(1)* %res) #0 !dbg !7 !kernel_arg_addr_space !15 !kernel_arg_access_qual !16 !kernel_arg_type !17 !kernel_arg_base_type !17 !kernel_arg_type_qual !18 {
26+
entry:
27+
call void @llvm.dbg.value(metadata i32 addrspace(1)* %res, metadata !14, metadata !DIExpression()), !dbg !19
28+
ret void, !dbg !20
29+
}
30+
31+
; Function Attrs: nounwind readnone speculatable
32+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
33+
34+
; Function Attrs: convergent nounwind
35+
define spir_kernel void @testKernel(i32 addrspace(1)* %res) #0 !dbg !21 !kernel_arg_addr_space !15 !kernel_arg_access_qual !16 !kernel_arg_type !17 !kernel_arg_base_type !17 !kernel_arg_type_qual !18 {
36+
entry:
37+
%ndrange = alloca %struct.ndrange_t, align 4
38+
%block = alloca <{ i32, i32, i32 addrspace(1)* }>, align 4
39+
%tmp = alloca %struct.ndrange_t, align 4
40+
call void @llvm.dbg.value(metadata i32 addrspace(1)* %res, metadata !23, metadata !DIExpression()), !dbg !45
41+
%0 = bitcast %struct.ndrange_t* %ndrange to i8*, !dbg !46
42+
call void @llvm.lifetime.start.p0i8(i64 40, i8* %0) #5, !dbg !46
43+
call void @llvm.dbg.declare(metadata %struct.ndrange_t* %ndrange, metadata !24, metadata !DIExpression()), !dbg !47
44+
%block.size = getelementptr inbounds <{ i32, i32, i32 addrspace(1)* }>, <{ i32, i32, i32 addrspace(1)* }>* %block, i32 0, i32 0, !dbg !48
45+
store i32 12, i32* %block.size, align 4, !dbg !48
46+
%block.align = getelementptr inbounds <{ i32, i32, i32 addrspace(1)* }>, <{ i32, i32, i32 addrspace(1)* }>* %block, i32 0, i32 1, !dbg !48
47+
store i32 4, i32* %block.align, align 4, !dbg !48
48+
49+
%block.captured = getelementptr inbounds <{ i32, i32, i32 addrspace(1)* }>, <{ i32, i32, i32 addrspace(1)* }>* %block, i32 0, i32 2, !dbg !48
50+
store i32 addrspace(1)* %res, i32 addrspace(1)** %block.captured, align 4, !dbg !48, !tbaa !49
51+
%1 = bitcast <{ i32, i32, i32 addrspace(1)* }>* %block to void ()*, !dbg !48
52+
%2 = addrspacecast void ()* %1 to void () addrspace(4)*, !dbg !48
53+
call void @llvm.dbg.value(metadata void () addrspace(4)* %2, metadata !38, metadata !DIExpression()), !dbg !53
54+
%call = call spir_func %opencl.queue_t* @_Z17get_default_queuev() #6, !dbg !54
55+
; CHECK: InBoundsPtrAccessChain
56+
; CHECK: Store
57+
; SPIRVLowerOCLBlocks pass has removed bitcast and addrspacecast, because their operands are function pointers.
58+
; CHECK-NOT: BitCast
59+
; CHECK-NOT: PtrCastToGeneric
60+
; The result of these casts was used by llvm.dbg.value. This intrinsic becomes invalid,
61+
; so we do not translate it and its debug location
62+
; CHECK-NOT: DebugValue
63+
; CHECK: GetDefaultQueue
64+
65+
%3 = bitcast %struct.ndrange_t* %tmp to i8*, !dbg !55
66+
%4 = bitcast %struct.ndrange_t* %ndrange to i8*, !dbg !55
67+
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %3, i8* align 4 %4, i32 40, i1 false), !dbg !55, !tbaa.struct !56
68+
%5 = addrspacecast void ()* %1 to i8 addrspace(4)*, !dbg !60
69+
%6 = call i32 @__enqueue_kernel_basic(%opencl.queue_t* %call, i32 0, %struct.ndrange_t* byval %tmp, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*)* @__testKernel_block_invoke_kernel to i8*) to i8 addrspace(4)*), i8 addrspace(4)* %5), !dbg !60
70+
%7 = bitcast %struct.ndrange_t* %ndrange to i8*, !dbg !61
71+
call void @llvm.lifetime.end.p0i8(i64 40, i8* %7) #5, !dbg !61
72+
ret void, !dbg !61
73+
}
74+
75+
; Function Attrs: argmemonly nounwind
76+
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #2
77+
78+
; Function Attrs: convergent nounwind
79+
define internal spir_func void @__testKernel_block_invoke(i8 addrspace(4)* %.block_descriptor) #3 !dbg !62 {
80+
entry:
81+
call void @llvm.dbg.value(metadata i8 addrspace(4)* %.block_descriptor, metadata !67, metadata !DIExpression()), !dbg !74
82+
%block = bitcast i8 addrspace(4)* %.block_descriptor to <{ i32, i32, i32 addrspace(1)* }> addrspace(4)*, !dbg !75
83+
call void @llvm.dbg.declare(metadata <{ i32, i32, i32 addrspace(1)* }> addrspace(4)* %block, metadata !76, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 8)), !dbg !77
84+
%block.capture.addr = getelementptr inbounds <{ i32, i32, i32 addrspace(1)* }>, <{ i32, i32, i32 addrspace(1)* }> addrspace(4)* %block, i32 0, i32 2, !dbg !78
85+
%0 = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(4)* %block.capture.addr, align 4, !dbg !78, !tbaa !49
86+
call spir_kernel void @kernel_fn(i32 addrspace(1)* %0) #7, !dbg !80
87+
ret void, !dbg !81
88+
}
89+
90+
; Function Attrs: convergent
91+
declare spir_func %opencl.queue_t* @_Z17get_default_queuev() #4
92+
93+
; Function Attrs: argmemonly nounwind
94+
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1) #2
95+
96+
; Function Attrs: nounwind
97+
define internal spir_kernel void @__testKernel_block_invoke_kernel(i8 addrspace(4)*) #5 {
98+
entry:
99+
call void @__testKernel_block_invoke(i8 addrspace(4)* %0), !dbg !60
100+
ret void, !dbg !60
101+
}
102+
103+
declare i32 @__enqueue_kernel_basic(%opencl.queue_t*, i32, %struct.ndrange_t*, i8 addrspace(4)*, i8 addrspace(4)*)
104+
105+
; Function Attrs: argmemonly nounwind
106+
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #2
107+
108+
; Function Attrs: nounwind readnone speculatable
109+
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
110+
111+
attributes #0 = { convergent nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "denorms-are-zero"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "uniform-work-group-size"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
112+
attributes #1 = { nounwind readnone speculatable }
113+
attributes #2 = { argmemonly nounwind }
114+
attributes #3 = { convergent nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "denorms-are-zero"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
115+
attributes #4 = { convergent "correctly-rounded-divide-sqrt-fp-math"="false" "denorms-are-zero"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
116+
attributes #5 = { nounwind }
117+
attributes #6 = { convergent }
118+
attributes #7 = { convergent "uniform-work-group-size"="false" }
119+
120+
!llvm.dbg.cu = !{!0}
121+
!llvm.module.flags = !{!3, !4}
122+
!opencl.ocl.version = !{!5}
123+
!opencl.spir.version = !{!5}
124+
!llvm.ident = !{!6}
125+
126+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 7.0.1-svn348686-1~exp1~20181221231927.53 (branches/release_70)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
127+
!1 = !DIFile(filename: "/work/tmp/<stdin>", directory: "/work/SPIRV-LLVM-Translator/build")
128+
!2 = !{}
129+
!3 = !{i32 2, !"Debug Info Version", i32 3}
130+
!4 = !{i32 1, !"wchar_size", i32 4}
131+
!5 = !{i32 2, i32 0}
132+
!6 = !{!"clang version 7.0.1-svn348686-1~exp1~20181221231927.53 (branches/release_70)"}
133+
!7 = distinct !DISubprogram(name: "kernel_fn", scope: !8, file: !8, line: 17, type: !9, isLocal: false, isDefinition: true, scopeLine: 17, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !13)
134+
!8 = !DIFile(filename: "/work/tmp/tmp.cl", directory: "/work/SPIRV-LLVM-Translator/build")
135+
!9 = !DISubroutineType(cc: DW_CC_LLVM_OpenCLKernel, types: !10)
136+
!10 = !{null, !11}
137+
!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 32)
138+
!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
139+
!13 = !{!14}
140+
!14 = !DILocalVariable(name: "res", arg: 1, scope: !7, file: !8, line: 17, type: !11)
141+
!15 = !{i32 1}
142+
!16 = !{!"none"}
143+
!17 = !{!"int*"}
144+
!18 = !{!""}
145+
!19 = !DILocation(line: 17, column: 39, scope: !7)
146+
!20 = !DILocation(line: 17, column: 45, scope: !7)
147+
!21 = distinct !DISubprogram(name: "testKernel", scope: !8, file: !8, line: 19, type: !9, isLocal: false, isDefinition: true, scopeLine: 19, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !22)
148+
!22 = !{!23, !24, !38}
149+
!23 = !DILocalVariable(name: "res", arg: 1, scope: !21, file: !8, line: 19, type: !11)
150+
!24 = !DILocalVariable(name: "ndrange", scope: !21, file: !8, line: 20, type: !25)
151+
!25 = !DIDerivedType(tag: DW_TAG_typedef, name: "ndrange_t", file: !26, line: 15755, baseType: !27)
152+
!26 = !DIFile(filename: "/usr/lib/llvm-7/bin/../lib/clang/7.0.1/include/opencl-c.h", directory: "/work/SPIRV-LLVM-Translator/build")
153+
!27 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !26, line: 15750, size: 320, elements: !28)
154+
!28 = !{!29, !31, !36, !37}
155+
!29 = !DIDerivedType(tag: DW_TAG_member, name: "workDimension", scope: !27, file: !26, line: 15751, baseType: !30, size: 32)
156+
!30 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
157+
!31 = !DIDerivedType(tag: DW_TAG_member, name: "globalWorkOffset", scope: !27, file: !26, line: 15752, baseType: !32, size: 96, offset: 32)
158+
!32 = !DICompositeType(tag: DW_TAG_array_type, baseType: !33, size: 96, elements: !34)
159+
!33 = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", file: !26, line: 60, baseType: !30)
160+
!34 = !{!35}
161+
!35 = !DISubrange(count: 3)
162+
!36 = !DIDerivedType(tag: DW_TAG_member, name: "globalWorkSize", scope: !27, file: !26, line: 15753, baseType: !32, size: 96, offset: 128)
163+
!37 = !DIDerivedType(tag: DW_TAG_member, name: "localWorkSize", scope: !27, file: !26, line: 15754, baseType: !32, size: 96, offset: 224)
164+
!38 = !DILocalVariable(name: "kernelBlock", scope: !21, file: !8, line: 21, type: !39)
165+
!39 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !40)
166+
!40 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !41, size: 32)
167+
!41 = !DICompositeType(tag: DW_TAG_structure_type, scope: !8, size: 64, flags: DIFlagAppleBlock, elements: !42)
168+
!42 = !{!43, !44}
169+
!43 = !DIDerivedType(tag: DW_TAG_member, name: "__size", scope: !8, file: !8, baseType: !12, size: 32)
170+
!44 = !DIDerivedType(tag: DW_TAG_member, name: "__align", scope: !8, file: !8, baseType: !12, size: 32, offset: 32)
171+
!45 = !DILocation(line: 19, column: 40, scope: !21)
172+
!46 = !DILocation(line: 20, column: 3, scope: !21)
173+
!47 = !DILocation(line: 20, column: 13, scope: !21)
174+
!48 = !DILocation(line: 21, column: 31, scope: !21)
175+
!49 = !{!50, !50, i64 0}
176+
!50 = !{!"any pointer", !51, i64 0}
177+
!51 = !{!"omnipotent char", !52, i64 0}
178+
!52 = !{!"Simple C/C++ TBAA"}
179+
!53 = !DILocation(line: 21, column: 10, scope: !21)
180+
!54 = !DILocation(line: 22, column: 18, scope: !21)
181+
!55 = !DILocation(line: 22, column: 66, scope: !21)
182+
!56 = !{i64 0, i64 4, !57, i64 4, i64 12, !59, i64 16, i64 12, !59, i64 28, i64 12, !59}
183+
!57 = !{!58, !58, i64 0}
184+
!58 = !{!"int", !51, i64 0}
185+
!59 = !{!51, !51, i64 0}
186+
!60 = !DILocation(line: 22, column: 3, scope: !21)
187+
!61 = !DILocation(line: 23, column: 1, scope: !21)
188+
!62 = distinct !DISubprogram(name: "__testKernel_block_invoke", scope: !8, file: !8, line: 21, type: !63, isLocal: true, isDefinition: true, scopeLine: 21, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !66)
189+
!63 = !DISubroutineType(types: !64)
190+
!64 = !{null, !65}
191+
!65 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 32)
192+
!66 = !{!67}
193+
!67 = !DILocalVariable(name: ".block_descriptor", arg: 1, scope: !62, file: !8, line: 21, type: !68, flags: DIFlagArtificial)
194+
!68 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !69, size: 32)
195+
!69 = !DICompositeType(tag: DW_TAG_structure_type, name: "__block_literal_1", scope: !8, file: !8, line: 21, size: 96, elements: !70)
196+
!70 = !{!71, !72, !73}
197+
!71 = !DIDerivedType(tag: DW_TAG_member, name: "__size", scope: !8, file: !8, line: 21, baseType: !12, size: 32, flags: DIFlagPublic)
198+
!72 = !DIDerivedType(tag: DW_TAG_member, name: "__align", scope: !8, file: !8, line: 21, baseType: !12, size: 32, offset: 32, flags: DIFlagPublic)
199+
!73 = !DIDerivedType(tag: DW_TAG_member, name: "res", scope: !8, file: !8, line: 21, baseType: !11, size: 32, offset: 64, flags: DIFlagPublic)
200+
!74 = !DILocation(line: 21, column: 31, scope: !62)
201+
!75 = !DILocation(line: 21, column: 32, scope: !62)
202+
!76 = !DILocalVariable(name: "res", scope: !62, file: !8, line: 19, type: !11)
203+
!77 = !DILocation(line: 19, column: 40, scope: !62)
204+
!78 = !DILocation(line: 21, column: 44, scope: !79)
205+
!79 = distinct !DILexicalBlock(scope: !62, file: !8, line: 21, column: 32)
206+
!80 = !DILocation(line: 21, column: 34, scope: !79)
207+
!81 = !DILocation(line: 21, column: 50, scope: !62)

0 commit comments

Comments
 (0)