Skip to content

Commit 26beffa

Browse files
committed
fix multi-level instructions
1 parent 3f7cb64 commit 26beffa

3 files changed

Lines changed: 49 additions & 35 deletions

File tree

crates/rustc_codegen_spirv/src/linker/destructure_composites.rs

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,56 @@ 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();
2733

28-
let origin = loop {
29-
if let Some(inst) = reference.get(&composite) {
30-
match inst.class.opcode {
31-
Op::CompositeInsert => {
32-
let insert_index = inst.operands[2].unwrap_literal_bit32();
33-
if insert_index == index {
34-
break Some(inst.operands[0].unwrap_id_ref());
34+
let mut search_id = current_id;
35+
let mut resolved_id = None;
36+
37+
loop {
38+
if let Some(ref_inst) = reference.get(&search_id) {
39+
match ref_inst.class.opcode {
40+
Op::CompositeInsert => {
41+
let insert_index = ref_inst.operands[2].unwrap_literal_bit32();
42+
if insert_index == index {
43+
resolved_id = Some(ref_inst.operands[0].unwrap_id_ref());
44+
break;
45+
}
46+
// if not our index, continue down the insert chain
47+
search_id = ref_inst.operands[1].unwrap_id_ref();
3548
}
36-
composite = inst.operands[1].unwrap_id_ref();
37-
}
38-
Op::CompositeConstruct => {
39-
break inst.operands.get(index as usize).map(|o| o.unwrap_id_ref());
49+
Op::CompositeConstruct => {
50+
resolved_id = ref_inst
51+
.operands
52+
.get(index as usize)
53+
.map(|o| o.unwrap_id_ref());
54+
break;
55+
}
56+
_ => unreachable!(),
4057
}
41-
_ => unreachable!(),
58+
} else {
59+
break;
4260
}
61+
}
62+
63+
if let Some(res) = resolved_id {
64+
current_id = res;
65+
final_origin = Some(res);
4366
} else {
44-
break None;
67+
final_origin = None;
68+
break;
4569
}
46-
};
70+
}
4771

48-
if let Some(origin_id) = origin {
72+
if let Some(origin_id) = final_origin {
4973
rewrite_rules.insert(
5074
inst.result_id.unwrap(),
5175
rewrite_rules.get(&origin_id).map_or(origin_id, |id| *id),

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)

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

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: `#[inline(never)]` function `member_ref_arg_broken::f` has been inlined
2-
--> <$DIR/member_ref_arg-broken.rs>:20:4
2+
--> <$DIR/member_ref_arg-broken.rs>:18:4
33
|
44
LL | fn f(x: &u32) -> u32 {
55
| ^
@@ -8,7 +8,7 @@ LL | fn f(x: &u32) -> u32 {
88
= note: called from `member_ref_arg_broken::main`
99

1010
warning: `#[inline(never)]` function `member_ref_arg_broken::g` has been inlined
11-
--> <$DIR/member_ref_arg-broken.rs>:25:4
11+
--> <$DIR/member_ref_arg-broken.rs>:23:4
1212
|
1313
LL | fn g(xy: (&u32, &u32)) -> (u32, u32) {
1414
| ^
@@ -17,7 +17,7 @@ LL | fn g(xy: (&u32, &u32)) -> (u32, u32) {
1717
= note: called from `member_ref_arg_broken::main`
1818

1919
warning: `#[inline(never)]` function `member_ref_arg_broken::h` has been inlined
20-
--> <$DIR/member_ref_arg-broken.rs>:30:4
20+
--> <$DIR/member_ref_arg-broken.rs>:28:4
2121
|
2222
LL | fn h(xyz: (&u32, &u32, &u32)) -> (u32, u32, u32) {
2323
| ^
@@ -26,20 +26,13 @@ LL | fn h(xyz: (&u32, &u32, &u32)) -> (u32, u32, u32) {
2626
= note: called from `member_ref_arg_broken::main`
2727

2828
warning: `#[inline(never)]` function `member_ref_arg_broken::h_newtyped` has been inlined
29-
--> <$DIR/member_ref_arg-broken.rs>:41:4
29+
--> <$DIR/member_ref_arg-broken.rs>:39:4
3030
|
3131
LL | fn h_newtyped(xyz: ((&u32, &u32, &u32),)) -> (u32, u32, u32) {
3232
| ^^^^^^^^^^
3333
|
3434
= note: inlining was required due to illegal parameter type
3535
= note: called from `member_ref_arg_broken::main`
3636

37-
error: error:0:0 - OpLoad Pointer <id> '$ID[%$ID]' is not a logical pointer.
38-
%39 = OpLoad %uint %38
39-
40-
|
41-
= note: spirv-val failed
42-
= note: module `$TEST_BUILD_DIR/lang/core/ref/member_ref_arg-broken`
43-
44-
error: aborting due to 1 previous error; 4 warnings emitted
37+
warning: 4 warnings emitted
4538

0 commit comments

Comments
 (0)