Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions crates/rustc_codegen_spirv/src/linker/simple_passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,18 @@ pub fn check_fragment_insts(sess: &Session, module: &Module) -> super::Result<()
let mut any_err = None;
for inst in module.functions[index].all_inst_iter() {
if inst.class.opcode == Op::FunctionCall {
let callee = func_id_to_idx[&inst.operands[0].unwrap_id_ref()];
let callee_had_err =
visit(sess, module, visited, stack, names, callee, func_id_to_idx).err();
any_err = any_err.or(callee_had_err);
let callee_id = inst.operands[0].unwrap_id_ref();
Comment on lines 239 to +240
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record, this code in simple_passes isn't incorrect.

The underlying bug¹ is that OpFunctionCall is still used with function pointers - the correct instruction is OpFunctionPointerCallINTEL (from the same SPIR-V extension that adds function pointers through a new CodeSectionINTEL Storage Class).

¹(which one of my branches fixes, been meaning to open a PR for that for a while, already landed most of its prerequisites earlier this year)

if let Some(&callee) = func_id_to_idx.get(&callee_id) {
if let Err(e) =
visit(sess, module, visited, stack, names, callee, func_id_to_idx)
{
any_err = any_err.or(Some(e));
}
} else {
// Indirect or external callee: nothing to traverse.
// Keep scanning this function for forbidden fragment ops.
continue;
}
}
if matches!(
inst.class.opcode,
Expand Down
18 changes: 18 additions & 0 deletions tests/compiletests/ui/lang/issue-452.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// build-fail

use spirv_std::spirv;

#[derive(Clone, Copy)]
struct Position(u32);

fn use_cmp(cmp: fn(&Position) -> u32) {
let a = Position(0);
let b = Position(1);

let _ = if cmp(&a) <= cmp(&b) { a } else { b };
}

#[spirv(compute(threads(1)))]
pub fn main() {
use_cmp(|p| p.0);
}
47 changes: 47 additions & 0 deletions tests/compiletests/ui/lang/issue-452.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
error: function pointer types are not allowed
--> $DIR/issue-452.rs:8:1
|
LL | fn use_cmp(cmp: fn(&Position) -> u32) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: used by unnamed global (%10)
note: used from within `issue_452::use_cmp`
--> $DIR/issue-452.rs:8:4
|
LL | fn use_cmp(cmp: fn(&Position) -> u32) {
| ^^^^^^^
note: called by `issue_452::main`
--> $DIR/issue-452.rs:17:5
|
LL | use_cmp(|p| p.0);
| ^^^^^^^^^^^^^^^^
note: called by `main`
--> $DIR/issue-452.rs:16:8
|
LL | pub fn main() {
| ^^^^

error: indirect calls are not supported in SPIR-V
--> $DIR/issue-452.rs:12:27
|
LL | let _ = if cmp(&a) <= cmp(&b) { a } else { b };
| ^^^^^^^
|
note: used from within `issue_452::use_cmp`
--> $DIR/issue-452.rs:8:4
|
LL | fn use_cmp(cmp: fn(&Position) -> u32) {
| ^^^^^^^
note: called by `issue_452::main`
--> $DIR/issue-452.rs:17:5
|
LL | use_cmp(|p| p.0);
| ^^^^^^^^^^^^^^^^
note: called by `main`
--> $DIR/issue-452.rs:16:8
|
LL | pub fn main() {
| ^^^^

error: aborting due to 2 previous errors