pub fn finish(&mut self, ops: &[LOpInfo]) {
        // Iterate through blocks and seal them. Also associate nodes with their
        // respective blocks.

        let mut wl = VecDeque::new();
        let mut seen = HashSet::new();
        let mut wasted_cycles = 0;
        wl.push_back(self.ssa.entry_node().expect("No entry block!"));

        while !wl.is_empty() {
            if wasted_cycles > wl.len() {
                break;
            }
            // wl[0] is safe to access
            let current = wl.pop_front().expect("Cannot be `None`");
            let preds = self.ssa.preds_of(current);
            // All preds must be sealed before we process this.
            let push_current_back = if preds
                .iter()
                .filter(|&&x| x != current)
                .all(|x| self.sealed_blocks.contains(x))
            {
                // Check if have not already sealed this block
                if !self.sealed_blocks.contains(&current) {
                    self.seal_block(current);
                    wasted_cycles = 0;
                }
                false
            } else {
                wasted_cycles += 1;
                true
            };
            // If this block was sealed now, add its successors to process.
            if !seen.contains(&current) {
                wl.extend(self.ssa.succs_of(current).iter());
                seen.insert(current);
            }

            if push_current_back {
                wl.push_back(current);
            }
        }

        for block in wl {
            self.seal_block(block);
        }

        for node in &self.ssa.values() {
            if let Some(addr) = self.index_to_addr.get(node).cloned() {
                self.associate_block(node, addr);
                // Mark selector.
                if let Ok(ndata) = self.ssa.node_data(*node) {
                    if let NodeType::Op(MOpcode::OpITE) = ndata.nt {
                        let block = self.block_of(addr);
                        if let Some(cond_node) = self.ssa.operands_of(*node).get(0) {
                            self.ssa.set_selector(*cond_node, block.unwrap());
                            self.ssa.remove_value(*node);
                        } else {
                            radeco_warn!("Lost selector!");
                        }
                    }
                }
            }
        }

        // Associate basic block with correct block sizes.
        for opn in ops.windows(2) {
            let op1 = &opn[0];
            let op2 = &opn[1];
            let off1 = MAddress::new(op1.offset.unwrap_or(0), 0);
            let off2 = MAddress::new(op2.offset.unwrap_or(0), 0);

            match (self.block_of(off1), self.block_of(off2)) {
                (Some(b1), Some(b2)) if b1 == b2 => { /* Nothing to do */ }
                (Some(b1), Some(_)) => {
                    if let Some(start) = self.ssa.starting_address(b1) {
                        let size = off1.address - start.address;
                        self.ssa.set_block_size(b1, size);
                    }
                }
                (_, _) => {}
            }
        }
    }
// Performs SSA finish operation such as assigning the blocks in the final
// graph, sealing blocks, running basic dead code elimination etc.
Performs SSA finish operation such as assigning the blocks in the final
graph, sealing blocks, running basic dead code elimination etc.
Performs SSA finish operation such as assigning the blocks in the final graph sealing blocks running basic dead code elimination etc .
pub fn finish(&mut self, ops: &[LOpInfo]) {
        // Iterate through blocks and seal them. Also associate nodes with their
        // respective blocks.
        let mut wl = VecDeque::new();
        let mut seen = HashSet::new();
        let mut wasted_cycles = 0;
        wl.push_back(self.ssa.entry_node().expect("No entry block!"));
        while !wl.is_empty() {
            if wasted_cycles > wl.len() {
                break;
            }
            // wl[0] is safe to access
            let current = wl.pop_front().expect("Cannot be `None`");
            let preds = self.ssa.preds_of(current);
            // All preds must be sealed before we process this.
            let push_current_back = if preds
                .iter()
                .filter(|&&x| x != current)
                .all(|x| self.sealed_blocks.contains(x))
            {
                // Check if have not already sealed this block
                if !self.sealed_blocks.contains(&current) {
                    self.seal_block(current);
                    wasted_cycles = 0;
                }
                false
            } else {
                wasted_cycles += 1;
                true
            };
            // If this block was sealed now, add its successors to process.
            if !seen.contains(&current) {
                wl.extend(self.ssa.succs_of(current).iter());
                seen.insert(current);
            }
            if push_current_back {
                wl.push_back(current);
            }
        }
        for block in wl {
            self.seal_block(block);
        }
        for node in &self.ssa.values() {
            if let Some(addr) = self.index_to_addr.get(node).cloned() {
                self.associate_block(node, addr);
                // Mark selector.
                if let Ok(ndata) = self.ssa.node_data(*node) {
                    if let NodeType::Op(MOpcode::OpITE) = ndata.nt {
                        let block = self.block_of(addr);
                        if let Some(cond_node) = self.ssa.operands_of(*node).get(0) {
                            self.ssa.set_selector(*cond_node, block.unwrap());
                            self.ssa.remove_value(*node);
                        } else {
                            radeco_warn!("Lost selector!");
                        }
                    }
                }
            }
        }
        // Associate basic block with correct block sizes.
        for opn in ops.windows(2) {
            let op1 = &opn[0];
            let op2 = &opn[1];
            let off1 = MAddress::new(op1.offset.unwrap_or(0), 0);
            let off2 = MAddress::new(op2.offset.unwrap_or(0), 0);
            match (self.block_of(off1), self.block_of(off2)) {
                (Some(b1), Some(b2)) if b1 == b2 => { /* Nothing to do */ }
                (Some(b1), Some(_)) => {
                    if let Some(start) = self.ssa.starting_address(b1) {
                        let size = off1.address - start.address;
                        self.ssa.set_block_size(b1, size);
                    }
                }
                (_, _) => {}
            }
        }
    }
pub fn finish ( & mut self , ops : & [ LOpInfo ] ) { // Iterate through blocks and seal them. Also associate nodes with their // respective blocks. let mut wl = VecDeque :: new ( ) ; let mut seen = HashSet :: new ( ) ; let mut wasted_cycles = 0 ; wl . push_back ( self . ssa . entry_node ( ) . expect ( " " ) ) ; while ! wl . is_empty ( ) { if wasted_cycles > wl . len ( ) { break ; } // wl[0] is safe to access let current = wl . pop_front ( ) . expect ( " " ) ; let preds = self . ssa . preds_of ( current ) ; // All preds must be sealed before we process this. let push_current_back = if preds . iter ( ) . filter ( | & & x | x != current ) . all ( | x | self . sealed_blocks . contains ( x ) ) { // Check if have not already sealed this block if ! self . sealed_blocks . contains ( & current ) { self . seal_block ( current ) ; wasted_cycles = 0 ; } false } else { wasted_cycles += 1 ; true } ; // If this block was sealed now, add its successors to process. if ! seen . contains ( & current ) { wl . extend ( self . ssa . succs_of ( current ) . iter ( ) ) ; seen . insert ( current ) ; } if push_current_back { wl . push_back ( current ) ; } } for block in wl { self . seal_block ( block ) ; } for node in & self . ssa . values ( ) { if let Some ( addr ) = self . index_to_addr . get ( node ) . cloned ( ) { self . associate_block ( node , addr ) ; // Mark selector. if let Ok ( ndata ) = self . ssa . node_data ( * node ) { if let NodeType :: Op ( MOpcode :: OpITE ) = ndata . nt { let block = self . block_of ( addr ) ; if let Some ( cond_node ) = self . ssa . operands_of ( * node ) . get ( 0 ) { self . ssa . set_selector ( * cond_node , block . unwrap ( ) ) ; self . ssa . remove_value ( * node ) ; } else { radeco_warn ! ( " " ) ; } } } } } // Associate basic block with correct block sizes. for opn in ops . windows ( 2 ) { let op1 = & opn [ 0 ] ; let op2 = & opn [ 1 ] ; let off1 = MAddress :: new ( op1 . offset . unwrap_or ( 0 ) , 0 ) ; let off2 = MAddress :: new ( op2 . offset . unwrap_or ( 0 ) , 0 ) ; match ( self . block_of ( off1 ) , self . block_of ( off2 ) ) { ( Some ( b1 ) , Some ( b2 ) ) if b1 == b2 => { /* Nothing to do */ } ( Some ( b1 ) , Some ( _ ) ) => { if let Some ( start ) = self . ssa . starting_address ( b1 ) { let size = off1 . address - start . address ; self . ssa . set_block_size ( b1 , size ) ; } } ( _ , _ ) => { } } } }
Performs SSA finish operation such as assigning the blocks in the final
graph, sealing blocks, running basic dead code elimination etc.
Performs SSA finish operation such as assigning the blocks in the final graph sealing blocks running basic dead code elimination etc .
&mut self
ops
&[LOpInfo]
&mut self
ops
&[LOpInfo]