summaryrefslogtreecommitdiff
path: root/zjit/src/codegen.rs
diff options
context:
space:
mode:
Diffstat (limited to 'zjit/src/codegen.rs')
-rw-r--r--zjit/src/codegen.rs21
1 files changed, 21 insertions, 0 deletions
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs
index b1869f71c0..90c3ce640e 100644
--- a/zjit/src/codegen.rs
+++ b/zjit/src/codegen.rs
@@ -260,6 +260,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
Insn::IfFalse { val, target } => return gen_if_false(jit, asm, opnd!(val), target),
Insn::SendWithoutBlock { call_info, cd, state, self_val, args, .. } => gen_send_without_block(jit, asm, call_info, *cd, &function.frame_state(*state), self_val, args)?,
Insn::SendWithoutBlockDirect { cme, iseq, self_val, args, state, .. } => gen_send_without_block_direct(cb, jit, asm, *cme, *iseq, opnd!(self_val), args, &function.frame_state(*state))?,
+ Insn::InvokeBuiltin { bf, args, state } => gen_invokebuiltin(jit, asm, &function.frame_state(*state), bf, args)?,
Insn::Return { val } => return Some(gen_return(asm, opnd!(val))?),
Insn::FixnumAdd { left, right, state } => gen_fixnum_add(jit, asm, opnd!(left), opnd!(right), &function.frame_state(*state))?,
Insn::FixnumSub { left, right, state } => gen_fixnum_sub(jit, asm, opnd!(left), opnd!(right), &function.frame_state(*state))?,
@@ -311,6 +312,26 @@ fn gen_get_constant_path(asm: &mut Assembler, ic: *const iseq_inline_constant_ca
val
}
+fn gen_invokebuiltin(jit: &mut JITState, asm: &mut Assembler, state: &FrameState, bf: &rb_builtin_function, args: &Vec<InsnId>) -> Option<lir::Opnd> {
+ // Ensure we have enough room fit ec, self, and arguments
+ // TODO remove this check when we have stack args (we can use Time.new to test it)
+ if bf.argc + 2 > (C_ARG_OPNDS.len() as i32) {
+ return None;
+ }
+
+ gen_save_pc(asm, state);
+
+ let mut cargs = vec![EC];
+ for &arg in args.iter() {
+ let opnd = jit.get_opnd(arg)?;
+ cargs.push(opnd);
+ }
+
+ let val = asm.ccall(bf.func_ptr as *const u8, cargs);
+
+ Some(val)
+}
+
/// Lowering for [`Insn::CCall`]. This is a low-level raw call that doesn't know
/// anything about the callee, so handling for e.g. GC safety is dealt with elsewhere.
fn gen_ccall(jit: &mut JITState, asm: &mut Assembler, cfun: *const u8, args: &[InsnId]) -> Option<lir::Opnd> {