diff options
author | Takashi Kokubun <[email protected]> | 2023-02-10 22:07:34 -0800 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2023-03-05 23:28:59 -0800 |
commit | 39b787448126d9c6363bb5d8ce5e82ffef6a1c22 (patch) | |
tree | b9a52c3e0c0b9c740d94f911c6e8c2387e21126d /lib | |
parent | e111d3ae8d3d88e1435e2a28adb1a7ed7277f70a (diff) |
Implement variadic C func calls
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/7448
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ruby_vm/mjit/assembler.rb | 5 | ||||
-rw-r--r-- | lib/ruby_vm/mjit/exit_compiler.rb | 10 | ||||
-rw-r--r-- | lib/ruby_vm/mjit/insn_compiler.rb | 24 |
3 files changed, 21 insertions, 18 deletions
diff --git a/lib/ruby_vm/mjit/assembler.rb b/lib/ruby_vm/mjit/assembler.rb index e50cbdf600..ad197fbc14 100644 --- a/lib/ruby_vm/mjit/assembler.rb +++ b/lib/ruby_vm/mjit/assembler.rb @@ -3,8 +3,9 @@ module RubyVM::MJIT # 32-bit memory access class DwordPtr < Data.define(:reg, :disp); end - # C call argument registers - C_ARG_OPNDS = [:rdi, :rsi, :rdx, :rcx, :r8, :r9] + # SystemV x64 calling convention + C_ARGS = [:rdi, :rsi, :rdx, :rcx, :r8, :r9] + C_RET = :rax # https://www.intel.com/content/dam/develop/public/us/en/documents/325383-sdm-vol-2abcd.pdf # Mostly an x86_64 assembler, but this also has some stuff that is useful for any architecture. diff --git a/lib/ruby_vm/mjit/exit_compiler.rb b/lib/ruby_vm/mjit/exit_compiler.rb index 6d3a0406a7..20645fdb9e 100644 --- a/lib/ruby_vm/mjit/exit_compiler.rb +++ b/lib/ruby_vm/mjit/exit_compiler.rb @@ -20,7 +20,7 @@ module RubyVM::MJIT asm.pop(EC) asm.pop(CFP) - asm.mov(:rax, Qundef) + asm.mov(C_RET, Qundef) asm.ret end @@ -45,8 +45,8 @@ module RubyVM::MJIT # RAX to contain the return value of the C method. asm.comment('full cfunc return') - asm.mov(C_ARG_OPNDS[0], EC) - asm.mov(C_ARG_OPNDS[1], :rax) + asm.mov(C_ARGS[0], EC) + asm.mov(C_ARGS[1], :rax) asm.call(C.rb_full_cfunc_return) # TODO: count the exit @@ -56,7 +56,7 @@ module RubyVM::MJIT asm.pop(EC) asm.pop(CFP) - asm.mov(:rax, Qundef) + asm.mov(C_RET, Qundef) asm.ret end @@ -76,7 +76,7 @@ module RubyVM::MJIT asm.pop(EC) asm.pop(CFP) - asm.mov(:rax, Qundef) + asm.mov(C_RET, Qundef) asm.ret end diff --git a/lib/ruby_vm/mjit/insn_compiler.rb b/lib/ruby_vm/mjit/insn_compiler.rb index e868534200..2ae537d9f6 100644 --- a/lib/ruby_vm/mjit/insn_compiler.rb +++ b/lib/ruby_vm/mjit/insn_compiler.rb @@ -632,7 +632,7 @@ module RubyVM::MJIT ctx.stack_pop(2) stack_ret = ctx.stack_push - asm.mov(stack_ret, :rax) + asm.mov(stack_ret, C_RET) # Let guard chains share the same successor jump_to_next_insn(jit, ctx, asm) @@ -1170,11 +1170,6 @@ module RubyVM::MJIT def jit_call_cfunc_with_frame(jit, ctx, asm, ci, cme, flags, argc) cfunc = cme.def.body.cfunc - # TODO: support them - if cfunc.argc < 0 - asm.incr_counter(:send_cfunc_variadic) - return CantCompile - end if argc + 1 > 6 asm.incr_counter(:send_cfunc_too_many_args) return CantCompile @@ -1192,7 +1187,7 @@ module RubyVM::MJIT end # rb_check_arity - if argc != cfunc.argc + if cfunc.argc >= 0 && argc != cfunc.argc asm.incr_counter(:send_arity) return CantCompile end @@ -1211,9 +1206,16 @@ module RubyVM::MJIT jit_push_frame(jit, ctx, asm, ci, cme, flags, argc, frame_type) asm.comment('call C function') - # Push receiver and args - (1 + argc).times do |i| - asm.mov(C_ARG_OPNDS[i], ctx.stack_opnd(argc - i)) # TODO: +1 for VM_CALL_ARGS_BLOCKARG + case cfunc.argc + in (0..) # Non-variadic method + # Push receiver and args + (1 + argc).times do |i| + asm.mov(C_ARGS[i], ctx.stack_opnd(argc - i)) # TODO: +1 for VM_CALL_ARGS_BLOCKARG + end + in -1 # Variadic method: rb_f_puts(int argc, VALUE *argv, VALUE recv) + asm.mov(C_ARGS[0], argc) + asm.lea(C_ARGS[1], ctx.stack_opnd(argc - 1)) # argv + asm.mov(C_ARGS[2], ctx.stack_opnd(argc)) # recv end asm.mov(:rax, cfunc.func) asm.call(:rax) # TODO: use rel32 if close enough @@ -1223,7 +1225,7 @@ module RubyVM::MJIT asm.comment('push the return value') stack_ret = ctx.stack_push - asm.mov(stack_ret, :rax) + asm.mov(stack_ret, C_RET) asm.comment('pop the stack frame') asm.mov([EC, C.rb_execution_context_t.offsetof(:cfp)], CFP) |