Skip to content

Commit 31df306

Browse files
committed
fix multi-level instructions
1 parent 3f7cb64 commit 31df306

4 files changed

Lines changed: 73 additions & 63 deletions

File tree

crates/rustc_codegen_spirv/src/linker/destructure_composites.rs

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,52 @@ pub fn destructure_composites(function: &mut Function) {
2020
_ => None,
2121
})
2222
.collect();
23+
2324
for inst in function.all_inst_iter_mut() {
24-
if inst.class.opcode == Op::CompositeExtract && inst.operands.len() == 2 {
25-
let mut composite = inst.operands[0].unwrap_id_ref();
26-
let index = inst.operands[1].unwrap_literal_bit32();
25+
// multi-index extraction for nested tuples/structs
26+
if inst.class.opcode == Op::CompositeExtract && inst.operands.len() >= 2 {
27+
let mut current_id = inst.operands[0].unwrap_id_ref();
28+
let mut final_origin = None;
29+
30+
// step through each index sequentially to resolve deeply nested extracts
31+
for index_operand in &inst.operands[1..] {
32+
let index = index_operand.unwrap_literal_bit32();
33+
34+
let mut search_id = current_id;
35+
let mut resolved_id = None;
2736

28-
let origin = loop {
29-
if let Some(inst) = reference.get(&composite) {
30-
match inst.class.opcode {
37+
while let Some(ref_inst) = reference.get(&search_id) {
38+
match ref_inst.class.opcode {
3139
Op::CompositeInsert => {
32-
let insert_index = inst.operands[2].unwrap_literal_bit32();
40+
let insert_index = ref_inst.operands[2].unwrap_literal_bit32();
3341
if insert_index == index {
34-
break Some(inst.operands[0].unwrap_id_ref());
42+
resolved_id = Some(ref_inst.operands[0].unwrap_id_ref());
43+
break;
3544
}
36-
composite = inst.operands[1].unwrap_id_ref();
45+
// If not our index, continue down the insert chain
46+
search_id = ref_inst.operands[1].unwrap_id_ref();
3747
}
3848
Op::CompositeConstruct => {
39-
break inst.operands.get(index as usize).map(|o| o.unwrap_id_ref());
49+
resolved_id = ref_inst
50+
.operands
51+
.get(index as usize)
52+
.map(|o| o.unwrap_id_ref());
53+
break;
4054
}
4155
_ => unreachable!(),
4256
}
57+
}
58+
59+
if let Some(res) = resolved_id {
60+
current_id = res;
61+
final_origin = Some(res);
4362
} else {
44-
break None;
63+
final_origin = None;
64+
break;
4565
}
46-
};
66+
}
4767

48-
if let Some(origin_id) = origin {
68+
if let Some(origin_id) = final_origin {
4969
rewrite_rules.insert(
5070
inst.result_id.unwrap(),
5171
rewrite_rules.get(&origin_id).map_or(origin_id, |id| *id),

tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.stderr

Lines changed: 0 additions & 45 deletions
This file was deleted.

tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.rs renamed to tests/compiletests/ui/lang/core/ref/member_ref_arg_tuples.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
// FIXME(eddyb) this is like `member_ref_arg`, but testing the error messages
2-
// in some broken cases - this test should eventually pass, but for now
3-
// we care more that the error messages do not regress too much.
4-
5-
// build-fail
1+
// build-pass
62
// normalize-stderr-test "ref/member_ref_arg-broken\.[^`]*" -> "ref/member_ref_arg-broken"
73
// normalize-stderr-test "38\[%38\]" -> "$$ID[%$$ID]"
84

@@ -37,6 +33,7 @@ fn h(xyz: (&u32, &u32, &u32)) -> (u32, u32, u32) {
3733
// instructions, but the extra nesting here stops them dead in their tracks
3834
// (they're also not really the right solution for this problem, such composites
3935
// should just never exist by-value, and `qptr` may very well get rid of them).
36+
// update : this now works but idealy it should be fixed by `qptr` but for now w'll use `destructure_composites`
4037
#[inline(never)]
4138
fn h_newtyped(xyz: ((&u32, &u32, &u32),)) -> (u32, u32, u32) {
4239
(*xyz.0.0, *xyz.0.1, *xyz.0.2)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
warning: `#[inline(never)]` function `member_ref_arg_tuples::f` has been inlined
2+
--> <$DIR/member_ref_arg_tuples.rs>:16:4
3+
|
4+
LL | fn f(x: &u32) -> u32 {
5+
| ^
6+
|
7+
= note: inlining was required due to illegal (pointer) argument
8+
= note: called from `member_ref_arg_tuples::main`
9+
10+
warning: `#[inline(never)]` function `member_ref_arg_tuples::g` has been inlined
11+
--> <$DIR/member_ref_arg_tuples.rs>:21:4
12+
|
13+
LL | fn g(xy: (&u32, &u32)) -> (u32, u32) {
14+
| ^
15+
|
16+
= note: inlining was required due to illegal (pointer) argument
17+
= note: called from `member_ref_arg_tuples::main`
18+
19+
warning: `#[inline(never)]` function `member_ref_arg_tuples::h` has been inlined
20+
--> <$DIR/member_ref_arg_tuples.rs>:26:4
21+
|
22+
LL | fn h(xyz: (&u32, &u32, &u32)) -> (u32, u32, u32) {
23+
| ^
24+
|
25+
= note: inlining was required due to illegal parameter type
26+
= note: called from `member_ref_arg_tuples::main`
27+
28+
warning: `#[inline(never)]` function `member_ref_arg_tuples::h_newtyped` has been inlined
29+
--> <$DIR/member_ref_arg_tuples.rs>:38:4
30+
|
31+
LL | fn h_newtyped(xyz: ((&u32, &u32, &u32),)) -> (u32, u32, u32) {
32+
| ^^^^^^^^^^
33+
|
34+
= note: inlining was required due to illegal parameter type
35+
= note: called from `member_ref_arg_tuples::main`
36+
37+
warning: 4 warnings emitted
38+

0 commit comments

Comments
 (0)