Add number of registers to platform
This commit is contained in:
parent
8df2e4bf08
commit
8832df3221
@ -10,5 +10,8 @@ module Arm
|
|||||||
def padding
|
def padding
|
||||||
0x11000 - loaded_at
|
0x11000 - loaded_at
|
||||||
end
|
end
|
||||||
|
def num_registers
|
||||||
|
16
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
module Risc
|
module Risc
|
||||||
|
|
||||||
# A BlockCompiler is much like a MethodCompiler, exept for it's for blocks
|
# A BlockCompiler is much like a MethodCompiler, exept for it's for blocks
|
||||||
# This only changes scoping for variables, lsee slot_type
|
# This only changes scoping for variables, see slot_type
|
||||||
|
# (dynamic resolve, as needed when the block is passed, is not implemented)
|
||||||
#
|
#
|
||||||
class BlockCompiler < CallableCompiler
|
class BlockCompiler < CallableCompiler
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ module Risc
|
|||||||
end
|
end
|
||||||
attr_reader :risc_instructions , :constants , :callable , :current
|
attr_reader :risc_instructions , :constants , :callable , :current
|
||||||
|
|
||||||
|
# find the return label. Every methd should have exactly one
|
||||||
def return_label
|
def return_label
|
||||||
@risc_instructions.each do |ins|
|
@risc_instructions.each do |ins|
|
||||||
next unless ins.is_a?(Label)
|
next unless ins.is_a?(Label)
|
||||||
@ -33,6 +34,7 @@ module Risc
|
|||||||
end
|
end
|
||||||
|
|
||||||
# add a constant (which get created during compilation and need to be linked)
|
# add a constant (which get created during compilation and need to be linked)
|
||||||
|
# constants must be Parfait instances
|
||||||
def add_constant(const)
|
def add_constant(const)
|
||||||
raise "Must be Parfait #{const}" unless const.is_a?(Parfait::Object)
|
raise "Must be Parfait #{const}" unless const.is_a?(Parfait::Object)
|
||||||
@constants << const
|
@constants << const
|
||||||
|
@ -29,7 +29,7 @@ module Risc
|
|||||||
@registers = {}
|
@registers = {}
|
||||||
@flags = { :zero => false , :plus => false ,
|
@flags = { :zero => false , :plus => false ,
|
||||||
:minus => false , :overflow => false }
|
:minus => false , :overflow => false }
|
||||||
(0...12).each do |reg|
|
(0...InterpreterPlatform.new.num_registers).each do |reg|
|
||||||
set_register "r#{reg}".to_sym , "r#{reg}:unknown"
|
set_register "r#{reg}".to_sym , "r#{reg}:unknown"
|
||||||
end
|
end
|
||||||
@linker = linker
|
@linker = linker
|
||||||
|
@ -10,6 +10,9 @@ module Risc
|
|||||||
def padding
|
def padding
|
||||||
0x100 - loaded_at
|
0x100 - loaded_at
|
||||||
end
|
end
|
||||||
|
def num_registers
|
||||||
|
16
|
||||||
|
end
|
||||||
end
|
end
|
||||||
class Instruction
|
class Instruction
|
||||||
def nil_next
|
def nil_next
|
||||||
|
@ -13,6 +13,11 @@ module Risc
|
|||||||
# return an integer where the binary is loaded
|
# return an integer where the binary is loaded
|
||||||
def loaded_at
|
def loaded_at
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# return the number of registers the platform supports
|
||||||
|
def num_registers
|
||||||
|
end
|
||||||
|
|
||||||
# Factory method to create a Platform object according to the platform
|
# Factory method to create a Platform object according to the platform
|
||||||
# string given.
|
# string given.
|
||||||
# Currently only "Arm" and "Interpreter"
|
# Currently only "Arm" and "Interpreter"
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
module SlotMachine
|
module SlotMachine
|
||||||
|
|
||||||
# A BlockCompiler is much like a MehtodCompiler, exept for blocks
|
# A BlockCompiler is much like a MethodCompiler, except for blocks
|
||||||
|
# Blocks are much like methods (hence the base classes) , just the
|
||||||
|
# scope for accessing variables is different. (This only applies to static
|
||||||
|
# blocks, not ones being passed around. That is undone because it needs runtime
|
||||||
|
# code to resolve variables)
|
||||||
#
|
#
|
||||||
class BlockCompiler < CallableCompiler
|
class BlockCompiler < CallableCompiler
|
||||||
|
|
||||||
@ -16,6 +20,8 @@ module SlotMachine
|
|||||||
"#{@method.self_type.name}.init"
|
"#{@method.self_type.name}.init"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Create the risc equivalent, which is a also a (Risc) BlockCompiler
|
||||||
|
# sintructions are converted from slot to risc in instructions_to_risc (in base class)
|
||||||
def to_risc
|
def to_risc
|
||||||
risc_compiler = Risc::BlockCompiler.new(@callable , @method , slot_instructions)
|
risc_compiler = Risc::BlockCompiler.new(@callable , @method , slot_instructions)
|
||||||
instructions_to_risc(risc_compiler)
|
instructions_to_risc(risc_compiler)
|
||||||
|
@ -6,6 +6,9 @@ module SlotMachine
|
|||||||
# - slot_instructions: The sequence of slot level instructions that was compiled to
|
# - slot_instructions: The sequence of slot level instructions that was compiled to
|
||||||
# Instructions derive from class Instruction and form a linked list
|
# Instructions derive from class Instruction and form a linked list
|
||||||
|
|
||||||
|
# Since we have many different compilers, and they are kept in lists, the
|
||||||
|
# Util CompilerList encapsulates the list behaviour
|
||||||
|
#
|
||||||
class CallableCompiler
|
class CallableCompiler
|
||||||
include Util::CompilerList
|
include Util::CompilerList
|
||||||
|
|
||||||
@ -21,6 +24,8 @@ module SlotMachine
|
|||||||
end
|
end
|
||||||
attr_reader :slot_instructions , :constants , :callable , :current
|
attr_reader :slot_instructions , :constants , :callable , :current
|
||||||
|
|
||||||
|
# find the return_label, every method should have exactly one (see constructor)
|
||||||
|
# used during return sequence code generation
|
||||||
def return_label
|
def return_label
|
||||||
@slot_instructions.each do |ins|
|
@slot_instructions.each do |ins|
|
||||||
next unless ins.is_a?(Label)
|
next unless ins.is_a?(Label)
|
||||||
|
@ -5,6 +5,30 @@ module SlotMachine
|
|||||||
|
|
||||||
class MethodCompiler < CallableCompiler
|
class MethodCompiler < CallableCompiler
|
||||||
|
|
||||||
|
# helper method for builtin mainly
|
||||||
|
# the class_name is a symbol, which is resolved to the instance_type of that class
|
||||||
|
#
|
||||||
|
# return compiler_for_type with the resolved type
|
||||||
|
#
|
||||||
|
def self.compiler_for_class( class_name , method_name , args , frame )
|
||||||
|
raise "create_method #{class_name}.#{class_name.class}" unless class_name.is_a? Symbol
|
||||||
|
clazz = Parfait.object_space.get_class_by_name! class_name
|
||||||
|
compiler_for_type( clazz.instance_type , method_name , args , frame)
|
||||||
|
end
|
||||||
|
|
||||||
|
# create a method for the given type ( Parfait type object)
|
||||||
|
# method_name is a Symbol
|
||||||
|
# args a hash that will be converted to a type
|
||||||
|
# the created method is set as the current and the given type too
|
||||||
|
# return the compiler
|
||||||
|
def self.compiler_for_type( type , method_name , args , frame)
|
||||||
|
raise "create_method #{type.inspect} is not a Type" unless type.is_a? Parfait::Type
|
||||||
|
raise "Args must be Type #{args}" unless args.is_a?(Parfait::Type)
|
||||||
|
raise "create_method #{method_name}.#{method_name.class}" unless method_name.is_a? Symbol
|
||||||
|
method = type.create_method( method_name , args , frame)
|
||||||
|
self.new(method)
|
||||||
|
end
|
||||||
|
|
||||||
def initialize( method )
|
def initialize( method )
|
||||||
super(method)
|
super(method)
|
||||||
end
|
end
|
||||||
@ -30,38 +54,13 @@ module SlotMachine
|
|||||||
risc_compiler
|
risc_compiler
|
||||||
end
|
end
|
||||||
|
|
||||||
# helper method for builtin mainly
|
# create a block in the scope of the method.
|
||||||
# the class_name is a symbol, which is resolved to the instance_type of that class
|
# Blocks are like other constants, exept with code.
|
||||||
#
|
# They need to be compiled, so a list of them is kept
|
||||||
# return compiler_for_type with the resolved type
|
|
||||||
#
|
|
||||||
def self.compiler_for_class( class_name , method_name , args , frame )
|
|
||||||
raise "create_method #{class_name}.#{class_name.class}" unless class_name.is_a? Symbol
|
|
||||||
clazz = Parfait.object_space.get_class_by_name! class_name
|
|
||||||
compiler_for_type( clazz.instance_type , method_name , args , frame)
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_method_to( target )
|
|
||||||
target.add_method( @callable )
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_block(arg_type , frame_type)
|
def create_block(arg_type , frame_type)
|
||||||
@callable.create_block(arg_type ,frame_type)
|
@callable.create_block(arg_type ,frame_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
# create a method for the given type ( Parfait type object)
|
|
||||||
# method_name is a Symbol
|
|
||||||
# args a hash that will be converted to a type
|
|
||||||
# the created method is set as the current and the given type too
|
|
||||||
# return the compiler
|
|
||||||
def self.compiler_for_type( type , method_name , args , frame)
|
|
||||||
raise "create_method #{type.inspect} is not a Type" unless type.is_a? Parfait::Type
|
|
||||||
raise "Args must be Type #{args}" unless args.is_a?(Parfait::Type)
|
|
||||||
raise "create_method #{method_name}.#{method_name.class}" unless method_name.is_a? Symbol
|
|
||||||
method = type.create_method( method_name , args , frame)
|
|
||||||
self.new(method)
|
|
||||||
end
|
|
||||||
|
|
||||||
# determine how given name need to be accsessed.
|
# determine how given name need to be accsessed.
|
||||||
# For methods the options are args or frame
|
# For methods the options are args or frame
|
||||||
def slot_type_for(name)
|
def slot_type_for(name)
|
||||||
|
@ -14,5 +14,8 @@ module Arm
|
|||||||
def test_platform_loaded_class
|
def test_platform_loaded_class
|
||||||
assert_equal ::Integer , @arm.loaded_at.class
|
assert_equal ::Integer , @arm.loaded_at.class
|
||||||
end
|
end
|
||||||
|
def test_registers
|
||||||
|
assert_equal 16 , @arm.num_registers
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -20,7 +20,7 @@ module Risc
|
|||||||
assert_equal :stopped , Interpreter.new(@linker).state
|
assert_equal :stopped , Interpreter.new(@linker).state
|
||||||
end
|
end
|
||||||
def test_has_regs
|
def test_has_regs
|
||||||
assert_equal 12 , Interpreter.new(@linker).registers.length
|
assert_equal 16 , Interpreter.new(@linker).registers.length
|
||||||
end
|
end
|
||||||
def test_has_r0
|
def test_has_r0
|
||||||
assert_equal :r0 , Interpreter.new(@linker).registers.keys.first
|
assert_equal :r0 , Interpreter.new(@linker).registers.keys.first
|
||||||
|
@ -17,6 +17,9 @@ module Risc
|
|||||||
def test_translator
|
def test_translator
|
||||||
assert IdentityTranslator.new
|
assert IdentityTranslator.new
|
||||||
end
|
end
|
||||||
|
def test_registers
|
||||||
|
assert_equal 16 , @inter.num_registers
|
||||||
|
end
|
||||||
end
|
end
|
||||||
class TestIdentityTranslator < MiniTest::Test
|
class TestIdentityTranslator < MiniTest::Test
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
require_relative "../helper"
|
require_relative "../helper"
|
||||||
|
|
||||||
module Sol
|
module Sol
|
||||||
class TestSendCachedSimpleSlotMachine < MiniTest::Test
|
class TestNotFoundSlotMachine < MiniTest::Test
|
||||||
include SolCompile
|
include SolCompile
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
|
Loading…
x
Reference in New Issue
Block a user