mirror of
https://github.com/ruby/ruby.git
synced 2025-09-16 00:54:01 +02:00
48 lines
1.1 KiB
Ruby
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
|