mirror of
https://github.com/ruby/ruby.git
synced 2025-08-25 22:14:37 +02:00
Compile putnil properly
This commit is contained in:
parent
8deb0438c4
commit
145c937f3f
3 changed files with 65 additions and 37 deletions
|
@ -1,14 +1,21 @@
|
|||
module RubyVM::MJIT
|
||||
# ec: rdi
|
||||
# cfp: rsi
|
||||
# sp: rbx
|
||||
# scratch regs: rax
|
||||
class InsnCompiler
|
||||
def putnil(_asm)
|
||||
# TODO
|
||||
# Ruby constants
|
||||
Qnil = Fiddle::Qnil
|
||||
|
||||
def putnil(asm)
|
||||
asm.mov([:rbx], Qnil)
|
||||
KeepCompiling
|
||||
end
|
||||
|
||||
def leave(asm)
|
||||
# pop the current frame (ec->cfp++)
|
||||
asm.add(:rsi, C.rb_control_frame_t.size)
|
||||
asm.mov([:rdi, C.rb_execution_context_t.offsetof(:cfp)], :rsi)
|
||||
asm.add(:rsi, C.rb_control_frame_t.size) # rsi = cfp + 1
|
||||
asm.mov([:rdi, C.rb_execution_context_t.offsetof(:cfp)], :rsi) # ec->cfp = rsi
|
||||
|
||||
# return a value
|
||||
asm.mov(:rax, 1001)
|
||||
|
|
|
@ -43,14 +43,24 @@ module RubyVM::MJIT
|
|||
|
||||
def mov(dst, src)
|
||||
case [dst, src]
|
||||
# MOV r/m64, imm32
|
||||
# MOV r/m64, imm32 (Mod 00)
|
||||
in [[Symbol => dst_reg], Integer => src_imm] if r_reg?(dst_reg)
|
||||
# REX.W + C7 /0 id
|
||||
# MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64
|
||||
insn(
|
||||
prefix: REX_W,
|
||||
opcode: 0xc7,
|
||||
mod_rm: mod_rm(mod: 0b00, rm: reg_code(dst_reg)), # Mod 00: [reg]
|
||||
imm: imm32(src_imm),
|
||||
)
|
||||
# MOV r/m64, imm32 (Mod 11)
|
||||
in [Symbol => dst_reg, Integer => src_imm] if r_reg?(dst_reg)
|
||||
# REX.W + C7 /0 id
|
||||
# MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64
|
||||
insn(
|
||||
prefix: REX_W,
|
||||
opcode: 0xc7,
|
||||
mod_rm: mod_rm(mod: 0b11, rm: reg_code(dst_reg)),
|
||||
mod_rm: mod_rm(mod: 0b11, rm: reg_code(dst_reg)), # Mod 11: reg
|
||||
imm: imm32(src_imm),
|
||||
)
|
||||
# MOV r/m64, r64
|
||||
|
@ -60,9 +70,19 @@ module RubyVM::MJIT
|
|||
insn(
|
||||
prefix: REX_W,
|
||||
opcode: 0x89,
|
||||
mod_rm: mod_rm(mod: 0b01, reg: reg_code(src_reg), rm: reg_code(dst_reg)), # disp8
|
||||
mod_rm: mod_rm(mod: 0b01, reg: reg_code(src_reg), rm: reg_code(dst_reg)), # Mod 01: [reg]+disp8
|
||||
disp: dst_offset,
|
||||
)
|
||||
# MOV r64, r/m64
|
||||
in [Symbol => dst_reg, [Symbol => src_reg, Integer => src_offset]] if r_reg?(dst_reg) && r_reg?(src_reg) && src_offset <= 0xff
|
||||
# REX.W + 8B /r
|
||||
# RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
|
||||
insn(
|
||||
prefix: REX_W,
|
||||
opcode: 0x8b,
|
||||
mod_rm: mod_rm(mod: 0b01, reg: reg_code(dst_reg), rm: reg_code(src_reg)), # Mod 01: [reg]+disp8
|
||||
disp: src_offset,
|
||||
)
|
||||
else
|
||||
raise NotImplementedError, "mov: not-implemented input: #{dst.inspect}, #{src.inspect}"
|
||||
end
|
||||
|
|
|
@ -9,9 +9,6 @@ module RubyVM::MJIT
|
|||
EndBlock = :end_block
|
||||
|
||||
class Compiler
|
||||
# Ruby constants
|
||||
Qundef = Fiddle::Qundef
|
||||
|
||||
attr_accessor :write_pos
|
||||
|
||||
# @param mem_block [Integer] JIT buffer address
|
||||
|
@ -24,7 +21,11 @@ module RubyVM::MJIT
|
|||
# @param iseq [RubyVM::MJIT::CPointer::Struct]
|
||||
def call(iseq)
|
||||
return if iseq.body.location.label == '<main>'
|
||||
iseq.body.jit_func = compile_block(iseq)
|
||||
|
||||
asm = X86Assembler.new
|
||||
compile_prologue(asm)
|
||||
compile_block(asm, iseq)
|
||||
iseq.body.jit_func = compile(asm)
|
||||
rescue Exception => e
|
||||
$stderr.puts e.full_message # TODO: check verbose
|
||||
end
|
||||
|
@ -35,6 +36,32 @@ module RubyVM::MJIT
|
|||
|
||||
private
|
||||
|
||||
# ec: rdi
|
||||
# cfp: rsi
|
||||
def compile_prologue(asm)
|
||||
asm.mov(:rbx, [:rsi, C.rb_control_frame_t.offsetof(:sp)]) # rbx = cfp->sp
|
||||
end
|
||||
|
||||
def compile_block(asm, iseq)
|
||||
index = 0
|
||||
while index < iseq.body.iseq_size
|
||||
insn = decode_insn(iseq.body.iseq_encoded[index])
|
||||
status = compile_insn(asm, insn)
|
||||
if status == EndBlock
|
||||
break
|
||||
end
|
||||
index += insn.len
|
||||
end
|
||||
end
|
||||
|
||||
def compile_insn(asm, insn)
|
||||
case insn.name
|
||||
when :putnil then @insn_compiler.putnil(asm)
|
||||
when :leave then @insn_compiler.leave(asm)
|
||||
else raise NotImplementedError, "insn '#{insn.name}' is not supported yet"
|
||||
end
|
||||
end
|
||||
|
||||
def compile(asm)
|
||||
start_addr = write_addr
|
||||
|
||||
|
@ -49,32 +76,6 @@ module RubyVM::MJIT
|
|||
start_addr
|
||||
end
|
||||
|
||||
# ec -> RDI, cfp -> RSI
|
||||
def compile_block(iseq)
|
||||
addr = write_addr
|
||||
asm = X86Assembler.new
|
||||
|
||||
index = 0
|
||||
while index < iseq.body.iseq_size
|
||||
insn = decode_insn(iseq.body.iseq_encoded[index])
|
||||
status = compile_insn(asm, insn)
|
||||
if status == EndBlock
|
||||
break
|
||||
end
|
||||
index += insn.len
|
||||
end
|
||||
|
||||
compile(asm)
|
||||
end
|
||||
|
||||
def compile_insn(asm, insn)
|
||||
case insn.name
|
||||
when :putnil then @insn_compiler.putnil(asm)
|
||||
when :leave then @insn_compiler.leave(asm)
|
||||
else raise NotImplementedError, "insn '#{insn.name}' is not supported yet"
|
||||
end
|
||||
end
|
||||
|
||||
def decode_insn(encoded)
|
||||
INSNS.fetch(C.rb_vm_insn_decode(encoded))
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue