We generate a function in multiple stages: First we generate a random number of empty blocks Then we generate a random pool of variables to be used throughout the function We then visit each block and generate random instructions Because we generate all blocks and variables up front we already know everything that we need when generating instructions (i.e. jump targets / variables)
(mut self)
| 1942 | /// Because we generate all blocks and variables up front we already know everything that |
| 1943 | /// we need when generating instructions (i.e. jump targets / variables) |
| 1944 | pub fn generate(mut self) -> Result<Function> { |
| 1945 | let mut fn_builder_ctx = FunctionBuilderContext::new(); |
| 1946 | let mut func = Function::with_name_signature(self.name.clone(), self.signature.clone()); |
| 1947 | |
| 1948 | let mut builder = FunctionBuilder::new(&mut func, &mut fn_builder_ctx); |
| 1949 | |
| 1950 | // Build the function references before generating the block CFG since we store |
| 1951 | // function references in the CFG. |
| 1952 | self.generate_funcrefs(&mut builder)?; |
| 1953 | self.generate_blocks(&mut builder)?; |
| 1954 | |
| 1955 | // Function preamble |
| 1956 | self.generate_stack_slots(&mut builder)?; |
| 1957 | |
| 1958 | // Main instruction generation loop |
| 1959 | for (block, block_sig) in self.resources.blocks.clone().into_iter() { |
| 1960 | let is_block0 = block.as_u32() == 0; |
| 1961 | builder.switch_to_block(block); |
| 1962 | |
| 1963 | if is_block0 { |
| 1964 | // The first block is special because we must create variables both for the |
| 1965 | // block signature and for the variable pool. Additionally, we must also define |
| 1966 | // initial values for all variables that are not the function signature. |
| 1967 | self.build_variable_pool(&mut builder)?; |
| 1968 | |
| 1969 | // Stack slots have random bytes at the beginning of the function |
| 1970 | // initialize them to a constant value so that execution stays predictable. |
| 1971 | self.initialize_stack_slots(&mut builder)?; |
| 1972 | } else { |
| 1973 | // Define variables for the block params |
| 1974 | for (i, ty) in block_sig.iter().enumerate() { |
| 1975 | let var = self.get_variable_of_type(*ty)?; |
| 1976 | let block_param = builder.block_params(block)[i]; |
| 1977 | builder.def_var(var, block_param); |
| 1978 | } |
| 1979 | } |
| 1980 | |
| 1981 | // Generate block instructions |
| 1982 | self.generate_instructions(&mut builder)?; |
| 1983 | |
| 1984 | // Insert a terminator to safely exit the block |
| 1985 | self.insert_terminator(&mut builder, block)?; |
| 1986 | } |
| 1987 | |
| 1988 | builder.seal_all_blocks(); |
| 1989 | builder.finalize(); |
| 1990 | |
| 1991 | Ok(func) |
| 1992 | } |
| 1993 | } |
no test coverage detected