RJIT: Start testing Assembler
This commit is contained in:
parent
6440d159b3
commit
76808b1ee4
@ -58,19 +58,20 @@ module RubyVM::RJIT
|
|||||||
(@mem_block...(@mem_block + @mem_size)).include?(addr)
|
(@mem_block...(@mem_block + @mem_size)).include?(addr)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
def dump_disasm(from, to, io: STDOUT, color: true)
|
||||||
|
|
||||||
def dump_disasm(from, to)
|
|
||||||
C.dump_disasm(from, to).each do |address, mnemonic, op_str|
|
C.dump_disasm(from, to).each do |address, mnemonic, op_str|
|
||||||
@comments.fetch(address, []).each do |comment|
|
@comments.fetch(address, []).each do |comment|
|
||||||
puts colorize(" # #{comment}", bold: true)
|
io.puts colorize(" # #{comment}", bold: true, color:)
|
||||||
end
|
end
|
||||||
puts colorize(" 0x#{format("%x", address)}: #{mnemonic} #{op_str}")
|
io.puts colorize(" 0x#{format("%x", address)}: #{mnemonic} #{op_str}", color:)
|
||||||
end
|
end
|
||||||
puts
|
io.puts
|
||||||
end
|
end
|
||||||
|
|
||||||
def colorize(text, bold: false)
|
private
|
||||||
|
|
||||||
|
def colorize(text, bold: false, color:)
|
||||||
|
return text unless color
|
||||||
buf = +''
|
buf = +''
|
||||||
buf << "\e[1m" if bold
|
buf << "\e[1m" if bold
|
||||||
buf << "\e[34m" if @outlined
|
buf << "\e[34m" if @outlined
|
||||||
|
10
rjit_c.rb
10
rjit_c.rb
@ -474,6 +474,16 @@ module RubyVM::RJIT # :nodoc: all
|
|||||||
Primitive.cexpr! '(VALUE)NUM2PTR(value)'
|
Primitive.cexpr! '(VALUE)NUM2PTR(value)'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def HAVE_LIBCAPSTONE
|
||||||
|
Primitive.cstmt! %{
|
||||||
|
#ifdef HAVE_LIBCAPSTONE
|
||||||
|
return Qtrue;
|
||||||
|
#else
|
||||||
|
return Qfalse;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Utilities: Not used by RJIT, but useful for debugging
|
# Utilities: Not used by RJIT, but useful for debugging
|
||||||
#
|
#
|
||||||
|
66
test/ruby/rjit/test_assembler.rb
Normal file
66
test/ruby/rjit/test_assembler.rb
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
require 'test/unit'
|
||||||
|
require_relative '../../lib/jit_support'
|
||||||
|
|
||||||
|
return unless JITSupport.rjit_supported?
|
||||||
|
return unless RubyVM::RJIT.enabled?
|
||||||
|
return unless RubyVM::RJIT::C.HAVE_LIBCAPSTONE
|
||||||
|
|
||||||
|
require 'stringio'
|
||||||
|
require 'ruby_vm/rjit/assembler'
|
||||||
|
|
||||||
|
module RubyVM::RJIT
|
||||||
|
class TestAssembler < Test::Unit::TestCase
|
||||||
|
MEM_SIZE = 16 * 1024
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@mem_block ||= C.mmap(MEM_SIZE)
|
||||||
|
@cb = CodeBlock.new(mem_block: @mem_block, mem_size: MEM_SIZE)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_add
|
||||||
|
asm = Assembler.new
|
||||||
|
asm.add(:rax, 255)
|
||||||
|
assert_compile(asm, '0x0: add rax, 0xff')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_jmp
|
||||||
|
asm = Assembler.new
|
||||||
|
label = asm.new_label('label')
|
||||||
|
asm.jmp(label)
|
||||||
|
asm.write_label(label)
|
||||||
|
asm.jmp(label)
|
||||||
|
assert_compile(asm, <<~EOS)
|
||||||
|
0x0: jmp 0x2
|
||||||
|
0x2: jmp 0x2
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def assert_compile(asm, expected)
|
||||||
|
actual = compile(asm)
|
||||||
|
assert_equal expected, actual, "---\n#{actual}---"
|
||||||
|
end
|
||||||
|
|
||||||
|
def compile(asm)
|
||||||
|
start_addr = @cb.write_addr
|
||||||
|
@cb.write(asm)
|
||||||
|
end_addr = @cb.write_addr
|
||||||
|
|
||||||
|
io = StringIO.new
|
||||||
|
@cb.dump_disasm(start_addr, end_addr, io:, color: false)
|
||||||
|
io.seek(0)
|
||||||
|
disasm = io.read
|
||||||
|
|
||||||
|
disasm.gsub!(/^ /, '')
|
||||||
|
disasm.sub!(/\n\z/, '')
|
||||||
|
if disasm.lines.size == 1
|
||||||
|
disasm.rstrip!
|
||||||
|
end
|
||||||
|
(start_addr...end_addr).each do |addr|
|
||||||
|
disasm.gsub!("0x#{addr.to_s(16)}", "0x#{(addr - start_addr).to_s(16)}")
|
||||||
|
end
|
||||||
|
disasm
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user