diff --git a/compiler/gen_wasm/src/backend.rs b/compiler/gen_wasm/src/backend.rs index d81de8bca2..9f13adc4c2 100644 --- a/compiler/gen_wasm/src/backend.rs +++ b/compiler/gen_wasm/src/backend.rs @@ -58,6 +58,8 @@ pub struct WasmBackend<'a> { /// how many blocks deep are we (used for jumps) block_depth: u32, joinpoint_label_map: MutMap)>, + + debug_current_proc_index: usize, } impl<'a> WasmBackend<'a> { @@ -149,6 +151,8 @@ impl<'a> WasmBackend<'a> { code_builder: CodeBuilder::new(arena), storage: Storage::new(arena), 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>) { // println!("\ngenerating procedure {:?}\n", proc.name); + self.debug_current_proc_index += 1; self.start_proc(proc); @@ -1246,4 +1251,18 @@ impl<'a> WasmBackend<'a> { self.code_builder .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, + } + } } diff --git a/compiler/gen_wasm/src/wasm_module/code_builder.rs b/compiler/gen_wasm/src/wasm_module/code_builder.rs index 20eb055acd..66b066641f 100644 --- a/compiler/gen_wasm/src/wasm_module/code_builder.rs +++ b/compiler/gen_wasm/src/wasm_module/code_builder.rs @@ -901,4 +901,17 @@ impl<'a> CodeBuilder<'a> { instruction_no_args!(i64_reinterpret_f64, I64REINTERPRETF64, 1, true); instruction_no_args!(f32_reinterpret_i32, F32REINTERPRETI32, 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); + } } diff --git a/compiler/test_gen/src/helpers/wasm.rs b/compiler/test_gen/src/helpers/wasm.rs index caac7b397e..8156967354 100644 --- a/compiler/test_gen/src/helpers/wasm.rs +++ b/compiler/test_gen/src/helpers/wasm.rs @@ -247,10 +247,16 @@ where _ => 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::()); } - + 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 = ::decode(memory, address as u32); Ok(output) @@ -267,12 +273,17 @@ pub fn debug_memory_hex(memory: &Memory, address: i32, size: usize) { }; let extra_words = 2; - let offset = (address as usize) / 4; - let start = offset - extra_words; - let end = offset + (size / 4) + extra_words; + let result_start = (address as usize) / 4; + let result_end = result_start + ((size + 3) / 4); + let start = result_start - extra_words; + let end = result_end + extra_words; for index in start..end { - let result_marker = if index == offset { "*" } else { " " }; + let result_marker = if index >= result_start && index < result_end { + "|" + } else { + " " + }; println!( "{:x} {} {:08x}", index * 4, @@ -280,6 +291,7 @@ pub fn debug_memory_hex(memory: &Memory, address: i32, size: usize) { memory_words[index] ); } + println!(); } #[allow(unused_macros)] diff --git a/compiler/test_gen/src/helpers/wasm_test_platform.c b/compiler/test_gen/src/helpers/wasm_test_platform.c index 2201cb8cea..8624b5147d 100644 --- a/compiler/test_gen/src/helpers/wasm_test_platform.c +++ b/compiler/test_gen/src/helpers/wasm_test_platform.c @@ -3,7 +3,18 @@ // If any printf is included for compilation, even if unused, test runs take 50% longer #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, unsigned int alignment)