From c0e42a7e8fefc4f89d4723c762319a91f573027c Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Thu, 6 Feb 2025 10:41:55 -0500 Subject: [PATCH] Add CRuby bindings --- zjit/src/cruby.rs | 843 +++++++++++++++++++++ zjit/src/cruby_bindings.inc.rs | 1300 ++++++++++++++++++++++++++++++++ zjit/src/main.rs | 2 + 3 files changed, 2145 insertions(+) create mode 100644 zjit/src/cruby.rs create mode 100644 zjit/src/cruby_bindings.inc.rs diff --git a/zjit/src/cruby.rs b/zjit/src/cruby.rs new file mode 100644 index 0000000000..5a28777624 --- /dev/null +++ b/zjit/src/cruby.rs @@ -0,0 +1,843 @@ +//! This module deals with making relevant C functions available to Rust YJIT. +//! Some C functions we use we maintain, some are public C extension APIs, +//! some are internal CRuby APIs. +//! +//! ## General notes about linking +//! +//! The YJIT crate compiles to a native static library, which for our purposes +//! we can understand as a collection of object files. On ELF platforms at least, +//! object files can refer to "external symbols" which we could take some +//! liberty and understand as assembly labels that refer to code defined in other +//! object files resolved when linking. When we are linking, say to produce miniruby, +//! the linker resolves and put concrete addresses for each usage of C function in +//! the Rust static library. +//! +//! By declaring external functions and using them, we are asserting the symbols +//! we use have definition in one of the object files we pass to the linker. Declaring +//! a function here that has no definition anywhere causes a linking error. +//! +//! There are more things going on during linking and this section makes a lot of +//! simplifications but hopefully this gives a good enough working mental model. +//! +//! ## Difference from example in the Rustonomicon +//! +//! You might be wondering about why this is different from the [FFI example] +//! in the Nomicon, an official book about Unsafe Rust. +//! +//! There is no `#[link]` attribute because we are not linking against an external +//! library, but rather implicitly asserting that we'll supply a concrete definition +//! for all C functions we call, similar to how pure C projects put functions +//! across different compilation units and link them together. +//! +//! TODO(alan): is the model different enough on Windows that this setup is unworkable? +//! Seems prudent to at least learn more about Windows binary tooling before +//! committing to a design. +//! +//! Alan recommends reading the Nomicon cover to cover as he thinks the book is +//! not very long in general and especially for something that can save hours of +//! debugging Undefined Behavior (UB) down the road. +//! +//! UBs can cause Safe Rust to crash, at which point it's hard to tell which +//! usage of `unsafe` in the codebase invokes UB. Providing safe Rust interface +//! wrapping `unsafe` Rust is a good technique, but requires practice and knowledge +//! about what's well defined and what's undefined. +//! +//! For an extremely advanced example of building safe primitives using Unsafe Rust, +//! see the [GhostCell] paper. Some parts of the paper assume less background knowledge +//! than other parts, so there should be learning opportunities in it for all experience +//! levels. +//! +//! ## Binding generation +//! +//! For the moment declarations on the Rust side are hand written. The code is boilerplate +//! and could be generated automatically with a custom tooling that depend on +//! rust-lang/rust-bindgen. The output Rust code could be checked in to version control +//! and verified on CI like `make update-deps`. +//! +//! Upsides for this design: +//! - the YJIT static lib that links with miniruby and friends will not need bindgen +//! as a dependency at all. This is an important property so Ruby end users can +//! build a YJIT enabled Ruby with no internet connection using a release tarball +//! - Less hand-typed boilerplate +//! - Helps reduce risk of C definitions and Rust declaration going out of sync since +//! CI verifies synchronicity +//! +//! Downsides and known unknowns: +//! - Using rust-bindgen this way seems unusual. We might be depending on parts +//! that the project is not committed to maintaining +//! - This setup assumes rust-bindgen gives deterministic output, which can't be taken +//! for granted +//! - YJIT contributors will need to install libclang on their system to get rust-bindgen +//! to work if they want to run the generation tool locally +//! +//! The elephant in the room is that we'll still need to use Unsafe Rust to call C functions, +//! and the binding generation can't magically save us from learning Unsafe Rust. +//! +//! +//! [FFI example]: https://doc.rust-lang.org/nomicon/ffi.html +//! [GhostCell]: http://plv.mpi-sws.org/rustbelt/ghostcell/ + +// CRuby types use snake_case. Allow them so we use one name across languages. +#![allow(non_camel_case_types)] +// A lot of imported CRuby globals aren't all-caps +#![allow(non_upper_case_globals)] + +// Some of this code may not be used yet +#![allow(dead_code)] +#![allow(unused_macros)] +#![allow(unused_imports)] + +use std::convert::From; +use std::ffi::{CString, CStr}; +use std::fmt::{Debug, Formatter}; +use std::os::raw::{c_char, c_int, c_uint}; +use std::panic::{catch_unwind, UnwindSafe}; + +// We check that we can do this with the configure script and a couple of +// static asserts. u64 and not usize to play nice with lowering to x86. +pub type size_t = u64; + +/// A type alias for the redefinition flags coming from CRuby. These are just +/// shifted 1s but not explicitly an enum. +pub type RedefinitionFlag = u32; + +#[allow(dead_code)] +#[allow(clippy::all)] +mod autogened { + use super::*; + // Textually include output from rust-bindgen as suggested by its user guide. + include!("cruby_bindings.inc.rs"); +} +pub use autogened::*; + +// TODO: For #defines that affect memory layout, we need to check for them +// on build and fail if they're wrong. e.g. USE_FLONUM *must* be true. + +// These are functions we expose from C files, not in any header. +// Parsing it would result in a lot of duplicate definitions. +// Use bindgen for functions that are defined in headers or in yjit.c. +#[cfg_attr(test, allow(unused))] // We don't link against C code when testing +extern "C" { + pub fn rb_check_overloaded_cme( + me: *const rb_callable_method_entry_t, + ci: *const rb_callinfo, + ) -> *const rb_callable_method_entry_t; + + // Floats within range will be encoded without creating objects in the heap. + // (Range is 0x3000000000000001 to 0x4fffffffffffffff (1.7272337110188893E-77 to 2.3158417847463237E+77). + pub fn rb_float_new(d: f64) -> VALUE; + + pub fn rb_hash_empty_p(hash: VALUE) -> VALUE; + pub fn rb_yjit_str_concat_codepoint(str: VALUE, codepoint: VALUE); + pub fn rb_str_setbyte(str: VALUE, index: VALUE, value: VALUE) -> VALUE; + pub fn rb_vm_splat_array(flag: VALUE, ary: VALUE) -> VALUE; + pub fn rb_vm_concat_array(ary1: VALUE, ary2st: VALUE) -> VALUE; + pub fn rb_vm_concat_to_array(ary1: VALUE, ary2st: VALUE) -> VALUE; + pub fn rb_vm_defined( + ec: EcPtr, + reg_cfp: CfpPtr, + op_type: rb_num_t, + obj: VALUE, + v: VALUE, + ) -> bool; + pub fn rb_vm_set_ivar_id(obj: VALUE, idx: u32, val: VALUE) -> VALUE; + pub fn rb_vm_setinstancevariable(iseq: IseqPtr, obj: VALUE, id: ID, val: VALUE, ic: IVC); + pub fn rb_aliased_callable_method_entry( + me: *const rb_callable_method_entry_t, + ) -> *const rb_callable_method_entry_t; + pub fn rb_vm_getclassvariable(iseq: IseqPtr, cfp: CfpPtr, id: ID, ic: ICVARC) -> VALUE; + pub fn rb_vm_setclassvariable( + iseq: IseqPtr, + cfp: CfpPtr, + id: ID, + val: VALUE, + ic: ICVARC, + ) -> VALUE; + pub fn rb_vm_ic_hit_p(ic: IC, reg_ep: *const VALUE) -> bool; + pub fn rb_vm_stack_canary() -> VALUE; + pub fn rb_vm_push_cfunc_frame(cme: *const rb_callable_method_entry_t, recv_idx: c_int); +} + +// Renames +pub use rb_insn_name as raw_insn_name; +pub use rb_get_ec_cfp as get_ec_cfp; +pub use rb_get_cfp_iseq as get_cfp_iseq; +pub use rb_get_cfp_pc as get_cfp_pc; +pub use rb_get_cfp_sp as get_cfp_sp; +pub use rb_get_cfp_self as get_cfp_self; +pub use rb_get_cfp_ep as get_cfp_ep; +pub use rb_get_cfp_ep_level as get_cfp_ep_level; +pub use rb_vm_base_ptr as get_cfp_bp; +pub use rb_get_cme_def_type as get_cme_def_type; +pub use rb_get_cme_def_body_attr_id as get_cme_def_body_attr_id; +pub use rb_get_cme_def_body_optimized_type as get_cme_def_body_optimized_type; +pub use rb_get_cme_def_body_optimized_index as get_cme_def_body_optimized_index; +pub use rb_get_cme_def_body_cfunc as get_cme_def_body_cfunc; +pub use rb_get_def_method_serial as get_def_method_serial; +pub use rb_get_def_original_id as get_def_original_id; +pub use rb_get_mct_argc as get_mct_argc; +pub use rb_get_mct_func as get_mct_func; +pub use rb_get_def_iseq_ptr as get_def_iseq_ptr; +pub use rb_iseq_encoded_size as get_iseq_encoded_size; +pub use rb_get_iseq_body_local_iseq as get_iseq_body_local_iseq; +pub use rb_get_iseq_body_iseq_encoded as get_iseq_body_iseq_encoded; +pub use rb_get_iseq_body_stack_max as get_iseq_body_stack_max; +pub use rb_get_iseq_body_type as get_iseq_body_type; +pub use rb_get_iseq_flags_has_lead as get_iseq_flags_has_lead; +pub use rb_get_iseq_flags_has_opt as get_iseq_flags_has_opt; +pub use rb_get_iseq_flags_has_kw as get_iseq_flags_has_kw; +pub use rb_get_iseq_flags_has_rest as get_iseq_flags_has_rest; +pub use rb_get_iseq_flags_has_post as get_iseq_flags_has_post; +pub use rb_get_iseq_flags_has_kwrest as get_iseq_flags_has_kwrest; +pub use rb_get_iseq_flags_has_block as get_iseq_flags_has_block; +pub use rb_get_iseq_flags_ambiguous_param0 as get_iseq_flags_ambiguous_param0; +pub use rb_get_iseq_flags_accepts_no_kwarg as get_iseq_flags_accepts_no_kwarg; +pub use rb_get_iseq_body_local_table_size as get_iseq_body_local_table_size; +pub use rb_get_iseq_body_param_keyword as get_iseq_body_param_keyword; +pub use rb_get_iseq_body_param_size as get_iseq_body_param_size; +pub use rb_get_iseq_body_param_lead_num as get_iseq_body_param_lead_num; +pub use rb_get_iseq_body_param_opt_num as get_iseq_body_param_opt_num; +pub use rb_get_iseq_body_param_opt_table as get_iseq_body_param_opt_table; +pub use rb_get_cikw_keyword_len as get_cikw_keyword_len; +pub use rb_get_cikw_keywords_idx as get_cikw_keywords_idx; +pub use rb_get_call_data_ci as get_call_data_ci; +pub use rb_yarv_str_eql_internal as rb_str_eql_internal; +pub use rb_yarv_ary_entry_internal as rb_ary_entry_internal; +pub use rb_yjit_fix_div_fix as rb_fix_div_fix; +pub use rb_yjit_fix_mod_fix as rb_fix_mod_fix; +pub use rb_FL_TEST as FL_TEST; +pub use rb_FL_TEST_RAW as FL_TEST_RAW; +pub use rb_RB_TYPE_P as RB_TYPE_P; +pub use rb_BASIC_OP_UNREDEFINED_P as BASIC_OP_UNREDEFINED_P; +pub use rb_RSTRUCT_LEN as RSTRUCT_LEN; +pub use rb_RSTRUCT_SET as RSTRUCT_SET; +pub use rb_vm_ci_argc as vm_ci_argc; +pub use rb_vm_ci_mid as vm_ci_mid; +pub use rb_vm_ci_flag as vm_ci_flag; +pub use rb_vm_ci_kwarg as vm_ci_kwarg; +pub use rb_METHOD_ENTRY_VISI as METHOD_ENTRY_VISI; +pub use rb_RCLASS_ORIGIN as RCLASS_ORIGIN; + +/// Helper so we can get a Rust string for insn_name() +pub fn insn_name(opcode: usize) -> String { + unsafe { + // Look up Ruby's NULL-terminated insn name string + let op_name = raw_insn_name(VALUE(opcode)); + + // Convert the op name C string to a Rust string and concat + let op_name = CStr::from_ptr(op_name).to_str().unwrap(); + + // Convert into an owned string + op_name.to_string() + } +} + +#[allow(unused_variables)] +pub fn insn_len(opcode: usize) -> u32 { + #[cfg(test)] + panic!("insn_len is a CRuby function, and we don't link against CRuby for Rust testing!"); + + #[cfg(not(test))] + unsafe { + rb_insn_len(VALUE(opcode)).try_into().unwrap() + } +} + +/// Opaque iseq type for opaque iseq pointers from vm_core.h +/// See: +#[repr(C)] +pub struct rb_iseq_t { + _data: [u8; 0], + _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, +} + +/// An object handle similar to VALUE in the C code. Our methods assume +/// that this is a handle. Sometimes the C code briefly uses VALUE as +/// an unsigned integer type and don't necessarily store valid handles but +/// thankfully those cases are rare and don't cross the FFI boundary. +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +#[repr(transparent)] // same size and alignment as simply `usize` +pub struct VALUE(pub usize); + +/// Pointer to an ISEQ +pub type IseqPtr = *const rb_iseq_t; + +// Given an ISEQ pointer, convert PC to insn_idx +pub fn iseq_pc_to_insn_idx(iseq: IseqPtr, pc: *mut VALUE) -> Option { + let pc_zero = unsafe { rb_iseq_pc_at_idx(iseq, 0) }; + unsafe { pc.offset_from(pc_zero) }.try_into().ok() +} + +/// Given an ISEQ pointer and an instruction index, return an opcode. +pub fn iseq_opcode_at_idx(iseq: IseqPtr, insn_idx: u32) -> u32 { + let pc = unsafe { rb_iseq_pc_at_idx(iseq, insn_idx) }; + unsafe { rb_iseq_opcode_at_pc(iseq, pc) as u32 } +} + +/// Return a poison value to be set above the stack top to verify leafness. +#[cfg(not(test))] +pub fn vm_stack_canary() -> u64 { + unsafe { rb_vm_stack_canary() }.as_u64() +} + +/// Avoid linking the C function in `cargo test` +#[cfg(test)] +pub fn vm_stack_canary() -> u64 { + 0 +} + +/// Opaque execution-context type from vm_core.h +#[repr(C)] +pub struct rb_execution_context_struct { + _data: [u8; 0], + _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, +} +/// Alias for rb_execution_context_struct used by CRuby sometimes +pub type rb_execution_context_t = rb_execution_context_struct; + +/// Pointer to an execution context (rb_execution_context_struct) +pub type EcPtr = *const rb_execution_context_struct; + +// From method.h +#[repr(C)] +pub struct rb_method_definition_t { + _data: [u8; 0], + _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, +} +type rb_method_definition_struct = rb_method_definition_t; + +/// Opaque cfunc type from method.h +#[repr(C)] +pub struct rb_method_cfunc_t { + _data: [u8; 0], + _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, +} + +/// Opaque call-cache type from vm_callinfo.h +#[repr(C)] +pub struct rb_callcache { + _data: [u8; 0], + _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, +} + +/// Opaque control_frame (CFP) struct from vm_core.h +#[repr(C)] +pub struct rb_control_frame_struct { + _data: [u8; 0], + _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, +} + +/// Pointer to a control frame pointer (CFP) +pub type CfpPtr = *mut rb_control_frame_struct; + +/// Opaque struct from vm_core.h +#[repr(C)] +pub struct rb_cref_t { + _data: [u8; 0], + _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, +} + +impl VALUE { + /// Dump info about the value to the console similarly to rp(VALUE) + pub fn dump_info(self) { + unsafe { rb_obj_info_dump(self) } + } + + /// Return whether the value is truthy or falsy in Ruby -- only nil and false are falsy. + pub fn test(self) -> bool { + let VALUE(cval) = self; + let VALUE(qnilval) = Qnil; + (cval & !qnilval) != 0 + } + + /// Return true if the number is an immediate integer, flonum or static symbol + fn immediate_p(self) -> bool { + let VALUE(cval) = self; + let mask = RUBY_IMMEDIATE_MASK as usize; + (cval & mask) != 0 + } + + /// Return true if the value is a Ruby immediate integer, flonum, static symbol, nil or false + pub fn special_const_p(self) -> bool { + self.immediate_p() || !self.test() + } + + /// Return true if the value is a heap object + pub fn heap_object_p(self) -> bool { + !self.special_const_p() + } + + /// Return true if the value is a Ruby Fixnum (immediate-size integer) + pub fn fixnum_p(self) -> bool { + let VALUE(cval) = self; + let flag = RUBY_FIXNUM_FLAG as usize; + (cval & flag) == flag + } + + /// Return true if the value is an immediate Ruby floating-point number (flonum) + pub fn flonum_p(self) -> bool { + let VALUE(cval) = self; + let mask = RUBY_FLONUM_MASK as usize; + let flag = RUBY_FLONUM_FLAG as usize; + (cval & mask) == flag + } + + /// Return true if the value is a Ruby symbol (RB_SYMBOL_P) + pub fn symbol_p(self) -> bool { + self.static_sym_p() || self.dynamic_sym_p() + } + + /// Return true for a static (non-heap) Ruby symbol (RB_STATIC_SYM_P) + pub fn static_sym_p(self) -> bool { + let VALUE(cval) = self; + let flag = RUBY_SYMBOL_FLAG as usize; + (cval & 0xff) == flag + } + + /// Return true for a dynamic Ruby symbol (RB_DYNAMIC_SYM_P) + fn dynamic_sym_p(self) -> bool { + return if self.special_const_p() { + false + } else { + self.builtin_type() == RUBY_T_SYMBOL + } + } + + /// Returns true if the value is T_HASH + pub fn hash_p(self) -> bool { + !self.special_const_p() && self.builtin_type() == RUBY_T_HASH + } + + /// Returns true or false depending on whether the value is nil + pub fn nil_p(self) -> bool { + self == Qnil + } + + pub fn string_p(self) -> bool { + self.class_of() == unsafe { rb_cString } + } + + /// Read the flags bits from the RBasic object, then return a Ruby type enum (e.g. RUBY_T_ARRAY) + pub fn builtin_type(self) -> ruby_value_type { + (self.builtin_flags() & (RUBY_T_MASK as usize)) as ruby_value_type + } + + pub fn builtin_flags(self) -> usize { + assert!(!self.special_const_p()); + + let VALUE(cval) = self; + let rbasic_ptr = cval as *const RBasic; + let flags_bits: usize = unsafe { (*rbasic_ptr).flags }.as_usize(); + return flags_bits; + } + + pub fn class_of(self) -> VALUE { + if !self.special_const_p() { + let builtin_type = self.builtin_type(); + assert_ne!(builtin_type, RUBY_T_NONE, "YJIT should only see live objects"); + assert_ne!(builtin_type, RUBY_T_MOVED, "YJIT should only see live objects"); + } + + unsafe { rb_yarv_class_of(self) } + } + + pub fn is_frozen(self) -> bool { + unsafe { rb_obj_frozen_p(self) != VALUE(0) } + } + + pub fn shape_too_complex(self) -> bool { + unsafe { rb_shape_obj_too_complex(self) } + } + + pub fn shape_id_of(self) -> u32 { + unsafe { rb_shape_get_shape_id(self) } + } + + pub fn shape_of(self) -> *mut rb_shape { + unsafe { + let shape = rb_shape_get_shape_by_id(self.shape_id_of()); + + if shape.is_null() { + panic!("Shape should not be null"); + } else { + shape + } + } + } + + pub fn embedded_p(self) -> bool { + unsafe { + FL_TEST_RAW(self, VALUE(ROBJECT_EMBED as usize)) != VALUE(0) + } + } + + pub fn as_isize(self) -> isize { + let VALUE(is) = self; + is as isize + } + + pub fn as_i32(self) -> i32 { + self.as_i64().try_into().unwrap() + } + + pub fn as_u32(self) -> u32 { + let VALUE(i) = self; + i.try_into().unwrap() + } + + pub fn as_i64(self) -> i64 { + let VALUE(i) = self; + i as i64 + } + + pub fn as_u64(self) -> u64 { + let VALUE(i) = self; + i.try_into().unwrap() + } + + pub fn as_usize(self) -> usize { + let VALUE(us) = self; + us + } + + pub fn as_ptr(self) -> *const T { + let VALUE(us) = self; + us as *const T + } + + pub fn as_mut_ptr(self) -> *mut T { + let VALUE(us) = self; + us as *mut T + } + + /// For working with opaque pointers and encoding null check. + /// Similar to [std::ptr::NonNull], but for `*const T`. `NonNull` + /// is for `*mut T` while our C functions are setup to use `*const T`. + /// Casting from `NonNull` to `*const T` is too noisy. + pub fn as_optional_ptr(self) -> Option<*const T> { + let ptr: *const T = self.as_ptr(); + + if ptr.is_null() { + None + } else { + Some(ptr) + } + } + + /// Assert that `self` is an iseq in debug builds + pub fn as_iseq(self) -> IseqPtr { + let ptr: IseqPtr = self.as_ptr(); + + #[cfg(debug_assertions)] + if !ptr.is_null() { + unsafe { rb_assert_iseq_handle(self) } + } + + ptr + } + + /// Assert that `self` is a method entry in debug builds + pub fn as_cme(self) -> *const rb_callable_method_entry_t { + let ptr: *const rb_callable_method_entry_t = self.as_ptr(); + + #[cfg(debug_assertions)] + if !ptr.is_null() { + unsafe { rb_assert_cme_handle(self) } + } + + ptr + } + + pub fn fixnum_from_usize(item: usize) -> Self { + assert!(item <= (RUBY_FIXNUM_MAX as usize)); // An unsigned will always be greater than RUBY_FIXNUM_MIN + let k: usize = item.wrapping_add(item.wrapping_add(1)); + VALUE(k) + } +} + +impl From for VALUE { + /// For `.into()` convenience + fn from(iseq: IseqPtr) -> Self { + VALUE(iseq as usize) + } +} + +impl From<*const rb_callable_method_entry_t> for VALUE { + /// For `.into()` convenience + fn from(cme: *const rb_callable_method_entry_t) -> Self { + VALUE(cme as usize) + } +} + +impl From<&str> for VALUE { + fn from(value: &str) -> Self { + rust_str_to_ruby(value) + } +} + +impl From for VALUE { + fn from(value: String) -> Self { + rust_str_to_ruby(&value) + } +} + +impl From for u64 { + fn from(value: VALUE) -> Self { + let VALUE(uimm) = value; + uimm as u64 + } +} + +impl From for i64 { + fn from(value: VALUE) -> Self { + let VALUE(uimm) = value; + assert!(uimm <= (i64::MAX as usize)); + uimm as i64 + } +} + +impl From for i32 { + fn from(value: VALUE) -> Self { + let VALUE(uimm) = value; + assert!(uimm <= (i32::MAX as usize)); + uimm.try_into().unwrap() + } +} + +impl From for u16 { + fn from(value: VALUE) -> Self { + let VALUE(uimm) = value; + uimm.try_into().unwrap() + } +} + +/// Produce a Ruby string from a Rust string slice +pub fn rust_str_to_ruby(str: &str) -> VALUE { + unsafe { rb_utf8_str_new(str.as_ptr() as *const _, str.len() as i64) } +} + +/// Produce a Ruby symbol from a Rust string slice +pub fn rust_str_to_sym(str: &str) -> VALUE { + let c_str = CString::new(str).unwrap(); + let c_ptr: *const c_char = c_str.as_ptr(); + unsafe { rb_id2sym(rb_intern(c_ptr)) } +} + +/// Produce an owned Rust String from a C char pointer +pub fn cstr_to_rust_string(c_char_ptr: *const c_char) -> Option { + assert!(c_char_ptr != std::ptr::null()); + + let c_str: &CStr = unsafe { CStr::from_ptr(c_char_ptr) }; + + match c_str.to_str() { + Ok(rust_str) => Some(rust_str.to_string()), + Err(_) => None + } +} + +/// A location in Rust code for integrating with debugging facilities defined in C. +/// Use the [src_loc!] macro to crate an instance. +pub struct SourceLocation { + pub file: &'static CStr, + pub line: c_int, +} + +impl Debug for SourceLocation { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!("{}:{}", self.file.to_string_lossy(), self.line)) + } +} + +/// Make a [SourceLocation] at the current spot. +macro_rules! src_loc { + () => { + { + // Nul-terminated string with static lifetime, make a CStr out of it safely. + let file: &'static str = concat!(file!(), '\0'); + $crate::cruby::SourceLocation { + file: unsafe { std::ffi::CStr::from_ptr(file.as_ptr().cast()) }, + line: line!().try_into().unwrap(), + } + } + }; +} + +pub(crate) use src_loc; + +/// Run GC write barrier. Required after making a new edge in the object reference +/// graph from `old` to `young`. +macro_rules! obj_written { + ($old: expr, $young: expr) => { + let (old, young): (VALUE, VALUE) = ($old, $young); + let src_loc = $crate::cruby::src_loc!(); + unsafe { rb_yjit_obj_written(old, young, src_loc.file.as_ptr(), src_loc.line) }; + }; +} +pub(crate) use obj_written; + +/// Acquire the VM lock, make sure all other Ruby threads are asleep then run +/// some code while holding the lock. Returns whatever `func` returns. +/// Use with [src_loc!]. +/// +/// Required for code patching in the presence of ractors. +pub fn with_vm_lock(loc: SourceLocation, func: F) -> R +where + F: FnOnce() -> R + UnwindSafe, +{ + let file = loc.file.as_ptr(); + let line = loc.line; + let mut recursive_lock_level: c_uint = 0; + + unsafe { rb_yjit_vm_lock_then_barrier(&mut recursive_lock_level, file, line) }; + + let ret = match catch_unwind(func) { + Ok(result) => result, + Err(_) => { + // Theoretically we can recover from some of these panics, + // but it's too late if the unwind reaches here. + + let _ = catch_unwind(|| { + // IO functions can panic too. + eprintln!( + "YJIT panicked while holding VM lock acquired at {}:{}. Aborting...", + loc.file.to_string_lossy(), + line, + ); + }); + std::process::abort(); + } + }; + + unsafe { rb_yjit_vm_unlock(&mut recursive_lock_level, file, line) }; + + ret +} + +// Non-idiomatic capitalization for consistency with CRuby code +#[allow(non_upper_case_globals)] +pub const Qfalse: VALUE = VALUE(RUBY_Qfalse as usize); +#[allow(non_upper_case_globals)] +pub const Qnil: VALUE = VALUE(RUBY_Qnil as usize); +#[allow(non_upper_case_globals)] +pub const Qtrue: VALUE = VALUE(RUBY_Qtrue as usize); +#[allow(non_upper_case_globals)] +pub const Qundef: VALUE = VALUE(RUBY_Qundef as usize); + +#[allow(unused)] +mod manual_defs { + use super::*; + + pub const SIZEOF_VALUE: usize = 8; + pub const SIZEOF_VALUE_I32: i32 = SIZEOF_VALUE as i32; + pub const VALUE_BITS: u8 = 8 * SIZEOF_VALUE as u8; + + pub const RUBY_LONG_MIN: isize = std::os::raw::c_long::MIN as isize; + pub const RUBY_LONG_MAX: isize = std::os::raw::c_long::MAX as isize; + + pub const RUBY_FIXNUM_MIN: isize = RUBY_LONG_MIN / 2; + pub const RUBY_FIXNUM_MAX: isize = RUBY_LONG_MAX / 2; + + // From vm_callinfo.h - uses calculation that seems to confuse bindgen + pub const VM_CALL_ARGS_SIMPLE: u32 = 1 << VM_CALL_ARGS_SIMPLE_bit; + pub const VM_CALL_ARGS_SPLAT: u32 = 1 << VM_CALL_ARGS_SPLAT_bit; + pub const VM_CALL_ARGS_BLOCKARG: u32 = 1 << VM_CALL_ARGS_BLOCKARG_bit; + pub const VM_CALL_FORWARDING: u32 = 1 << VM_CALL_FORWARDING_bit; + pub const VM_CALL_FCALL: u32 = 1 << VM_CALL_FCALL_bit; + pub const VM_CALL_KWARG: u32 = 1 << VM_CALL_KWARG_bit; + pub const VM_CALL_KW_SPLAT: u32 = 1 << VM_CALL_KW_SPLAT_bit; + pub const VM_CALL_TAILCALL: u32 = 1 << VM_CALL_TAILCALL_bit; + pub const VM_CALL_ZSUPER : u32 = 1 << VM_CALL_ZSUPER_bit; + pub const VM_CALL_OPT_SEND : u32 = 1 << VM_CALL_OPT_SEND_bit; + + // From internal/struct.h - in anonymous enum, so we can't easily import it + pub const RSTRUCT_EMBED_LEN_MASK: usize = (RUBY_FL_USER7 | RUBY_FL_USER6 | RUBY_FL_USER5 | RUBY_FL_USER4 | RUBY_FL_USER3 |RUBY_FL_USER2 | RUBY_FL_USER1) as usize; + + // From iseq.h - via a different constant, which seems to confuse bindgen + pub const ISEQ_TRANSLATED: usize = RUBY_FL_USER7 as usize; + + // We'll need to encode a lot of Ruby struct/field offsets as constants unless we want to + // redeclare all the Ruby C structs and write our own offsetof macro. For now, we use constants. + pub const RUBY_OFFSET_RBASIC_FLAGS: i32 = 0; // struct RBasic, field "flags" + pub const RUBY_OFFSET_RBASIC_KLASS: i32 = 8; // struct RBasic, field "klass" + pub const RUBY_OFFSET_RARRAY_AS_HEAP_LEN: i32 = 16; // struct RArray, subfield "as.heap.len" + pub const RUBY_OFFSET_RARRAY_AS_HEAP_PTR: i32 = 32; // struct RArray, subfield "as.heap.ptr" + pub const RUBY_OFFSET_RARRAY_AS_ARY: i32 = 16; // struct RArray, subfield "as.ary" + + pub const RUBY_OFFSET_RSTRUCT_AS_HEAP_PTR: i32 = 24; // struct RStruct, subfield "as.heap.ptr" + pub const RUBY_OFFSET_RSTRUCT_AS_ARY: i32 = 16; // struct RStruct, subfield "as.ary" + + pub const RUBY_OFFSET_RSTRING_AS_HEAP_PTR: i32 = 24; // struct RString, subfield "as.heap.ptr" + pub const RUBY_OFFSET_RSTRING_AS_ARY: i32 = 24; // struct RString, subfield "as.embed.ary" + + // Constants from rb_control_frame_t vm_core.h + pub const RUBY_OFFSET_CFP_PC: i32 = 0; + pub const RUBY_OFFSET_CFP_SP: i32 = 8; + pub const RUBY_OFFSET_CFP_ISEQ: i32 = 16; + pub const RUBY_OFFSET_CFP_SELF: i32 = 24; + pub const RUBY_OFFSET_CFP_EP: i32 = 32; + pub const RUBY_OFFSET_CFP_BLOCK_CODE: i32 = 40; + pub const RUBY_OFFSET_CFP_JIT_RETURN: i32 = 48; + pub const RUBY_SIZEOF_CONTROL_FRAME: usize = 56; + + // Constants from rb_execution_context_t vm_core.h + pub const RUBY_OFFSET_EC_CFP: i32 = 16; + pub const RUBY_OFFSET_EC_INTERRUPT_FLAG: i32 = 32; // rb_atomic_t (u32) + pub const RUBY_OFFSET_EC_INTERRUPT_MASK: i32 = 36; // rb_atomic_t (u32) + pub const RUBY_OFFSET_EC_THREAD_PTR: i32 = 48; + + // Constants from rb_thread_t in vm_core.h + pub const RUBY_OFFSET_THREAD_SELF: i32 = 16; + + // Constants from iseq_inline_constant_cache (IC) and iseq_inline_constant_cache_entry (ICE) in vm_core.h + pub const RUBY_OFFSET_IC_ENTRY: i32 = 0; + pub const RUBY_OFFSET_ICE_VALUE: i32 = 8; +} +pub use manual_defs::*; + +/// Interned ID values for Ruby symbols and method names. +/// See [type@crate::cruby::ID] and usages outside of YJIT. +pub(crate) mod ids { + use std::sync::atomic::AtomicU64; + /// Globals to cache IDs on boot. Atomic to use with relaxed ordering + /// so reads can happen without `unsafe`. Synchronization done through + /// the VM lock. + macro_rules! def_ids { + ($(name: $ident:ident content: $str:literal)*) => { + $( + #[doc = concat!("[type@crate::cruby::ID] for `", stringify!($str), "`")] + pub static $ident: AtomicU64 = AtomicU64::new(0); + )* + + pub(crate) fn init() { + $( + let content = &$str; + let ptr: *const u8 = content.as_ptr(); + + // Lookup and cache each ID + $ident.store( + unsafe { $crate::cruby::rb_intern2(ptr.cast(), content.len() as _) }, + std::sync::atomic::Ordering::Relaxed + ); + )* + + } + } + } + + def_ids! { + name: NULL content: b"" + name: respond_to_missing content: b"respond_to_missing?" + name: to_ary content: b"to_ary" + name: to_s content: b"to_s" + name: eq content: b"==" + name: include_p content: b"include?" + } +} + +/// Get an CRuby `ID` to an interned string, e.g. a particular method name. +macro_rules! ID { + ($id_name:ident) => { + $crate::cruby::ids::$id_name.load(std::sync::atomic::Ordering::Relaxed) + } +} +pub(crate) use ID; diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs new file mode 100644 index 0000000000..7ad24a274c --- /dev/null +++ b/zjit/src/cruby_bindings.inc.rs @@ -0,0 +1,1300 @@ +/* automatically generated by rust-bindgen 0.70.1 */ + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { + *byte |= mask; + } else { + *byte &= !mask; + } + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } +} +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[inline] + pub const fn new() -> Self { + __BindgenUnionField(::std::marker::PhantomData) + } + #[inline] + pub unsafe fn as_ref(&self) -> &T { + ::std::mem::transmute(self) + } + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + ::std::mem::transmute(self) + } +} +impl ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { + Self::new() + } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { + *self + } +} +impl ::std::marker::Copy for __BindgenUnionField {} +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +impl ::std::hash::Hash for __BindgenUnionField { + fn hash(&self, _state: &mut H) {} +} +impl ::std::cmp::PartialEq for __BindgenUnionField { + fn eq(&self, _other: &__BindgenUnionField) -> bool { + true + } +} +impl ::std::cmp::Eq for __BindgenUnionField {} +pub const INTEGER_REDEFINED_OP_FLAG: u32 = 1; +pub const FLOAT_REDEFINED_OP_FLAG: u32 = 2; +pub const STRING_REDEFINED_OP_FLAG: u32 = 4; +pub const ARRAY_REDEFINED_OP_FLAG: u32 = 8; +pub const HASH_REDEFINED_OP_FLAG: u32 = 16; +pub const SYMBOL_REDEFINED_OP_FLAG: u32 = 64; +pub const TIME_REDEFINED_OP_FLAG: u32 = 128; +pub const REGEXP_REDEFINED_OP_FLAG: u32 = 256; +pub const NIL_REDEFINED_OP_FLAG: u32 = 512; +pub const TRUE_REDEFINED_OP_FLAG: u32 = 1024; +pub const FALSE_REDEFINED_OP_FLAG: u32 = 2048; +pub const PROC_REDEFINED_OP_FLAG: u32 = 4096; +pub const VM_ENV_DATA_SIZE: u32 = 3; +pub const VM_ENV_DATA_INDEX_ME_CREF: i32 = -2; +pub const VM_ENV_DATA_INDEX_SPECVAL: i32 = -1; +pub const VM_ENV_DATA_INDEX_FLAGS: u32 = 0; +pub const VM_BLOCK_HANDLER_NONE: u32 = 0; +pub const SHAPE_ID_NUM_BITS: u32 = 32; +pub const OBJ_TOO_COMPLEX_SHAPE_ID: u32 = 2; +pub type ID = ::std::os::raw::c_ulong; +pub type rb_alloc_func_t = ::std::option::Option VALUE>; +pub const RUBY_Qfalse: ruby_special_consts = 0; +pub const RUBY_Qnil: ruby_special_consts = 4; +pub const RUBY_Qtrue: ruby_special_consts = 20; +pub const RUBY_Qundef: ruby_special_consts = 36; +pub const RUBY_IMMEDIATE_MASK: ruby_special_consts = 7; +pub const RUBY_FIXNUM_FLAG: ruby_special_consts = 1; +pub const RUBY_FLONUM_MASK: ruby_special_consts = 3; +pub const RUBY_FLONUM_FLAG: ruby_special_consts = 2; +pub const RUBY_SYMBOL_FLAG: ruby_special_consts = 12; +pub const RUBY_SPECIAL_SHIFT: ruby_special_consts = 8; +pub type ruby_special_consts = u32; +#[repr(C)] +pub struct RBasic { + pub flags: VALUE, + pub klass: VALUE, +} +pub const RUBY_T_NONE: ruby_value_type = 0; +pub const RUBY_T_OBJECT: ruby_value_type = 1; +pub const RUBY_T_CLASS: ruby_value_type = 2; +pub const RUBY_T_MODULE: ruby_value_type = 3; +pub const RUBY_T_FLOAT: ruby_value_type = 4; +pub const RUBY_T_STRING: ruby_value_type = 5; +pub const RUBY_T_REGEXP: ruby_value_type = 6; +pub const RUBY_T_ARRAY: ruby_value_type = 7; +pub const RUBY_T_HASH: ruby_value_type = 8; +pub const RUBY_T_STRUCT: ruby_value_type = 9; +pub const RUBY_T_BIGNUM: ruby_value_type = 10; +pub const RUBY_T_FILE: ruby_value_type = 11; +pub const RUBY_T_DATA: ruby_value_type = 12; +pub const RUBY_T_MATCH: ruby_value_type = 13; +pub const RUBY_T_COMPLEX: ruby_value_type = 14; +pub const RUBY_T_RATIONAL: ruby_value_type = 15; +pub const RUBY_T_NIL: ruby_value_type = 17; +pub const RUBY_T_TRUE: ruby_value_type = 18; +pub const RUBY_T_FALSE: ruby_value_type = 19; +pub const RUBY_T_SYMBOL: ruby_value_type = 20; +pub const RUBY_T_FIXNUM: ruby_value_type = 21; +pub const RUBY_T_UNDEF: ruby_value_type = 22; +pub const RUBY_T_IMEMO: ruby_value_type = 26; +pub const RUBY_T_NODE: ruby_value_type = 27; +pub const RUBY_T_ICLASS: ruby_value_type = 28; +pub const RUBY_T_ZOMBIE: ruby_value_type = 29; +pub const RUBY_T_MOVED: ruby_value_type = 30; +pub const RUBY_T_MASK: ruby_value_type = 31; +pub type ruby_value_type = u32; +pub const RUBY_FL_USHIFT: ruby_fl_ushift = 12; +pub type ruby_fl_ushift = u32; +pub const RUBY_FL_WB_PROTECTED: ruby_fl_type = 32; +pub const RUBY_FL_PROMOTED: ruby_fl_type = 32; +pub const RUBY_FL_UNUSED6: ruby_fl_type = 64; +pub const RUBY_FL_FINALIZE: ruby_fl_type = 128; +pub const RUBY_FL_TAINT: ruby_fl_type = 0; +pub const RUBY_FL_SHAREABLE: ruby_fl_type = 256; +pub const RUBY_FL_UNTRUSTED: ruby_fl_type = 0; +pub const RUBY_FL_SEEN_OBJ_ID: ruby_fl_type = 512; +pub const RUBY_FL_EXIVAR: ruby_fl_type = 1024; +pub const RUBY_FL_FREEZE: ruby_fl_type = 2048; +pub const RUBY_FL_USER0: ruby_fl_type = 4096; +pub const RUBY_FL_USER1: ruby_fl_type = 8192; +pub const RUBY_FL_USER2: ruby_fl_type = 16384; +pub const RUBY_FL_USER3: ruby_fl_type = 32768; +pub const RUBY_FL_USER4: ruby_fl_type = 65536; +pub const RUBY_FL_USER5: ruby_fl_type = 131072; +pub const RUBY_FL_USER6: ruby_fl_type = 262144; +pub const RUBY_FL_USER7: ruby_fl_type = 524288; +pub const RUBY_FL_USER8: ruby_fl_type = 1048576; +pub const RUBY_FL_USER9: ruby_fl_type = 2097152; +pub const RUBY_FL_USER10: ruby_fl_type = 4194304; +pub const RUBY_FL_USER11: ruby_fl_type = 8388608; +pub const RUBY_FL_USER12: ruby_fl_type = 16777216; +pub const RUBY_FL_USER13: ruby_fl_type = 33554432; +pub const RUBY_FL_USER14: ruby_fl_type = 67108864; +pub const RUBY_FL_USER15: ruby_fl_type = 134217728; +pub const RUBY_FL_USER16: ruby_fl_type = 268435456; +pub const RUBY_FL_USER17: ruby_fl_type = 536870912; +pub const RUBY_FL_USER18: ruby_fl_type = 1073741824; +pub const RUBY_FL_USER19: ruby_fl_type = -2147483648; +pub const RUBY_ELTS_SHARED: ruby_fl_type = 4096; +pub const RUBY_FL_SINGLETON: ruby_fl_type = 8192; +pub type ruby_fl_type = i32; +pub const RSTRING_NOEMBED: ruby_rstring_flags = 8192; +pub const RSTRING_FSTR: ruby_rstring_flags = 536870912; +pub type ruby_rstring_flags = u32; +pub type st_data_t = ::std::os::raw::c_ulong; +pub type st_index_t = st_data_t; +pub const ST_CONTINUE: st_retval = 0; +pub const ST_STOP: st_retval = 1; +pub const ST_DELETE: st_retval = 2; +pub const ST_CHECK: st_retval = 3; +pub const ST_REPLACE: st_retval = 4; +pub type st_retval = u32; +pub type st_foreach_callback_func = ::std::option::Option< + unsafe extern "C" fn( + arg1: st_data_t, + arg2: st_data_t, + arg3: st_data_t, + ) -> ::std::os::raw::c_int, +>; +pub const RARRAY_EMBED_FLAG: ruby_rarray_flags = 8192; +pub const RARRAY_EMBED_LEN_MASK: ruby_rarray_flags = 4161536; +pub type ruby_rarray_flags = u32; +pub const RARRAY_EMBED_LEN_SHIFT: ruby_rarray_consts = 15; +pub type ruby_rarray_consts = u32; +pub const RMODULE_IS_REFINEMENT: ruby_rmodule_flags = 32768; +pub type ruby_rmodule_flags = u32; +pub const ROBJECT_EMBED: ruby_robject_flags = 8192; +pub type ruby_robject_flags = u32; +pub type rb_block_call_func = ::std::option::Option< + unsafe extern "C" fn( + yielded_arg: VALUE, + callback_arg: VALUE, + argc: ::std::os::raw::c_int, + argv: *const VALUE, + blockarg: VALUE, + ) -> VALUE, +>; +pub type rb_block_call_func_t = rb_block_call_func; +pub const RUBY_ENCODING_INLINE_MAX: ruby_encoding_consts = 127; +pub const RUBY_ENCODING_SHIFT: ruby_encoding_consts = 22; +pub const RUBY_ENCODING_MASK: ruby_encoding_consts = 532676608; +pub const RUBY_ENCODING_MAXNAMELEN: ruby_encoding_consts = 42; +pub type ruby_encoding_consts = u32; +pub const RUBY_ENCINDEX_ASCII_8BIT: ruby_preserved_encindex = 0; +pub const RUBY_ENCINDEX_UTF_8: ruby_preserved_encindex = 1; +pub const RUBY_ENCINDEX_US_ASCII: ruby_preserved_encindex = 2; +pub const RUBY_ENCINDEX_UTF_16BE: ruby_preserved_encindex = 3; +pub const RUBY_ENCINDEX_UTF_16LE: ruby_preserved_encindex = 4; +pub const RUBY_ENCINDEX_UTF_32BE: ruby_preserved_encindex = 5; +pub const RUBY_ENCINDEX_UTF_32LE: ruby_preserved_encindex = 6; +pub const RUBY_ENCINDEX_UTF_16: ruby_preserved_encindex = 7; +pub const RUBY_ENCINDEX_UTF_32: ruby_preserved_encindex = 8; +pub const RUBY_ENCINDEX_UTF8_MAC: ruby_preserved_encindex = 9; +pub const RUBY_ENCINDEX_EUC_JP: ruby_preserved_encindex = 10; +pub const RUBY_ENCINDEX_Windows_31J: ruby_preserved_encindex = 11; +pub const RUBY_ENCINDEX_BUILTIN_MAX: ruby_preserved_encindex = 12; +pub type ruby_preserved_encindex = u32; +pub const BOP_PLUS: ruby_basic_operators = 0; +pub const BOP_MINUS: ruby_basic_operators = 1; +pub const BOP_MULT: ruby_basic_operators = 2; +pub const BOP_DIV: ruby_basic_operators = 3; +pub const BOP_MOD: ruby_basic_operators = 4; +pub const BOP_EQ: ruby_basic_operators = 5; +pub const BOP_EQQ: ruby_basic_operators = 6; +pub const BOP_LT: ruby_basic_operators = 7; +pub const BOP_LE: ruby_basic_operators = 8; +pub const BOP_LTLT: ruby_basic_operators = 9; +pub const BOP_AREF: ruby_basic_operators = 10; +pub const BOP_ASET: ruby_basic_operators = 11; +pub const BOP_LENGTH: ruby_basic_operators = 12; +pub const BOP_SIZE: ruby_basic_operators = 13; +pub const BOP_EMPTY_P: ruby_basic_operators = 14; +pub const BOP_NIL_P: ruby_basic_operators = 15; +pub const BOP_SUCC: ruby_basic_operators = 16; +pub const BOP_GT: ruby_basic_operators = 17; +pub const BOP_GE: ruby_basic_operators = 18; +pub const BOP_NOT: ruby_basic_operators = 19; +pub const BOP_NEQ: ruby_basic_operators = 20; +pub const BOP_MATCH: ruby_basic_operators = 21; +pub const BOP_FREEZE: ruby_basic_operators = 22; +pub const BOP_UMINUS: ruby_basic_operators = 23; +pub const BOP_MAX: ruby_basic_operators = 24; +pub const BOP_MIN: ruby_basic_operators = 25; +pub const BOP_HASH: ruby_basic_operators = 26; +pub const BOP_CALL: ruby_basic_operators = 27; +pub const BOP_AND: ruby_basic_operators = 28; +pub const BOP_OR: ruby_basic_operators = 29; +pub const BOP_CMP: ruby_basic_operators = 30; +pub const BOP_DEFAULT: ruby_basic_operators = 31; +pub const BOP_PACK: ruby_basic_operators = 32; +pub const BOP_INCLUDE_P: ruby_basic_operators = 33; +pub const BOP_LAST_: ruby_basic_operators = 34; +pub type ruby_basic_operators = u32; +pub type rb_serial_t = ::std::os::raw::c_ulonglong; +pub const imemo_env: imemo_type = 0; +pub const imemo_cref: imemo_type = 1; +pub const imemo_svar: imemo_type = 2; +pub const imemo_throw_data: imemo_type = 3; +pub const imemo_ifunc: imemo_type = 4; +pub const imemo_memo: imemo_type = 5; +pub const imemo_ment: imemo_type = 6; +pub const imemo_iseq: imemo_type = 7; +pub const imemo_tmpbuf: imemo_type = 8; +pub const imemo_ast: imemo_type = 9; +pub const imemo_parser_strterm: imemo_type = 10; +pub const imemo_callinfo: imemo_type = 11; +pub const imemo_callcache: imemo_type = 12; +pub const imemo_constcache: imemo_type = 13; +pub type imemo_type = u32; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct vm_ifunc_argc { + pub min: ::std::os::raw::c_int, + pub max: ::std::os::raw::c_int, +} +#[repr(C)] +pub struct vm_ifunc { + pub flags: VALUE, + pub svar_lep: *mut VALUE, + pub func: rb_block_call_func_t, + pub data: *const ::std::os::raw::c_void, + pub argc: vm_ifunc_argc, +} +pub const METHOD_VISI_UNDEF: rb_method_visibility_t = 0; +pub const METHOD_VISI_PUBLIC: rb_method_visibility_t = 1; +pub const METHOD_VISI_PRIVATE: rb_method_visibility_t = 2; +pub const METHOD_VISI_PROTECTED: rb_method_visibility_t = 3; +pub const METHOD_VISI_MASK: rb_method_visibility_t = 3; +pub type rb_method_visibility_t = u32; +#[repr(C)] +pub struct rb_method_entry_struct { + pub flags: VALUE, + pub defined_class: VALUE, + pub def: *mut rb_method_definition_struct, + pub called_id: ID, + pub owner: VALUE, +} +pub type rb_method_entry_t = rb_method_entry_struct; +#[repr(C)] +pub struct rb_callable_method_entry_struct { + pub flags: VALUE, + pub defined_class: VALUE, + pub def: *mut rb_method_definition_struct, + pub called_id: ID, + pub owner: VALUE, +} +pub type rb_callable_method_entry_t = rb_callable_method_entry_struct; +pub const VM_METHOD_TYPE_ISEQ: rb_method_type_t = 0; +pub const VM_METHOD_TYPE_CFUNC: rb_method_type_t = 1; +pub const VM_METHOD_TYPE_ATTRSET: rb_method_type_t = 2; +pub const VM_METHOD_TYPE_IVAR: rb_method_type_t = 3; +pub const VM_METHOD_TYPE_BMETHOD: rb_method_type_t = 4; +pub const VM_METHOD_TYPE_ZSUPER: rb_method_type_t = 5; +pub const VM_METHOD_TYPE_ALIAS: rb_method_type_t = 6; +pub const VM_METHOD_TYPE_UNDEF: rb_method_type_t = 7; +pub const VM_METHOD_TYPE_NOTIMPLEMENTED: rb_method_type_t = 8; +pub const VM_METHOD_TYPE_OPTIMIZED: rb_method_type_t = 9; +pub const VM_METHOD_TYPE_MISSING: rb_method_type_t = 10; +pub const VM_METHOD_TYPE_REFINED: rb_method_type_t = 11; +pub type rb_method_type_t = u32; +pub type rb_cfunc_t = ::std::option::Option VALUE>; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct rb_method_cfunc_struct { + pub func: rb_cfunc_t, + pub invoker: ::std::option::Option< + unsafe extern "C" fn( + recv: VALUE, + argc: ::std::os::raw::c_int, + argv: *const VALUE, + func: ::std::option::Option VALUE>, + ) -> VALUE, + >, + pub argc: ::std::os::raw::c_int, +} +pub const OPTIMIZED_METHOD_TYPE_SEND: method_optimized_type = 0; +pub const OPTIMIZED_METHOD_TYPE_CALL: method_optimized_type = 1; +pub const OPTIMIZED_METHOD_TYPE_BLOCK_CALL: method_optimized_type = 2; +pub const OPTIMIZED_METHOD_TYPE_STRUCT_AREF: method_optimized_type = 3; +pub const OPTIMIZED_METHOD_TYPE_STRUCT_ASET: method_optimized_type = 4; +pub const OPTIMIZED_METHOD_TYPE__MAX: method_optimized_type = 5; +pub type method_optimized_type = u32; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct rb_id_table { + _unused: [u8; 0], +} +pub type rb_num_t = ::std::os::raw::c_ulong; +pub const RUBY_TAG_NONE: ruby_tag_type = 0; +pub const RUBY_TAG_RETURN: ruby_tag_type = 1; +pub const RUBY_TAG_BREAK: ruby_tag_type = 2; +pub const RUBY_TAG_NEXT: ruby_tag_type = 3; +pub const RUBY_TAG_RETRY: ruby_tag_type = 4; +pub const RUBY_TAG_REDO: ruby_tag_type = 5; +pub const RUBY_TAG_RAISE: ruby_tag_type = 6; +pub const RUBY_TAG_THROW: ruby_tag_type = 7; +pub const RUBY_TAG_FATAL: ruby_tag_type = 8; +pub const RUBY_TAG_MASK: ruby_tag_type = 15; +pub type ruby_tag_type = u32; +pub const VM_THROW_NO_ESCAPE_FLAG: ruby_vm_throw_flags = 32768; +pub const VM_THROW_STATE_MASK: ruby_vm_throw_flags = 255; +pub type ruby_vm_throw_flags = u32; +#[repr(C)] +pub struct iseq_inline_constant_cache_entry { + pub flags: VALUE, + pub value: VALUE, + pub _unused1: VALUE, + pub _unused2: VALUE, + pub ic_cref: *const rb_cref_t, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct iseq_inline_constant_cache { + pub entry: *mut iseq_inline_constant_cache_entry, + pub segments: *const ID, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct iseq_inline_iv_cache_entry { + pub value: usize, + pub iv_set_name: ID, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct iseq_inline_cvar_cache_entry { + pub entry: *mut rb_cvar_class_tbl_entry, +} +pub const ISEQ_TYPE_TOP: rb_iseq_type = 0; +pub const ISEQ_TYPE_METHOD: rb_iseq_type = 1; +pub const ISEQ_TYPE_BLOCK: rb_iseq_type = 2; +pub const ISEQ_TYPE_CLASS: rb_iseq_type = 3; +pub const ISEQ_TYPE_RESCUE: rb_iseq_type = 4; +pub const ISEQ_TYPE_ENSURE: rb_iseq_type = 5; +pub const ISEQ_TYPE_EVAL: rb_iseq_type = 6; +pub const ISEQ_TYPE_MAIN: rb_iseq_type = 7; +pub const ISEQ_TYPE_PLAIN: rb_iseq_type = 8; +pub type rb_iseq_type = u32; +pub const BUILTIN_ATTR_LEAF: rb_builtin_attr = 1; +pub const BUILTIN_ATTR_SINGLE_NOARG_LEAF: rb_builtin_attr = 2; +pub const BUILTIN_ATTR_INLINE_BLOCK: rb_builtin_attr = 4; +pub const BUILTIN_ATTR_C_TRACE: rb_builtin_attr = 8; +pub type rb_builtin_attr = u32; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct rb_iseq_constant_body__bindgen_ty_1_rb_iseq_param_keyword { + pub num: ::std::os::raw::c_int, + pub required_num: ::std::os::raw::c_int, + pub bits_start: ::std::os::raw::c_int, + pub rest_start: ::std::os::raw::c_int, + pub table: *const ID, + pub default_values: *mut VALUE, +} +#[repr(C)] +pub struct rb_captured_block { + pub self_: VALUE, + pub ep: *const VALUE, + pub code: rb_captured_block__bindgen_ty_1, +} +#[repr(C)] +pub struct rb_captured_block__bindgen_ty_1 { + pub iseq: __BindgenUnionField<*const rb_iseq_t>, + pub ifunc: __BindgenUnionField<*const vm_ifunc>, + pub val: __BindgenUnionField, + pub bindgen_union_field: u64, +} +pub const block_type_iseq: rb_block_type = 0; +pub const block_type_ifunc: rb_block_type = 1; +pub const block_type_symbol: rb_block_type = 2; +pub const block_type_proc: rb_block_type = 3; +pub type rb_block_type = u32; +#[repr(C)] +pub struct rb_block { + pub as_: rb_block__bindgen_ty_1, + pub type_: rb_block_type, +} +#[repr(C)] +pub struct rb_block__bindgen_ty_1 { + pub captured: __BindgenUnionField, + pub symbol: __BindgenUnionField, + pub proc_: __BindgenUnionField, + pub bindgen_union_field: [u64; 3usize], +} +pub type rb_control_frame_t = rb_control_frame_struct; +#[repr(C)] +pub struct rb_proc_t { + pub block: rb_block, + pub _bitfield_align_1: [u8; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, + pub __bindgen_padding_0: [u8; 7usize], +} +impl rb_proc_t { + #[inline] + pub fn is_from_method(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } + } + #[inline] + pub fn set_is_from_method(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 1u8, val as u64) + } + } + #[inline] + pub fn is_lambda(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } + } + #[inline] + pub fn set_is_lambda(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(1usize, 1u8, val as u64) + } + } + #[inline] + pub fn is_isolated(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u32) } + } + #[inline] + pub fn set_is_isolated(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(2usize, 1u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1( + is_from_method: ::std::os::raw::c_uint, + is_lambda: ::std::os::raw::c_uint, + is_isolated: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit.set(0usize, 1u8, { + let is_from_method: u32 = unsafe { ::std::mem::transmute(is_from_method) }; + is_from_method as u64 + }); + __bindgen_bitfield_unit.set(1usize, 1u8, { + let is_lambda: u32 = unsafe { ::std::mem::transmute(is_lambda) }; + is_lambda as u64 + }); + __bindgen_bitfield_unit.set(2usize, 1u8, { + let is_isolated: u32 = unsafe { ::std::mem::transmute(is_isolated) }; + is_isolated as u64 + }); + __bindgen_bitfield_unit + } +} +pub const VM_CHECKMATCH_TYPE_WHEN: vm_check_match_type = 1; +pub const VM_CHECKMATCH_TYPE_CASE: vm_check_match_type = 2; +pub const VM_CHECKMATCH_TYPE_RESCUE: vm_check_match_type = 3; +pub type vm_check_match_type = u32; +pub const VM_OPT_NEWARRAY_SEND_MAX: vm_opt_newarray_send_type = 1; +pub const VM_OPT_NEWARRAY_SEND_MIN: vm_opt_newarray_send_type = 2; +pub const VM_OPT_NEWARRAY_SEND_HASH: vm_opt_newarray_send_type = 3; +pub const VM_OPT_NEWARRAY_SEND_PACK: vm_opt_newarray_send_type = 4; +pub const VM_OPT_NEWARRAY_SEND_PACK_BUFFER: vm_opt_newarray_send_type = 5; +pub const VM_OPT_NEWARRAY_SEND_INCLUDE_P: vm_opt_newarray_send_type = 6; +pub type vm_opt_newarray_send_type = u32; +pub const VM_SPECIAL_OBJECT_VMCORE: vm_special_object_type = 1; +pub const VM_SPECIAL_OBJECT_CBASE: vm_special_object_type = 2; +pub const VM_SPECIAL_OBJECT_CONST_BASE: vm_special_object_type = 3; +pub type vm_special_object_type = u32; +pub type IC = *mut iseq_inline_constant_cache; +pub type IVC = *mut iseq_inline_iv_cache_entry; +pub type ICVARC = *mut iseq_inline_cvar_cache_entry; +pub const VM_FRAME_MAGIC_METHOD: vm_frame_env_flags = 286326785; +pub const VM_FRAME_MAGIC_BLOCK: vm_frame_env_flags = 572653569; +pub const VM_FRAME_MAGIC_CLASS: vm_frame_env_flags = 858980353; +pub const VM_FRAME_MAGIC_TOP: vm_frame_env_flags = 1145307137; +pub const VM_FRAME_MAGIC_CFUNC: vm_frame_env_flags = 1431633921; +pub const VM_FRAME_MAGIC_IFUNC: vm_frame_env_flags = 1717960705; +pub const VM_FRAME_MAGIC_EVAL: vm_frame_env_flags = 2004287489; +pub const VM_FRAME_MAGIC_RESCUE: vm_frame_env_flags = 2022178817; +pub const VM_FRAME_MAGIC_DUMMY: vm_frame_env_flags = 2040070145; +pub const VM_FRAME_MAGIC_MASK: vm_frame_env_flags = 2147418113; +pub const VM_FRAME_FLAG_FINISH: vm_frame_env_flags = 32; +pub const VM_FRAME_FLAG_BMETHOD: vm_frame_env_flags = 64; +pub const VM_FRAME_FLAG_CFRAME: vm_frame_env_flags = 128; +pub const VM_FRAME_FLAG_LAMBDA: vm_frame_env_flags = 256; +pub const VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM: vm_frame_env_flags = 512; +pub const VM_FRAME_FLAG_CFRAME_KW: vm_frame_env_flags = 1024; +pub const VM_FRAME_FLAG_PASSED: vm_frame_env_flags = 2048; +pub const VM_ENV_FLAG_LOCAL: vm_frame_env_flags = 2; +pub const VM_ENV_FLAG_ESCAPED: vm_frame_env_flags = 4; +pub const VM_ENV_FLAG_WB_REQUIRED: vm_frame_env_flags = 8; +pub const VM_ENV_FLAG_ISOLATED: vm_frame_env_flags = 16; +pub type vm_frame_env_flags = u32; +pub type attr_index_t = u32; +pub type shape_id_t = u32; +pub type redblack_id_t = u32; +pub type redblack_node_t = redblack_node; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct rb_shape { + pub edges: *mut rb_id_table, + pub edge_name: ID, + pub next_iv_index: attr_index_t, + pub capacity: u32, + pub type_: u8, + pub heap_index: u8, + pub parent_id: shape_id_t, + pub ancestor_index: *mut redblack_node_t, +} +pub type rb_shape_t = rb_shape; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct redblack_node { + pub key: ID, + pub value: *mut rb_shape_t, + pub l: redblack_id_t, + pub r: redblack_id_t, +} +#[repr(C)] +pub struct rb_cvar_class_tbl_entry { + pub index: u32, + pub global_cvar_state: rb_serial_t, + pub cref: *const rb_cref_t, + pub class_value: VALUE, +} +pub const VM_CALL_ARGS_SPLAT_bit: vm_call_flag_bits = 0; +pub const VM_CALL_ARGS_BLOCKARG_bit: vm_call_flag_bits = 1; +pub const VM_CALL_FCALL_bit: vm_call_flag_bits = 2; +pub const VM_CALL_VCALL_bit: vm_call_flag_bits = 3; +pub const VM_CALL_ARGS_SIMPLE_bit: vm_call_flag_bits = 4; +pub const VM_CALL_KWARG_bit: vm_call_flag_bits = 5; +pub const VM_CALL_KW_SPLAT_bit: vm_call_flag_bits = 6; +pub const VM_CALL_TAILCALL_bit: vm_call_flag_bits = 7; +pub const VM_CALL_SUPER_bit: vm_call_flag_bits = 8; +pub const VM_CALL_ZSUPER_bit: vm_call_flag_bits = 9; +pub const VM_CALL_OPT_SEND_bit: vm_call_flag_bits = 10; +pub const VM_CALL_KW_SPLAT_MUT_bit: vm_call_flag_bits = 11; +pub const VM_CALL_ARGS_SPLAT_MUT_bit: vm_call_flag_bits = 12; +pub const VM_CALL_FORWARDING_bit: vm_call_flag_bits = 13; +pub const VM_CALL__END: vm_call_flag_bits = 14; +pub type vm_call_flag_bits = u32; +#[repr(C)] +pub struct rb_callinfo_kwarg { + pub keyword_len: ::std::os::raw::c_int, + pub references: ::std::os::raw::c_int, + pub keywords: __IncompleteArrayField, +} +#[repr(C)] +pub struct rb_callinfo { + pub flags: VALUE, + pub kwarg: *const rb_callinfo_kwarg, + pub mid: VALUE, + pub flag: VALUE, + pub argc: VALUE, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct rb_call_data { + pub ci: *const rb_callinfo, + pub cc: *const rb_callcache, +} +pub const RSTRING_CHILLED: ruby_rstring_private_flags = 49152; +pub type ruby_rstring_private_flags = u32; +pub const RHASH_PASS_AS_KEYWORDS: ruby_rhash_flags = 8192; +pub const RHASH_PROC_DEFAULT: ruby_rhash_flags = 16384; +pub const RHASH_ST_TABLE_FLAG: ruby_rhash_flags = 32768; +pub const RHASH_AR_TABLE_SIZE_MASK: ruby_rhash_flags = 983040; +pub const RHASH_AR_TABLE_SIZE_SHIFT: ruby_rhash_flags = 16; +pub const RHASH_AR_TABLE_BOUND_MASK: ruby_rhash_flags = 15728640; +pub const RHASH_AR_TABLE_BOUND_SHIFT: ruby_rhash_flags = 20; +pub const RHASH_LEV_SHIFT: ruby_rhash_flags = 25; +pub const RHASH_LEV_MAX: ruby_rhash_flags = 127; +pub type ruby_rhash_flags = u32; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct rb_builtin_function { + pub func_ptr: *const ::std::os::raw::c_void, + pub argc: ::std::os::raw::c_int, + pub index: ::std::os::raw::c_int, + pub name: *const ::std::os::raw::c_char, +} +pub const YARVINSN_nop: ruby_vminsn_type = 0; +pub const YARVINSN_getlocal: ruby_vminsn_type = 1; +pub const YARVINSN_setlocal: ruby_vminsn_type = 2; +pub const YARVINSN_getblockparam: ruby_vminsn_type = 3; +pub const YARVINSN_setblockparam: ruby_vminsn_type = 4; +pub const YARVINSN_getblockparamproxy: ruby_vminsn_type = 5; +pub const YARVINSN_getspecial: ruby_vminsn_type = 6; +pub const YARVINSN_setspecial: ruby_vminsn_type = 7; +pub const YARVINSN_getinstancevariable: ruby_vminsn_type = 8; +pub const YARVINSN_setinstancevariable: ruby_vminsn_type = 9; +pub const YARVINSN_getclassvariable: ruby_vminsn_type = 10; +pub const YARVINSN_setclassvariable: ruby_vminsn_type = 11; +pub const YARVINSN_opt_getconstant_path: ruby_vminsn_type = 12; +pub const YARVINSN_getconstant: ruby_vminsn_type = 13; +pub const YARVINSN_setconstant: ruby_vminsn_type = 14; +pub const YARVINSN_getglobal: ruby_vminsn_type = 15; +pub const YARVINSN_setglobal: ruby_vminsn_type = 16; +pub const YARVINSN_putnil: ruby_vminsn_type = 17; +pub const YARVINSN_putself: ruby_vminsn_type = 18; +pub const YARVINSN_putobject: ruby_vminsn_type = 19; +pub const YARVINSN_putspecialobject: ruby_vminsn_type = 20; +pub const YARVINSN_putstring: ruby_vminsn_type = 21; +pub const YARVINSN_putchilledstring: ruby_vminsn_type = 22; +pub const YARVINSN_concatstrings: ruby_vminsn_type = 23; +pub const YARVINSN_anytostring: ruby_vminsn_type = 24; +pub const YARVINSN_toregexp: ruby_vminsn_type = 25; +pub const YARVINSN_intern: ruby_vminsn_type = 26; +pub const YARVINSN_newarray: ruby_vminsn_type = 27; +pub const YARVINSN_pushtoarraykwsplat: ruby_vminsn_type = 28; +pub const YARVINSN_duparray: ruby_vminsn_type = 29; +pub const YARVINSN_duphash: ruby_vminsn_type = 30; +pub const YARVINSN_expandarray: ruby_vminsn_type = 31; +pub const YARVINSN_concatarray: ruby_vminsn_type = 32; +pub const YARVINSN_concattoarray: ruby_vminsn_type = 33; +pub const YARVINSN_pushtoarray: ruby_vminsn_type = 34; +pub const YARVINSN_splatarray: ruby_vminsn_type = 35; +pub const YARVINSN_splatkw: ruby_vminsn_type = 36; +pub const YARVINSN_newhash: ruby_vminsn_type = 37; +pub const YARVINSN_newrange: ruby_vminsn_type = 38; +pub const YARVINSN_pop: ruby_vminsn_type = 39; +pub const YARVINSN_dup: ruby_vminsn_type = 40; +pub const YARVINSN_dupn: ruby_vminsn_type = 41; +pub const YARVINSN_swap: ruby_vminsn_type = 42; +pub const YARVINSN_opt_reverse: ruby_vminsn_type = 43; +pub const YARVINSN_topn: ruby_vminsn_type = 44; +pub const YARVINSN_setn: ruby_vminsn_type = 45; +pub const YARVINSN_adjuststack: ruby_vminsn_type = 46; +pub const YARVINSN_defined: ruby_vminsn_type = 47; +pub const YARVINSN_definedivar: ruby_vminsn_type = 48; +pub const YARVINSN_checkmatch: ruby_vminsn_type = 49; +pub const YARVINSN_checkkeyword: ruby_vminsn_type = 50; +pub const YARVINSN_checktype: ruby_vminsn_type = 51; +pub const YARVINSN_defineclass: ruby_vminsn_type = 52; +pub const YARVINSN_definemethod: ruby_vminsn_type = 53; +pub const YARVINSN_definesmethod: ruby_vminsn_type = 54; +pub const YARVINSN_send: ruby_vminsn_type = 55; +pub const YARVINSN_sendforward: ruby_vminsn_type = 56; +pub const YARVINSN_opt_send_without_block: ruby_vminsn_type = 57; +pub const YARVINSN_objtostring: ruby_vminsn_type = 58; +pub const YARVINSN_opt_ary_freeze: ruby_vminsn_type = 59; +pub const YARVINSN_opt_hash_freeze: ruby_vminsn_type = 60; +pub const YARVINSN_opt_str_freeze: ruby_vminsn_type = 61; +pub const YARVINSN_opt_nil_p: ruby_vminsn_type = 62; +pub const YARVINSN_opt_str_uminus: ruby_vminsn_type = 63; +pub const YARVINSN_opt_duparray_send: ruby_vminsn_type = 64; +pub const YARVINSN_opt_newarray_send: ruby_vminsn_type = 65; +pub const YARVINSN_invokesuper: ruby_vminsn_type = 66; +pub const YARVINSN_invokesuperforward: ruby_vminsn_type = 67; +pub const YARVINSN_invokeblock: ruby_vminsn_type = 68; +pub const YARVINSN_leave: ruby_vminsn_type = 69; +pub const YARVINSN_throw: ruby_vminsn_type = 70; +pub const YARVINSN_jump: ruby_vminsn_type = 71; +pub const YARVINSN_branchif: ruby_vminsn_type = 72; +pub const YARVINSN_branchunless: ruby_vminsn_type = 73; +pub const YARVINSN_branchnil: ruby_vminsn_type = 74; +pub const YARVINSN_once: ruby_vminsn_type = 75; +pub const YARVINSN_opt_case_dispatch: ruby_vminsn_type = 76; +pub const YARVINSN_opt_plus: ruby_vminsn_type = 77; +pub const YARVINSN_opt_minus: ruby_vminsn_type = 78; +pub const YARVINSN_opt_mult: ruby_vminsn_type = 79; +pub const YARVINSN_opt_div: ruby_vminsn_type = 80; +pub const YARVINSN_opt_mod: ruby_vminsn_type = 81; +pub const YARVINSN_opt_eq: ruby_vminsn_type = 82; +pub const YARVINSN_opt_neq: ruby_vminsn_type = 83; +pub const YARVINSN_opt_lt: ruby_vminsn_type = 84; +pub const YARVINSN_opt_le: ruby_vminsn_type = 85; +pub const YARVINSN_opt_gt: ruby_vminsn_type = 86; +pub const YARVINSN_opt_ge: ruby_vminsn_type = 87; +pub const YARVINSN_opt_ltlt: ruby_vminsn_type = 88; +pub const YARVINSN_opt_and: ruby_vminsn_type = 89; +pub const YARVINSN_opt_or: ruby_vminsn_type = 90; +pub const YARVINSN_opt_aref: ruby_vminsn_type = 91; +pub const YARVINSN_opt_aset: ruby_vminsn_type = 92; +pub const YARVINSN_opt_aset_with: ruby_vminsn_type = 93; +pub const YARVINSN_opt_aref_with: ruby_vminsn_type = 94; +pub const YARVINSN_opt_length: ruby_vminsn_type = 95; +pub const YARVINSN_opt_size: ruby_vminsn_type = 96; +pub const YARVINSN_opt_empty_p: ruby_vminsn_type = 97; +pub const YARVINSN_opt_succ: ruby_vminsn_type = 98; +pub const YARVINSN_opt_not: ruby_vminsn_type = 99; +pub const YARVINSN_opt_regexpmatch2: ruby_vminsn_type = 100; +pub const YARVINSN_invokebuiltin: ruby_vminsn_type = 101; +pub const YARVINSN_opt_invokebuiltin_delegate: ruby_vminsn_type = 102; +pub const YARVINSN_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 103; +pub const YARVINSN_getlocal_WC_0: ruby_vminsn_type = 104; +pub const YARVINSN_getlocal_WC_1: ruby_vminsn_type = 105; +pub const YARVINSN_setlocal_WC_0: ruby_vminsn_type = 106; +pub const YARVINSN_setlocal_WC_1: ruby_vminsn_type = 107; +pub const YARVINSN_putobject_INT2FIX_0_: ruby_vminsn_type = 108; +pub const YARVINSN_putobject_INT2FIX_1_: ruby_vminsn_type = 109; +pub const YARVINSN_trace_nop: ruby_vminsn_type = 110; +pub const YARVINSN_trace_getlocal: ruby_vminsn_type = 111; +pub const YARVINSN_trace_setlocal: ruby_vminsn_type = 112; +pub const YARVINSN_trace_getblockparam: ruby_vminsn_type = 113; +pub const YARVINSN_trace_setblockparam: ruby_vminsn_type = 114; +pub const YARVINSN_trace_getblockparamproxy: ruby_vminsn_type = 115; +pub const YARVINSN_trace_getspecial: ruby_vminsn_type = 116; +pub const YARVINSN_trace_setspecial: ruby_vminsn_type = 117; +pub const YARVINSN_trace_getinstancevariable: ruby_vminsn_type = 118; +pub const YARVINSN_trace_setinstancevariable: ruby_vminsn_type = 119; +pub const YARVINSN_trace_getclassvariable: ruby_vminsn_type = 120; +pub const YARVINSN_trace_setclassvariable: ruby_vminsn_type = 121; +pub const YARVINSN_trace_opt_getconstant_path: ruby_vminsn_type = 122; +pub const YARVINSN_trace_getconstant: ruby_vminsn_type = 123; +pub const YARVINSN_trace_setconstant: ruby_vminsn_type = 124; +pub const YARVINSN_trace_getglobal: ruby_vminsn_type = 125; +pub const YARVINSN_trace_setglobal: ruby_vminsn_type = 126; +pub const YARVINSN_trace_putnil: ruby_vminsn_type = 127; +pub const YARVINSN_trace_putself: ruby_vminsn_type = 128; +pub const YARVINSN_trace_putobject: ruby_vminsn_type = 129; +pub const YARVINSN_trace_putspecialobject: ruby_vminsn_type = 130; +pub const YARVINSN_trace_putstring: ruby_vminsn_type = 131; +pub const YARVINSN_trace_putchilledstring: ruby_vminsn_type = 132; +pub const YARVINSN_trace_concatstrings: ruby_vminsn_type = 133; +pub const YARVINSN_trace_anytostring: ruby_vminsn_type = 134; +pub const YARVINSN_trace_toregexp: ruby_vminsn_type = 135; +pub const YARVINSN_trace_intern: ruby_vminsn_type = 136; +pub const YARVINSN_trace_newarray: ruby_vminsn_type = 137; +pub const YARVINSN_trace_pushtoarraykwsplat: ruby_vminsn_type = 138; +pub const YARVINSN_trace_duparray: ruby_vminsn_type = 139; +pub const YARVINSN_trace_duphash: ruby_vminsn_type = 140; +pub const YARVINSN_trace_expandarray: ruby_vminsn_type = 141; +pub const YARVINSN_trace_concatarray: ruby_vminsn_type = 142; +pub const YARVINSN_trace_concattoarray: ruby_vminsn_type = 143; +pub const YARVINSN_trace_pushtoarray: ruby_vminsn_type = 144; +pub const YARVINSN_trace_splatarray: ruby_vminsn_type = 145; +pub const YARVINSN_trace_splatkw: ruby_vminsn_type = 146; +pub const YARVINSN_trace_newhash: ruby_vminsn_type = 147; +pub const YARVINSN_trace_newrange: ruby_vminsn_type = 148; +pub const YARVINSN_trace_pop: ruby_vminsn_type = 149; +pub const YARVINSN_trace_dup: ruby_vminsn_type = 150; +pub const YARVINSN_trace_dupn: ruby_vminsn_type = 151; +pub const YARVINSN_trace_swap: ruby_vminsn_type = 152; +pub const YARVINSN_trace_opt_reverse: ruby_vminsn_type = 153; +pub const YARVINSN_trace_topn: ruby_vminsn_type = 154; +pub const YARVINSN_trace_setn: ruby_vminsn_type = 155; +pub const YARVINSN_trace_adjuststack: ruby_vminsn_type = 156; +pub const YARVINSN_trace_defined: ruby_vminsn_type = 157; +pub const YARVINSN_trace_definedivar: ruby_vminsn_type = 158; +pub const YARVINSN_trace_checkmatch: ruby_vminsn_type = 159; +pub const YARVINSN_trace_checkkeyword: ruby_vminsn_type = 160; +pub const YARVINSN_trace_checktype: ruby_vminsn_type = 161; +pub const YARVINSN_trace_defineclass: ruby_vminsn_type = 162; +pub const YARVINSN_trace_definemethod: ruby_vminsn_type = 163; +pub const YARVINSN_trace_definesmethod: ruby_vminsn_type = 164; +pub const YARVINSN_trace_send: ruby_vminsn_type = 165; +pub const YARVINSN_trace_sendforward: ruby_vminsn_type = 166; +pub const YARVINSN_trace_opt_send_without_block: ruby_vminsn_type = 167; +pub const YARVINSN_trace_objtostring: ruby_vminsn_type = 168; +pub const YARVINSN_trace_opt_ary_freeze: ruby_vminsn_type = 169; +pub const YARVINSN_trace_opt_hash_freeze: ruby_vminsn_type = 170; +pub const YARVINSN_trace_opt_str_freeze: ruby_vminsn_type = 171; +pub const YARVINSN_trace_opt_nil_p: ruby_vminsn_type = 172; +pub const YARVINSN_trace_opt_str_uminus: ruby_vminsn_type = 173; +pub const YARVINSN_trace_opt_duparray_send: ruby_vminsn_type = 174; +pub const YARVINSN_trace_opt_newarray_send: ruby_vminsn_type = 175; +pub const YARVINSN_trace_invokesuper: ruby_vminsn_type = 176; +pub const YARVINSN_trace_invokesuperforward: ruby_vminsn_type = 177; +pub const YARVINSN_trace_invokeblock: ruby_vminsn_type = 178; +pub const YARVINSN_trace_leave: ruby_vminsn_type = 179; +pub const YARVINSN_trace_throw: ruby_vminsn_type = 180; +pub const YARVINSN_trace_jump: ruby_vminsn_type = 181; +pub const YARVINSN_trace_branchif: ruby_vminsn_type = 182; +pub const YARVINSN_trace_branchunless: ruby_vminsn_type = 183; +pub const YARVINSN_trace_branchnil: ruby_vminsn_type = 184; +pub const YARVINSN_trace_once: ruby_vminsn_type = 185; +pub const YARVINSN_trace_opt_case_dispatch: ruby_vminsn_type = 186; +pub const YARVINSN_trace_opt_plus: ruby_vminsn_type = 187; +pub const YARVINSN_trace_opt_minus: ruby_vminsn_type = 188; +pub const YARVINSN_trace_opt_mult: ruby_vminsn_type = 189; +pub const YARVINSN_trace_opt_div: ruby_vminsn_type = 190; +pub const YARVINSN_trace_opt_mod: ruby_vminsn_type = 191; +pub const YARVINSN_trace_opt_eq: ruby_vminsn_type = 192; +pub const YARVINSN_trace_opt_neq: ruby_vminsn_type = 193; +pub const YARVINSN_trace_opt_lt: ruby_vminsn_type = 194; +pub const YARVINSN_trace_opt_le: ruby_vminsn_type = 195; +pub const YARVINSN_trace_opt_gt: ruby_vminsn_type = 196; +pub const YARVINSN_trace_opt_ge: ruby_vminsn_type = 197; +pub const YARVINSN_trace_opt_ltlt: ruby_vminsn_type = 198; +pub const YARVINSN_trace_opt_and: ruby_vminsn_type = 199; +pub const YARVINSN_trace_opt_or: ruby_vminsn_type = 200; +pub const YARVINSN_trace_opt_aref: ruby_vminsn_type = 201; +pub const YARVINSN_trace_opt_aset: ruby_vminsn_type = 202; +pub const YARVINSN_trace_opt_aset_with: ruby_vminsn_type = 203; +pub const YARVINSN_trace_opt_aref_with: ruby_vminsn_type = 204; +pub const YARVINSN_trace_opt_length: ruby_vminsn_type = 205; +pub const YARVINSN_trace_opt_size: ruby_vminsn_type = 206; +pub const YARVINSN_trace_opt_empty_p: ruby_vminsn_type = 207; +pub const YARVINSN_trace_opt_succ: ruby_vminsn_type = 208; +pub const YARVINSN_trace_opt_not: ruby_vminsn_type = 209; +pub const YARVINSN_trace_opt_regexpmatch2: ruby_vminsn_type = 210; +pub const YARVINSN_trace_invokebuiltin: ruby_vminsn_type = 211; +pub const YARVINSN_trace_opt_invokebuiltin_delegate: ruby_vminsn_type = 212; +pub const YARVINSN_trace_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 213; +pub const YARVINSN_trace_getlocal_WC_0: ruby_vminsn_type = 214; +pub const YARVINSN_trace_getlocal_WC_1: ruby_vminsn_type = 215; +pub const YARVINSN_trace_setlocal_WC_0: ruby_vminsn_type = 216; +pub const YARVINSN_trace_setlocal_WC_1: ruby_vminsn_type = 217; +pub const YARVINSN_trace_putobject_INT2FIX_0_: ruby_vminsn_type = 218; +pub const YARVINSN_trace_putobject_INT2FIX_1_: ruby_vminsn_type = 219; +pub const VM_INSTRUCTION_SIZE: ruby_vminsn_type = 220; +pub type ruby_vminsn_type = u32; +pub type rb_iseq_callback = ::std::option::Option< + unsafe extern "C" fn(arg1: *const rb_iseq_t, arg2: *mut ::std::os::raw::c_void), +>; +pub const DEFINED_NOT_DEFINED: defined_type = 0; +pub const DEFINED_NIL: defined_type = 1; +pub const DEFINED_IVAR: defined_type = 2; +pub const DEFINED_LVAR: defined_type = 3; +pub const DEFINED_GVAR: defined_type = 4; +pub const DEFINED_CVAR: defined_type = 5; +pub const DEFINED_CONST: defined_type = 6; +pub const DEFINED_METHOD: defined_type = 7; +pub const DEFINED_YIELD: defined_type = 8; +pub const DEFINED_ZSUPER: defined_type = 9; +pub const DEFINED_SELF: defined_type = 10; +pub const DEFINED_TRUE: defined_type = 11; +pub const DEFINED_FALSE: defined_type = 12; +pub const DEFINED_ASGN: defined_type = 13; +pub const DEFINED_EXPR: defined_type = 14; +pub const DEFINED_REF: defined_type = 15; +pub const DEFINED_FUNC: defined_type = 16; +pub const DEFINED_CONST_FROM: defined_type = 17; +pub type defined_type = u32; +pub const ROBJECT_OFFSET_AS_HEAP_IVPTR: robject_offsets = 16; +pub const ROBJECT_OFFSET_AS_HEAP_IV_INDEX_TBL: robject_offsets = 24; +pub const ROBJECT_OFFSET_AS_ARY: robject_offsets = 16; +pub type robject_offsets = u32; +pub const RUBY_OFFSET_RSTRING_LEN: rstring_offsets = 16; +pub type rstring_offsets = u32; +pub type rb_seq_param_keyword_struct = rb_iseq_constant_body__bindgen_ty_1_rb_iseq_param_keyword; +extern "C" { + pub fn ruby_xfree(ptr: *mut ::std::os::raw::c_void); + pub fn rb_class_attached_object(klass: VALUE) -> VALUE; + pub fn rb_singleton_class(obj: VALUE) -> VALUE; + pub fn rb_get_alloc_func(klass: VALUE) -> rb_alloc_func_t; + pub fn rb_method_basic_definition_p(klass: VALUE, mid: ID) -> ::std::os::raw::c_int; + pub fn rb_bug(fmt: *const ::std::os::raw::c_char, ...) -> !; + pub fn rb_float_new(d: f64) -> VALUE; + pub fn rb_gc_mark(obj: VALUE); + pub fn rb_gc_mark_movable(obj: VALUE); + pub fn rb_gc_location(obj: VALUE) -> VALUE; + pub fn rb_gc_writebarrier(old: VALUE, young: VALUE); + pub fn rb_class_get_superclass(klass: VALUE) -> VALUE; + pub static mut rb_mKernel: VALUE; + pub static mut rb_cBasicObject: VALUE; + pub static mut rb_cArray: VALUE; + pub static mut rb_cClass: VALUE; + pub static mut rb_cFalseClass: VALUE; + pub static mut rb_cFloat: VALUE; + pub static mut rb_cHash: VALUE; + pub static mut rb_cIO: VALUE; + pub static mut rb_cInteger: VALUE; + pub static mut rb_cModule: VALUE; + pub static mut rb_cNilClass: VALUE; + pub static mut rb_cNumeric: VALUE; + pub static mut rb_cString: VALUE; + pub static mut rb_cSymbol: VALUE; + pub static mut rb_cThread: VALUE; + pub static mut rb_cTrueClass: VALUE; + pub fn rb_obj_class(obj: VALUE) -> VALUE; + pub fn rb_ary_new_capa(capa: ::std::os::raw::c_long) -> VALUE; + pub fn rb_ary_store(ary: VALUE, key: ::std::os::raw::c_long, val: VALUE); + pub fn rb_ary_dup(ary: VALUE) -> VALUE; + pub fn rb_ary_resurrect(ary: VALUE) -> VALUE; + pub fn rb_ary_cat(ary: VALUE, train: *const VALUE, len: ::std::os::raw::c_long) -> VALUE; + pub fn rb_ary_push(ary: VALUE, elem: VALUE) -> VALUE; + pub fn rb_ary_clear(ary: VALUE) -> VALUE; + pub fn rb_hash_new() -> VALUE; + pub fn rb_hash_aref(hash: VALUE, key: VALUE) -> VALUE; + pub fn rb_hash_aset(hash: VALUE, key: VALUE, val: VALUE) -> VALUE; + pub fn rb_hash_bulk_insert(argc: ::std::os::raw::c_long, argv: *const VALUE, hash: VALUE); + pub fn rb_obj_is_proc(recv: VALUE) -> VALUE; + pub fn rb_sym2id(obj: VALUE) -> ID; + pub fn rb_id2sym(id: ID) -> VALUE; + pub fn rb_intern(name: *const ::std::os::raw::c_char) -> ID; + pub fn rb_intern2(name: *const ::std::os::raw::c_char, len: ::std::os::raw::c_long) -> ID; + pub fn rb_id2name(id: ID) -> *const ::std::os::raw::c_char; + pub fn rb_class2name(klass: VALUE) -> *const ::std::os::raw::c_char; + pub fn rb_obj_is_kind_of(obj: VALUE, klass: VALUE) -> VALUE; + pub fn rb_obj_frozen_p(obj: VALUE) -> VALUE; + pub fn rb_backref_get() -> VALUE; + pub fn rb_range_new(beg: VALUE, end: VALUE, excl: ::std::os::raw::c_int) -> VALUE; + pub fn rb_reg_nth_match(n: ::std::os::raw::c_int, md: VALUE) -> VALUE; + pub fn rb_reg_last_match(md: VALUE) -> VALUE; + pub fn rb_reg_match_pre(md: VALUE) -> VALUE; + pub fn rb_reg_match_post(md: VALUE) -> VALUE; + pub fn rb_reg_match_last(md: VALUE) -> VALUE; + pub fn rb_utf8_str_new( + ptr: *const ::std::os::raw::c_char, + len: ::std::os::raw::c_long, + ) -> VALUE; + pub fn rb_str_buf_append(dst: VALUE, src: VALUE) -> VALUE; + pub fn rb_str_dup(str_: VALUE) -> VALUE; + pub fn rb_str_intern(str_: VALUE) -> VALUE; + pub fn rb_mod_name(mod_: VALUE) -> VALUE; + pub fn rb_ivar_get(obj: VALUE, name: ID) -> VALUE; + pub fn rb_ivar_defined(obj: VALUE, name: ID) -> VALUE; + pub fn rb_attr_get(obj: VALUE, name: ID) -> VALUE; + pub fn rb_obj_info_dump(obj: VALUE); + pub fn rb_class_allocate_instance(klass: VALUE) -> VALUE; + pub fn rb_obj_equal(obj1: VALUE, obj2: VALUE) -> VALUE; + pub fn rb_reg_new_ary(ary: VALUE, options: ::std::os::raw::c_int) -> VALUE; + pub fn rb_ary_tmp_new_from_values( + arg1: VALUE, + arg2: ::std::os::raw::c_long, + arg3: *const VALUE, + ) -> VALUE; + pub fn rb_ec_ary_new_from_values( + ec: *mut rb_execution_context_struct, + n: ::std::os::raw::c_long, + elts: *const VALUE, + ) -> VALUE; + pub fn rb_vm_top_self() -> VALUE; + pub fn rb_method_entry_at(obj: VALUE, id: ID) -> *const rb_method_entry_t; + pub fn rb_callable_method_entry(klass: VALUE, id: ID) -> *const rb_callable_method_entry_t; + pub fn rb_callable_method_entry_or_negative( + klass: VALUE, + id: ID, + ) -> *const rb_callable_method_entry_t; + pub static mut rb_mRubyVMFrozenCore: VALUE; + pub static mut rb_block_param_proxy: VALUE; + pub fn rb_vm_ep_local_ep(ep: *const VALUE) -> *const VALUE; + pub fn rb_iseq_path(iseq: *const rb_iseq_t) -> VALUE; + pub fn rb_vm_env_write(ep: *const VALUE, index: ::std::os::raw::c_int, v: VALUE); + pub fn rb_vm_bh_to_procval(ec: *const rb_execution_context_t, block_handler: VALUE) -> VALUE; + pub fn rb_vm_frame_method_entry( + cfp: *const rb_control_frame_t, + ) -> *const rb_callable_method_entry_t; + pub fn rb_obj_info(obj: VALUE) -> *const ::std::os::raw::c_char; + pub fn rb_ec_stack_check(ec: *mut rb_execution_context_struct) -> ::std::os::raw::c_int; + pub fn rb_shape_id_offset() -> i32; + pub fn rb_shape_get_shape_by_id(shape_id: shape_id_t) -> *mut rb_shape_t; + pub fn rb_shape_get_shape_id(obj: VALUE) -> shape_id_t; + pub fn rb_shape_get_iv_index(shape: *mut rb_shape_t, id: ID, value: *mut attr_index_t) -> bool; + pub fn rb_shape_obj_too_complex(obj: VALUE) -> bool; + pub fn rb_shape_get_next_no_warnings( + shape: *mut rb_shape_t, + obj: VALUE, + id: ID, + ) -> *mut rb_shape_t; + pub fn rb_shape_id(shape: *mut rb_shape_t) -> shape_id_t; + pub fn rb_gvar_get(arg1: ID) -> VALUE; + pub fn rb_gvar_set(arg1: ID, arg2: VALUE) -> VALUE; + pub fn rb_ensure_iv_list_size(obj: VALUE, len: u32, newsize: u32); + pub fn rb_vm_barrier(); + pub fn rb_str_byte_substr(str_: VALUE, beg: VALUE, len: VALUE) -> VALUE; + pub fn rb_str_substr_two_fixnums( + str_: VALUE, + beg: VALUE, + len: VALUE, + empty: ::std::os::raw::c_int, + ) -> VALUE; + pub fn rb_obj_as_string_result(str_: VALUE, obj: VALUE) -> VALUE; + pub fn rb_str_concat_literals(num: usize, strary: *const VALUE) -> VALUE; + pub fn rb_ec_str_resurrect( + ec: *mut rb_execution_context_struct, + str_: VALUE, + chilled: bool, + ) -> VALUE; + pub fn rb_to_hash_type(obj: VALUE) -> VALUE; + pub fn rb_hash_stlike_foreach( + hash: VALUE, + func: st_foreach_callback_func, + arg: st_data_t, + ) -> ::std::os::raw::c_int; + pub fn rb_hash_new_with_size(size: st_index_t) -> VALUE; + pub fn rb_hash_resurrect(hash: VALUE) -> VALUE; + pub fn rb_hash_stlike_lookup( + hash: VALUE, + key: st_data_t, + pval: *mut st_data_t, + ) -> ::std::os::raw::c_int; + pub fn rb_insn_len(insn: VALUE) -> ::std::os::raw::c_int; + pub fn rb_vm_insn_decode(encoded: VALUE) -> ::std::os::raw::c_int; + pub fn rb_float_plus(x: VALUE, y: VALUE) -> VALUE; + pub fn rb_float_minus(x: VALUE, y: VALUE) -> VALUE; + pub fn rb_float_mul(x: VALUE, y: VALUE) -> VALUE; + pub fn rb_float_div(x: VALUE, y: VALUE) -> VALUE; + pub fn rb_fix_aref(fix: VALUE, idx: VALUE) -> VALUE; + pub fn rb_vm_insn_addr2opcode(addr: *const ::std::os::raw::c_void) -> ::std::os::raw::c_int; + pub fn rb_iseq_line_no(iseq: *const rb_iseq_t, pos: usize) -> ::std::os::raw::c_uint; + pub fn rb_iseqw_to_iseq(iseqw: VALUE) -> *const rb_iseq_t; + pub fn rb_iseq_label(iseq: *const rb_iseq_t) -> VALUE; + pub fn rb_profile_frames( + start: ::std::os::raw::c_int, + limit: ::std::os::raw::c_int, + buff: *mut VALUE, + lines: *mut ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; + pub fn rb_jit_cont_each_iseq(callback: rb_iseq_callback, data: *mut ::std::os::raw::c_void); + pub fn rb_yjit_mark_writable(mem_block: *mut ::std::os::raw::c_void, mem_size: u32) -> bool; + pub fn rb_yjit_mark_executable(mem_block: *mut ::std::os::raw::c_void, mem_size: u32); + pub fn rb_yjit_vm_insns_count() -> u64; + pub fn rb_yjit_mark_unused(mem_block: *mut ::std::os::raw::c_void, mem_size: u32) -> bool; + pub fn rb_yjit_array_len(a: VALUE) -> ::std::os::raw::c_long; + pub fn rb_yjit_icache_invalidate( + start: *mut ::std::os::raw::c_void, + end: *mut ::std::os::raw::c_void, + ); + pub fn rb_yjit_exit_locations_dict( + yjit_raw_samples: *mut VALUE, + yjit_line_samples: *mut ::std::os::raw::c_int, + samples_len: ::std::os::raw::c_int, + ) -> VALUE; + pub fn rb_yjit_get_page_size() -> u32; + pub fn rb_yjit_reserve_addr_space(mem_size: u32) -> *mut u8; + pub fn rb_c_method_tracing_currently_enabled(ec: *const rb_execution_context_t) -> bool; + pub fn rb_full_cfunc_return(ec: *mut rb_execution_context_t, return_value: VALUE); + pub fn rb_iseq_encoded_size(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; + pub fn rb_iseq_get_yjit_payload(iseq: *const rb_iseq_t) -> *mut ::std::os::raw::c_void; + pub fn rb_iseq_set_yjit_payload(iseq: *const rb_iseq_t, payload: *mut ::std::os::raw::c_void); + pub fn rb_iseq_reset_jit_func(iseq: *const rb_iseq_t); + pub fn rb_iseq_pc_at_idx(iseq: *const rb_iseq_t, insn_idx: u32) -> *mut VALUE; + pub fn rb_iseq_opcode_at_pc(iseq: *const rb_iseq_t, pc: *const VALUE) -> ::std::os::raw::c_int; + pub fn rb_RSTRING_LEN(str_: VALUE) -> ::std::os::raw::c_ulong; + pub fn rb_RSTRING_PTR(str_: VALUE) -> *mut ::std::os::raw::c_char; + pub fn rb_yjit_get_proc_ptr(procv: VALUE) -> *mut rb_proc_t; + pub fn rb_insn_name(insn: VALUE) -> *const ::std::os::raw::c_char; + pub fn rb_vm_ci_argc(ci: *const rb_callinfo) -> ::std::os::raw::c_uint; + pub fn rb_vm_ci_mid(ci: *const rb_callinfo) -> ID; + pub fn rb_vm_ci_flag(ci: *const rb_callinfo) -> ::std::os::raw::c_uint; + pub fn rb_vm_ci_kwarg(ci: *const rb_callinfo) -> *const rb_callinfo_kwarg; + pub fn rb_get_cikw_keyword_len(cikw: *const rb_callinfo_kwarg) -> ::std::os::raw::c_int; + pub fn rb_get_cikw_keywords_idx( + cikw: *const rb_callinfo_kwarg, + idx: ::std::os::raw::c_int, + ) -> VALUE; + pub fn rb_METHOD_ENTRY_VISI(me: *const rb_callable_method_entry_t) -> rb_method_visibility_t; + pub fn rb_get_cme_def_type(cme: *const rb_callable_method_entry_t) -> rb_method_type_t; + pub fn rb_get_cme_def_body_attr_id(cme: *const rb_callable_method_entry_t) -> ID; + pub fn rb_get_symbol_id(namep: VALUE) -> ID; + pub fn rb_get_cme_def_body_optimized_type( + cme: *const rb_callable_method_entry_t, + ) -> method_optimized_type; + pub fn rb_get_cme_def_body_optimized_index( + cme: *const rb_callable_method_entry_t, + ) -> ::std::os::raw::c_uint; + pub fn rb_get_cme_def_body_cfunc( + cme: *const rb_callable_method_entry_t, + ) -> *mut rb_method_cfunc_t; + pub fn rb_get_def_method_serial(def: *const rb_method_definition_t) -> usize; + pub fn rb_get_def_original_id(def: *const rb_method_definition_t) -> ID; + pub fn rb_get_mct_argc(mct: *const rb_method_cfunc_t) -> ::std::os::raw::c_int; + pub fn rb_get_mct_func(mct: *const rb_method_cfunc_t) -> *mut ::std::os::raw::c_void; + pub fn rb_get_def_iseq_ptr(def: *mut rb_method_definition_t) -> *const rb_iseq_t; + pub fn rb_get_def_bmethod_proc(def: *mut rb_method_definition_t) -> VALUE; + pub fn rb_get_iseq_body_local_iseq(iseq: *const rb_iseq_t) -> *const rb_iseq_t; + pub fn rb_get_iseq_body_parent_iseq(iseq: *const rb_iseq_t) -> *const rb_iseq_t; + pub fn rb_get_iseq_body_local_table_size(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; + pub fn rb_get_iseq_body_iseq_encoded(iseq: *const rb_iseq_t) -> *mut VALUE; + pub fn rb_get_iseq_body_stack_max(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; + pub fn rb_get_iseq_body_type(iseq: *const rb_iseq_t) -> rb_iseq_type; + pub fn rb_get_iseq_flags_has_lead(iseq: *const rb_iseq_t) -> bool; + pub fn rb_get_iseq_flags_has_opt(iseq: *const rb_iseq_t) -> bool; + pub fn rb_get_iseq_flags_has_kw(iseq: *const rb_iseq_t) -> bool; + pub fn rb_get_iseq_flags_has_post(iseq: *const rb_iseq_t) -> bool; + pub fn rb_get_iseq_flags_has_kwrest(iseq: *const rb_iseq_t) -> bool; + pub fn rb_get_iseq_flags_anon_kwrest(iseq: *const rb_iseq_t) -> bool; + pub fn rb_get_iseq_flags_has_rest(iseq: *const rb_iseq_t) -> bool; + pub fn rb_get_iseq_flags_ruby2_keywords(iseq: *const rb_iseq_t) -> bool; + pub fn rb_get_iseq_flags_has_block(iseq: *const rb_iseq_t) -> bool; + pub fn rb_get_iseq_flags_ambiguous_param0(iseq: *const rb_iseq_t) -> bool; + pub fn rb_get_iseq_flags_accepts_no_kwarg(iseq: *const rb_iseq_t) -> bool; + pub fn rb_get_iseq_flags_forwardable(iseq: *const rb_iseq_t) -> bool; + pub fn rb_get_iseq_body_param_keyword( + iseq: *const rb_iseq_t, + ) -> *const rb_seq_param_keyword_struct; + pub fn rb_get_iseq_body_param_size(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; + pub fn rb_get_iseq_body_param_lead_num(iseq: *const rb_iseq_t) -> ::std::os::raw::c_int; + pub fn rb_get_iseq_body_param_opt_num(iseq: *const rb_iseq_t) -> ::std::os::raw::c_int; + pub fn rb_get_iseq_body_param_opt_table(iseq: *const rb_iseq_t) -> *const VALUE; + pub fn rb_optimized_call( + recv: *mut VALUE, + ec: *mut rb_execution_context_t, + argc: ::std::os::raw::c_int, + argv: *mut VALUE, + kw_splat: ::std::os::raw::c_int, + block_handler: VALUE, + ) -> VALUE; + pub fn rb_yjit_iseq_builtin_attrs(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; + pub fn rb_yjit_builtin_function(iseq: *const rb_iseq_t) -> *const rb_builtin_function; + pub fn rb_yjit_str_simple_append(str1: VALUE, str2: VALUE) -> VALUE; + pub fn rb_get_ec_cfp(ec: *const rb_execution_context_t) -> *mut rb_control_frame_struct; + pub fn rb_get_cfp_iseq(cfp: *mut rb_control_frame_struct) -> *const rb_iseq_t; + pub fn rb_get_cfp_pc(cfp: *mut rb_control_frame_struct) -> *mut VALUE; + pub fn rb_get_cfp_sp(cfp: *mut rb_control_frame_struct) -> *mut VALUE; + pub fn rb_set_cfp_pc(cfp: *mut rb_control_frame_struct, pc: *const VALUE); + pub fn rb_set_cfp_sp(cfp: *mut rb_control_frame_struct, sp: *mut VALUE); + pub fn rb_get_cfp_self(cfp: *mut rb_control_frame_struct) -> VALUE; + pub fn rb_get_cfp_ep(cfp: *mut rb_control_frame_struct) -> *mut VALUE; + pub fn rb_get_cfp_ep_level(cfp: *mut rb_control_frame_struct, lv: u32) -> *const VALUE; + pub fn rb_vm_base_ptr(cfp: *mut rb_control_frame_struct) -> *mut VALUE; + pub fn rb_yarv_class_of(obj: VALUE) -> VALUE; + pub fn rb_yarv_str_eql_internal(str1: VALUE, str2: VALUE) -> VALUE; + pub fn rb_str_neq_internal(str1: VALUE, str2: VALUE) -> VALUE; + pub fn rb_yarv_ary_entry_internal(ary: VALUE, offset: ::std::os::raw::c_long) -> VALUE; + pub fn rb_ary_unshift_m(argc: ::std::os::raw::c_int, argv: *mut VALUE, ary: VALUE) -> VALUE; + pub fn rb_yjit_rb_ary_subseq_length(ary: VALUE, beg: ::std::os::raw::c_long) -> VALUE; + pub fn rb_yjit_fix_div_fix(recv: VALUE, obj: VALUE) -> VALUE; + pub fn rb_yjit_fix_mod_fix(recv: VALUE, obj: VALUE) -> VALUE; + pub fn rb_yjit_ruby2_keywords_splat_p(obj: VALUE) -> usize; + pub fn rb_yjit_splat_varg_checks( + sp: *mut VALUE, + splat_array: VALUE, + cfp: *mut rb_control_frame_t, + ) -> VALUE; + pub fn rb_yjit_splat_varg_cfunc(stack_splat_array: *mut VALUE) -> ::std::os::raw::c_int; + pub fn rb_yjit_dump_iseq_loc(iseq: *const rb_iseq_t, insn_idx: u32); + pub fn rb_yjit_iseq_inspect(iseq: *const rb_iseq_t) -> *mut ::std::os::raw::c_char; + pub fn rb_FL_TEST(obj: VALUE, flags: VALUE) -> VALUE; + pub fn rb_FL_TEST_RAW(obj: VALUE, flags: VALUE) -> VALUE; + pub fn rb_RB_TYPE_P(obj: VALUE, t: ruby_value_type) -> bool; + pub fn rb_RSTRUCT_LEN(st: VALUE) -> ::std::os::raw::c_long; + pub fn rb_RSTRUCT_SET(st: VALUE, k: ::std::os::raw::c_int, v: VALUE); + pub fn rb_get_call_data_ci(cd: *const rb_call_data) -> *const rb_callinfo; + pub fn rb_BASIC_OP_UNREDEFINED_P(bop: ruby_basic_operators, klass: u32) -> bool; + pub fn rb_RCLASS_ORIGIN(c: VALUE) -> VALUE; + pub fn rb_ENCODING_GET(obj: VALUE) -> ::std::os::raw::c_int; + pub fn rb_yjit_multi_ractor_p() -> bool; + pub fn rb_assert_iseq_handle(handle: VALUE); + pub fn rb_IMEMO_TYPE_P(imemo: VALUE, imemo_type: imemo_type) -> ::std::os::raw::c_int; + pub fn rb_yjit_constcache_shareable(ice: *const iseq_inline_constant_cache_entry) -> bool; + pub fn rb_assert_cme_handle(handle: VALUE); + pub fn rb_yjit_for_each_iseq(callback: rb_iseq_callback, data: *mut ::std::os::raw::c_void); + pub fn rb_yjit_obj_written( + old: VALUE, + young: VALUE, + file: *const ::std::os::raw::c_char, + line: ::std::os::raw::c_int, + ); + pub fn rb_yjit_vm_lock_then_barrier( + recursive_lock_level: *mut ::std::os::raw::c_uint, + file: *const ::std::os::raw::c_char, + line: ::std::os::raw::c_int, + ); + pub fn rb_yjit_vm_unlock( + recursive_lock_level: *mut ::std::os::raw::c_uint, + file: *const ::std::os::raw::c_char, + line: ::std::os::raw::c_int, + ); + pub fn rb_object_shape_count() -> VALUE; + pub fn rb_yjit_assert_holding_vm_lock(); + pub fn rb_yjit_sendish_sp_pops(ci: *const rb_callinfo) -> usize; + pub fn rb_yjit_invokeblock_sp_pops(ci: *const rb_callinfo) -> usize; + pub fn rb_yjit_set_exception_return( + cfp: *mut rb_control_frame_t, + leave_exit: *mut ::std::os::raw::c_void, + leave_exception: *mut ::std::os::raw::c_void, + ); +} diff --git a/zjit/src/main.rs b/zjit/src/main.rs index e4fe75d2da..89774abe85 100644 --- a/zjit/src/main.rs +++ b/zjit/src/main.rs @@ -1,3 +1,5 @@ +mod cruby; + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct InsnId(usize); #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]