@@ -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) ,
0 commit comments