Skip to content

Commit

Permalink
feat(codegen): mark no-op for push asm operations
Browse files Browse the repository at this point in the history
  • Loading branch information
clearloop committed Feb 4, 2024
1 parent 9fc2841 commit 0ad600b
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 28 deletions.
1 change: 1 addition & 0 deletions codegen/src/visitor/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
3 changes: 3 additions & 0 deletions codegen/src/wasm/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -39,6 +41,7 @@ impl TryFrom<(&str, &str)> for HostFunc {
fn try_from(import: (&str, &str)) -> Result<Self> {
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())
Expand Down
15 changes: 7 additions & 8 deletions compiler/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?,
_ => {}
Expand Down Expand Up @@ -83,7 +83,7 @@ impl<'p> Parser<'p> {
}

/// Parse import section.
pub fn imports(reader: &SectionLimited<Import>) -> Imports {
pub fn imports(reader: &SectionLimited<Import>) -> Result<Imports> {
// TODO: use real index from WASM. (#122)
let mut index = 0;

Expand All @@ -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.
Expand Down
24 changes: 11 additions & 13 deletions zink/codegen/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]
Expand All @@ -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();
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions zink/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::[<push_ $ty>](*self); }
paste! { ffi::asm::[<push_ $ty>](self); }
}
}
}
};
($len:expr) => {
impl Asm for [u8; $len] {
fn push(&self) {
fn push(self) {
unsafe {
paste! { ffi::evm::[<push $len>](self.as_ptr() as i32); }
}
Expand Down
2 changes: 1 addition & 1 deletion zink/src/ffi/asm.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
4 changes: 2 additions & 2 deletions zink/src/ffi/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down

0 comments on commit 0ad600b

Please sign in to comment.