From 0ad600b4686ecb143ada440d913cdbce37c32bdb Mon Sep 17 00:00:00 2001 From: clearloop Date: Mon, 5 Feb 2024 07:34:03 +0800 Subject: [PATCH] feat(codegen): mark no-op for push asm operations --- codegen/src/visitor/call.rs | 1 + codegen/src/wasm/host.rs | 3 +++ compiler/src/parser.rs | 15 +++++++-------- zink/codegen/src/storage.rs | 24 +++++++++++------------- zink/src/asm.rs | 8 ++++---- zink/src/ffi/asm.rs | 2 +- zink/src/ffi/evm.rs | 4 ++-- 7 files changed, 29 insertions(+), 28 deletions(-) diff --git a/codegen/src/visitor/call.rs b/codegen/src/visitor/call.rs index 199831bf9..3963c9779 100644 --- a/codegen/src/visitor/call.rs +++ b/codegen/src/visitor/call.rs @@ -68,6 +68,7 @@ impl Function { HostFunc::Evm(OpCode::LOG3) => self.log(3), HostFunc::Evm(OpCode::LOG4) => self.log(4), HostFunc::Evm(op) => self.masm.emit_op(op), + HostFunc::NoOp => Ok(()), _ => { tracing::error!("unsupported host function {func:?}"); Err(Error::UnsupportedHostFunc(func)) diff --git a/codegen/src/wasm/host.rs b/codegen/src/wasm/host.rs index 1d074c90d..f5bc64fc7 100644 --- a/codegen/src/wasm/host.rs +++ b/codegen/src/wasm/host.rs @@ -9,6 +9,8 @@ use opcodes::{OpCode as _, ShangHai as OpCode}; pub enum HostFunc { /// EVM assemble operations. Evm(OpCode), + /// No operations, this only covers `push_$ty` at the moment. + NoOp, // Zinkc helper functions // /// Emit ABI to the compiler. @@ -39,6 +41,7 @@ impl TryFrom<(&str, &str)> for HostFunc { fn try_from(import: (&str, &str)) -> Result { let (module, name) = import; match import { + ("asm", _) => Ok(Self::NoOp), ("evm", name) => { Ok(Self::Evm(OpCode::from_str(name).map_err(|_| { Error::HostFuncNotFound(module.into(), name.into()) diff --git a/compiler/src/parser.rs b/compiler/src/parser.rs index a1f281f30..d3fac7471 100644 --- a/compiler/src/parser.rs +++ b/compiler/src/parser.rs @@ -28,7 +28,7 @@ impl<'p> Parser<'p> { let valid_payload = validator.payload(&payload)?; match &payload { - Payload::ImportSection(reader) => self.imports = Self::imports(reader), + Payload::ImportSection(reader) => self.imports = Self::imports(reader)?, Payload::DataSection(reader) => self.data = Self::data(reader)?, Payload::ExportSection(reader) => self.exports = Self::exports(reader)?, _ => {} @@ -83,7 +83,7 @@ impl<'p> Parser<'p> { } /// Parse import section. - pub fn imports(reader: &SectionLimited) -> Imports { + pub fn imports(reader: &SectionLimited) -> Result { // TODO: use real index from WASM. (#122) let mut index = 0; @@ -95,14 +95,13 @@ impl<'p> Parser<'p> { ty: TypeRef::Func(_), })) = iter.next() { - if let Ok(func) = HostFunc::try_from((module, name)) { - tracing::trace!("imported function: {}::{} at {index}", module, name); - imports.insert(index, func); - index += 1; - } + let func = HostFunc::try_from((module, name))?; + tracing::trace!("imported function: {}::{} at {index}", module, name); + imports.insert(index, func); + index += 1; } - imports + Ok(imports) } /// Returns constructor if some. diff --git a/zink/codegen/src/storage.rs b/zink/codegen/src/storage.rs index a73c25c98..f9ab591db 100644 --- a/zink/codegen/src/storage.rs +++ b/zink/codegen/src/storage.rs @@ -9,22 +9,17 @@ static IOTA: AtomicI32 = AtomicI32::new(0); /// Parse storage attribute. /// -/// Method `get` unwraps the ptr as the original type in WASM, +/// Method `get` unwraps the ptr as the original type, mainly /// mainly for passing the compilation checks at the moment, -/// it works for WASM as well. +/// and it works for WASM in real cases as well. /// -/// But for the cases in EVM, it doesn't matter what if it returns -/// pointer since the value will be left on stack anyway. +/// For the cases in EVM, it doesn't matter it returns pointer +/// since the value will be left on stack anyway. pub fn parse(input: ItemType) -> TokenStream { let name = input.ident; let ty = input.ty.to_token_stream(); - match ty.to_string().as_str() { - "i32" => (), - _ => unimplemented!("Only support i32 as storage key for now."), - }; - - // temporary solution, we'll switch to 32 byte storage keys later + // Temporary solution, we'll switch to 32 byte storage keys later let key = IOTA.fetch_add(1, Relaxed); let expanded = quote! { #[doc = concat!(" Storage ", stringify!($variable_name))] @@ -33,16 +28,19 @@ pub fn parse(input: ItemType) -> TokenStream { impl zink::Storage<#ty> for #name { const STORAGE_KEY: i32 = #key; + fn get() -> #ty { + zink::Asm::push(Self::STORAGE_KEY); unsafe { - *(zink::ffi::evm::sload(Self::STORAGE_KEY) as *const #ty) + *(zink::ffi::evm::sload() as *const #ty) } } fn set(value: #ty) { + zink::Asm::push(value); + zink::Asm::push(Self::STORAGE_KEY); unsafe { - zink::Asm::push(&value); - zink::ffi::evm::sstore(Self::STORAGE_KEY); + zink::ffi::evm::sstore(); } } } diff --git a/zink/src/asm.rs b/zink/src/asm.rs index fae4f1e8e..b26b94bdf 100644 --- a/zink/src/asm.rs +++ b/zink/src/asm.rs @@ -6,22 +6,22 @@ use paste::paste; /// Types implemented this trait are able to be pushed on stack. pub trait Asm { /// Push self on the stack. - fn push(&self); + fn push(self); } macro_rules! impl_asm { ($ty:ident) => { impl Asm for $ty { - fn push(&self) { + fn push(self) { unsafe { - paste! { ffi::asm::[](*self); } + paste! { ffi::asm::[](self); } } } } }; ($len:expr) => { impl Asm for [u8; $len] { - fn push(&self) { + fn push(self) { unsafe { paste! { ffi::evm::[](self.as_ptr() as i32); } } diff --git a/zink/src/ffi/asm.rs b/zink/src/ffi/asm.rs index 95935825d..5a1c3a471 100644 --- a/zink/src/ffi/asm.rs +++ b/zink/src/ffi/asm.rs @@ -1,6 +1,6 @@ //! Assembly FFI. -#[link(wasm_import_module = "zinkc")] +#[link(wasm_import_module = "asm")] #[allow(improper_ctypes)] extern "C" { /// Push a 8-bit signed integer to the stack. diff --git a/zink/src/ffi/evm.rs b/zink/src/ffi/evm.rs index ba411c3a3..cd803e19f 100644 --- a/zink/src/ffi/evm.rs +++ b/zink/src/ffi/evm.rs @@ -103,10 +103,10 @@ extern "C" { pub fn push32(val: i32); /// Store a value in the storage - pub fn sstore(key: i32); + pub fn sstore(); /// Load a value from the storage - pub fn sload(key: i32) -> *const i32; + pub fn sload() -> *const i32; /// Append log record with no topics pub fn log0(name: &'static [u8]);