//! The LLVM function EVM legacy assembly data. use std::collections::BTreeMap; use crate::polkavm::context::function::block::evmla_data::key::Key as BlockKey; use crate::polkavm::context::function::block::Block; /// The LLVM function EVM legacy assembly data. /// Describes some data that is only relevant to the EVM legacy assembly. #[derive(Debug)] pub struct EVMLAData<'ctx> { /// The ordinary blocks with numeric tags. /// Is only used by the Solidity EVM compiler. pub blocks: BTreeMap>>, /// The function stack size. pub stack_size: usize, } impl<'ctx> EVMLAData<'ctx> { /// A shortcut constructor. pub fn new(stack_size: usize) -> Self { Self { blocks: BTreeMap::new(), stack_size, } } /// Inserts a function block. pub fn insert_block(&mut self, key: BlockKey, block: Block<'ctx>) { if let Some(blocks) = self.blocks.get_mut(&key) { blocks.push(block); } else { self.blocks.insert(key, vec![block]); } } /// Returns the block with the specified tag and initial stack pattern. /// If there is only one block, it is returned unconditionally. pub fn find_block( &self, key: &BlockKey, stack_hash: &md5::Digest, ) -> anyhow::Result> { if self .blocks .get(key) .ok_or_else(|| anyhow::anyhow!("Undeclared function block {}", key))? .len() == 1 { return self .blocks .get(key) .ok_or_else(|| anyhow::anyhow!("Undeclared function block {}", key))? .first() .cloned() .ok_or_else(|| anyhow::anyhow!("Undeclared function block {}", key)); } self.blocks .get(key) .ok_or_else(|| anyhow::anyhow!("Undeclared function block {}", key))? .iter() .find(|block| { block .evm() .stack_hashes .iter() .any(|hash| hash == stack_hash) }) .cloned() .ok_or_else(|| anyhow::anyhow!("Undeclared function block {}", key)) } }