pub fn generate(
        &mut self,
        locals: &[SignatureToken],
        signature: &FunctionSignature,
        module: CompiledModuleMut,
    ) -> Vec<Bytecode> {
        let number_of_blocks = self.rng.gen_range(1, MAX_CFG_BLOCKS + 1);
        // The number of basic blocks must be at least one based on the
        // generation range.
        assume!(number_of_blocks > 0);
        let mut cfg = CFG::new(&mut self.rng, locals, signature, number_of_blocks);
        let cfg_copy = cfg.clone();
        for (block_id, block) in cfg.get_basic_blocks_mut().iter_mut() {
            debug!("+++++++++++++++++ Starting new block +++++++++++++++++");
            let state1 = AbstractState::from_locals(module.clone(), block.get_locals_in().clone());
            let state2 = AbstractState::from_locals(module.clone(), block.get_locals_out().clone());
            let mut bytecode = self.generate_block(state1, state2.clone(), module.clone());
            let mut state_f = state2;
            if cfg_copy.num_children(*block_id) == 2 {
                // BrTrue, BrFalse: Add bool and branching instruction randomly
                state_f = self.apply_instruction(state_f, &mut bytecode, Bytecode::LdFalse);
                if self.rng.gen_range(0, 1) == 1 {
                    self.apply_instruction(state_f, &mut bytecode, Bytecode::BrTrue(0));
                } else {
                    self.apply_instruction(state_f, &mut bytecode, Bytecode::BrFalse(0));
                }
            } else if cfg_copy.num_children(*block_id) == 1 {
                // Branch: Add branch instruction
                self.apply_instruction(state_f, &mut bytecode, Bytecode::Branch(0));
            } else if cfg_copy.num_children(*block_id) == 0 {
                // TODO: Abort
                // Return: Add return types to last block
                for token_type in signature.return_types.iter() {
                    let next_instruction = match token_type {
                        SignatureToken::String => Bytecode::LdStr(UserStringIndex::new(0)),
                        SignatureToken::Address => Bytecode::LdAddr(AddressPoolIndex::new(0)),
                        SignatureToken::U64 => Bytecode::LdConst(0),
                        SignatureToken::Bool => Bytecode::LdFalse,
                        SignatureToken::ByteArray => {
                            Bytecode::LdByteArray(ByteArrayPoolIndex::new(0))
                        }
                        _ => unimplemented!("Unsupported return type: {:#?}", token_type),
                    };
                    state_f = self.apply_instruction(state_f, &mut bytecode, next_instruction);
                }
                self.apply_instruction(state_f, &mut bytecode, Bytecode::Ret);
            }
            debug!("Instructions generated: {}", bytecode.len());
            block.set_instructions(bytecode);
        }
        // The CFG will be non-empty if we set the number of basic blocks to generate
        // to be non-zero
        verify!(number_of_blocks > 0 || cfg.get_basic_blocks().is_empty());
        cfg.serialize()
    }
/// Generate the body of a function definition given a set of starting `locals` and a target
/// return `signature`. The sequence should contain at least `target_min` and at most
/// `target_max` instructions.
Generate the body of a function definition given a set of starting `locals` and a target
return `signature`. The sequence should contain at least `target_min` and at most
`target_max` instructions.
Generate the body of a function definition given a set of starting ` locals ` and a target return ` signature ` . The sequence should contain at least ` target_min ` and at most ` target_max ` instructions .
pub fn generate(
        &mut self,
        locals: &[SignatureToken],
        signature: &FunctionSignature,
        module: CompiledModuleMut,
    ) -> Vec<Bytecode> {
        let number_of_blocks = self.rng.gen_range(1, MAX_CFG_BLOCKS + 1);
        // The number of basic blocks must be at least one based on the
        // generation range.
        assume!(number_of_blocks > 0);
        let mut cfg = CFG::new(&mut self.rng, locals, signature, number_of_blocks);
        let cfg_copy = cfg.clone();
        for (block_id, block) in cfg.get_basic_blocks_mut().iter_mut() {
            debug!("+++++++++++++++++ Starting new block +++++++++++++++++");
            let state1 = AbstractState::from_locals(module.clone(), block.get_locals_in().clone());
            let state2 = AbstractState::from_locals(module.clone(), block.get_locals_out().clone());
            let mut bytecode = self.generate_block(state1, state2.clone(), module.clone());
            let mut state_f = state2;
            if cfg_copy.num_children(*block_id) == 2 {
                // BrTrue, BrFalse: Add bool and branching instruction randomly
                state_f = self.apply_instruction(state_f, &mut bytecode, Bytecode::LdFalse);
                if self.rng.gen_range(0, 1) == 1 {
                    self.apply_instruction(state_f, &mut bytecode, Bytecode::BrTrue(0));
                } else {
                    self.apply_instruction(state_f, &mut bytecode, Bytecode::BrFalse(0));
                }
            } else if cfg_copy.num_children(*block_id) == 1 {
                // Branch: Add branch instruction
                self.apply_instruction(state_f, &mut bytecode, Bytecode::Branch(0));
            } else if cfg_copy.num_children(*block_id) == 0 {
                // TODO: Abort
                // Return: Add return types to last block
                for token_type in signature.return_types.iter() {
                    let next_instruction = match token_type {
                        SignatureToken::String => Bytecode::LdStr(UserStringIndex::new(0)),
                        SignatureToken::Address => Bytecode::LdAddr(AddressPoolIndex::new(0)),
                        SignatureToken::U64 => Bytecode::LdConst(0),
                        SignatureToken::Bool => Bytecode::LdFalse,
                        SignatureToken::ByteArray => {
                            Bytecode::LdByteArray(ByteArrayPoolIndex::new(0))
                        }
                        _ => unimplemented!("Unsupported return type: {:#?}", token_type),
                    };
                    state_f = self.apply_instruction(state_f, &mut bytecode, next_instruction);
                }
                self.apply_instruction(state_f, &mut bytecode, Bytecode::Ret);
            }
            debug!("Instructions generated: {}", bytecode.len());
            block.set_instructions(bytecode);
        }
        // The CFG will be non-empty if we set the number of basic blocks to generate
        // to be non-zero
        verify!(number_of_blocks > 0 || cfg.get_basic_blocks().is_empty());
        cfg.serialize()
    }
pub fn generate ( & mut self , locals : & [ SignatureToken ] , signature : & FunctionSignature , module : CompiledModuleMut , ) -> Vec < Bytecode > { let number_of_blocks = self . rng . gen_range ( 1 , MAX_CFG_BLOCKS + 1 ) ; // The number of basic blocks must be at least one based on the // generation range. assume ! ( number_of_blocks 0 ) ; let mut cfg = CFG :: new ( & mut self . rng , locals , signature , number_of_blocks ) ; let cfg_copy = cfg . clone ( ) ; for ( block_id , block ) in cfg . get_basic_blocks_mut ( ) . iter_mut ( ) { debug ! ( " " ) ; let state1 = AbstractState :: from_locals ( module . clone ( ) , block . get_locals_in ( ) . clone ( ) ) ; let state2 = AbstractState :: from_locals ( module . clone ( ) , block . get_locals_out ( ) . clone ( ) ) ; let mut bytecode = self . generate_block ( state1 , state2 . clone ( ) , module . clone ( ) ) ; let mut state_f = state2 ; if cfg_copy . num_children ( * block_id ) == 2 { // BrTrue, BrFalse: Add bool and branching instruction randomly state_f = self . apply_instruction ( state_f , & mut bytecode , Bytecode :: LdFalse ) ; if self . rng . gen_range ( 0 , 1 ) == 1 { self . apply_instruction ( state_f , & mut bytecode , Bytecode :: BrTrue ( 0 ) ) ; } else { self . apply_instruction ( state_f , & mut bytecode , Bytecode :: BrFalse ( 0 ) ) ; } } else if cfg_copy . num_children ( * block_id ) == 1 { // Branch: Add branch instruction self . apply_instruction ( state_f , & mut bytecode , Bytecode :: Branch ( 0 ) ) ; } else if cfg_copy . num_children ( * block_id ) == 0 { // TODO: Abort // Return: Add return types to last block for token_type in signature . return_types . iter ( ) { let next_instruction = match token_type { SignatureToken :: String => Bytecode :: LdStr ( UserStringIndex :: new ( 0 ) ) , SignatureToken :: Address => Bytecode :: LdAddr ( AddressPoolIndex :: new ( 0 ) ) , SignatureToken :: U64 => Bytecode :: LdConst ( 0 ) , SignatureToken :: Bool => Bytecode :: LdFalse , SignatureToken :: ByteArray => { Bytecode :: LdByteArray ( ByteArrayPoolIndex :: new ( 0 ) ) } _ => unimplemented ! ( " " token_type ) , } ; state_f = self . apply_instruction ( state_f , & mut bytecode , next_instruction ) ; } self . apply_instruction ( state_f , & mut bytecode , Bytecode :: Ret ) ; } debug ! ( " " bytecode len ( ) ) ; block . set_instructions ( bytecode ) ; } // The CFG will be non-empty if we set the number of basic blocks to generate // to be non-zero verify ! ( number_of_blocks 0 cfg get_basic_blocks ( ) is_empty ( ) ) ; cfg . serialize ( ) }
Generate the body of a function definition given a set of starting `locals` and a target
return `signature`.
Generate the body of a function definition given a set of starting ` locals ` and a target return ` signature ` .
&mut self
locals
&[SignatureToken]
signature
&FunctionSignature
module
CompiledModuleMut