diff --git a/.github/actions/install-conta/action.yml b/.github/actions/install-conta/action.yml index 28e013189..33f0db826 100644 --- a/.github/actions/install-conta/action.yml +++ b/.github/actions/install-conta/action.yml @@ -13,4 +13,5 @@ runs: key: ${{ runner.os }}-conta - name: Install Conta + shell: bash run: cargo install conta diff --git a/.github/workflows/deps.yml b/.github/workflows/deps.yml new file mode 100644 index 000000000..4d3869c31 --- /dev/null +++ b/.github/workflows/deps.yml @@ -0,0 +1,15 @@ +name: Deps + +on: + pull_request: + branches: [main] + +jobs: + review: + name: Review + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + - name: Dependency Review + uses: actions/dependency-review-action@v3 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 229cf36c6..ee1ff46e3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -42,13 +42,3 @@ jobs: run: cargo fmt --check - name: Clippy run: cargo clippy --all -- -D warnings - - dep: - name: Review - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - name: Dependency Review - uses: actions/dependency-review-action@v3 diff --git a/Cargo.lock b/Cargo.lock index 6cc2cfa2d..0ab3567e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -828,11 +828,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1371,11 +1371,9 @@ dependencies = [ "auto_impl", "bitflags 2.4.1", "bitvec", - "c-kzg", "enumn", "hashbrown", "hex", - "once_cell", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 90ad30641..c7ba3c30c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ paste = "1.0.14" postcard = { version = "1.0.8", default-features = false } proc-macro2 = "1.0.71" quote = "1.0.33" -revm = "3.5.0" +revm = { version = "3.5.0", default-features = false } semver = "1.0.20" serde = { version = "1.0.193", default-features = false } serde_json = "1.0.108" diff --git a/codegen/src/code/func.rs b/codegen/src/code/func.rs deleted file mode 100644 index 06a042a05..000000000 --- a/codegen/src/code/func.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! External Function for the code section. -use opcodes::ShangHai as OpCode; - -trait OpCodesToBytes { - fn to_bytes(self) -> Vec; -} - -impl OpCodesToBytes for &[OpCode] { - fn to_bytes(self) -> Vec { - [&[OpCode::JUMPDEST], self] - .concat() - .iter() - .map(|op| (*op).into()) - .collect() - } -} - -/// External function in code section. -#[derive(PartialEq, Eq, Debug, Clone, Hash)] -pub struct ExtFunc { - /// Stack input. - pub stack_out: u8, - /// Stack output. - pub stack_in: u8, - /// The bytecode of the external function. - pub bytecode: Vec, -} diff --git a/codegen/src/code/mod.rs b/codegen/src/codegen/code.rs similarity index 84% rename from codegen/src/code/mod.rs rename to codegen/src/codegen/code.rs index 188d72d00..3b443c159 100644 --- a/codegen/src/code/mod.rs +++ b/codegen/src/codegen/code.rs @@ -1,13 +1,11 @@ //! Table for the code section. -pub use func::ExtFunc; use indexmap::IndexMap; -mod func; - /// Code section for EVM. #[derive(Clone, Default, Debug)] pub struct Code { + /// The offset of the code section offset: usize, /// Function table. funcs: IndexMap, @@ -67,3 +65,14 @@ impl Code { code } } + +/// External function in code section. +#[derive(PartialEq, Eq, Debug, Clone, Hash)] +pub struct ExtFunc { + /// Stack input. + pub stack_out: u8, + /// Stack output. + pub stack_in: u8, + /// The bytecode of the external function. + pub bytecode: Vec, +} diff --git a/codegen/src/constructor.rs b/codegen/src/codegen/constructor.rs similarity index 93% rename from codegen/src/constructor.rs rename to codegen/src/codegen/constructor.rs index 850f425dc..16c50db56 100644 --- a/codegen/src/constructor.rs +++ b/codegen/src/codegen/constructor.rs @@ -1,6 +1,9 @@ //! Contract constructor. -use crate::{Buffer, CodeGen, Function, JumpTable, MacroAssembler, Result, ToLSBytes}; +use crate::{ + wasm::{self, ToLSBytes}, + Buffer, Function, JumpTable, MacroAssembler, Result, +}; /// Contract constructor. /// @@ -25,10 +28,10 @@ pub struct Constructor { impl Constructor { /// Create a new constructor. - pub fn new(constructor: Option>, runtime_bytecode: Buffer) -> Result { + pub fn new(constructor: Option>, runtime_bytecode: Buffer) -> Result { let mut init_code = Buffer::new(); if let Some(constructor) = constructor { - let codegen = CodeGen::new( + let codegen = Function::new( constructor.sig()?, Default::default(), Default::default(), diff --git a/codegen/src/dispatcher.rs b/codegen/src/codegen/dispatcher.rs similarity index 93% rename from codegen/src/dispatcher.rs rename to codegen/src/codegen/dispatcher.rs index 0e2882c13..0ab85b1fc 100644 --- a/codegen/src/dispatcher.rs +++ b/codegen/src/codegen/dispatcher.rs @@ -1,8 +1,9 @@ //! Code generator for EVM dispatcher. use crate::{ - code::ExtFunc, DataSet, Error, Exports, Function, Functions, Imports, JumpTable, - MacroAssembler, Result, ToLSBytes, + codegen::code::ExtFunc, + wasm::{self, Data, Exports, Functions, Imports, ToLSBytes}, + Error, JumpTable, MacroAssembler, Result, }; use wasmparser::{FuncType, Operator}; use zabi::Abi; @@ -18,12 +19,12 @@ pub struct Dispatcher<'d> { /// Module imports pub imports: Imports, /// Module data - pub data: DataSet, + pub data: Data, /// Jump table pub table: JumpTable, /// ABI for the current function /// - /// TODO: refactor this. (#192) + /// TODO: refactor this. (#206) pub abi: Vec, } @@ -54,7 +55,7 @@ impl<'d> Dispatcher<'d> { } /// Set data for the dispatcher. - pub fn data(&mut self, data: DataSet) -> &mut Self { + pub fn data(&mut self, data: Data) -> &mut Self { self.data = data; self } @@ -62,7 +63,7 @@ impl<'d> Dispatcher<'d> { /// Query exported function from selector. fn query_func(&self, name: &str) -> Result { for (index, export) in self.exports.iter() { - if export.name == name { + if export == name { return Ok(*index); } } @@ -71,7 +72,7 @@ impl<'d> Dispatcher<'d> { } /// Load function ABI. - fn load_abi(&mut self, selector: &Function<'_>) -> Result { + fn load_abi(&mut self, selector: &wasm::Function<'_>) -> Result { let mut reader = selector.body.get_operators_reader()?; let Operator::I32Const { value: offset } = reader.read()? else { @@ -182,10 +183,10 @@ impl<'d> Dispatcher<'d> { } /// Emit selector to buffer. - fn emit_selector(&mut self, selector: &Function<'_>, last: bool) -> Result<()> { + fn emit_selector(&mut self, selector: &wasm::Function<'_>, last: bool) -> Result<()> { let abi = self.load_abi(selector)?; - // TODO: refactor this. (#192) + // TODO: refactor this. (#206) self.abi.push(abi.clone()); let selector_bytes = abi.selector(); diff --git a/codegen/src/codegen.rs b/codegen/src/codegen/function.rs similarity index 94% rename from codegen/src/codegen.rs rename to codegen/src/codegen/function.rs index 0a476a1f0..b876db278 100644 --- a/codegen/src/codegen.rs +++ b/codegen/src/codegen/function.rs @@ -6,18 +6,19 @@ use crate::{ local::{LocalSlot, LocalSlotType, Locals}, masm::MacroAssembler, validator::ValidateThenVisit, - Buffer, DataSet, Error, Imports, Result, + wasm::{Data, Imports}, + Buffer, Error, Result, }; use wasmparser::{FuncType, FuncValidator, LocalsReader, OperatorsReader, ValidatorResources}; /// The code generation abstraction. -pub struct CodeGen { +pub struct Function { /// The backtrace. pub(crate) backtrace: Backtrace, /// Control stack frames. pub(crate) control: ControlStack, /// Control stack frames. - pub(crate) dataset: DataSet, + pub(crate) dataset: Data, /// The function environment. pub(crate) env: FuncType, /// The defined locals for a function. @@ -32,9 +33,9 @@ pub struct CodeGen { pub(crate) is_main: bool, } -impl CodeGen { +impl Function { /// Create a new code generator. - pub fn new(env: FuncType, dataset: DataSet, imports: Imports, is_main: bool) -> Result { + pub fn new(env: FuncType, dataset: Data, imports: Imports, is_main: bool) -> Result { let mut params_count = 0; if !is_main { params_count = env.params().len() as u8; @@ -109,7 +110,7 @@ impl CodeGen { Ok(()) } - /// Emit function operators + /// Emit function operators. pub fn emit_operators( &mut self, ops: &mut OperatorsReader<'_>, diff --git a/codegen/src/codegen/mod.rs b/codegen/src/codegen/mod.rs new file mode 100644 index 000000000..80fac4e5e --- /dev/null +++ b/codegen/src/codegen/mod.rs @@ -0,0 +1,18 @@ +//! Code generators +//! +//! - CONSTRUCTOR +//! - DISPATCHER +//! - FUNCTION +//! - CODE + +mod code; +mod constructor; +mod dispatcher; +mod function; + +pub use self::{ + code::{Code, ExtFunc}, + constructor::Constructor, + dispatcher::Dispatcher, + function::Function, +}; diff --git a/codegen/src/export.rs b/codegen/src/export.rs deleted file mode 100644 index 8c1b5098d..000000000 --- a/codegen/src/export.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! Exports in code generation. - -use std::{ - collections::BTreeMap, - ops::{Deref, DerefMut}, -}; - -/// WASM export. -#[derive(Clone, Debug)] -pub struct Export { - /// Name of the export. - pub name: String, -} - -/// WASM exports -#[derive(Debug, Default, Clone)] -pub struct Exports(BTreeMap); - -impl Deref for Exports { - type Target = BTreeMap; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for Exports { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -impl Exports { - /// Create a new empty exports. - pub fn new() -> Self { - Exports(BTreeMap::new()) - } - - /// Add an export. - pub fn add(&mut self, index: u32, name: &str) { - self.0.insert(index, Export { name: name.into() }); - } - - /// Get an export by index. - pub fn get(&self, index: u32) -> Option<&Export> { - self.0.get(&index) - } - - /// Get all function selectors - pub fn selectors(&self) -> Vec { - let mut selectors = Vec::new(); - - for (index, export) in self.iter() { - if export.name.ends_with("_selector") { - selectors.push(*index); - } - } - - selectors - } -} diff --git a/codegen/src/jump/mod.rs b/codegen/src/jump/mod.rs index e202acc0f..c46899bd4 100644 --- a/codegen/src/jump/mod.rs +++ b/codegen/src/jump/mod.rs @@ -1,6 +1,6 @@ //! Jump table implementation. -use crate::code::ExtFunc; +use crate::codegen::ExtFunc; pub use table::JumpTable; mod pc; diff --git a/codegen/src/jump/relocate.rs b/codegen/src/jump/relocate.rs index 34cef189f..9bb08eec5 100644 --- a/codegen/src/jump/relocate.rs +++ b/codegen/src/jump/relocate.rs @@ -2,7 +2,8 @@ use crate::{ jump::{relocate, JumpTable}, - Buffer, Error, Result, ToLSBytes, BUFFER_LIMIT, + wasm::ToLSBytes, + Buffer, Error, Result, BUFFER_LIMIT, }; use opcodes::ShangHai as OpCode; diff --git a/codegen/src/jump/table.rs b/codegen/src/jump/table.rs index 8113a3023..c32c6b31c 100644 --- a/codegen/src/jump/table.rs +++ b/codegen/src/jump/table.rs @@ -1,6 +1,6 @@ //! Jump Table -use crate::{code::ExtFunc, jump::Jump, Code, Error, Result}; +use crate::{codegen::ExtFunc, jump::Jump, Code, Error, Result}; use std::collections::BTreeMap; /// Jump table implementation. diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index f24e952f4..2e1665770 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -3,17 +3,9 @@ #![recursion_limit = "1024"] pub use crate::{ - abi::{ToLSBytes, Type}, asm::Assembler, - code::Code, - codegen::CodeGen, - constructor::Constructor, + codegen::{Code, Constructor, Dispatcher, Function}, control::{ControlStack, ControlStackFrame, ControlStackFrameType}, - data::DataSet, - dispatcher::Dispatcher, - export::Exports, - func::{Function, Functions}, - import::{Func, Imports}, jump::JumpTable, local::{LocalSlot, Locals}, masm::MacroAssembler, @@ -21,24 +13,17 @@ pub use crate::{ }; use smallvec::SmallVec; -pub mod abi; mod asm; mod backtrace; -mod code; mod codegen; -mod constructor; mod control; -mod data; -mod dispatcher; -mod export; -mod func; -mod import; mod jump; mod local; mod masm; mod result; mod validator; mod visitor; +pub mod wasm; /// Maximum size of a evm bytecode in bytes. pub const BUFFER_LIMIT: usize = 0x6000; diff --git a/codegen/src/local.rs b/codegen/src/local.rs index 1e1052ce2..664c2b229 100644 --- a/codegen/src/local.rs +++ b/codegen/src/local.rs @@ -1,7 +1,7 @@ //! WASM local slot. use crate::{ - abi::{ToLSBytes, Type}, + wasm::{ToLSBytes, Type}, Error, Result, }; use smallvec::SmallVec; diff --git a/codegen/src/masm/integer.rs b/codegen/src/masm/integer.rs index ff65c2575..a0087dd53 100644 --- a/codegen/src/masm/integer.rs +++ b/codegen/src/masm/integer.rs @@ -1,6 +1,6 @@ // Integer instructions -use crate::{MacroAssembler, Result, ToLSBytes}; +use crate::{wasm::ToLSBytes, MacroAssembler, Result}; use wasmparser::{Ieee32, Ieee64}; impl MacroAssembler { diff --git a/codegen/src/masm/mod.rs b/codegen/src/masm/mod.rs index 4af470001..5f0ff72ed 100644 --- a/codegen/src/masm/mod.rs +++ b/codegen/src/masm/mod.rs @@ -1,8 +1,8 @@ //! MacroAssembler used by the code generation. use crate::{ - abi::{ToLSBytes, Type}, asm::Assembler, + wasm::{ToLSBytes, Type}, Error, Result, }; use smallvec::SmallVec; diff --git a/codegen/src/masm/ret.rs b/codegen/src/masm/ret.rs index 05b7741b8..cf9fadd9e 100644 --- a/codegen/src/masm/ret.rs +++ b/codegen/src/masm/ret.rs @@ -1,6 +1,6 @@ //! Return handlers -use crate::{Error, MacroAssembler, Result, ToLSBytes}; +use crate::{wasm::ToLSBytes, Error, MacroAssembler, Result}; use wasmparser::ValType; impl MacroAssembler { diff --git a/codegen/src/result.rs b/codegen/src/result.rs index 335e1adb8..60c703e64 100644 --- a/codegen/src/result.rs +++ b/codegen/src/result.rs @@ -95,7 +95,7 @@ pub enum Error { StackNotBalanced(u8), /// Failed to queue host functions. #[error("Unsupported host function {0:?}")] - UnsupportedHostFunc(crate::Func), + UnsupportedHostFunc(crate::wasm::HostFunc), } /// Codegen result diff --git a/codegen/src/validator.rs b/codegen/src/validator.rs index b6dfa9cfd..b6cbd06c0 100644 --- a/codegen/src/validator.rs +++ b/codegen/src/validator.rs @@ -1,12 +1,10 @@ //! Pre-visitor for parsing WASM. -use crate::Result; +use crate::{Function, Result}; use wasmparser::{Operator, VisitOperator}; -use crate::CodeGen; - /// A pre-visitor that validates the WASM and then visits it. -pub struct ValidateThenVisit<'a, T>(pub T, pub &'a mut CodeGen); +pub struct ValidateThenVisit<'a, T>(pub T, pub &'a mut Function); macro_rules! validate_then_visit { ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => { @@ -40,7 +38,7 @@ trait ReachableState { fn is_reachable(&self) -> bool; } -impl ReachableState for CodeGen { +impl ReachableState for Function { fn is_reachable(&self) -> bool { true } diff --git a/codegen/src/visitor/call.rs b/codegen/src/visitor/call.rs index 4ff8ca59b..6c6b8c521 100644 --- a/codegen/src/visitor/call.rs +++ b/codegen/src/visitor/call.rs @@ -1,8 +1,8 @@ //! call instructions -use crate::{CodeGen, Error, Func, Result}; +use crate::{wasm::HostFunc, Error, Function, Result}; -impl CodeGen { +impl Function { /// The call indirect instruction calls a function indirectly /// through an operand indexing into a table. pub fn _call_indirect( @@ -60,15 +60,15 @@ impl CodeGen { .ok_or(Error::ImportedFuncNotFound(index))?; match func { - Func::Sstore => self.masm._sstore(), - Func::Sload => self.masm._sload(), - Func::Log0 => self.log(0), - Func::Log1 => self.log(1), - Func::Log2 => self.log(2), - Func::Log3 => self.log(3), - Func::Log4 => self.log(4), + HostFunc::Sstore => self.masm._sstore(), + HostFunc::Sload => self.masm._sload(), + HostFunc::Log0 => self.log(0), + HostFunc::Log1 => self.log(1), + HostFunc::Log2 => self.log(2), + HostFunc::Log3 => self.log(3), + HostFunc::Log4 => self.log(4), _ => { - tracing::error!("unsupported embedded function {func:?}"); + tracing::error!("unsupported host function {func:?}"); Err(Error::UnsupportedHostFunc(func)) } } diff --git a/codegen/src/visitor/control.rs b/codegen/src/visitor/control.rs index ac86c08e3..361743f9c 100644 --- a/codegen/src/visitor/control.rs +++ b/codegen/src/visitor/control.rs @@ -2,11 +2,11 @@ use crate::{ control::{ControlStackFrame, ControlStackFrameType}, - CodeGen, Result, + Function, Result, }; use wasmparser::{BlockType, BrTable}; -impl CodeGen { +impl Function { /// The beginning of an if construct with an implicit block. pub fn _if(&mut self, blockty: BlockType) -> Result<()> { // Emit iszero to check the condition. diff --git a/codegen/src/visitor/handlers.rs b/codegen/src/visitor/handlers.rs index d78768d2d..01d41e8d2 100644 --- a/codegen/src/visitor/handlers.rs +++ b/codegen/src/visitor/handlers.rs @@ -1,8 +1,8 @@ //! Case handlers -use crate::{CodeGen, ControlStackFrame, ControlStackFrameType, Result}; +use crate::{ControlStackFrame, ControlStackFrameType, Function, Result}; -impl CodeGen { +impl Function { /// Handle the end of the function. pub(crate) fn handle_return(&mut self) -> Result<()> { let results = self.env.results(); diff --git a/codegen/src/visitor/local.rs b/codegen/src/visitor/local.rs index a1d2fb887..76dadda58 100644 --- a/codegen/src/visitor/local.rs +++ b/codegen/src/visitor/local.rs @@ -1,8 +1,8 @@ //! Local instructions -use crate::{CodeGen, Error, Result}; +use crate::{Error, Function, Result}; -impl CodeGen { +impl Function { /// This instruction gets the value of a variable. pub fn _local_get(&mut self, local_index: u32) -> Result<()> { let local_index = local_index as usize; diff --git a/codegen/src/visitor/log.rs b/codegen/src/visitor/log.rs index a17c190e0..3704df5f1 100644 --- a/codegen/src/visitor/log.rs +++ b/codegen/src/visitor/log.rs @@ -1,8 +1,8 @@ //! System instructions -use crate::{masm::MemoryInfo, CodeGen, Error, Result, ToLSBytes}; +use crate::{masm::MemoryInfo, wasm::ToLSBytes, Error, Function, Result}; -impl CodeGen { +impl Function { /// Parse log data from the bytecode. fn log_data(&mut self) -> Result<(i32, i32)> { let buffer: Vec = self.masm.buffer().into(); diff --git a/codegen/src/visitor/mod.rs b/codegen/src/visitor/mod.rs index 8485a91fe..374652ae5 100644 --- a/codegen/src/visitor/mod.rs +++ b/codegen/src/visitor/mod.rs @@ -1,10 +1,10 @@ //! This module is the central place for machine code emission. //! //! It defines an implementation of wasmparser's Visitor trait for -//! `CodeGen`; which defines a visitor per op-code, which validates +//! `Function`; which defines a visitor per op-code, which validates //! and dispatches to the corresponding machine code emitter. -use crate::{CodeGen, Result}; +use crate::{Function, Result}; use paste::paste; use tracing::trace; use wasmparser::{for_each_operator, BlockType, BrTable, Ieee32, Ieee64, MemArg, VisitOperator}; @@ -189,7 +189,7 @@ macro_rules! map_wasm_operators { }; } -impl<'a> VisitOperator<'a> for CodeGen { +impl<'a> VisitOperator<'a> for Function { type Output = Result<()>; for_each_operator!(impl_visit_operator); diff --git a/codegen/src/abi.rs b/codegen/src/wasm/abi.rs similarity index 100% rename from codegen/src/abi.rs rename to codegen/src/wasm/abi.rs diff --git a/codegen/src/data.rs b/codegen/src/wasm/data.rs similarity index 89% rename from codegen/src/data.rs rename to codegen/src/wasm/data.rs index d5fe50731..d3ffbf0e2 100644 --- a/codegen/src/data.rs +++ b/codegen/src/wasm/data.rs @@ -10,9 +10,9 @@ use std::{ /// /// NOTE: current only support constant expression. #[derive(Default, Clone, Debug)] -pub struct DataSet(BTreeMap>); +pub struct Data(BTreeMap>); -impl DataSet { +impl Data { /// Load data from offset and size pub fn load(&self, offset: i32, size: usize) -> Result> { for ptr in self.0.keys().cloned().rev() { @@ -28,7 +28,7 @@ impl DataSet { } } -impl Deref for DataSet { +impl Deref for Data { type Target = BTreeMap>; fn deref(&self) -> &Self::Target { @@ -36,7 +36,7 @@ impl Deref for DataSet { } } -impl DerefMut for DataSet { +impl DerefMut for Data { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } diff --git a/codegen/src/func.rs b/codegen/src/wasm/func.rs similarity index 96% rename from codegen/src/func.rs rename to codegen/src/wasm/func.rs index 8fd15d9b8..46c190e73 100644 --- a/codegen/src/func.rs +++ b/codegen/src/wasm/func.rs @@ -1,5 +1,5 @@ //! Function handler -use crate::{Error, Exports, Result}; +use crate::{wasm::Exports, Error, Result}; use std::{ collections::BTreeMap, ops::{Deref, DerefMut}, @@ -71,7 +71,7 @@ impl<'f> Functions<'f> { /// Remove constructor function pub fn remove_constructor(&mut self, exports: &Exports) -> Option> { for (index, export) in exports.iter() { - if &export.name == "constructor" { + if export.as_str() == "constructor" { return self.remove(index); } } diff --git a/codegen/src/import.rs b/codegen/src/wasm/host.rs similarity index 70% rename from codegen/src/import.rs rename to codegen/src/wasm/host.rs index a44eb6789..adcc95f78 100644 --- a/codegen/src/import.rs +++ b/codegen/src/wasm/host.rs @@ -1,14 +1,10 @@ -//! Built-in functions for EVM -use std::{ - collections::BTreeMap, - ops::{Deref, DerefMut}, -}; +//! Host functions use crate::{Error, Result}; /// EVM built-in function. #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] -pub enum Func { +pub enum HostFunc { // EVM functions. // /// Run function sload. @@ -26,14 +22,13 @@ pub enum Func { /// Run function log4. Log4, - // // Zinkc helper functions // /// Emit ABI to the compiler. EmitABI, } -impl Func { +impl HostFunc { /// Stack input size. pub fn stack_in(&self) -> u8 { match self { @@ -63,14 +58,11 @@ impl Func { } } -impl TryFrom<(&str, &str)> for Func { +impl TryFrom<(&str, &str)> for HostFunc { type Error = Error; fn try_from(import: (&str, &str)) -> Result { let (module, name) = import; - // NOTE: `select` is not external call - // so we don't need to check process it - // here match import { ("evm", "sload") => Ok(Self::Sload), ("evm", "sstore") => Ok(Self::Sstore), @@ -87,28 +79,3 @@ impl TryFrom<(&str, &str)> for Func { } } } - -/// Imported functions -#[derive(Clone, Debug, Default)] -pub struct Imports(BTreeMap); - -impl Imports { - /// If the function is `emit_abi`. - pub fn is_emit_abi(&self, index: u32) -> bool { - self.0.get(&index) == Some(&Func::EmitABI) - } -} - -impl Deref for Imports { - type Target = BTreeMap; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for Imports { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} diff --git a/codegen/src/wasm/ie.rs b/codegen/src/wasm/ie.rs new file mode 100644 index 000000000..85536876a --- /dev/null +++ b/codegen/src/wasm/ie.rs @@ -0,0 +1,31 @@ +//! Imports and exports + +use crate::wasm::HostFunc; +use std::collections::BTreeMap; + +impl_deref! { + ("WASM import section", Imports, BTreeMap), + ("WASM export section", Exports, BTreeMap) +} + +impl Imports { + /// If the function is `emit_abi`. + pub fn is_emit_abi(&self, index: u32) -> bool { + self.get(&index) == Some(&HostFunc::EmitABI) + } +} + +impl Exports { + /// Get all function selectors + pub fn selectors(&self) -> Vec { + self.iter() + .filter_map(|(index, export)| { + if export.ends_with("_selector") { + Some(*index) + } else { + None + } + }) + .collect::>() + } +} diff --git a/codegen/src/wasm/mod.rs b/codegen/src/wasm/mod.rs new file mode 100644 index 000000000..6d9614a4e --- /dev/null +++ b/codegen/src/wasm/mod.rs @@ -0,0 +1,40 @@ +//! WASM related primitives. + +macro_rules! impl_deref { + ($doc:literal, $name:ident, $target:ty) => { + #[derive(Clone, Debug, Default)] + #[doc = concat!(" ", $doc)] + pub struct $name($target); + + impl core::ops::Deref for $name { + type Target = $target; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl core::ops::DerefMut for $name { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + }; + ($(($doc:literal, $name:ident, $target:ty)),*) => { + $( impl_deref!($doc, $name, $target); )* + }; +} + +mod abi; +mod data; +mod func; +mod host; +mod ie; + +pub use self::{ + abi::{ToLSBytes, Type}, + data::Data, + func::{Function, Functions}, + host::HostFunc, + ie::{Exports, Imports}, +}; diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index d15e38a5e..4f9f91da3 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -3,7 +3,8 @@ use crate::{parser::Parser, Config, Error, Result}; use zabi::Abi; use zingen::{ - Buffer, CodeGen, Constructor, DataSet, Dispatcher, Function, Imports, JumpTable, BUFFER_LIMIT, + wasm::{self, Data, Imports}, + Buffer, Constructor, Dispatcher, Function, JumpTable, BUFFER_LIMIT, }; /// Zink Compiler @@ -80,9 +81,9 @@ impl Compiler { /// Compile WASM function. pub fn compile_func( &mut self, - dataset: DataSet, + dataset: Data, imports: Imports, - mut func: Function<'_>, + mut func: wasm::Function<'_>, ) -> Result<()> { let func_index = func.index(); let sig = func.sig()?; @@ -94,7 +95,7 @@ impl Compiler { func_index - (imports.len() as u32) == 0 }; - let mut codegen = CodeGen::new(sig, dataset, imports, is_main)?; + let mut codegen = Function::new(sig, dataset, imports, is_main)?; let mut locals_reader = func.body.get_locals_reader()?; let mut ops_reader = func.body.get_operators_reader()?; @@ -106,7 +107,7 @@ impl Compiler { } /// Emit buffer to the inner buffer. - fn emit_buffer(&mut self, func_index: u32, codegen: CodeGen) -> Result<()> { + fn emit_buffer(&mut self, func_index: u32, codegen: Function) -> Result<()> { let buffer = codegen.finish(&mut self.table, self.buffer.len() as u16)?; self.table .call_offset(func_index, self.buffer.len() as u16)?; @@ -125,7 +126,7 @@ impl Compiler { } /// Returns bytecode. - fn bytecode(&self, constructor: Option>) -> Result { + fn bytecode(&self, constructor: Option>) -> Result { Constructor::new(constructor, self.buffer.clone())? .finish() .map_err(Into::into) diff --git a/compiler/src/parser.rs b/compiler/src/parser.rs index 6c624e0c7..baf5cc8c5 100644 --- a/compiler/src/parser.rs +++ b/compiler/src/parser.rs @@ -6,7 +6,7 @@ use wasmparser::{ Data, DataKind, Export, ExternalKind, Import, Operator, Payload, SectionLimited, TypeRef, ValidPayload, Validator, }; -use zingen::{DataSet, Exports, Func, Function, Functions, Imports}; +use zingen::wasm::{self, Data as DataSet, Exports, Functions, HostFunc, Imports}; /// WASM module parser #[derive(Default)] @@ -76,7 +76,7 @@ impl<'p> Parser<'p> { index, })) = iter.next() { - exports.add(index, name); + exports.insert(index, name.into()); } Ok(exports) @@ -95,7 +95,7 @@ impl<'p> Parser<'p> { ty: TypeRef::Func(_), })) = iter.next() { - if let Ok(func) = Func::try_from((module, name)) { + if let Ok(func) = HostFunc::try_from((module, name)) { tracing::trace!("imported function: {}::{} at {index}", module, name); imports.insert(index, func); index += 1; @@ -106,7 +106,7 @@ impl<'p> Parser<'p> { } /// Returns constructor if some. - pub fn remove_constructor(&mut self) -> Option> { + pub fn remove_constructor(&mut self) -> Option> { self.funcs.remove_constructor(&self.exports) } } diff --git a/zint/Cargo.toml b/zint/Cargo.toml index 02ca6cb80..79007335a 100644 --- a/zint/Cargo.toml +++ b/zint/Cargo.toml @@ -14,7 +14,7 @@ anyhow.workspace = true cargo_metadata.workspace = true etc.workspace = true hex.workspace = true -revm.workspace = true +revm = { workspace = true, features = [ "std" ] } serde = { workspace = true, features = [ "derive" ] } serde_json.workspace = true thiserror.workspace = true