Add some debug features to gen_wasm

This commit is contained in:
Brian Carroll 2021-12-11 18:58:03 +00:00
parent 96380d5bfe
commit 9594b05c96
4 changed files with 62 additions and 7 deletions

View file

@ -58,6 +58,8 @@ pub struct WasmBackend<'a> {
/// how many blocks deep are we (used for jumps) /// how many blocks deep are we (used for jumps)
block_depth: u32, block_depth: u32,
joinpoint_label_map: MutMap<JoinPointId, (u32, Vec<'a, StoredValue>)>, joinpoint_label_map: MutMap<JoinPointId, (u32, Vec<'a, StoredValue>)>,
debug_current_proc_index: usize,
} }
impl<'a> WasmBackend<'a> { impl<'a> WasmBackend<'a> {
@ -149,6 +151,8 @@ impl<'a> WasmBackend<'a> {
code_builder: CodeBuilder::new(arena), code_builder: CodeBuilder::new(arena),
storage: Storage::new(arena), storage: Storage::new(arena),
symbol_layouts: MutMap::default(), symbol_layouts: MutMap::default(),
debug_current_proc_index: 0,
} }
} }
@ -203,6 +207,7 @@ impl<'a> WasmBackend<'a> {
pub fn build_proc(&mut self, proc: &Proc<'a>) { pub fn build_proc(&mut self, proc: &Proc<'a>) {
// println!("\ngenerating procedure {:?}\n", proc.name); // println!("\ngenerating procedure {:?}\n", proc.name);
self.debug_current_proc_index += 1;
self.start_proc(proc); self.start_proc(proc);
@ -1246,4 +1251,18 @@ impl<'a> WasmBackend<'a> {
self.code_builder self.code_builder
.call(fn_index, linker_symbol_index, num_wasm_args, has_return_val); .call(fn_index, linker_symbol_index, num_wasm_args, has_return_val);
} }
/// Debug utility
///
/// if _debug_current_proc_is("#UserApp_foo_1") {
/// self.code_builder._debug_assert_i32(0x1234);
/// }
fn _debug_current_proc_is(&self, linker_name: &'static str) -> bool {
let (_, linker_sym_index) = self.proc_symbols[self.debug_current_proc_index];
let sym_info = &self.linker_symbols[linker_sym_index as usize];
match sym_info {
SymInfo::Function(WasmObjectSymbol::Defined { name, .. }) => name == linker_name,
_ => false,
}
}
} }

View file

@ -901,4 +901,17 @@ impl<'a> CodeBuilder<'a> {
instruction_no_args!(i64_reinterpret_f64, I64REINTERPRETF64, 1, true); instruction_no_args!(i64_reinterpret_f64, I64REINTERPRETF64, 1, true);
instruction_no_args!(f32_reinterpret_i32, F32REINTERPRETI32, 1, true); instruction_no_args!(f32_reinterpret_i32, F32REINTERPRETI32, 1, true);
instruction_no_args!(f64_reinterpret_i64, F64REINTERPRETI64, 1, true); instruction_no_args!(f64_reinterpret_i64, F64REINTERPRETI64, 1, true);
/// Generate a debug assertion for an expected i32 value
pub fn _debug_assert_i32(&mut self, expected: i32) {
self.i32_const(expected);
self.i32_eq();
self.i32_eqz();
self.if_(BlockType::NoResult);
self.unreachable_(); // Tell Wasm runtime to throw an exception
self.end();
// It matches. Restore the original value to the VM stack and continue the program.
// We know it matched the expected value, so just use that!
self.i32_const(expected);
}
} }

View file

@ -247,10 +247,16 @@ where
_ => panic!(), _ => panic!(),
}; };
if false { if true {
println!("test_wrapper returned 0x{:x}", address);
println!("Stack:");
crate::helpers::wasm::debug_memory_hex(memory, address, std::mem::size_of::<T>()); crate::helpers::wasm::debug_memory_hex(memory, address, std::mem::size_of::<T>());
} }
if true {
println!("Heap:");
// Manually provide address and size based on printf in test_platform.c
crate::helpers::wasm::debug_memory_hex(memory, 0x11440, 24);
}
let output = <T as FromWasm32Memory>::decode(memory, address as u32); let output = <T as FromWasm32Memory>::decode(memory, address as u32);
Ok(output) Ok(output)
@ -267,12 +273,17 @@ pub fn debug_memory_hex(memory: &Memory, address: i32, size: usize) {
}; };
let extra_words = 2; let extra_words = 2;
let offset = (address as usize) / 4; let result_start = (address as usize) / 4;
let start = offset - extra_words; let result_end = result_start + ((size + 3) / 4);
let end = offset + (size / 4) + extra_words; let start = result_start - extra_words;
let end = result_end + extra_words;
for index in start..end { for index in start..end {
let result_marker = if index == offset { "*" } else { " " }; let result_marker = if index >= result_start && index < result_end {
"|"
} else {
" "
};
println!( println!(
"{:x} {} {:08x}", "{:x} {} {:08x}",
index * 4, index * 4,
@ -280,6 +291,7 @@ pub fn debug_memory_hex(memory: &Memory, address: i32, size: usize) {
memory_words[index] memory_words[index]
); );
} }
println!();
} }
#[allow(unused_macros)] #[allow(unused_macros)]

View file

@ -3,7 +3,18 @@
// If any printf is included for compilation, even if unused, test runs take 50% longer // If any printf is included for compilation, even if unused, test runs take 50% longer
#define DEBUG 0 #define DEBUG 0
void *roc_alloc(size_t size, unsigned int alignment) { return malloc(size); } void *roc_alloc(size_t size, unsigned int alignment)
{
void *allocated = malloc(size);
if (!allocated)
{
fprintf(stderr, "roc_alloc failed\n");
exit(1);
} else {
printf("roc_alloc allocated %d bytes at %p\n", size, allocated);
}
return allocated;
}
void *roc_realloc(void *ptr, size_t new_size, size_t old_size, void *roc_realloc(void *ptr, size_t new_size, size_t old_size,
unsigned int alignment) unsigned int alignment)