Skip to content
Open
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
46 changes: 33 additions & 13 deletions crates/rustc_codegen_spirv/src/linker/destructure_composites.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,52 @@ pub fn destructure_composites(function: &mut Function) {
_ => None,
})
.collect();

for inst in function.all_inst_iter_mut() {
if inst.class.opcode == Op::CompositeExtract && inst.operands.len() == 2 {
let mut composite = inst.operands[0].unwrap_id_ref();
let index = inst.operands[1].unwrap_literal_bit32();
// multi-index extraction for nested tuples/structs
if inst.class.opcode == Op::CompositeExtract && inst.operands.len() >= 2 {
let mut current_id = inst.operands[0].unwrap_id_ref();
let mut final_origin = None;

// step through each index sequentially to resolve deeply nested extracts
for index_operand in &inst.operands[1..] {
let index = index_operand.unwrap_literal_bit32();

let mut search_id = current_id;
let mut resolved_id = None;

let origin = loop {
if let Some(inst) = reference.get(&composite) {
match inst.class.opcode {
while let Some(ref_inst) = reference.get(&search_id) {
match ref_inst.class.opcode {
Op::CompositeInsert => {
let insert_index = inst.operands[2].unwrap_literal_bit32();
let insert_index = ref_inst.operands[2].unwrap_literal_bit32();
if insert_index == index {
break Some(inst.operands[0].unwrap_id_ref());
resolved_id = Some(ref_inst.operands[0].unwrap_id_ref());
break;
}
composite = inst.operands[1].unwrap_id_ref();
// If not our index, continue down the insert chain
search_id = ref_inst.operands[1].unwrap_id_ref();
}
Op::CompositeConstruct => {
break inst.operands.get(index as usize).map(|o| o.unwrap_id_ref());
resolved_id = ref_inst
.operands
.get(index as usize)
.map(|o| o.unwrap_id_ref());
break;
}
_ => unreachable!(),
}
}

if let Some(res) = resolved_id {
current_id = res;
final_origin = Some(res);
} else {
break None;
final_origin = None;
break;
}
};
}

if let Some(origin_id) = origin {
if let Some(origin_id) = final_origin {
rewrite_rules.insert(
inst.result_id.unwrap(),
rewrite_rules.get(&origin_id).map_or(origin_id, |id| *id),
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
// FIXME(eddyb) this is like `member_ref_arg`, but testing the error messages
// in some broken cases - this test should eventually pass, but for now
// we care more that the error messages do not regress too much.

// build-fail
// build-pass
// normalize-stderr-test "ref/member_ref_arg-broken\.[^`]*" -> "ref/member_ref_arg-broken"
// normalize-stderr-test "38\[%38\]" -> "$$ID[%$$ID]"

Expand Down Expand Up @@ -37,6 +33,7 @@ fn h(xyz: (&u32, &u32, &u32)) -> (u32, u32, u32) {
// instructions, but the extra nesting here stops them dead in their tracks
// (they're also not really the right solution for this problem, such composites
// should just never exist by-value, and `qptr` may very well get rid of them).
// update : this now works but idealy it should be fixed by `qptr` but for now w'll use `destructure_composites`
#[inline(never)]
fn h_newtyped(xyz: ((&u32, &u32, &u32),)) -> (u32, u32, u32) {
(*xyz.0.0, *xyz.0.1, *xyz.0.2)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
warning: `#[inline(never)]` function `member_ref_arg_tuples::f` has been inlined
--> <$DIR/member_ref_arg_tuples.rs>:16:4
|
LL | fn f(x: &u32) -> u32 {
| ^
|
= note: inlining was required due to illegal (pointer) argument
= note: called from `member_ref_arg_tuples::main`

warning: `#[inline(never)]` function `member_ref_arg_tuples::g` has been inlined
--> <$DIR/member_ref_arg_tuples.rs>:21:4
|
LL | fn g(xy: (&u32, &u32)) -> (u32, u32) {
| ^
|
= note: inlining was required due to illegal (pointer) argument
= note: called from `member_ref_arg_tuples::main`

warning: `#[inline(never)]` function `member_ref_arg_tuples::h` has been inlined
--> <$DIR/member_ref_arg_tuples.rs>:26:4
|
LL | fn h(xyz: (&u32, &u32, &u32)) -> (u32, u32, u32) {
| ^
|
= note: inlining was required due to illegal parameter type
= note: called from `member_ref_arg_tuples::main`

warning: `#[inline(never)]` function `member_ref_arg_tuples::h_newtyped` has been inlined
--> <$DIR/member_ref_arg_tuples.rs>:38:4
|
LL | fn h_newtyped(xyz: ((&u32, &u32, &u32),)) -> (u32, u32, u32) {
| ^^^^^^^^^^
|
= note: inlining was required due to illegal parameter type
= note: called from `member_ref_arg_tuples::main`

warning: 4 warnings emitted

Loading