Debugging improvements

This commit is contained in:
Brian Carroll 2021-11-30 09:48:15 +00:00
parent 8a137126fe
commit a08633fd36
5 changed files with 59 additions and 41 deletions

View File

@ -36,11 +36,6 @@ const CONST_SEGMENT_BASE_ADDR: u32 = 1024;
/// Index of the data segment where we store constants
const CONST_SEGMENT_INDEX: usize = 0;
#[cfg(debug_assertions)]
const DEBUG_BUILD: bool = true;
#[cfg(not(debug_assertions))]
const DEBUG_BUILD: bool = false;
pub struct WasmBackend<'a> {
env: &'a Env<'a>,
interns: &'a mut Interns,
@ -168,16 +163,24 @@ impl<'a> WasmBackend<'a> {
}
pub fn finalize_module(mut self) -> WasmModule<'a> {
if DEBUG_BUILD {
let module_id = self.env.module_id;
let ident_ids = self.interns.all_ident_ids.get(&module_id).unwrap();
self.env.module_id.register_debug_idents(ident_ids);
}
let symbol_table = LinkingSubSection::SymbolTable(self.linker_symbols);
self.module.linking.subsections.push(symbol_table);
self.module
}
/// Register the debug names of Symbols in a global lookup table
/// so that they have meaningful names when you print them.
/// Particularly useful after generating IR for refcount procedures
#[cfg(debug_assertions)]
pub fn register_symbol_debug_names(&self) {
let module_id = self.env.module_id;
let ident_ids = self.interns.all_ident_ids.get(&module_id).unwrap();
self.env.module_id.register_debug_idents(ident_ids);
}
#[cfg(not(debug_assertions))]
fn register_debug_idents(&self) {}
/// Reset function-level data
fn reset(&mut self) {
// Push the completed CodeBuilder into the module and swap it for a new empty one

View File

@ -104,6 +104,15 @@ pub fn build_module_help<'a>(
// Generate IR for refcounting procs
let refcount_procs = backend.generate_refcount_procs();
backend.register_symbol_debug_names();
if false {
for proc in refcount_procs.iter() {
println!("{}", proc.to_pretty(200));
println!("{:#?}", proc);
}
}
// Generate Wasm for refcounting procs
for proc in refcount_procs.iter() {
backend.build_proc(proc)?;
@ -111,12 +120,6 @@ pub fn build_module_help<'a>(
let module = backend.finalize_module();
if true {
for proc in refcount_procs.into_iter() {
println!("{}", proc.to_pretty(200));
}
}
Ok((module, main_fn_index.unwrap()))
}

View File

@ -79,6 +79,7 @@ impl StoredValue {
/// Helper structure for WasmBackend, to keep track of how values are stored,
/// including the VM stack, local variables, and linear memory
#[derive(Debug)]
pub struct Storage<'a> {
pub arg_types: Vec<'a, ValueType>,
pub local_types: Vec<'a, ValueType>,

View File

@ -234,7 +234,9 @@ impl<'a> CodeBuilder<'a> {
pub fn set_top_symbol(&mut self, sym: Symbol) -> VmSymbolState {
let current_stack = &mut self.vm_block_stack.last_mut().unwrap().value_stack;
let pushed_at = self.code.len();
let top_symbol: &mut Symbol = current_stack.last_mut().unwrap();
let top_symbol: &mut Symbol = current_stack
.last_mut()
.unwrap_or_else(|| unreachable!("Empty stack when trying to set Symbol {:?}", sym));
*top_symbol = sym;
VmSymbolState::Pushed { pushed_at }

View File

@ -167,33 +167,42 @@ pub fn helper_wasm<'a, T: Wasm32TestResult>(
// write the module to a file so the linker can access it
std::fs::write(&app_o_file, &module_bytes).unwrap();
let _linker_output = std::process::Command::new("zig")
.args(&[
"wasm-ld",
// input files
app_o_file.to_str().unwrap(),
bitcode::BUILTINS_WASM32_OBJ_PATH,
libc_a_file,
// output
"-o",
final_wasm_file.to_str().unwrap(),
// we don't define `_start`
"--no-entry",
// If you only specify test_wrapper, it will stop at the call to UserApp_main_1
// But if you specify both exports, you get all the dependencies.
//
// It seems that it will not write out an export you didn't explicitly specify,
// even if it's a dependency of another export!
// In our case we always export main and test_wrapper so that's OK.
"--export",
"test_wrapper",
"--export",
"#UserApp_main_1",
])
let args = &[
"wasm-ld",
// input files
app_o_file.to_str().unwrap(),
bitcode::BUILTINS_WASM32_OBJ_PATH,
libc_a_file,
// output
"-o",
final_wasm_file.to_str().unwrap(),
// we don't define `_start`
"--no-entry",
// If you only specify test_wrapper, it will stop at the call to UserApp_main_1
// But if you specify both exports, you get all the dependencies.
//
// It seems that it will not write out an export you didn't explicitly specify,
// even if it's a dependency of another export!
// In our case we always export main and test_wrapper so that's OK.
"--export",
"test_wrapper",
"--export",
"#UserApp_main_1",
];
let linker_output = std::process::Command::new("zig")
.args(args)
.output()
.unwrap();
// dbg!(_linker_output);
if !linker_output.status.success() {
print!("\nLINKER FAILED\n");
for arg in args {
print!("{} ", arg);
}
println!("\n{}", std::str::from_utf8(&linker_output.stdout).unwrap());
println!("{}", std::str::from_utf8(&linker_output.stderr).unwrap());
}
Module::from_file(&store, &final_wasm_file).unwrap()
};