ruby/lib/mjit/x86_64/assembler.rb
2023-03-05 22:11:20 -08:00

48 lines
1.1 KiB
Ruby

class RubyVM::MJIT::Assembler
ByteWriter = RubyVM::MJIT::CType::Immediate.parse('char')
def initialize
@bytes = []
end
def compile(compiler)
with_dump_disasm(compiler) do
RubyVM::MJIT::C.mjit_mark_writable
write_bytes(compiler.write_addr, @bytes)
RubyVM::MJIT::C.mjit_mark_executable
compiler.write_pos += @bytes.size
@bytes.clear
end
end
def mov(_reg, val)
@bytes.push(0xb8, val, 0x00, 0x00, 0x00)
end
def ret
@bytes.push(0xc3)
end
private
def with_dump_disasm(compiler)
from = compiler.write_addr
yield
to = compiler.write_addr
if RubyVM::MJIT::C.mjit_opts.dump_disasm && from < to
RubyVM::MJIT::C.dump_disasm(from, to).each do |address, mnemonic, op_str|
puts " 0x#{"%p" % address}: #{mnemonic} #{op_str}"
end
end
end
def write_bytes(addr, bytes)
writer = ByteWriter.new(addr)
# If you pack bytes containing \x00, Ruby fails to recognize bytes after \x00.
# So writing byte by byte to avoid hitting that situation.
bytes.each_with_index do |byte, index|
writer[index] = byte
end
end
end