Skip to content

Commit d8f6ce5

Browse files
AlexeySachkovromanovvlad
authored andcommitted
Fix detection of recursive data types in presence of function pointers
Signed-off-by: Alexey Sachkov <[email protected]>
1 parent feeacc1 commit d8f6ce5

File tree

2 files changed

+96
-2
lines changed

2 files changed

+96
-2
lines changed

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,17 @@ static bool recursiveType(const StructType *ST, const Type *Ty) {
223223
StructTy->element_end();
224224
}
225225

226-
if (auto *PtrTy = dyn_cast<PointerType>(Ty))
227-
return Run(PtrTy->getPointerElementType());
226+
if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
227+
Type *ElTy = PtrTy->getPointerElementType();
228+
if (auto *FTy = dyn_cast<FunctionType>(ElTy)) {
229+
// If we have a function pointer, then argument types and return type of
230+
// the referenced function also need to be checked
231+
return Run(FTy->getReturnType()) ||
232+
any_of(FTy->param_begin(), FTy->param_end(), Run);
233+
}
234+
235+
return Run(ElTy);
236+
}
228237

229238
if (auto *ArrayTy = dyn_cast<ArrayType>(Ty))
230239
return Run(ArrayTy->getArrayElementType());
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
; RUN: llvm-as %s -o %t.bc
2+
; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_function_pointers -o %t.spv
3+
; RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV
4+
;
5+
; This tests that translator is able to convert the following recursive data
6+
; type which contains function pointers:
7+
;
8+
; typedef void(*fp_t)(struct Desc *);
9+
; typedef Desc *(*fp2_t)();
10+
;
11+
; struct Type;
12+
;
13+
; struct Desc {
14+
; int B;
15+
; Type *Ptr;
16+
; };
17+
;
18+
; struct Type {
19+
; int A;
20+
; fp_t FP;
21+
; };
22+
;
23+
; __kernel void foo() {
24+
; Type T;
25+
; fp2_t ptr;
26+
; }
27+
;
28+
; Without proper recursive types detection, the translator crashes while trying
29+
; to translate this LLVM IR example with the following error:
30+
;
31+
; virtual SPIRV::SPIRVEntry* SPIRV::SPIRVModuleImpl::getEntry(SPIRV::SPIRVId) const: Assertion `Loc != IdEntryMap.end() && "Id is not in map"' failed.
32+
;
33+
; CHECK-SPIRV: TypeInt [[INTTY:[0-9]+]] 32 0
34+
; CHECK-SPIRV: TypeVoid [[VOIDTY:[0-9]+]]
35+
; CHECK-SPIRV: TypeStruct [[TYPETY:[0-9]+]] [[INTTY]] [[FPTRTY:[0-9]+]]
36+
; CHECK-SPIRV: TypeStruct [[DESCTY:[0-9]+]] [[INTTY]] [[TYPEPTRTY:[0-9]+]]
37+
; CHECK-SPIRV: TypePointer [[TYPEPTRTY]] {{[0-9]+}} [[TYPETY]]
38+
; CHECK-SPIRV: TypePointer [[DESCPTRTY:[0-9]+]] {{[0-9]+}} [[DESCTY]]
39+
; CHECK-SPIRV: TypeFunction [[FTY:[0-9]+]] [[VOIDTY]] [[DESCPTRTY]]
40+
; CHECK-SPIRV: TypePointer [[FPTRTY]] {{[0-9]+}} [[FTY]]
41+
; CHECK-SPIRV: TypePointer [[DESCPTR1TY:[0-9]+]] {{[0-9]+}} [[TYPETY]]
42+
; CHECK-SPIRV: TypeFunction [[F2TY:[0-9]+]] [[DESCPTRTY]]
43+
; CHECK-SPIRV: TypePointer [[FPTR2TY:[0-9]+]] {{[0-9]+}} [[F2TY]]
44+
; CHECK-SPIRV: TypePointer [[FPTR2ALLOCATY:[0-9]+]] {{[0-9]+}} [[FPTR2TY]]
45+
; CHECK-SPIRV: Variable [[DESCPTR1TY]]
46+
; CHECK-SPIRV: Variable [[FPTR2ALLOCATY]]
47+
48+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
49+
target triple = "spir64-unknown-unknown"
50+
51+
%struct.Type = type { i32, void (%struct.Desc addrspace(4)*) addrspace(4)* }
52+
%struct.Desc = type { i32, %struct.Type addrspace(4)* }
53+
54+
define spir_kernel void @foo() #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !4 !kernel_arg_type !4 !kernel_arg_base_type !4 !kernel_arg_type_qual !4 {
55+
entry:
56+
%t = alloca %struct.Type, align 8
57+
%ptr = alloca %struct.Desc addrspace(4)* () *, align 8
58+
ret void
59+
}
60+
61+
; Function Attrs: argmemonly nounwind willreturn
62+
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
63+
64+
; Function Attrs: argmemonly nounwind willreturn
65+
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
66+
67+
attributes #0 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "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"="true" "unsafe-fp-math"="false" "use-soft-float"="false" }
68+
attributes #1 = { argmemonly nounwind willreturn }
69+
attributes #2 = { inlinehint nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "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" }
70+
attributes #3 = { nounwind }
71+
72+
!llvm.module.flags = !{!0}
73+
!opencl.spir.version = !{!1}
74+
!spirv.Source = !{!2}
75+
!llvm.ident = !{!3}
76+
77+
!0 = !{i32 1, !"wchar_size", i32 4}
78+
!1 = !{i32 1, i32 2}
79+
!2 = !{i32 4, i32 100000}
80+
!3 = !{!"clang version 10.0.0 "}
81+
!4 = !{}
82+
!5 = !{!6, !6, i64 0}
83+
!6 = !{!"any pointer", !7, i64 0}
84+
!7 = !{!"omnipotent char", !8, i64 0}
85+
!8 = !{!"Simple C++ TBAA"}

0 commit comments

Comments
 (0)