Format code.
This commit is contained in:
parent
c04997ad17
commit
5e93fa1963
|
@ -5,7 +5,7 @@ module Chalk
|
||||||
class CodeGenerator
|
class CodeGenerator
|
||||||
include Emitter
|
include Emitter
|
||||||
RETURN_REG = 14
|
RETURN_REG = 14
|
||||||
STACK_REG = 13
|
STACK_REG = 13
|
||||||
|
|
||||||
def initialize(table, @function : TreeFunction)
|
def initialize(table, @function : TreeFunction)
|
||||||
@registers = 0
|
@registers = 0
|
||||||
|
|
|
@ -26,8 +26,8 @@ module Chalk
|
||||||
@logger.debug("Beginning constant folding")
|
@logger.debug("Beginning constant folding")
|
||||||
folder = ConstantFolder.new
|
folder = ConstantFolder.new
|
||||||
trees.map! do |tree|
|
trees.map! do |tree|
|
||||||
@logger.debug("Constant folding #{tree.name}")
|
@logger.debug("Constant folding #{tree.name}")
|
||||||
tree.apply(folder).as(TreeFunction)
|
tree.apply(folder).as(TreeFunction)
|
||||||
end
|
end
|
||||||
@logger.debug("Done constant folding")
|
@logger.debug("Done constant folding")
|
||||||
return trees
|
return trees
|
||||||
|
@ -47,9 +47,9 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
private def create_code(tree : TreeFunction, table)
|
private def create_code(tree : TreeFunction, table)
|
||||||
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!
|
return generator.generate!
|
||||||
end
|
end
|
||||||
|
|
||||||
private def create_code(trees : Array(TreeFunction), table)
|
private def create_code(trees : Array(TreeFunction), table)
|
||||||
|
@ -82,32 +82,32 @@ module Chalk
|
||||||
context = InstructionContext.new table, instructions.size
|
context = InstructionContext.new table, instructions.size
|
||||||
binary = instructions.map_with_index { |it, i| it.to_bin(context, i).to_u16 }
|
binary = instructions.map_with_index { |it, i| it.to_bin(context, i).to_u16 }
|
||||||
binary.each do |inst|
|
binary.each do |inst|
|
||||||
first = (inst >> 8).to_u8
|
first = (inst >> 8).to_u8
|
||||||
dest.write_byte(first)
|
dest.write_byte(first)
|
||||||
second = (inst & 0xff).to_u8
|
second = (inst & 0xff).to_u8
|
||||||
dest.write_byte(second)
|
dest.write_byte(second)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private def collect_calls(table)
|
private def collect_calls(table)
|
||||||
open = Set(String).new
|
open = Set(String).new
|
||||||
done = Set(String).new
|
done = Set(String).new
|
||||||
|
|
||||||
open << "main"
|
open << "main"
|
||||||
while !open.empty?
|
while !open.empty?
|
||||||
first = open.first
|
first = open.first
|
||||||
open.delete first
|
open.delete first
|
||||||
done << first
|
done << first
|
||||||
|
|
||||||
entry = table[first]?
|
entry = table[first]?
|
||||||
raise "Unknown function" unless entry && entry.is_a?(FunctionEntry)
|
raise "Unknown function" unless entry && entry.is_a?(FunctionEntry)
|
||||||
next unless entry.function.is_a?(TreeFunction)
|
next unless entry.function.is_a?(TreeFunction)
|
||||||
|
|
||||||
visitor = CallVisitor.new
|
visitor = CallVisitor.new
|
||||||
entry.function.accept(visitor)
|
entry.function.accept(visitor)
|
||||||
open.concat(visitor.calls - done)
|
open.concat(visitor.calls - done)
|
||||||
end
|
end
|
||||||
return done
|
return done
|
||||||
end
|
end
|
||||||
|
|
||||||
private def run_binary
|
private def run_binary
|
||||||
|
|
|
@ -1,75 +1,75 @@
|
||||||
module Chalk
|
module Chalk
|
||||||
module Emitter
|
module Emitter
|
||||||
private def load(into, value)
|
private def load(into, value)
|
||||||
inst = LoadInstruction.new into, value.to_i32
|
inst = LoadInstruction.new into, value.to_i32
|
||||||
@instructions << inst
|
@instructions << inst
|
||||||
return inst
|
return inst
|
||||||
end
|
|
||||||
|
|
||||||
private def loadr(into, from)
|
|
||||||
inst = LoadRegInstruction.new into, from
|
|
||||||
@instructions << inst
|
|
||||||
return inst
|
|
||||||
end
|
|
||||||
|
|
||||||
private def op(op, into, from)
|
|
||||||
inst = OpInstruction.new op, into, from
|
|
||||||
@instructions << inst
|
|
||||||
return inst
|
|
||||||
end
|
|
||||||
|
|
||||||
private def opr(op, into, from)
|
|
||||||
inst = OpRegInstruction.new op, into, from
|
|
||||||
@instructions << inst
|
|
||||||
return inst
|
|
||||||
end
|
|
||||||
|
|
||||||
private def sne(l, r)
|
|
||||||
inst = SkipNeInstruction.new l, r
|
|
||||||
@instructions << inst
|
|
||||||
return inst
|
|
||||||
end
|
|
||||||
|
|
||||||
private def jr(o)
|
|
||||||
inst = JumpRelativeInstruction.new o
|
|
||||||
@instructions << inst
|
|
||||||
return inst
|
|
||||||
end
|
|
||||||
|
|
||||||
private def store(up_to)
|
|
||||||
inst = StoreInstruction.new up_to
|
|
||||||
@instructions << inst
|
|
||||||
return inst
|
|
||||||
end
|
|
||||||
|
|
||||||
private def restore(up_to)
|
|
||||||
inst = RestoreInstruction.new up_to
|
|
||||||
@instructions << inst
|
|
||||||
return inst
|
|
||||||
end
|
|
||||||
|
|
||||||
private def ret
|
|
||||||
inst = ReturnInstruction.new
|
|
||||||
@instructions << inst
|
|
||||||
return inst
|
|
||||||
end
|
|
||||||
|
|
||||||
private def call(func)
|
|
||||||
inst = CallInstruction.new func
|
|
||||||
@instructions << inst
|
|
||||||
return inst
|
|
||||||
end
|
|
||||||
|
|
||||||
private def setis
|
|
||||||
inst = SetIStackInstruction.new
|
|
||||||
@instructions << inst
|
|
||||||
return inst
|
|
||||||
end
|
|
||||||
|
|
||||||
private def addi(reg)
|
|
||||||
inst = AddIRegInstruction.new reg
|
|
||||||
@instructions << inst
|
|
||||||
return inst
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private def loadr(into, from)
|
||||||
|
inst = LoadRegInstruction.new into, from
|
||||||
|
@instructions << inst
|
||||||
|
return inst
|
||||||
|
end
|
||||||
|
|
||||||
|
private def op(op, into, from)
|
||||||
|
inst = OpInstruction.new op, into, from
|
||||||
|
@instructions << inst
|
||||||
|
return inst
|
||||||
|
end
|
||||||
|
|
||||||
|
private def opr(op, into, from)
|
||||||
|
inst = OpRegInstruction.new op, into, from
|
||||||
|
@instructions << inst
|
||||||
|
return inst
|
||||||
|
end
|
||||||
|
|
||||||
|
private def sne(l, r)
|
||||||
|
inst = SkipNeInstruction.new l, r
|
||||||
|
@instructions << inst
|
||||||
|
return inst
|
||||||
|
end
|
||||||
|
|
||||||
|
private def jr(o)
|
||||||
|
inst = JumpRelativeInstruction.new o
|
||||||
|
@instructions << inst
|
||||||
|
return inst
|
||||||
|
end
|
||||||
|
|
||||||
|
private def store(up_to)
|
||||||
|
inst = StoreInstruction.new up_to
|
||||||
|
@instructions << inst
|
||||||
|
return inst
|
||||||
|
end
|
||||||
|
|
||||||
|
private def restore(up_to)
|
||||||
|
inst = RestoreInstruction.new up_to
|
||||||
|
@instructions << inst
|
||||||
|
return inst
|
||||||
|
end
|
||||||
|
|
||||||
|
private def ret
|
||||||
|
inst = ReturnInstruction.new
|
||||||
|
@instructions << inst
|
||||||
|
return inst
|
||||||
|
end
|
||||||
|
|
||||||
|
private def call(func)
|
||||||
|
inst = CallInstruction.new func
|
||||||
|
@instructions << inst
|
||||||
|
return inst
|
||||||
|
end
|
||||||
|
|
||||||
|
private def setis
|
||||||
|
inst = SetIStackInstruction.new
|
||||||
|
@instructions << inst
|
||||||
|
return inst
|
||||||
|
end
|
||||||
|
|
||||||
|
private def addi(reg)
|
||||||
|
inst = AddIRegInstruction.new reg
|
||||||
|
@instructions << inst
|
||||||
|
return inst
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
module Chalk
|
module Chalk
|
||||||
class CallVisitor < Visitor
|
class CallVisitor < Visitor
|
||||||
property calls : Set(String)
|
property calls : Set(String)
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@calls = Set(String).new
|
@calls = Set(String).new
|
||||||
end
|
|
||||||
|
|
||||||
def visit(t : TreeCall)
|
|
||||||
@calls << t.name
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def visit(t : TreeCall)
|
||||||
|
@calls << t.name
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,11 +8,11 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
class InstructionContext
|
class InstructionContext
|
||||||
property table : Table
|
property table : Table
|
||||||
property stack : Int32
|
property stack : Int32
|
||||||
|
|
||||||
def initialize(@table, @stack)
|
def initialize(@table, @stack)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class LoadInstruction < Instruction
|
class LoadInstruction < Instruction
|
||||||
|
@ -29,7 +29,7 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
0x6000 | (register << 8) | value
|
0x6000 | (register << 8) | value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
0x8000 | (into << 8) | (from << 4)
|
0x8000 | (into << 8) | (from << 4)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -67,12 +67,12 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
case op
|
case op
|
||||||
when TokenType::OpAdd
|
when TokenType::OpAdd
|
||||||
return 0x7000 | (into << 8) | value
|
return 0x7000 | (into << 8) | value
|
||||||
else
|
else
|
||||||
raise "Invalid instruction"
|
raise "Invalid instruction"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -92,22 +92,22 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
code = 0
|
code = 0
|
||||||
case op
|
case op
|
||||||
when TokenType::OpAdd
|
when TokenType::OpAdd
|
||||||
code = 4
|
code = 4
|
||||||
when TokenType::OpSub
|
when TokenType::OpSub
|
||||||
code = 5
|
code = 5
|
||||||
when TokenType::OpOr
|
when TokenType::OpOr
|
||||||
code = 1
|
code = 1
|
||||||
when TokenType::OpAnd
|
when TokenType::OpAnd
|
||||||
code = 2
|
code = 2
|
||||||
when TokenType::OpXor
|
when TokenType::OpXor
|
||||||
code = 3
|
code = 3
|
||||||
else
|
else
|
||||||
raise "Invalid instruction"
|
raise "Invalid instruction"
|
||||||
end
|
end
|
||||||
return 0x8000 | (into << 8) | (from << 4) | code
|
return 0x8000 | (into << 8) | (from << 4) | code
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
return 0xf055 | (up_to << 8)
|
return 0xf055 | (up_to << 8)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -139,12 +139,12 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
return 0xf065 | (up_to << 8)
|
return 0xf065 | (up_to << 8)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ReturnInstruction < Instruction
|
class ReturnInstruction < Instruction
|
||||||
def initialize()
|
def initialize
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
|
@ -152,7 +152,7 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
return 0x00ee
|
return 0x00ee
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
return 0x1000 | ((offset + index) * 2 + 0x200)
|
return 0x1000 | ((offset + index) * 2 + 0x200)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
return 0x3000 | (left << 8) | right
|
return 0x3000 | (left << 8) | right
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
return 0x4000 | (left << 8) | right
|
return 0x4000 | (left << 8) | right
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
return 0x5000 | (left << 8) | (right << 4)
|
return 0x5000 | (left << 8) | (right << 4)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
return 0x9000 | (left << 8) | (right << 4)
|
return 0x9000 | (left << 8) | (right << 4)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -256,17 +256,17 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
return 0x2000 | (i.table[name]?.as(FunctionEntry).addr * 2 + 0x200)
|
return 0x2000 | (i.table[name]?.as(FunctionEntry).addr * 2 + 0x200)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class SetIStackInstruction < Instruction
|
class SetIStackInstruction < Instruction
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
io << "setis"
|
io << "setis"
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
return 0xa000 | (i.stack * 2 + 0x200)
|
return 0xa000 | (i.stack * 2 + 0x200)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ module Chalk
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bin(i, index)
|
def to_bin(i, index)
|
||||||
return 0xf000 | (reg << 8) | 0x1e
|
return 0xf000 | (reg << 8) | 0x1e
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
module Chalk
|
module Chalk
|
||||||
class Optimizer
|
class Optimizer
|
||||||
def initialize(instructions : Array(Instruction))
|
def initialize(instructions : Array(Instruction))
|
||||||
@instructions = instructions.dup
|
@instructions = instructions.dup
|
||||||
end
|
|
||||||
|
|
||||||
private def optimize!(range)
|
|
||||||
offset = 0
|
|
||||||
range.each do |index|
|
|
||||||
if check_dead(@instructions[index + offset])
|
|
||||||
@instructions.delete_at(index + offset)
|
|
||||||
offset -= 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return offset
|
|
||||||
end
|
|
||||||
|
|
||||||
private def optimize!
|
|
||||||
block_boundaries = [ @instructions.size ]
|
|
||||||
@instructions.each_with_index do |inst, i|
|
|
||||||
if inst.is_a?(JumpRelativeInstruction)
|
|
||||||
block_boundaries << (inst.offset + i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
block_boundaries.sort!
|
|
||||||
|
|
||||||
previous = 0
|
|
||||||
offset = 0
|
|
||||||
block_boundaries.each do |boundary|
|
|
||||||
range = (previous + offset)...(boundary + offset)
|
|
||||||
offset += optimize!(range)
|
|
||||||
previous = boundary
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private def optimize!(range)
|
||||||
|
offset = 0
|
||||||
|
range.each do |index|
|
||||||
|
if check_dead(@instructions[index + offset])
|
||||||
|
@instructions.delete_at(index + offset)
|
||||||
|
offset -= 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return offset
|
||||||
|
end
|
||||||
|
|
||||||
|
private def optimize!
|
||||||
|
block_boundaries = [@instructions.size]
|
||||||
|
@instructions.each_with_index do |inst, i|
|
||||||
|
if inst.is_a?(JumpRelativeInstruction)
|
||||||
|
block_boundaries << (inst.offset + i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
block_boundaries.sort!
|
||||||
|
|
||||||
|
previous = 0
|
||||||
|
offset = 0
|
||||||
|
block_boundaries.each do |boundary|
|
||||||
|
range = (previous + offset)...(boundary + offset)
|
||||||
|
offset += optimize!(range)
|
||||||
|
previous = boundary
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user