Fix optimizer to adjust jumps after instruction deletion.
This commit is contained in:
parent
147837c011
commit
cd0e5c2919
|
@ -52,13 +52,16 @@ module Chalk
|
||||||
return table
|
return table
|
||||||
end
|
end
|
||||||
|
|
||||||
private def create_code(tree : TreeFunction, table)
|
private def create_code(tree : TreeFunction, table, instruction = ReturnInstruction.new)
|
||||||
|
optimizer = Optimizer.new
|
||||||
generator = CodeGenerator.new table, tree
|
generator = CodeGenerator.new table, tree
|
||||||
@logger.debug("Generating code for #{tree.name}")
|
@logger.debug("Generating code for #{tree.name}")
|
||||||
return generator.generate!
|
code = generator.generate!
|
||||||
|
code << instruction
|
||||||
|
return optimizer.optimize(code)
|
||||||
end
|
end
|
||||||
|
|
||||||
private def create_code(tree : BuiltinFunction, table)
|
private def create_code(tree : BuiltinFunction, table, instruction = nil)
|
||||||
instructions = [] of Instruction
|
instructions = [] of Instruction
|
||||||
tree.generate!(instructions)
|
tree.generate!(instructions)
|
||||||
return instructions
|
return instructions
|
||||||
|
@ -132,9 +135,9 @@ module Chalk
|
||||||
names.delete "main"
|
names.delete "main"
|
||||||
|
|
||||||
main_entry = table["main"]?.as(FunctionEntry)
|
main_entry = table["main"]?.as(FunctionEntry)
|
||||||
all_instructions.concat create_code(main_entry.function.as(TreeFunction), table)
|
all_instructions.concat create_code(main_entry.function.as(TreeFunction),
|
||||||
|
table, JumpRelativeInstruction.new 0)
|
||||||
main_entry.addr = 0
|
main_entry.addr = 0
|
||||||
all_instructions << JumpRelativeInstruction.new 0
|
|
||||||
|
|
||||||
names.each do |name|
|
names.each do |name|
|
||||||
entry = table[name]?.as(FunctionEntry)
|
entry = table[name]?.as(FunctionEntry)
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
module Chalk
|
module Chalk
|
||||||
class Optimizer
|
class Optimizer
|
||||||
private def check_dead(inst)
|
private def check_dead(inst)
|
||||||
if inst.is_a?(LoadRegInstruction)
|
if inst.is_a?(LoadRegInstruction)
|
||||||
return inst.from == inst.into
|
return inst.from == inst.into
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
private def optimize!(instructions, range)
|
private def optimize!(instructions, range, deletions, deletions_at)
|
||||||
offset = 0
|
|
||||||
range.each do |index|
|
range.each do |index|
|
||||||
if check_dead(instructions[index + offset])
|
if check_dead(instructions[index])
|
||||||
instructions.delete_at(index + offset)
|
deletions << index
|
||||||
offset -= 1
|
|
||||||
end
|
end
|
||||||
|
deletions_at[index] = deletions.size
|
||||||
end
|
end
|
||||||
return offset
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def optimize(instructions)
|
def optimize(instructions)
|
||||||
|
@ -23,18 +21,34 @@ module Chalk
|
||||||
block_boundaries = [instructions.size]
|
block_boundaries = [instructions.size]
|
||||||
instructions.each_with_index do |inst, i|
|
instructions.each_with_index do |inst, i|
|
||||||
if inst.is_a?(JumpRelativeInstruction)
|
if inst.is_a?(JumpRelativeInstruction)
|
||||||
|
block_boundaries << i
|
||||||
block_boundaries << (inst.offset + i)
|
block_boundaries << (inst.offset + i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
block_boundaries.sort!
|
block_boundaries.uniq!.sort!
|
||||||
|
|
||||||
previous = 0
|
previous = 0
|
||||||
offset = 0
|
deletions = [] of Int32
|
||||||
|
deletions_at = {} of Int32 => Int32
|
||||||
block_boundaries.each do |boundary|
|
block_boundaries.each do |boundary|
|
||||||
range = (previous + offset)...(boundary + offset)
|
range = previous...boundary
|
||||||
offset += optimize!(instructions, range)
|
optimize!(instructions, range, deletions, deletions_at)
|
||||||
previous = boundary
|
previous = boundary
|
||||||
end
|
end
|
||||||
|
|
||||||
|
instructions.each_with_index do |inst, i|
|
||||||
|
next if !inst.is_a?(JumpRelativeInstruction)
|
||||||
|
jump_to = inst.offset + i
|
||||||
|
next unless deletions_at[jump_to]?
|
||||||
|
deletions_offset = deletions_at[i] - deletions_at[jump_to]
|
||||||
|
inst.offset += deletions_offset
|
||||||
|
end
|
||||||
|
|
||||||
|
deletions.reverse!
|
||||||
|
deletions.each do |i|
|
||||||
|
instructions.delete_at i
|
||||||
|
end
|
||||||
|
|
||||||
return instructions
|
return instructions
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user