Skip to content

Commit 731636b

Browse files
committed
Do not ICE on indirect fn pointers
Fixes #452.
1 parent 808974a commit 731636b

File tree

3 files changed

+113
-4
lines changed

3 files changed

+113
-4
lines changed

crates/rustc_codegen_spirv/src/linker/simple_passes.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,18 @@ pub fn check_fragment_insts(sess: &Session, module: &Module) -> super::Result<()
237237
let mut any_err = None;
238238
for inst in module.functions[index].all_inst_iter() {
239239
if inst.class.opcode == Op::FunctionCall {
240-
let callee = func_id_to_idx[&inst.operands[0].unwrap_id_ref()];
241-
let callee_had_err =
242-
visit(sess, module, visited, stack, names, callee, func_id_to_idx).err();
243-
any_err = any_err.or(callee_had_err);
240+
let callee_id = inst.operands[0].unwrap_id_ref();
241+
if let Some(&callee) = func_id_to_idx.get(&callee_id) {
242+
if let Err(e) =
243+
visit(sess, module, visited, stack, names, callee, func_id_to_idx)
244+
{
245+
any_err = any_err.or(Some(e));
246+
}
247+
} else {
248+
// Indirect or external callee: nothing to traverse.
249+
// Keep scanning this function for forbidden fragment ops.
250+
continue;
251+
}
244252
}
245253
if matches!(
246254
inst.class.opcode,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// build-fail
2+
#![feature(stmt_expr_attributes)]
3+
4+
use spirv_std::spirv;
5+
6+
#[derive(Clone, Copy)]
7+
struct PositionR {
8+
position: u32,
9+
r: u32,
10+
}
11+
12+
const ELEMENTS_PER_THREAD: usize = 2;
13+
14+
fn sort_local_bucket(
15+
lane_id: u32,
16+
local_bucket: &mut [PositionR; ELEMENTS_PER_THREAD],
17+
cmp_key: fn(&PositionR) -> u32,
18+
) {
19+
let select_smaller = (lane_id as usize & 1) == 0;
20+
let a = local_bucket[0];
21+
let b = local_bucket[1];
22+
23+
let _ = if (cmp_key(&a) <= cmp_key(&b)) == select_smaller {
24+
a
25+
} else {
26+
b
27+
};
28+
}
29+
30+
#[spirv(compute(threads(1)))]
31+
pub fn main() {
32+
let mut bucket = [PositionR { position: 0, r: 0 }; ELEMENTS_PER_THREAD];
33+
34+
sort_local_bucket(
35+
0,
36+
&mut bucket,
37+
#[inline(always)]
38+
|position_r| position_r.position,
39+
);
40+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
error: function pointer types are not allowed
2+
--> $DIR/issue-452.rs:14:1
3+
|
4+
LL | / fn sort_local_bucket(
5+
LL | | lane_id: u32,
6+
LL | | local_bucket: &mut [PositionR; ELEMENTS_PER_THREAD],
7+
LL | | cmp_key: fn(&PositionR) -> u32,
8+
LL | | ) {
9+
| |_^
10+
|
11+
= note: used by unnamed global (%14)
12+
note: used from within `issue_452::sort_local_bucket`
13+
--> $DIR/issue-452.rs:14:4
14+
|
15+
LL | fn sort_local_bucket(
16+
| ^^^^^^^^^^^^^^^^^
17+
note: called by `issue_452::main`
18+
--> $DIR/issue-452.rs:34:5
19+
|
20+
LL | / sort_local_bucket(
21+
LL | | 0,
22+
LL | | &mut bucket,
23+
LL | | #[inline(always)]
24+
LL | | |position_r| position_r.position,
25+
LL | | );
26+
| |_____^
27+
note: called by `main`
28+
--> $DIR/issue-452.rs:31:8
29+
|
30+
LL | pub fn main() {
31+
| ^^^^
32+
33+
error: indirect calls are not supported in SPIR-V
34+
--> $DIR/issue-452.rs:23:32
35+
|
36+
LL | let _ = if (cmp_key(&a) <= cmp_key(&b)) == select_smaller {
37+
| ^^^^^^^^^^^
38+
|
39+
note: used from within `issue_452::sort_local_bucket`
40+
--> $DIR/issue-452.rs:14:4
41+
|
42+
LL | fn sort_local_bucket(
43+
| ^^^^^^^^^^^^^^^^^
44+
note: called by `issue_452::main`
45+
--> $DIR/issue-452.rs:34:5
46+
|
47+
LL | / sort_local_bucket(
48+
LL | | 0,
49+
LL | | &mut bucket,
50+
LL | | #[inline(always)]
51+
LL | | |position_r| position_r.position,
52+
LL | | );
53+
| |_____^
54+
note: called by `main`
55+
--> $DIR/issue-452.rs:31:8
56+
|
57+
LL | pub fn main() {
58+
| ^^^^
59+
60+
error: aborting due to 2 previous errors
61+

0 commit comments

Comments
 (0)