diff --git a/lib/clif-backend/Cargo.toml b/lib/clif-backend/Cargo.toml index 44855f1df..a26bea059 100644 --- a/lib/clif-backend/Cargo.toml +++ b/lib/clif-backend/Cargo.toml @@ -18,3 +18,6 @@ target-lexicon = "0.2.0" wasmparser = "0.23.0" byteorder = "1" nix = "0.12.0" + +[features] +debug = ["wasmer-runtime-core/debug"] \ No newline at end of file diff --git a/lib/clif-backend/src/module_env.rs b/lib/clif-backend/src/module_env.rs index 74e730693..f6df3fd7a 100644 --- a/lib/clif-backend/src/module_env.rs +++ b/lib/clif-backend/src/module_env.rs @@ -369,6 +369,163 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> func_translator.translate(body_bytes, &mut func, &mut func_env)?; + #[cfg(feature = "debug")] + { + use cranelift_codegen::cursor::{Cursor, FuncCursor}; + use cranelift_codegen::ir::InstBuilder; + let entry_ebb = func.layout.entry_block().unwrap(); + let ebb = func.dfg.make_ebb(); + func.layout.insert_ebb(ebb, entry_ebb); + let mut pos = FuncCursor::new(&mut func).at_first_insertion_point(ebb); + let params = pos.func.dfg.ebb_params(entry_ebb).to_vec(); + + let new_ebb_params: Vec<_> = params + .iter() + .map(|¶m| { + pos.func + .dfg + .append_ebb_param(ebb, pos.func.dfg.value_type(param)) + }) + .collect(); + + let start_debug = { + let signature = pos.func.import_signature(ir::Signature { + call_conv: self.target_config().default_call_conv, + params: vec![ + ir::AbiParam::new(ir::types::I32), + ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), + ], + returns: vec![], + }); + + let name = ir::ExternalName::testcase("strtdbug"); + + pos.func.import_function(ir::ExtFuncData { + name, + signature, + colocated: false, + }) + }; + + let end_debug = { + let signature = pos.func.import_signature(ir::Signature { + call_conv: self.target_config().default_call_conv, + params: vec![ir::AbiParam::special( + ir::types::I64, + ir::ArgumentPurpose::VMContext, + )], + returns: vec![], + }); + + let name = ir::ExternalName::testcase("enddbug"); + + pos.func.import_function(ir::ExtFuncData { + name, + signature, + colocated: false, + }) + }; + + let i32_print = { + let signature = pos.func.import_signature(ir::Signature { + call_conv: self.target_config().default_call_conv, + params: vec![ + ir::AbiParam::new(ir::types::I32), + ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), + ], + returns: vec![], + }); + + let name = ir::ExternalName::testcase("i32print"); + + pos.func.import_function(ir::ExtFuncData { + name, + signature, + colocated: false, + }) + }; + + let i64_print = { + let signature = pos.func.import_signature(ir::Signature { + call_conv: self.target_config().default_call_conv, + params: vec![ + ir::AbiParam::new(ir::types::I64), + ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), + ], + returns: vec![], + }); + + let name = ir::ExternalName::testcase("i64print"); + + pos.func.import_function(ir::ExtFuncData { + name, + signature, + colocated: false, + }) + }; + + let f32_print = { + let signature = pos.func.import_signature(ir::Signature { + call_conv: self.target_config().default_call_conv, + params: vec![ + ir::AbiParam::new(ir::types::F32), + ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), + ], + returns: vec![], + }); + + let name = ir::ExternalName::testcase("f32print"); + + pos.func.import_function(ir::ExtFuncData { + name, + signature, + colocated: false, + }) + }; + + let f64_print = { + let signature = pos.func.import_signature(ir::Signature { + call_conv: self.target_config().default_call_conv, + params: vec![ + ir::AbiParam::new(ir::types::F64), + ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext), + ], + returns: vec![], + }); + + let name = ir::ExternalName::testcase("f64print"); + + pos.func.import_function(ir::ExtFuncData { + name, + signature, + colocated: false, + }) + }; + + let vmctx = pos + .func + .special_param(ir::ArgumentPurpose::VMContext) + .expect("missing vmctx parameter"); + + let func_index = pos.ins().iconst(ir::types::I32, func_index.index() as i64); + + pos.ins().call(start_debug, &[func_index, vmctx]); + + for param in new_ebb_params.iter().cloned() { + match pos.func.dfg.value_type(param) { + ir::types::I32 => pos.ins().call(i32_print, &[param, vmctx]), + ir::types::I64 => pos.ins().call(i64_print, &[param, vmctx]), + ir::types::F32 => pos.ins().call(f32_print, &[param, vmctx]), + ir::types::F64 => pos.ins().call(f64_print, &[param, vmctx]), + _ => unimplemented!(), + }; + } + + pos.ins().call(end_debug, &[vmctx]); + + pos.ins().jump(entry_ebb, new_ebb_params.as_slice()); + } + func }; diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 7e3ab4ab1..4fe778c21 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -136,9 +136,17 @@ impl FuncResolverBuilder { msg: format!("unexpected libcall: {}", libcall), })?, }, - RelocationType::Intrinsic(ref name) => Err(CompileError::InternalError { - msg: format!("unexpected intrinsic: {}", name), - })?, + RelocationType::Intrinsic(ref name) => match name.as_str() { + "i32print" => i32_print as isize, + "i64print" => i64_print as isize, + "f32print" => f32_print as isize, + "f64print" => f64_print as isize, + "strtdbug" => start_debug as isize, + "enddbug" => end_debug as isize, + _ => Err(CompileError::InternalError { + msg: format!("unexpected intrinsic: {}", name), + })?, + }, RelocationType::VmCall(vmcall) => match vmcall { VmCall::Local(kind) => match kind { VmCallKind::StaticMemoryGrow => vmcalls::local_static_memory_grow as _, @@ -248,3 +256,22 @@ impl backend::FuncResolver for FuncResolver { fn round_up(n: usize, multiple: usize) -> usize { (n + multiple - 1) & !(multiple - 1) } + +extern "C" fn i32_print(n: i32) { + print!(" i32: {},", n); +} +extern "C" fn i64_print(n: i64) { + print!(" i64: {},", n); +} +extern "C" fn f32_print(n: f32) { + print!(" f32: {},", n); +} +extern "C" fn f64_print(n: f64) { + print!(" f64: {},", n); +} +extern "C" fn start_debug(func_index: u32) { + print!("func ({}), args: [", func_index); +} +extern "C" fn end_debug() { + println!(" ]"); +} diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index f1aee273c..09bda9b36 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -14,3 +14,4 @@ wasmer-clif-backend = { path = "../clif-backend", version = "0.1.2", optional = [features] default = ["wasmer-clif-backend"] +debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"] \ No newline at end of file