pub fn add_block(
        &mut self,
        at: MAddress,
        current_addr: Option<MAddress>,
        edge_type: Option<u8>,
    ) -> T::ActionRef {
        let seen = current_addr.map_or(false, |cur| {
            match cur.cmp(&at) {
                Ordering::Less | Ordering::Equal => false,
                // Check if `at` is before the first block.
                Ordering::Greater => self.block_of(at).is_some(),
            }
        });

        let upper_block = if seen {
            self.block_of(at).unwrap_or_else(|| {
                radeco_err!("Block not found @ {:?}", at);
                self.ssa.invalid_action().unwrap()
            })
        } else {
            self.ssa
                .invalid_action()
                .expect("Invalid Action is not defined")
        };

        // Create a new block and add the required type of edge.
        let lower_block = self.new_block(at);
        if let Some(e) = edge_type {
            if let Some(addr) = current_addr {
                let current_block = self.block_of(addr).unwrap_or_else(|| {
                    radeco_err!("Block not found @ {:?}", addr);
                    self.ssa.invalid_action().unwrap()
                });
                radeco_trace!(
                    "ADD BLOCK: phip_add_edge|{:?} --{}--> {:?}",
                    current_block,
                    e,
                    lower_block
                );
                self.ssa.insert_control_edge(current_block, lower_block, e);
            }
        }

        if upper_block == lower_block {
            return upper_block;
        }

        if seen {
            // Details on performing the split up.
            //   - Add an unconditional flow edge from the upper to the lower block.
            // - We first find the defs for every expr in the `lower` block arising out
            // of a
            //   split (lower block is the block that has aatat`).
            // - If these defs are in the `upper` block, then we add a phi (incomplete
            // phi) and
            //   this is used to provide the def for this use.

            // Copy all the outgoing CF edges.
            let invalid_edge = self
                .ssa
                .invalid_edge()
                .expect("Invalid Edge is not defined");
            let conditional_branches =
                if let Some(branches) = self.ssa.conditional_edges(upper_block) {
                    branches
                } else {
                    ConditionInfo::new(invalid_edge, invalid_edge)
                };
            let outgoing = [
                conditional_branches.false_side,
                conditional_branches.true_side,
                self.ssa
                    .unconditional_edge(upper_block)
                    .unwrap_or(invalid_edge),
            ];
            for (i, edge) in outgoing.iter().enumerate() {
                if *edge
                    != self
                        .ssa
                        .invalid_edge()
                        .expect("Invalid Edge is not defined")
                {
                    let target = self
                        .ssa
                        .edge_info(*edge)
                        .unwrap_or_else(|| {
                            radeco_err!("Less-endpoints edge");
                            EdgeInfo::new(
                                self.ssa.invalid_action().unwrap(),
                                self.ssa.invalid_action().unwrap(),
                            )
                        })
                        .target;
                    if lower_block != target {
                        radeco_trace!(
                            "ADD BLOCK: phip_add_edge|{:?} --{}--> {:?}",
                            lower_block,
                            i,
                            target
                        );
                        self.ssa.insert_control_edge(lower_block, target, i as u8);
                        self.ssa.remove_control_edge(*edge);
                    }
                }
            }

            radeco_trace!(
                "ADD BLOCK: phip_add_edge|{:?} --{}--> {:?}",
                upper_block,
                UNCOND_EDGE,
                lower_block
            );
            self.ssa
                .insert_control_edge(upper_block, lower_block, UNCOND_EDGE);
            self.blocks.insert(at, lower_block);

            // For there is no assignment to addr_to_index, the original code will
            // skip the loop below, causing losing necessary phi functions
            for (ni, addr) in self.index_to_addr.clone() {
                if addr < at {
                    continue;
                }
                if let Some(block) = self.block_of(addr) {
                    if block != lower_block {
                        break;
                    }
                }
                // Now, this node index belongs to the lower part of the split block.
                let operands = self.ssa.sparse_operands_of(ni);
                // Check if the operands belong to the upper block and if they do, remove the
                // operands edge, add a new phi and connect the edge from phi to ni.
                for operand_ in &operands {
                    let (i, operand) = *operand_;
                    // If operand is const, it cannot belong to any block.
                    match self.ssa.opcode(operand) {
                        Some(MOpcode::OpConst(_)) => {
                            continue;
                        }
                        _ => {}
                    }
                    let operand_addr = self.index_to_addr[&operand];
                    let operand_block = self.block_of(operand_addr).unwrap_or_else(|| {
                        radeco_err!("Block not found @ {:?}", operand_addr);
                        self.ssa.invalid_action().unwrap()
                    });
                    if operand_block == upper_block {
                        // Since the current block is not sealed, we can add an incomplete phi and
                        // modify the constructed SSA to take this phi as operand rather than the
                        // node.
                        // This can be summarized in the following operations:
                        //   - Remove the edge from the operand to ni.
                        //   - Add a new "incomplete" phi associated with the lower block.
                        //   - Connect the edge.
                        // The above two steps can easily be accomplished by doing a read_variable
                        // and adding an operand edge.
                        // BUG: Not all operands are the register residences.
                        // For example, OpZeroExt for 32-bit register. If we want to add a 32-bit register
                        // with a constant, our algorithm will add an Opwiden(64) node for the register,
                        // then add the OpZeroExt node with an Opconst. In this situation, OpZeroExt
                        // node isn't a residence for any register.
                        if !self.outputs.contains_key(&operand) {
                            continue;
                        }
                        self.ssa.op_unuse(ni, operand);
                        let output_varid = self.outputs[&operand];
                        let mut at_ = at;
                        // BUG: if current define is ni itself, this code may cause ni use itself
                        // as operand. So we have to do some check.
                        // A tricky way to solve the bug is to call read_variable_recursive, rather
                        // than read_variable, this will force the code generate a phi node.
                        let replacement_phi = self.read_variable_recursive(output_varid, &mut at_);
                        self.ssa.op_use(ni, i, replacement_phi);
                    }
                }
            }
        } else {
            self.blocks.insert(at, lower_block);
        }
        lower_block
    }
// In this new implementation, this method is a bit tricky.
// Let us break down this functionality into multiple steps.
// - add_block takes an address to add a block at.
// - It then determines if this address is already "seen".
// - If it has already seen this address, it means that we have a backwards
//   edge and we need to split the existing basic block at the target address.
//   Consequently, this method calls split_block to add references, phis etc.
// - If it is unseen, then a new basic block is created at this address and
//   kept ready to be used when instructions beloging to this basic block are
//   parsed for addition into the SSA.
//
// current_addr is the current address at which we are parsing. This is
// important to determine
// if the address we are trying to create a block is seen or not.
// - edge_type is the type of edge to be added between the block which contains
// the
// current_addr and the new block being added into the CFG.
In this new implementation, this method is a bit tricky.
Let us break down this functionality into multiple steps.
add_block takes an address to add a block at.
It then determines if this address is already "seen".
If it has already seen this address, it means that we have a backwards
edge and we need to split the existing basic block at the target address.
Consequently, this method calls split_block to add references, phis etc.
If it is unseen, then a new basic block is created at this address and
kept ready to be used when instructions beloging to this basic block are
parsed for addition into the SSA.

current_addr is the current address at which we are parsing. This is
important to determine
if the address we are trying to create a block is seen or not.
edge_type is the type of edge to be added between the block which contains
the
current_addr and the new block being added into the CFG.
In this new implementation this method is a bit tricky . Let us break down this functionality into multiple steps . add_block takes an address to add a block at . It then determines if this address is already " seen " . If it has already seen this address it means that we have a backwards edge and we need to split the existing basic block at the target address . Consequently this method calls split_block to add references phis etc . If it is unseen then a new basic block is created at this address and kept ready to be used when instructions beloging to this basic block are parsed for addition into the SSA . current_addr is the current address at which we are parsing . This is important to determine if the address we are trying to create a block is seen or not . edge_type is the type of edge to be added between the block which contains the current_addr and the new block being added into the CFG .
pub fn add_block(
        &mut self,
        at: MAddress,
        current_addr: Option<MAddress>,
        edge_type: Option<u8>,
    ) -> T::ActionRef {
        let seen = current_addr.map_or(false, |cur| {
            match cur.cmp(&at) {
                Ordering::Less | Ordering::Equal => false,
                // Check if `at` is before the first block.
                Ordering::Greater => self.block_of(at).is_some(),
            }
        });
        let upper_block = if seen {
            self.block_of(at).unwrap_or_else(|| {
                radeco_err!("Block not found @ {:?}", at);
                self.ssa.invalid_action().unwrap()
            })
        } else {
            self.ssa
                .invalid_action()
                .expect("Invalid Action is not defined")
        };
        // Create a new block and add the required type of edge.
        let lower_block = self.new_block(at);
        if let Some(e) = edge_type {
            if let Some(addr) = current_addr {
                let current_block = self.block_of(addr).unwrap_or_else(|| {
                    radeco_err!("Block not found @ {:?}", addr);
                    self.ssa.invalid_action().unwrap()
                });
                radeco_trace!(
                    "ADD BLOCK: phip_add_edge|{:?} --{}--> {:?}",
                    current_block,
                    e,
                    lower_block
                );
                self.ssa.insert_control_edge(current_block, lower_block, e);
            }
        }
        if upper_block == lower_block {
            return upper_block;
        }
        if seen {
            // Details on performing the split up.
            //   - Add an unconditional flow edge from the upper to the lower block.
            // - We first find the defs for every expr in the `lower` block arising out
            // of a
            //   split (lower block is the block that has aatat`).
            // - If these defs are in the `upper` block, then we add a phi (incomplete
            // phi) and
            //   this is used to provide the def for this use.
            // Copy all the outgoing CF edges.
            let invalid_edge = self
                .ssa
                .invalid_edge()
                .expect("Invalid Edge is not defined");
            let conditional_branches =
                if let Some(branches) = self.ssa.conditional_edges(upper_block) {
                    branches
                } else {
                    ConditionInfo::new(invalid_edge, invalid_edge)
                };
            let outgoing = [
                conditional_branches.false_side,
                conditional_branches.true_side,
                self.ssa
                    .unconditional_edge(upper_block)
                    .unwrap_or(invalid_edge),
            ];
            for (i, edge) in outgoing.iter().enumerate() {
                if *edge
                    != self
                        .ssa
                        .invalid_edge()
                        .expect("Invalid Edge is not defined")
                {
                    let target = self
                        .ssa
                        .edge_info(*edge)
                        .unwrap_or_else(|| {
                            radeco_err!("Less-endpoints edge");
                            EdgeInfo::new(
                                self.ssa.invalid_action().unwrap(),
                                self.ssa.invalid_action().unwrap(),
                            )
                        })
                        .target;
                    if lower_block != target {
                        radeco_trace!(
                            "ADD BLOCK: phip_add_edge|{:?} --{}--> {:?}",
                            lower_block,
                            i,
                            target
                        );
                        self.ssa.insert_control_edge(lower_block, target, i as u8);
                        self.ssa.remove_control_edge(*edge);
                    }
                }
            }
            radeco_trace!(
                "ADD BLOCK: phip_add_edge|{:?} --{}--> {:?}",
                upper_block,
                UNCOND_EDGE,
                lower_block
            );
            self.ssa
                .insert_control_edge(upper_block, lower_block, UNCOND_EDGE);
            self.blocks.insert(at, lower_block);
            // For there is no assignment to addr_to_index, the original code will
            // skip the loop below, causing losing necessary phi functions
            for (ni, addr) in self.index_to_addr.clone() {
                if addr < at {
                    continue;
                }
                if let Some(block) = self.block_of(addr) {
                    if block != lower_block {
                        break;
                    }
                }
                // Now, this node index belongs to the lower part of the split block.
                let operands = self.ssa.sparse_operands_of(ni);
                // Check if the operands belong to the upper block and if they do, remove the
                // operands edge, add a new phi and connect the edge from phi to ni.
                for operand_ in &operands {
                    let (i, operand) = *operand_;
                    // If operand is const, it cannot belong to any block.
                    match self.ssa.opcode(operand) {
                        Some(MOpcode::OpConst(_)) => {
                            continue;
                        }
                        _ => {}
                    }
                    let operand_addr = self.index_to_addr[&operand];
                    let operand_block = self.block_of(operand_addr).unwrap_or_else(|| {
                        radeco_err!("Block not found @ {:?}", operand_addr);
                        self.ssa.invalid_action().unwrap()
                    });
                    if operand_block == upper_block {
                        // Since the current block is not sealed, we can add an incomplete phi and
                        // modify the constructed SSA to take this phi as operand rather than the
                        // node.
                        // This can be summarized in the following operations:
                        //   - Remove the edge from the operand to ni.
                        //   - Add a new "incomplete" phi associated with the lower block.
                        //   - Connect the edge.
                        // The above two steps can easily be accomplished by doing a read_variable
                        // and adding an operand edge.
                        // BUG: Not all operands are the register residences.
                        // For example, OpZeroExt for 32-bit register. If we want to add a 32-bit register
                        // with a constant, our algorithm will add an Opwiden(64) node for the register,
                        // then add the OpZeroExt node with an Opconst. In this situation, OpZeroExt
                        // node isn't a residence for any register.
                        if !self.outputs.contains_key(&operand) {
                            continue;
                        }
                        self.ssa.op_unuse(ni, operand);
                        let output_varid = self.outputs[&operand];
                        let mut at_ = at;
                        // BUG: if current define is ni itself, this code may cause ni use itself
                        // as operand. So we have to do some check.
                        // A tricky way to solve the bug is to call read_variable_recursive, rather
                        // than read_variable, this will force the code generate a phi node.
                        let replacement_phi = self.read_variable_recursive(output_varid, &mut at_);
                        self.ssa.op_use(ni, i, replacement_phi);
                    }
                }
            }
        } else {
            self.blocks.insert(at, lower_block);
        }
        lower_block
    }
pub fn add_block ( & mut self , at : MAddress , current_addr : Option < MAddress > , edge_type : Option < u8 > , ) -> T :: ActionRef { let seen = current_addr . map_or ( false , | cur | { match cur . cmp ( & at ) { Ordering :: Less | Ordering :: Equal => false , // Check if `at` is before the first block. Ordering :: Greater => self . block_of ( at ) . is_some ( ) , } } ) ; let upper_block = if seen { self . block_of ( at ) . unwrap_or_else ( | | { radeco_err ! ( " " at ) ; self . ssa . invalid_action ( ) . unwrap ( ) } ) } else { self . ssa . invalid_action ( ) . expect ( " " ) } ; // Create a new block and add the required type of edge. let lower_block = self . new_block ( at ) ; if let Some ( e ) = edge_type { if let Some ( addr ) = current_addr { let current_block = self . block_of ( addr ) . unwrap_or_else ( | | { radeco_err ! ( " " addr ) ; self . ssa . invalid_action ( ) . unwrap ( ) } ) ; radeco_trace ! ( " " current_block e lower_block ) ; self . ssa . insert_control_edge ( current_block , lower_block , e ) ; } } if upper_block == lower_block { return upper_block ; } if seen { // Details on performing the split up. //   - Add an unconditional flow edge from the upper to the lower block. // - We first find the defs for every expr in the `lower` block arising out // of a //   split (lower block is the block that has aatat`). // - If these defs are in the `upper` block, then we add a phi (incomplete // phi) and //   this is used to provide the def for this use. // Copy all the outgoing CF edges. let invalid_edge = self . ssa . invalid_edge ( ) . expect ( " " ) ; let conditional_branches = if let Some ( branches ) = self . ssa . conditional_edges ( upper_block ) { branches } else { ConditionInfo :: new ( invalid_edge , invalid_edge ) } ; let outgoing = [ conditional_branches . false_side , conditional_branches . true_side , self . ssa . unconditional_edge ( upper_block ) . unwrap_or ( invalid_edge ) , ] ; for ( i , edge ) in outgoing . iter ( ) . enumerate ( ) { if * edge != self . ssa . invalid_edge ( ) . expect ( " " ) { let target = self . ssa . edge_info ( * edge ) . unwrap_or_else ( | | { radeco_err ! ( " " ) ; EdgeInfo :: new ( self . ssa . invalid_action ( ) . unwrap ( ) , self . ssa . invalid_action ( ) . unwrap ( ) , ) } ) . target ; if lower_block != target { radeco_trace ! ( " " lower_block i target ) ; self . ssa . insert_control_edge ( lower_block , target , i as u8 ) ; self . ssa . remove_control_edge ( * edge ) ; } } } radeco_trace ! ( " " upper_block UNCOND_EDGE lower_block ) ; self . ssa . insert_control_edge ( upper_block , lower_block , UNCOND_EDGE ) ; self . blocks . insert ( at , lower_block ) ; // For there is no assignment to addr_to_index, the original code will // skip the loop below, causing losing necessary phi functions for ( ni , addr ) in self . index_to_addr . clone ( ) { if addr < at { continue ; } if let Some ( block ) = self . block_of ( addr ) { if block != lower_block { break ; } } // Now, this node index belongs to the lower part of the split block. let operands = self . ssa . sparse_operands_of ( ni ) ; // Check if the operands belong to the upper block and if they do, remove the // operands edge, add a new phi and connect the edge from phi to ni. for operand_ in & operands { let ( i , operand ) = * operand_ ; // If operand is const, it cannot belong to any block. match self . ssa . opcode ( operand ) { Some ( MOpcode :: OpConst ( _ ) ) => { continue ; } _ => { } } let operand_addr = self . index_to_addr [ & operand ] ; let operand_block = self . block_of ( operand_addr ) . unwrap_or_else ( | | { radeco_err ! ( " " operand_addr ) ; self . ssa . invalid_action ( ) . unwrap ( ) } ) ; if operand_block == upper_block { // Since the current block is not sealed, we can add an incomplete phi and // modify the constructed SSA to take this phi as operand rather than the // node. // This can be summarized in the following operations: //   - Remove the edge from the operand to ni. //   - Add a new "incomplete" phi associated with the lower block. //   - Connect the edge. // The above two steps can easily be accomplished by doing a read_variable // and adding an operand edge. // BUG: Not all operands are the register residences. // For example, OpZeroExt for 32-bit register. If we want to add a 32-bit register // with a constant, our algorithm will add an Opwiden(64) node for the register, // then add the OpZeroExt node with an Opconst. In this situation, OpZeroExt // node isn't a residence for any register. if ! self . outputs . contains_key ( & operand ) { continue ; } self . ssa . op_unuse ( ni , operand ) ; let output_varid = self . outputs [ & operand ] ; let mut at_ = at ; // BUG: if current define is ni itself, this code may cause ni use itself // as operand. So we have to do some check. // A tricky way to solve the bug is to call read_variable_recursive, rather // than read_variable, this will force the code generate a phi node. let replacement_phi = self . read_variable_recursive ( output_varid , & mut at_ ) ; self . ssa . op_use ( ni , i , replacement_phi ) ; } } } } else { self . blocks . insert ( at , lower_block ) ; } lower_block }
In this new implementation, this method is a bit tricky.
In this new implementation this method is a bit tricky .
&mut self
at
MAddress
current_addr
Option<MAddress>
edge_type
Option<u8>
&mut self
at
MAddress
current_addr
Option<MAddress>
edge_type
Option<u8>