Skip to content

Commit 39ae2c0

Browse files
39aliFirestar99
authored andcommitted
fix multi-level instructions
1 parent 67f1ff2 commit 39ae2c0

4 files changed

Lines changed: 69 additions & 61 deletions

File tree

crates/rustc_codegen_spirv/src/linker/destructure_composites.rs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,50 @@ 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) {
37+
while let Some(inst) = reference.get(&search_id) {
3038
match inst.class.opcode {
3139
Op::CompositeInsert => {
3240
let insert_index = inst.operands[2].unwrap_literal_bit32();
3341
if insert_index == index {
34-
break Some(inst.operands[0].unwrap_id_ref());
42+
resolved_id = Some(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 = 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 =
50+
inst.operands.get(index as usize).map(|o| o.unwrap_id_ref());
51+
break;
4052
}
4153
_ => unreachable!(),
4254
}
55+
}
56+
57+
if let Some(res) = resolved_id {
58+
current_id = res;
59+
final_origin = Some(res);
4360
} else {
44-
break None;
61+
final_origin = None;
62+
break;
4563
}
46-
};
64+
}
4765

48-
if let Some(origin_id) = origin {
66+
if let Some(origin_id) = final_origin {
4967
rewrite_rules.insert(
5068
inst.result_id.unwrap(),
5169
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)