summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--zjit/Cargo.lock44
-rw-r--r--zjit/Cargo.toml9
-rw-r--r--zjit/src/disasm.rs55
-rw-r--r--zjit/src/lib.rs22
4 files changed, 120 insertions, 10 deletions
diff --git a/zjit/Cargo.lock b/zjit/Cargo.lock
index cdf798516c..f42fa9d735 100644
--- a/zjit/Cargo.lock
+++ b/zjit/Cargo.lock
@@ -3,5 +3,49 @@
version = 3
[[package]]
+name = "capstone"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "015ef5d5ca1743e3f94af9509ba6bd2886523cfee46e48d15c2ef5216fd4ac9a"
+dependencies = [
+ "capstone-sys",
+ "libc",
+]
+
+[[package]]
+name = "capstone-sys"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2267cb8d16a1e4197863ec4284ffd1aec26fe7e57c58af46b02590a0235809a0"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "cc"
+version = "1.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2"
+dependencies = [
+ "shlex",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.169"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
name = "zjit"
version = "0.0.0"
+dependencies = [
+ "capstone",
+]
diff --git a/zjit/Cargo.toml b/zjit/Cargo.toml
index 11cdc333c0..dc71f01692 100644
--- a/zjit/Cargo.toml
+++ b/zjit/Cargo.toml
@@ -21,3 +21,12 @@ debug = true
lto = "thin"
[dependencies]
+# No required dependencies to simplify build process. TODO: Link to yet to be
+# written rationale. Optional For development and testing purposes
+capstone = { version = "0.13.0", optional = true }
+
+# NOTE: Development builds select a set of these via configure.ac
+# For debugging, `make V=1` shows exact cargo invocation.
+[features]
+# Support --yjit-dump-disasm and RubyVM::YJIT.disasm using libcapstone.
+disasm = ["capstone"]
diff --git a/zjit/src/disasm.rs b/zjit/src/disasm.rs
new file mode 100644
index 0000000000..f18fad1ae0
--- /dev/null
+++ b/zjit/src/disasm.rs
@@ -0,0 +1,55 @@
+#[cfg(feature = "disasm")]
+pub fn disasm_addr_range(cb: &CodeBlock, start_addr: usize, end_addr: usize) -> String {
+ let mut out = String::from("");
+
+ // Initialize capstone
+ use capstone::prelude::*;
+
+ #[cfg(target_arch = "x86_64")]
+ let mut cs = Capstone::new()
+ .x86()
+ .mode(arch::x86::ArchMode::Mode64)
+ .syntax(arch::x86::ArchSyntax::Intel)
+ .build()
+ .unwrap();
+
+ #[cfg(target_arch = "aarch64")]
+ let mut cs = Capstone::new()
+ .arm64()
+ .mode(arch::arm64::ArchMode::Arm)
+ .detail(true)
+ .build()
+ .unwrap();
+ cs.set_skipdata(true).unwrap();
+
+ // Disassemble the instructions
+ let code_size = end_addr - start_addr;
+ let code_slice = unsafe { std::slice::from_raw_parts(start_addr as _, code_size) };
+ // Stabilize output for cargo test
+ #[cfg(test)]
+ let start_addr = 0;
+ let insns = cs.disasm_all(code_slice, start_addr as u64).unwrap();
+ let colors = get_colors();
+
+ // For each instruction in this block
+ for insn in insns.as_ref() {
+ // Comments for this block
+ if let Some(comment_list) = cb.comments_at(insn.address() as usize) {
+ for comment in comment_list {
+ if cb.outlined {
+ write!(&mut out, "{}", colors.blue_begin).unwrap(); // Make outlined code blue
+ }
+ writeln!(&mut out, " {}# {comment}{}", colors.bold_begin, colors.bold_end).unwrap(); // Make comments bold
+ }
+ }
+ if cb.outlined {
+ write!(&mut out, "{}", colors.blue_begin).unwrap(); // Make outlined code blue
+ }
+ writeln!(&mut out, " {insn}").unwrap();
+ if cb.outlined {
+ write!(&mut out, "{}", colors.blue_end).unwrap(); // Disable blue
+ }
+ }
+
+ return out;
+}
diff --git a/zjit/src/lib.rs b/zjit/src/lib.rs
index c096832edf..511999f9b7 100644
--- a/zjit/src/lib.rs
+++ b/zjit/src/lib.rs
@@ -9,8 +9,8 @@ mod utils;
mod virtualmem;
mod asm;
mod backend;
+mod disasm;
-#[cfg(target_arch = "x86_64")]
use backend::x86_emit;
use codegen::ZJITState;
use crate::cruby::*;
@@ -81,17 +81,19 @@ pub extern "C" fn rb_zjit_parse_option() -> bool {
pub extern "C" fn rb_zjit_iseq_gen_entry_point(iseq: IseqPtr, _ec: EcPtr) -> *const u8 {
ir::iseq_to_ssa(iseq);
- #[cfg(target_arch = "x86_64")]
- {
- let cb = ZJITState::get_code_block();
+ let cb = ZJITState::get_code_block();
+ let start_ptr = cb.get_write_ptr();
+ x86_emit(cb);
+ let _end_ptr = cb.get_write_ptr();
- let start_ptr = cb.get_write_ptr();
- x86_emit(cb);
+ #[cfg(feature = "disasm")]
+ {
+ let _disasm = disasm_addr_range();
+ }
- // TODO: use std::ptr::null() if compilation fails
+ if cfg!(target_arch = "x86_64") {
start_ptr.raw_ptr(cb)
+ } else {
+ std::ptr::null()
}
-
- #[cfg(target_arch = "aarch64")]
- std::ptr::null()
}