Add feature flag to output debug information while running wasm (#147)

* Generate debug info during execution

* feature cfg debug output
This commit is contained in:
Lachlan Sneff 2019-02-06 15:43:27 -08:00 committed by GitHub
parent d975a4c487
commit 2f2f86a4de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 191 additions and 3 deletions

View File

@ -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"]

View File

@ -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(|&param| {
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
};

View File

@ -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!(" ]");
}

View File

@ -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"]