diff --git a/codegen/src/asm.rs b/codegen/src/asm.rs index 73b713ca1..8ab558e43 100644 --- a/codegen/src/asm.rs +++ b/codegen/src/asm.rs @@ -5,6 +5,8 @@ use crate::{Buffer, Error, Result}; use opcodes::{for_each_cancun_operator, Cancun as OpCode, OpCode as _}; +const MAX_STACK_SIZE: u16 = 1024; + /// Low level assembler implementation for EVM. #[derive(Default, Clone, Debug)] pub struct Assembler { @@ -18,8 +20,8 @@ pub struct Assembler { gas: u128, /// Memory pointer for byte offset. pub mp: usize, - /// Stack pointer, maximum 1024 items. - pub sp: u8, + /// Stack pointer, maximum `MAX_STACK_SIZE` items. + pub sp: u16, } impl Assembler { @@ -41,7 +43,7 @@ impl Assembler { } /// Increment stack pointer - pub fn increment_sp(&mut self, items: u8) -> Result<()> { + pub fn increment_sp(&mut self, items: u16) -> Result<()> { if items == 0 { return Ok(()); } @@ -51,18 +53,20 @@ impl Assembler { self.sp, self.sp + items ); - self.sp += items; + self.sp = self + .sp + .checked_add(items) + .ok_or(Error::StackOverflow(self.sp, items))?; - // TODO: fix this limitation: should be 1024. (#127) - if self.sp > 254 { - return Err(Error::StackOverflow(self.sp)); + if self.sp > MAX_STACK_SIZE { + return Err(Error::StackOverflow(self.sp, items)); } Ok(()) } /// Decrement stack pointer - pub fn decrement_sp(&mut self, items: u8) -> Result<()> { + pub fn decrement_sp(&mut self, items: u16) -> Result<()> { if items == 0 { return Ok(()); } @@ -118,10 +122,10 @@ impl Assembler { /// the stack usages. pub fn emit_op(&mut self, opcode: OpCode) -> Result<()> { tracing::trace!("emit opcode: {:?}", opcode); - self.decrement_sp(opcode.stack_in() as u8)?; + self.decrement_sp(opcode.stack_in())?; self.emit(opcode.into()); self.increment_gas(opcode.gas().into()); - self.increment_sp(opcode.stack_out() as u8)?; + self.increment_sp(opcode.stack_out())?; Ok(()) } diff --git a/codegen/src/codegen/function.rs b/codegen/src/codegen/function.rs index 380983fab..3b5596adb 100644 --- a/codegen/src/codegen/function.rs +++ b/codegen/src/codegen/function.rs @@ -137,7 +137,7 @@ impl Function { /// Finish code generation. pub fn finish(self, jump_table: &mut JumpTable, pc: u16) -> Result { let sp = self.masm.sp(); - if !self.is_main && self.abi.is_none() && self.masm.sp() != self.ty.results().len() as u8 { + if !self.is_main && self.abi.is_none() && self.masm.sp() != self.ty.results().len() as u16 { return Err(Error::StackNotBalanced(sp)); } diff --git a/codegen/src/control.rs b/codegen/src/control.rs index 418c829f4..61d342431 100644 --- a/codegen/src/control.rs +++ b/codegen/src/control.rs @@ -38,7 +38,7 @@ pub struct ControlStackFrame { result: BlockType, /// Original stack pointer. - pub original_sp: u8, + pub original_sp: u16, } impl ControlStackFrame { @@ -46,7 +46,7 @@ impl ControlStackFrame { pub fn new( ty: ControlStackFrameType, original_pc_offset: u16, - original_sp: u8, + original_sp: u16, result: BlockType, ) -> Self { Self { diff --git a/codegen/src/masm/mod.rs b/codegen/src/masm/mod.rs index b78b57a55..0978a3ef1 100644 --- a/codegen/src/masm/mod.rs +++ b/codegen/src/masm/mod.rs @@ -139,7 +139,7 @@ impl MacroAssembler { 30 => self.asm._push30(), 31 => self.asm._push31(), 32 => self.asm._push32(), - _ => return Err(Error::StackIndexOutOfRange(len as u8)), + _ => return Err(Error::StackIndexOutOfRange(len as u16)), }?; self.asm.emitn(bytes); @@ -155,12 +155,12 @@ impl MacroAssembler { } /// Get the stack pointer. - pub fn sp(&self) -> u8 { + pub fn sp(&self) -> u16 { self.asm.sp } /// Swap memory by target index. - pub fn swap(&mut self, index: u8) -> Result<()> { + pub fn swap(&mut self, index: u16) -> Result<()> { tracing::trace!("swap index: {}", index); match index { 0 => Ok(()), @@ -185,7 +185,7 @@ impl MacroAssembler { } /// Duplicate stack item by target index. - pub fn dup(&mut self, index: u8) -> Result<()> { + pub fn dup(&mut self, index: u16) -> Result<()> { tracing::trace!("dup index: {}", index); match index { 0 => Ok(()), @@ -212,7 +212,7 @@ impl MacroAssembler { /// Shift the program counter to the bottom or the top of the /// parameters. This is used by the callee function for jumping /// back to the caller function. - pub fn shift_stack(&mut self, count: u8, from_top: bool) -> Result<()> { + pub fn shift_stack(&mut self, count: u16, from_top: bool) -> Result<()> { let mut swaps = 0; if from_top { diff --git a/codegen/src/masm/ret.rs b/codegen/src/masm/ret.rs index 84ef44ab2..ec5b65a04 100644 --- a/codegen/src/masm/ret.rs +++ b/codegen/src/masm/ret.rs @@ -31,7 +31,7 @@ impl MacroAssembler { /// Handle the return of a call. pub fn call_return(&mut self, results: &[ValType]) -> Result<()> { - let len = results.len() as u8; + let len = results.len() as u16; tracing::trace!("cleaning frame stack, target: {}", len + 1); // TODO: clean stacks via the count of nested control stacks. diff --git a/codegen/src/result.rs b/codegen/src/result.rs index 1889e1bbd..12816f3b4 100644 --- a/codegen/src/result.rs +++ b/codegen/src/result.rs @@ -86,16 +86,16 @@ pub enum Error { SelectorNotFound, /// Failed to index data on stack. #[error("Stack index is out of range {0}, max is 255 (0x400)")] - StackIndexOutOfRange(u8), + StackIndexOutOfRange(u16), /// Failed to increment stack pointer. - #[error("Stack overflow, max is 1024 stack items, got {0}")] - StackOverflow(u8), + #[error("Stack overflow, max is 1024 stack items, but add {1} to {0}")] + StackOverflow(u16, u16), /// Failed to decrement stack pointer. #[error("Stack underflow, current stack items {0}, expect at least {1}")] - StackUnderflow(u8, u8), + StackUnderflow(u16, u16), /// Failed to pop stack. #[error("Stack not balanced, current stack items {0}")] - StackNotBalanced(u8), + StackNotBalanced(u16), /// Failed to queue host functions. #[error("Unsupported host function {0:?}")] UnsupportedHostFunc(crate::wasm::HostFunc), diff --git a/codegen/src/visitor/call.rs b/codegen/src/visitor/call.rs index c61c93df0..cdf9066af 100644 --- a/codegen/src/visitor/call.rs +++ b/codegen/src/visitor/call.rs @@ -89,7 +89,7 @@ impl Function { // Adjust the stack pointer for the results. self.masm._jumpdest()?; - self.masm.increment_sp(*results as u8)?; + self.masm.increment_sp(*results as u16)?; Ok(()) }