Skip to content

Commit

Permalink
YJIT: Allow --yjit-dump-disasm to dump into a file (#6552)
Browse files Browse the repository at this point in the history
* YJIT: Allow --yjit-dump-disasm to dump into a file

* YJIT: Move IO implementation to disasm.rs

* YJIT: More consistent naming
  • Loading branch information
k0kubun committed Oct 17, 2022
1 parent 64c52c4 commit f11765a
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 29 deletions.
11 changes: 4 additions & 7 deletions yjit/src/backend/ir.rs
Expand Up @@ -1100,13 +1100,10 @@ impl Assembler
let gc_offsets = self.compile_with_regs(cb, alloc_regs);

#[cfg(feature = "disasm")]
if get_option!(dump_disasm) == DumpDisasm::All || (get_option!(dump_disasm) == DumpDisasm::Inline && cb.inline()) {
use crate::disasm::disasm_addr_range;
let last_ptr = cb.get_write_ptr();
let disasm = disasm_addr_range(cb, start_addr, last_ptr.raw_ptr() as usize - start_addr as usize);
if disasm.len() > 0 {
println!("{disasm}");
}
if let Some(dump_disasm) = get_option_ref!(dump_disasm) {
use crate::disasm::dump_disasm_addr_range;
let end_addr = cb.get_write_ptr().raw_ptr();
dump_disasm_addr_range(cb, start_addr, end_addr, dump_disasm)
}
gc_offsets
}
Expand Down
4 changes: 2 additions & 2 deletions yjit/src/codegen.rs
Expand Up @@ -612,7 +612,7 @@ pub fn gen_entry_prologue(cb: &mut CodeBlock, iseq: IseqPtr, insn_idx: u32) -> O
let code_ptr = cb.get_write_ptr();

let mut asm = Assembler::new();
if get_option!(dump_disasm).is_enabled() {
if get_option_ref!(dump_disasm).is_some() {
asm.comment(&format!("YJIT entry: {}", iseq_get_location(iseq)));
} else {
asm.comment("YJIT entry");
Expand Down Expand Up @@ -742,7 +742,7 @@ pub fn gen_single_block(
let mut asm = Assembler::new();

#[cfg(feature = "disasm")]
if get_option!(dump_disasm).is_enabled() {
if get_option_ref!(dump_disasm).is_some() {
asm.comment(&format!("Block: {} (ISEQ offset: {})", iseq_get_location(blockid.iseq), blockid.idx));
}

Expand Down
22 changes: 20 additions & 2 deletions yjit/src/disasm.rs
Expand Up @@ -2,6 +2,7 @@ use crate::core::*;
use crate::cruby::*;
use crate::yjit::yjit_enabled_p;
use crate::asm::CodeBlock;
use crate::options::DumpDisasm;

use std::fmt::Write;

Expand Down Expand Up @@ -95,7 +96,7 @@ pub fn disasm_iseq_insn_range(iseq: IseqPtr, start_idx: u32, end_idx: u32) -> St
writeln!(out, "== {:=<60}", block_ident).unwrap();

// Disassemble the instructions
out.push_str(&disasm_addr_range(global_cb, start_addr, code_size));
out.push_str(&disasm_addr_range(global_cb, start_addr, (start_addr as usize + code_size) as *const u8));

// If this is not the last block
if block_idx < block_list.len() - 1 {
Expand All @@ -115,9 +116,25 @@ pub fn disasm_iseq_insn_range(iseq: IseqPtr, start_idx: u32, end_idx: u32) -> St
return out;
}

#[cfg(feature = "disasm")]
pub fn dump_disasm_addr_range(cb: &CodeBlock, start_addr: *const u8, end_addr: *const u8, dump_disasm: &DumpDisasm) {
use std::fs::File;
use std::io::Write;

let disasm = disasm_addr_range(cb, start_addr, end_addr);
if disasm.len() > 0 {
match dump_disasm {
DumpDisasm::Stdout => println!("{disasm}"),
DumpDisasm::File(path) => {
let mut f = File::options().append(true).create(true).open(path).unwrap();
f.write_all(disasm.as_bytes()).unwrap();
}
};
}
}

#[cfg(feature = "disasm")]
pub fn disasm_addr_range(cb: &CodeBlock, start_addr: *const u8, code_size: usize) -> String {
pub fn disasm_addr_range(cb: &CodeBlock, start_addr: *const u8, end_addr: *const u8) -> String {
let mut out = String::from("");

// Initialize capstone
Expand All @@ -141,6 +158,7 @@ pub fn disasm_addr_range(cb: &CodeBlock, start_addr: *const u8, code_size: usize
cs.set_skipdata(true).unwrap();

// Disassemble the instructions
let code_size = end_addr as usize - start_addr as usize;
let code_slice = unsafe { std::slice::from_raw_parts(start_addr, code_size) };
let insns = cs.disasm_all(code_slice, start_addr as u64).unwrap();

Expand Down
32 changes: 14 additions & 18 deletions yjit/src/options.rs
Expand Up @@ -36,7 +36,7 @@ pub struct Options {
pub dump_insns: bool,

/// Dump all compiled instructions of target cbs.
pub dump_disasm: DumpDisasm,
pub dump_disasm: Option<DumpDisasm>,

/// Print when specific ISEQ items are compiled or invalidated
pub dump_iseq_disasm: Option<String>,
Expand All @@ -62,26 +62,18 @@ pub static mut OPTIONS: Options = Options {
gen_stats: false,
gen_trace_exits: false,
dump_insns: false,
dump_disasm: DumpDisasm::None,
dump_disasm: None,
verify_ctx: false,
global_constant_state: false,
dump_iseq_disasm: None,
};

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum DumpDisasm {
// Dump only inline cb
Inline,
// Dump both inline and outlined cbs
All,
// Dont dump anything
None,
}

impl DumpDisasm {
pub fn is_enabled(&self) -> bool {
*self != DumpDisasm::None
}
// Dump to stdout
Stdout,
// Dump to "yjit_{pid}.log" file under the specified directory
File(String),
}

/// Macro to get an option value by name
Expand Down Expand Up @@ -168,9 +160,13 @@ pub fn parse_option(str_ptr: *const std::os::raw::c_char) -> Option<()> {
},

("dump-disasm", _) => match opt_val.to_string().as_str() {
"all" => unsafe { OPTIONS.dump_disasm = DumpDisasm::All },
"" => unsafe { OPTIONS.dump_disasm = DumpDisasm::Inline },
_ => return None,
"" => unsafe { OPTIONS.dump_disasm = Some(DumpDisasm::Stdout) },
directory => {
let pid = std::process::id();
let path = format!("{directory}/yjit_{pid}.log");
println!("YJIT disasm dump: {path}");
unsafe { OPTIONS.dump_disasm = Some(DumpDisasm::File(path)) }
}
},

("dump-iseq-disasm", _) => unsafe {
Expand Down

0 comments on commit f11765a

Please sign in to comment.