From 6b1d74376e968ac28ea53aa986ee83e0f4f8e8da Mon Sep 17 00:00:00 2001 From: clearloop Date: Thu, 10 Oct 2024 07:52:26 +0800 Subject: [PATCH] chore(codegen): ban recursion --- codegen/src/visitor/call.rs | 8 ++ compiler/filetests/lib.rs | 7 +- .../filetests/wat/recursion/fibonacci.wat | 76 +++++++++---------- compiler/src/compiler.rs | 2 +- examples/fibonacci.rs | 1 + tests/recursion.rs | 2 + 6 files changed, 53 insertions(+), 43 deletions(-) diff --git a/codegen/src/visitor/call.rs b/codegen/src/visitor/call.rs index a425e1997..115c86080 100644 --- a/codegen/src/visitor/call.rs +++ b/codegen/src/visitor/call.rs @@ -4,6 +4,7 @@ use crate::{ wasm::{HostFunc, ToLSBytes}, Error, Function, Result, }; +use anyhow::anyhow; use opcodes::ShangHai as OpCode; impl Function { @@ -34,6 +35,13 @@ impl Function { /// Call internal functions fn call_internal(&mut self, index: u32) -> Result<()> { + if self.env.index == Some(index) { + return Err(anyhow!( + "Recursion is no more supported in this version, see https://github.com/zink-lang/zink/issues/248" + ) + .into()); + } + tracing::trace!("call internal function: index={index}"); let (params, results) = self.env.funcs.get(&index).unwrap_or(&(0, 0)); diff --git a/compiler/filetests/lib.rs b/compiler/filetests/lib.rs index 6661ca974..cba0fafcd 100644 --- a/compiler/filetests/lib.rs +++ b/compiler/filetests/lib.rs @@ -28,11 +28,10 @@ impl Test { let Test { module, name, wasm } = self; tracing::info!("Compiling {module}::{name}"); - let mut compiler = zinkc::Compiler::default(); - // TODO: after #166 + let compiler = zinkc::Compiler::default(); + // TODO: after #248 if name == "fibonacci" { - // return Ok(()); - compiler.config = compiler.config.dispatcher(true); + return Ok(()); } compiler.compile(&wasm)?; Ok(()) diff --git a/compiler/filetests/wat/recursion/fibonacci.wat b/compiler/filetests/wat/recursion/fibonacci.wat index f95146463..636fe6660 100644 --- a/compiler/filetests/wat/recursion/fibonacci.wat +++ b/compiler/filetests/wat/recursion/fibonacci.wat @@ -1,39 +1,39 @@ (module - (type (;0;) (func (param i32) (result i32))) - (func (;0;) (type 0) (param i32) (result i32) - local.get 0 - call 1) - (func (;1;) (type 0) (param i32) (result i32) - (local i32) - local.get 0 - i32.const 2 - i32.ge_u - if ;; label = @1 - loop ;; label = @2 - local.get 0 ;; 1 - i32.const 1 ;; 2 - i32.sub ;; 1 - call 1 ;; 1 - local.get 1 ;; 2 - i32.add ;; 1 - local.set 1 ;; 0 - local.get 0 ;; 1 - i32.const 2 ;; 2 - i32.sub ;; 1 - local.tee 0 ;; 1 - i32.const 1 ;; 2 - i32.gt_u ;; 1 - br_if 0 (;@2;) ;; 2 -> 0 - end - end - local.get 0 - local.get 1 - i32.add) - (memory (;0;) 16) - (global (;0;) i32 (i32.const 1048576)) - (global (;1;) i32 (i32.const 1048576)) - (export "memory" (memory 0)) - (export "fibonacci" (func 0)) - (export "recursion" (func 1)) - (export "__data_end" (global 0)) - (export "__heap_base" (global 1))) + (type (;0;) (func (param i32) (result i32))) + (func (;0;) (type 0) (param i32) (result i32) + local.get 0 + call 1) + (func (;1;) (type 0) (param i32) (result i32) + (local i32) + local.get 0 + i32.const 2 + i32.ge_u + if ;; label = @1 + loop ;; label = @2 + local.get 0 ;; 1 + i32.const 1 ;; 2 + i32.sub ;; 1 + call 1 ;; 1 + local.get 1 ;; 2 + i32.add ;; 1 + local.set 1 ;; 0 + local.get 0 ;; 1 + i32.const 2 ;; 2 + i32.sub ;; 1 + local.tee 0 ;; 1 + i32.const 1 ;; 2 + i32.gt_u ;; 1 + br_if 0 (;@2;) ;; 2 -> 0 + end + end + local.get 0 + local.get 1 + i32.add) + (memory (;0;) 16) + (global (;0;) i32 (i32.const 1048576)) + (global (;1;) i32 (i32.const 1048576)) + (export "memory" (memory 0)) + (export "fibonacci" (func 0)) + (export "recursion" (func 1)) + (export "__data_end" (global 0)) + (export "__heap_base" (global 1))) diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index 2b8d2884a..67cc50212 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -38,7 +38,7 @@ impl Compiler { self.compile_dispatcher(&mut parser)?; for func in parser.funcs.into_funcs() { - self.compile_func(env.clone(), func)?; + self.compile_func(env.with_index(func.index()), func)?; } self.table.code_offset(self.buffer.len() as u16); diff --git a/examples/fibonacci.rs b/examples/fibonacci.rs index 344dace8a..606518689 100644 --- a/examples/fibonacci.rs +++ b/examples/fibonacci.rs @@ -23,6 +23,7 @@ fn internal_rec(n: u64) -> u64 { #[cfg(not(target_arch = "wasm32"))] fn main() {} +#[ignore] #[test] fn test() -> anyhow::Result<()> { use zint::{Bytes32, Contract}; diff --git a/tests/recursion.rs b/tests/recursion.rs index b50d5f024..2008e6058 100644 --- a/tests/recursion.rs +++ b/tests/recursion.rs @@ -2,6 +2,7 @@ use anyhow::Result; use filetests::Test; use zint::{Bytes32, Contract}; +#[ignore] #[test] fn fibonacci() -> Result<()> { let mut contract = Contract::from(Test::RECURSION_FIBONACCI).pure().compile()?; @@ -16,6 +17,7 @@ fn fibonacci() -> Result<()> { // x = 2 let info = contract.execute([2])?; + assert_eq!(info.halt, None); assert_eq!(1.to_bytes32().to_vec(), info.ret); // x = 3