avoid adding risc instructions twice

that causes loops in the chain
infinite loops in the code that are hard to debug
closes #11
This commit is contained in:
Torsten Ruger 2018-08-19 17:29:04 +03:00
parent f85fe8a2cb
commit 9687d6611f
7 changed files with 37 additions and 19 deletions

View File

@ -12,8 +12,7 @@ module Mom
@label = label @label = label
end end
def to_risc(compiler) def to_risc(compiler)
label = @label.to_risc(compiler) compiler.add_code Risc::Branch.new(self , @label.risc_label)
compiler.add_code Risc::Branch.new(self , label)
end end
end end

View File

@ -8,16 +8,6 @@ module Mom
# #
# A Label has a name which is mainly used for debugging. # A Label has a name which is mainly used for debugging.
# #
class Label < Instruction
attr_reader :name
def initialize(name)
@name = name
end
def to_s
"Label: #{name}"
end
# A Mom::Label converts one2one to a Risc::Label. So in a way it could not be more # A Mom::Label converts one2one to a Risc::Label. So in a way it could not be more
# simple. # simple.
# Alas, since almost by definition several roads lead to this label, all those # Alas, since almost by definition several roads lead to this label, all those
@ -30,8 +20,31 @@ module Mom
# #
# Off course some specific place still has to be responsible for actually # Off course some specific place still has to be responsible for actually
# adding the label to the instruction list (usually an if/while) # adding the label to the instruction list (usually an if/while)
def to_risc(compiler)
class Label < Instruction
attr_reader :name
def initialize(name)
@name = name
end
def to_s
"Label: #{name}"
end
# generate the risc label lazily
def risc_label
@risc_label ||= Risc.label(self,name) @risc_label ||= Risc.label(self,name)
end end
# add the risc_label to the compiler (instruction flow)
# should only be called once
def to_risc(compiler)
if( @added )
raise "added already #{@added}"
else
@added = true
compiler.add_code( risc_label )
end
end
end end
end end

View File

@ -26,7 +26,7 @@ module Mom
l_reg = left.to_register(compiler, self) l_reg = left.to_register(compiler, self)
r_reg = right.to_register(compiler, self) r_reg = right.to_register(compiler, self)
compiler.add_code Risc.op( self , :- , l_reg , r_reg) compiler.add_code Risc.op( self , :- , l_reg , r_reg)
compiler.add_code Risc::IsZero.new( self, false_jump.to_risc(compiler)) compiler.add_code Risc::IsZero.new( self, false_jump.risc_label)
end end
end end
end end

View File

@ -19,7 +19,7 @@ module Mom
end end
def to_risc(compiler) def to_risc(compiler)
false_label = @false_jump.to_risc(compiler) false_label = @false_jump.risc_label
builder = compiler.builder("TruthCheck") builder = compiler.builder("TruthCheck")
condition_reg = @condition.to_register(compiler,self) condition_reg = @condition.to_register(compiler,self)
builder.build do builder.build do

View File

@ -16,10 +16,11 @@ module Risc
@constants = [] @constants = []
@block_compilers = [] @block_compilers = []
@risc_instructions = Risc.label(source_name, source_name) @risc_instructions = Risc.label(source_name, source_name)
@current = @risc_instructions @current = start = @risc_instructions
add_code Risc.label( source_name, "return_label") add_code Risc.label( source_name, "return_label")
Mom::ReturnSequence.new.to_risc(self) Mom::ReturnSequence.new.to_risc(self)
add_code Risc.label( source_name, "unreachable") add_code Risc.label( source_name, "unreachable")
@current = start
reset_regs reset_regs
end end
attr_reader :risc_instructions , :constants , :block_compilers , :callable , :current attr_reader :risc_instructions , :constants , :block_compilers , :callable , :current

View File

@ -50,5 +50,10 @@ module Risc
sl = @produced.next( 7 ) sl = @produced.next( 7 )
assert_reg_to_slot( sl , :r1 , :r3 , 7 ) assert_reg_to_slot( sl , :r1 , :r3 , 7 )
end end
def test_label
sl = @produced.next( 17 )
assert_equal Risc::Label , sl.class
assert_equal "return_label" , sl.name
end
end end
end end

View File

@ -1,4 +1,4 @@
require_relative "../helper" require_relative "helper"
module Risc module Risc
class TestReturnSequence < MiniTest::Test class TestReturnSequence < MiniTest::Test