diff --git a/src/eravm/context/function/block/evmla_data.rs b/src/context/function/block/evmla_data.rs similarity index 100% rename from src/eravm/context/function/block/evmla_data.rs rename to src/context/function/block/evmla_data.rs diff --git a/src/context/block_key.rs b/src/context/function/block/key.rs similarity index 91% rename from src/context/block_key.rs rename to src/context/function/block/key.rs index 306fb64..4ba0867 100644 --- a/src/context/block_key.rs +++ b/src/context/function/block/key.rs @@ -10,14 +10,14 @@ use crate::context::code_type::CodeType; /// Is only relevant to the EVM legacy assembly. /// #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct BlockKey { +pub struct Key { /// The block code type. pub code_type: CodeType, /// The block tag. pub tag: num::BigUint, } -impl BlockKey { +impl Key { /// /// A shortcut constructor. /// @@ -26,7 +26,7 @@ impl BlockKey { } } -impl std::fmt::Display for BlockKey { +impl std::fmt::Display for Key { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, diff --git a/src/eravm/context/function/block/mod.rs b/src/context/function/block/mod.rs similarity index 99% rename from src/eravm/context/function/block/mod.rs rename to src/context/function/block/mod.rs index ac7527c..117992c 100644 --- a/src/eravm/context/function/block/mod.rs +++ b/src/context/function/block/mod.rs @@ -3,6 +3,7 @@ //! pub mod evmla_data; +pub mod key; use self::evmla_data::EVMLAData; diff --git a/src/context/function/evmla_data.rs b/src/context/function/evmla_data.rs new file mode 100644 index 0000000..6b1bc20 --- /dev/null +++ b/src/context/function/evmla_data.rs @@ -0,0 +1,45 @@ +//! +//! The LLVM function EVM legacy assembly data. +//! + +use std::collections::BTreeMap; + +use crate::context::function::block::key::Key as BlockKey; +use crate::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]); + } + } +} diff --git a/src/context/function/mod.rs b/src/context/function/mod.rs index 1180db9..5893557 100644 --- a/src/context/function/mod.rs +++ b/src/context/function/mod.rs @@ -2,5 +2,7 @@ //! The common LLVM function entities. //! +pub mod block; pub mod declaration; +pub mod evmla_data; pub mod r#return; diff --git a/src/context/mod.rs b/src/context/mod.rs index 6bf688d..aecfefc 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -3,7 +3,6 @@ //! pub mod attribute; -pub mod block_key; pub mod code_type; pub mod function; pub mod r#loop; @@ -23,6 +22,7 @@ use self::pointer::Pointer; use self::r#loop::Loop; use self::traits::address_space::IAddressSpace; use self::traits::evmla_data::IEVMLAData; +use self::traits::evmla_function::IEVMLAFunction; /// /// The LLVM module context trait. @@ -42,7 +42,7 @@ pub trait IContext<'ctx> { /// /// The function type. /// - type Function; + type Function: IEVMLAFunction<'ctx>; /// /// The Solidity extra data type. @@ -80,12 +80,12 @@ pub trait IContext<'ctx> { fn module(&self) -> &inkwell::module::Module<'ctx>; /// - /// Sets the current code type (deploy or runtime). + /// Sets the code type. /// fn set_code_type(&mut self, code_type: CodeType); /// - /// Returns the current code type (deploy or runtime). + /// Returns the code type. /// fn code_type(&self) -> Option; diff --git a/src/context/traits/evmla_data.rs b/src/context/traits/evmla_data.rs index 0e637e8..2aabed9 100644 --- a/src/context/traits/evmla_data.rs +++ b/src/context/traits/evmla_data.rs @@ -1,11 +1,11 @@ //! -//! The LLVM IR EVMLA function trait. +//! The LLVM IR EVMLA data trait. //! use crate::context::value::Value; /// -/// The LLVM IR EVMLA function trait. +/// The LLVM IR EVMLA data trait. /// pub trait IEVMLAData<'ctx> { /// diff --git a/src/context/traits/evmla_function.rs b/src/context/traits/evmla_function.rs new file mode 100644 index 0000000..3fa7c67 --- /dev/null +++ b/src/context/traits/evmla_function.rs @@ -0,0 +1,18 @@ +//! +//! The LLVM IR EVMLA function trait. +//! + +use crate::context::function::block::key::Key as BlockKey; +use crate::context::function::block::Block; + +/// +/// The LLVM IR EVMLA function trait. +/// +pub trait IEVMLAFunction<'ctx> { + /// + /// Returns the block with the specified tag and initial stack pattern. + /// + /// If there is only one block, it is returned unconditionally. + /// + fn find_block(&self, key: &BlockKey, stack_hash: &md5::Digest) -> anyhow::Result>; +} diff --git a/src/context/traits/mod.rs b/src/context/traits/mod.rs index 5b2d92d..af840c9 100644 --- a/src/context/traits/mod.rs +++ b/src/context/traits/mod.rs @@ -4,3 +4,4 @@ pub mod address_space; pub mod evmla_data; +pub mod evmla_function; diff --git a/src/eravm/context/function/evmla_data.rs b/src/eravm/context/function/evmla_data.rs deleted file mode 100644 index 7282105..0000000 --- a/src/eravm/context/function/evmla_data.rs +++ /dev/null @@ -1,86 +0,0 @@ -//! -//! The LLVM function EVM legacy assembly data. -//! - -use std::collections::BTreeMap; - -use crate::context::block_key::BlockKey; -use crate::eravm::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)) - } -} diff --git a/src/eravm/context/function/mod.rs b/src/eravm/context/function/mod.rs index b583a18..1258e05 100644 --- a/src/eravm/context/function/mod.rs +++ b/src/eravm/context/function/mod.rs @@ -2,8 +2,6 @@ //! The LLVM IR generator function. //! -pub mod block; -pub mod evmla_data; pub mod intrinsics; pub mod llvm_runtime; pub mod runtime; @@ -13,14 +11,17 @@ pub mod yul_data; use std::collections::HashMap; use crate::context::attribute::Attribute; +use crate::context::function::block::key::Key as BlockKey; +use crate::context::function::block::Block; use crate::context::function::declaration::Declaration as FunctionDeclaration; +use crate::context::function::evmla_data::EVMLAData as FunctionEVMLAData; use crate::context::function::r#return::Return as FunctionReturn; use crate::context::pointer::Pointer; +use crate::context::traits::evmla_function::IEVMLAFunction; use crate::eravm::context::address_space::AddressSpace; use crate::optimizer::settings::size_level::SizeLevel; use crate::optimizer::Optimizer; -use self::evmla_data::EVMLAData; use self::runtime::Runtime; use self::vyper_data::VyperData; use self::yul_data::YulData; @@ -50,7 +51,7 @@ pub struct Function<'ctx> { /// The Yul compiler data. yul_data: Option, /// The EVM legacy assembly compiler data. - evmla_data: Option>, + evmla_data: Option>, /// The Vyper data. vyper_data: Option, } @@ -339,7 +340,7 @@ impl<'ctx> Function<'ctx> { /// /// Sets the EVM legacy assembly data. /// - pub fn set_evmla_data(&mut self, data: EVMLAData<'ctx>) { + pub fn set_evmla_data(&mut self, data: FunctionEVMLAData<'ctx>) { self.evmla_data = Some(data); } @@ -349,7 +350,7 @@ impl<'ctx> Function<'ctx> { /// # Panics /// If the EVM data has not been initialized. /// - pub fn evmla(&self) -> &EVMLAData<'ctx> { + pub fn evmla(&self) -> &FunctionEVMLAData<'ctx> { self.evmla_data .as_ref() .expect("The EVM data must have been initialized") @@ -361,7 +362,7 @@ impl<'ctx> Function<'ctx> { /// # Panics /// If the EVM data has not been initialized. /// - pub fn evmla_mut(&mut self) -> &mut EVMLAData<'ctx> { + pub fn evmla_mut(&mut self) -> &mut FunctionEVMLAData<'ctx> { self.evmla_data .as_mut() .expect("The EVM data must have been initialized") @@ -429,3 +430,40 @@ impl<'ctx> Function<'ctx> { .expect("The Yul data must have been initialized") } } + +impl<'ctx> IEVMLAFunction<'ctx> for Function<'ctx> { + fn find_block(&self, key: &BlockKey, stack_hash: &md5::Digest) -> anyhow::Result> { + let evmla_data = self.evmla(); + + if evmla_data + .blocks + .get(key) + .ok_or_else(|| anyhow::anyhow!("Undeclared function block {}", key))? + .len() + == 1 + { + return evmla_data + .blocks + .get(key) + .ok_or_else(|| anyhow::anyhow!("Undeclared function block {}", key))? + .first() + .cloned() + .ok_or_else(|| anyhow::anyhow!("Undeclared function block {}", key)); + } + + evmla_data + .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)) + } +} diff --git a/src/evm/context/function/block/evmla_data.rs b/src/evm/context/function/block/evmla_data.rs deleted file mode 100644 index 8d171ff..0000000 --- a/src/evm/context/function/block/evmla_data.rs +++ /dev/null @@ -1,23 +0,0 @@ -//! -//! The LLVM function block EVM legacy assembly data. -//! - -/// -/// The LLVM function block EVM legacy assembly data. -/// -/// Describes some data that is only relevant to the EVM legacy assembly. -/// -#[derive(Debug, Clone)] -pub struct EVMLAData { - /// The initial hashes of the allowed stack states. - pub stack_hashes: Vec, -} - -impl EVMLAData { - /// - /// A shortcut constructor. - /// - pub fn new(stack_hashes: Vec) -> Self { - Self { stack_hashes } - } -} diff --git a/src/evm/context/function/block/mod.rs b/src/evm/context/function/block/mod.rs deleted file mode 100644 index ac7527c..0000000 --- a/src/evm/context/function/block/mod.rs +++ /dev/null @@ -1,68 +0,0 @@ -//! -//! The LLVM IR generator function block. -//! - -pub mod evmla_data; - -use self::evmla_data::EVMLAData; - -/// -/// The LLVM IR generator function block. -/// -#[derive(Debug, Clone)] -pub struct Block<'ctx> { - /// The inner block. - inner: inkwell::basic_block::BasicBlock<'ctx>, - /// The EVM legacy assembly compiler data. - evmla_data: Option, -} - -impl<'ctx> Block<'ctx> { - /// - /// A shortcut constructor. - /// - pub fn new(inner: inkwell::basic_block::BasicBlock<'ctx>) -> Self { - Self { - inner, - evmla_data: None, - } - } - - /// - /// Sets the EVM legacy assembly data. - /// - pub fn set_evmla_data(&mut self, data: EVMLAData) { - self.evmla_data = Some(data); - } - - /// - /// The LLVM object reference. - /// - pub fn inner(&self) -> inkwell::basic_block::BasicBlock<'ctx> { - self.inner - } - - /// - /// Returns the EVM data reference. - /// - /// # Panics - /// If the EVM data has not been initialized. - /// - pub fn evm(&self) -> &EVMLAData { - self.evmla_data - .as_ref() - .expect("The EVM data must have been initialized") - } - - /// - /// Returns the EVM data mutable reference. - /// - /// # Panics - /// If the EVM data has not been initialized. - /// - pub fn evm_mut(&mut self) -> &mut EVMLAData { - self.evmla_data - .as_mut() - .expect("The EVM data must have been initialized") - } -} diff --git a/src/evm/context/function/evmla_data.rs b/src/evm/context/function/evmla_data.rs deleted file mode 100644 index d4a01d9..0000000 --- a/src/evm/context/function/evmla_data.rs +++ /dev/null @@ -1,86 +0,0 @@ -//! -//! The LLVM function EVM legacy assembly data. -//! - -use std::collections::BTreeMap; - -use crate::context::block_key::BlockKey; -use crate::evm::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)) - } -} diff --git a/src/evm/context/function/mod.rs b/src/evm/context/function/mod.rs index a1916ec..c03a512 100644 --- a/src/evm/context/function/mod.rs +++ b/src/evm/context/function/mod.rs @@ -2,8 +2,6 @@ //! The LLVM IR generator function. //! -pub mod block; -pub mod evmla_data; pub mod intrinsics; pub mod runtime; pub mod vyper_data; @@ -11,14 +9,17 @@ pub mod vyper_data; use std::collections::HashMap; use crate::context::attribute::Attribute; +use crate::context::function::block::key::Key as BlockKey; +use crate::context::function::block::Block; use crate::context::function::declaration::Declaration as FunctionDeclaration; +use crate::context::function::evmla_data::EVMLAData as FunctionEVMLAData; use crate::context::function::r#return::Return as FunctionReturn; use crate::context::pointer::Pointer; +use crate::context::traits::evmla_function::IEVMLAFunction; use crate::evm::context::address_space::AddressSpace; use crate::optimizer::settings::size_level::SizeLevel; use crate::optimizer::Optimizer; -use self::evmla_data::EVMLAData; use self::vyper_data::VyperData; /// @@ -44,7 +45,7 @@ pub struct Function<'ctx> { return_block: inkwell::basic_block::BasicBlock<'ctx>, /// The EVM legacy assembly compiler data. - evmla_data: Option>, + evmla_data: Option>, /// The Vyper data. vyper_data: Option, } @@ -268,7 +269,7 @@ impl<'ctx> Function<'ctx> { /// /// Sets the EVM legacy assembly data. /// - pub fn set_evmla_data(&mut self, data: EVMLAData<'ctx>) { + pub fn set_evmla_data(&mut self, data: FunctionEVMLAData<'ctx>) { self.evmla_data = Some(data); } @@ -278,7 +279,7 @@ impl<'ctx> Function<'ctx> { /// # Panics /// If the EVM data has not been initialized. /// - pub fn evmla(&self) -> &EVMLAData<'ctx> { + pub fn evmla(&self) -> &FunctionEVMLAData<'ctx> { self.evmla_data .as_ref() .expect("The EVM data must have been initialized") @@ -290,7 +291,7 @@ impl<'ctx> Function<'ctx> { /// # Panics /// If the EVM data has not been initialized. /// - pub fn evmla_mut(&mut self) -> &mut EVMLAData<'ctx> { + pub fn evmla_mut(&mut self) -> &mut FunctionEVMLAData<'ctx> { self.evmla_data .as_mut() .expect("The EVM data must have been initialized") @@ -327,3 +328,40 @@ impl<'ctx> Function<'ctx> { .expect("The Vyper data must have been initialized") } } + +impl<'ctx> IEVMLAFunction<'ctx> for Function<'ctx> { + fn find_block(&self, key: &BlockKey, stack_hash: &md5::Digest) -> anyhow::Result> { + let evmla_data = self.evmla(); + + if evmla_data + .blocks + .get(key) + .ok_or_else(|| anyhow::anyhow!("Undeclared function block {}", key))? + .len() + == 1 + { + return evmla_data + .blocks + .get(key) + .ok_or_else(|| anyhow::anyhow!("Undeclared function block {}", key))? + .first() + .cloned() + .ok_or_else(|| anyhow::anyhow!("Undeclared function block {}", key)); + } + + evmla_data + .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)) + } +} diff --git a/src/lib.rs b/src/lib.rs index d03c1cb..3d350cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,9 +10,12 @@ pub(crate) mod optimizer; pub(crate) mod target_machine; pub use self::context::attribute::Attribute; -pub use self::context::block_key::BlockKey; pub use self::context::code_type::CodeType; +pub use self::context::function::block::evmla_data::EVMLAData as FunctionBlockEVMLAData; +pub use self::context::function::block::key::Key as BlockKey; +pub use self::context::function::block::Block as FunctionBlock; pub use self::context::function::declaration::Declaration as FunctionDeclaration; +pub use self::context::function::evmla_data::EVMLAData as FunctionEVMLAData; pub use self::context::function::r#return::Return as FunctionReturn; pub use self::context::pointer::Pointer; pub use self::context::r#loop::Loop; @@ -26,9 +29,6 @@ pub use self::eravm::build_assembly_text as eravm_build_assembly_text; pub use self::eravm::context::address_space::AddressSpace as EraVMAddressSpace; pub use self::eravm::context::build::Build as EraVMBuild; pub use self::eravm::context::evmla_data::EVMLAData as EraVMContextEVMLAData; -pub use self::eravm::context::function::block::evmla_data::EVMLAData as EraVMFunctionBlockEVMLAData; -pub use self::eravm::context::function::block::Block as EraVMFunctionBlock; -pub use self::eravm::context::function::evmla_data::EVMLAData as EraVMFunctionEVMLAData; pub use self::eravm::context::function::intrinsics::Intrinsics as EraVMIntrinsicFunction; pub use self::eravm::context::function::llvm_runtime::LLVMRuntime as EraVMLLVMRuntime; pub use self::eravm::context::function::runtime::deploy_code::DeployCode as EraVMDeployCodeFunction; @@ -74,9 +74,6 @@ pub use self::eravm::WriteLLVM as EraVMWriteLLVM; pub use self::evm::context::address_space::AddressSpace as EVMAddressSpace; pub use self::evm::context::build::Build as EVMBuild; pub use self::evm::context::evmla_data::EVMLAData as EVMContextEVMLAData; -pub use self::evm::context::function::block::evmla_data::EVMLAData as EVMFunctionBlockEVMLAData; -pub use self::evm::context::function::block::Block as EVMFunctionBlock; -pub use self::evm::context::function::evmla_data::EVMLAData as EVMFunctionEVMLAData; pub use self::evm::context::function::intrinsics::Intrinsics as EVMIntrinsicFunction; pub use self::evm::context::function::runtime::entry::Entry as EVMEntryFunction; pub use self::evm::context::function::vyper_data::VyperData as EVMFunctionVyperData;