Intermediate commit. Remove type restrictions.
Code gen is very broken
This commit is contained in:
parent
3853d212b9
commit
23f95fe68c
|
@ -5,7 +5,6 @@ module Chalk
|
|||
config = Config.parse!
|
||||
exit unless config.validate!
|
||||
|
||||
generator = CodeGenerator.new (Table.new)
|
||||
compiler = Compiler.new config
|
||||
compiler.run
|
||||
end
|
||||
|
|
|
@ -2,53 +2,81 @@ require "./ir.cr"
|
|||
|
||||
module Chalk
|
||||
class CodeGenerator
|
||||
def initialize(@table : Table)
|
||||
def initialize(table, @function : TreeFunction)
|
||||
@register = 0
|
||||
@instructions = [] of Instruction
|
||||
@block_edges = [] of Int32
|
||||
@table = Table.new table
|
||||
|
||||
@function.params.each do |param|
|
||||
@table[param] = VarEntry.new @register
|
||||
@register += 1
|
||||
end
|
||||
end
|
||||
|
||||
private def load(into, value)
|
||||
@instructions << LoadInstruction.new into, value.to_i32
|
||||
inst = LoadInstruction.new into, value.to_i32
|
||||
@instructions << inst
|
||||
return inst
|
||||
end
|
||||
|
||||
private def loadr(into, from)
|
||||
@instructions << LoadRegInstruction.new into, from
|
||||
inst = LoadRegInstruction.new into, from
|
||||
@instructions << inst
|
||||
return inst
|
||||
end
|
||||
|
||||
private def op(op, into, from)
|
||||
@instructions << OpRegInstruction.new op, into, from
|
||||
inst = OpRegInstruction.new op, into, from
|
||||
@instructions << inst
|
||||
return inst
|
||||
end
|
||||
|
||||
private def jeq(rel, l, r)
|
||||
inst = JumpEqRegInstruction.new rel, l, r
|
||||
@instructions << inst
|
||||
return inst
|
||||
end
|
||||
|
||||
private def store(up_to)
|
||||
@instructions << StoreInstruction.new up_to
|
||||
inst = StoreInstruction.new up_to
|
||||
@instructions << inst
|
||||
return inst
|
||||
end
|
||||
|
||||
private def restore(up_to)
|
||||
@instructions << RestoreInstruction.new up_to
|
||||
inst = RestoreInstruction.new up_to
|
||||
@instructions << inst
|
||||
return inst
|
||||
end
|
||||
|
||||
private def ret(reg)
|
||||
@instructions << ReturnInstruction.new reg
|
||||
inst = ReturnInstruction.new reg
|
||||
@instructions << inst
|
||||
return inst
|
||||
end
|
||||
|
||||
def generate(tree : Tree, target : Int32)
|
||||
def generate!(tree, target)
|
||||
case tree
|
||||
when TreeId
|
||||
entry = @table[tree.id]?
|
||||
raise "Unknown variable" unless entry &&
|
||||
entry.is_a?(VarEntry)
|
||||
loadr target, entry.as(VarEntry).register
|
||||
loadr target, entry.register
|
||||
when TreeLit
|
||||
load target, tree.lit
|
||||
when TreeOp
|
||||
generate tree.left, target
|
||||
generate tree.right, @register
|
||||
op tree.op, target, @register
|
||||
into = @register
|
||||
@register += 1
|
||||
generate! tree.left, target
|
||||
generate! tree.right, into
|
||||
@register -= 1
|
||||
op tree.op, target, into
|
||||
when TreeBlock
|
||||
register = @register
|
||||
tree.children.each do |child|
|
||||
generate child, @register
|
||||
generate! child, @register
|
||||
end
|
||||
@register = register
|
||||
when TreeVar
|
||||
entry = @table[tree.name]?
|
||||
if entry == nil
|
||||
|
@ -57,22 +85,75 @@ module Chalk
|
|||
@table[tree.name] = entry
|
||||
end
|
||||
raise "Unknown variable" unless entry.is_a?(VarEntry)
|
||||
generate tree.expr, entry.register
|
||||
generate! tree.expr, entry.register
|
||||
when TreeAssign
|
||||
entry = @table[tree.name]?
|
||||
raise "Unknown variable" unless entry &&
|
||||
entry.is_a?(VarEntry)
|
||||
generate tree.expr, entry.as(VarEntry).register
|
||||
generate! tree.expr, entry.register
|
||||
when TreeIf
|
||||
cond_target = @register
|
||||
@register += 1
|
||||
|
||||
generate! tree.condition, cond_target
|
||||
load cond_target + 1, 0
|
||||
jump_inst = jeq 0, cond_target, cond_target + 1
|
||||
@register -= 1
|
||||
|
||||
old_size = @instructions.size
|
||||
generate! tree.block, @register
|
||||
jump_inst.offset = @instructions.size - old_size + 1
|
||||
|
||||
generate! tree.otherwise, @register if tree.otherwise
|
||||
when TreeReturn
|
||||
generate tree.rvalue, target
|
||||
ret target
|
||||
into = @register
|
||||
@register += 1
|
||||
generate! tree.rvalue, into
|
||||
@register -= 1
|
||||
ret into
|
||||
end
|
||||
end
|
||||
|
||||
def generate(tree : Tree)
|
||||
generate(tree, 0)
|
||||
@block_edges << @instructions.size
|
||||
@block_edges.sort!
|
||||
private def check_dead(inst)
|
||||
if inst.is_a?(LoadRegInstruction)
|
||||
return inst.from == inst.into
|
||||
end
|
||||
return false
|
||||
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?(JumpEqRegInstruction) ||
|
||||
inst.is_a?(JumpEqInstruction)
|
||||
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
|
||||
|
||||
def generate!
|
||||
generate!(@function.block, @register)
|
||||
optimize!
|
||||
return @instructions
|
||||
end
|
||||
end
|
||||
|
|
|
@ -40,11 +40,15 @@ module Chalk
|
|||
end
|
||||
|
||||
private def generate_code(trees, table)
|
||||
code = {} of String => Array(Instruction)
|
||||
trees.each do |tree|
|
||||
generator = CodeGenerator.new table
|
||||
instructions = generator.generate tree.as(TreeFunction).block
|
||||
instructions.each { |it| puts it }
|
||||
tree = tree.as(TreeFunction)
|
||||
generator = CodeGenerator.new table, tree
|
||||
@logger.debug("Generating code for #{tree.name}")
|
||||
instructions = generator.generate!
|
||||
code[tree.name] = instructions
|
||||
end
|
||||
return code
|
||||
end
|
||||
|
||||
private def run_tree
|
||||
|
@ -57,7 +61,13 @@ module Chalk
|
|||
private def run_intermediate
|
||||
trees = create_trees(@config.file)
|
||||
table = process_initial(trees)
|
||||
generate_code(trees, table)
|
||||
raise "No main function!" unless table["main"]?
|
||||
code = generate_code(trees, table)
|
||||
code.each do |name, insts|
|
||||
puts "Code for #{name}:"
|
||||
insts.each { |it| puts it }
|
||||
puts "-----"
|
||||
end
|
||||
end
|
||||
|
||||
private def run_binary
|
||||
|
|
|
@ -8,7 +8,7 @@ module Chalk
|
|||
property register : Int32
|
||||
property value : Int32
|
||||
|
||||
def initialize(@register : Int32, @value : Int32)
|
||||
def initialize(@register, @value)
|
||||
end
|
||||
|
||||
def to_s(io)
|
||||
|
@ -22,7 +22,7 @@ module Chalk
|
|||
property into : Int32
|
||||
property from : Int32
|
||||
|
||||
def initialize(@into : Int32, @from : Int32)
|
||||
def initialize(@into, @from)
|
||||
end
|
||||
|
||||
def to_s(io)
|
||||
|
@ -38,8 +38,7 @@ module Chalk
|
|||
property into : Int32
|
||||
property value : Int32
|
||||
|
||||
def initialize(@op : TokenType, @into : Int32,
|
||||
@value : Int32)
|
||||
def initialize(@op, @into, @value)
|
||||
end
|
||||
|
||||
def to_s(io)
|
||||
|
@ -54,7 +53,7 @@ module Chalk
|
|||
property into : Int32
|
||||
property from : Int32
|
||||
|
||||
def initialize(@op : TokenType, @into : Int32, @from : Int32)
|
||||
def initialize(@op, @into, @from)
|
||||
end
|
||||
|
||||
def to_s(io)
|
||||
|
@ -68,7 +67,7 @@ module Chalk
|
|||
class StoreInstruction < Instruction
|
||||
property up_to : Int32
|
||||
|
||||
def initialize(@up_to : Int32)
|
||||
def initialize(@up_to)
|
||||
end
|
||||
|
||||
def to_s(io)
|
||||
|
@ -80,7 +79,7 @@ module Chalk
|
|||
class RestoreInstruction < Instruction
|
||||
property up_to : Int32
|
||||
|
||||
def initialize(@up_to : Int32)
|
||||
def initialize(@up_to)
|
||||
end
|
||||
|
||||
def to_s(io)
|
||||
|
@ -92,7 +91,7 @@ module Chalk
|
|||
class ReturnInstruction < Instruction
|
||||
property to_return : Int32
|
||||
|
||||
def initialize(@to_return : Int32)
|
||||
def initialize(@to_return)
|
||||
end
|
||||
|
||||
def to_s(io)
|
||||
|
@ -100,4 +99,36 @@ module Chalk
|
|||
@to_return.to_s(16, io)
|
||||
end
|
||||
end
|
||||
|
||||
class JumpEqInstruction < Instruction
|
||||
property offset : Int32
|
||||
property left : Int32
|
||||
property right : Int32
|
||||
|
||||
def initialize(@offset, @left, @right)
|
||||
end
|
||||
|
||||
def to_s(io)
|
||||
io << "jeq " << offset << " R"
|
||||
@left.to_s(16, io)
|
||||
io << " " << right
|
||||
end
|
||||
end
|
||||
|
||||
class JumpEqRegInstruction < Instruction
|
||||
property offset : Int32
|
||||
property left : Int32
|
||||
property right : Int32
|
||||
|
||||
def initialize(@offset, @left, @right)
|
||||
end
|
||||
|
||||
def to_s(io)
|
||||
io << "jeq " << offset << " R"
|
||||
@left.to_s(16, io)
|
||||
io << " R"
|
||||
@right.to_s(16, io)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -5,8 +5,7 @@ module Chalk
|
|||
abstract def parse?(tokens : Array(Token),
|
||||
index : Int64) : Tuple(T, Int64)?
|
||||
|
||||
def parse(tokens : Array(Token),
|
||||
index : Int64) : Tuple(T, Int64)
|
||||
def parse(tokens, index)
|
||||
return parse?(tokens, index).not_nil!
|
||||
end
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ module Chalk
|
|||
property function : TreeFunction
|
||||
property addr : Int32
|
||||
|
||||
def initialize(@function : TreeFunction, @addr : Int32 = -1)
|
||||
def initialize(@function, @addr = -1)
|
||||
end
|
||||
|
||||
def to_s(io)
|
||||
|
@ -17,7 +17,7 @@ module Chalk
|
|||
class VarEntry < Entry
|
||||
property register : Int32
|
||||
|
||||
def initialize(@register : Int32)
|
||||
def initialize(@register)
|
||||
end
|
||||
|
||||
def to_s(io)
|
||||
|
@ -28,11 +28,11 @@ module Chalk
|
|||
class Table
|
||||
property parent : Table?
|
||||
|
||||
def initialize(@parent : Table? = nil)
|
||||
def initialize(@parent = nil)
|
||||
@data = {} of String => Entry
|
||||
end
|
||||
|
||||
def []?(key) : Entry?
|
||||
def []?(key)
|
||||
if entry = @data[key]?
|
||||
return entry
|
||||
end
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
module Chalk
|
||||
class Visitor
|
||||
def visit(tree : Tree)
|
||||
def visit(tree)
|
||||
end
|
||||
|
||||
def finish(tree : Tree)
|
||||
def finish(tree)
|
||||
end
|
||||
end
|
||||
|
||||
class Transformer
|
||||
def transform(tree : Tree) : Tree
|
||||
def transform(tree)
|
||||
return tree
|
||||
end
|
||||
end
|
||||
|
||||
class Tree
|
||||
def accept(v : Visitor)
|
||||
def accept(v)
|
||||
v.visit(self)
|
||||
v.finish(self)
|
||||
end
|
||||
|
||||
def apply(t : Transformer)
|
||||
def apply(t)
|
||||
return t.transform(self)
|
||||
end
|
||||
end
|
||||
|
@ -27,14 +27,14 @@ module Chalk
|
|||
class TreeId < Tree
|
||||
property id : String
|
||||
|
||||
def initialize(@id : String)
|
||||
def initialize(@id)
|
||||
end
|
||||
end
|
||||
|
||||
class TreeLit < Tree
|
||||
property lit : Int64
|
||||
|
||||
def initialize(@lit : Int64)
|
||||
def initialize(@lit)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -42,16 +42,16 @@ module Chalk
|
|||
property name : String
|
||||
property params : Array(Tree)
|
||||
|
||||
def initialize(@name : String, @params : Array(Tree))
|
||||
def initialize(@name, @params)
|
||||
end
|
||||
|
||||
def accept(v : Visitor)
|
||||
def accept(v)
|
||||
v.visit(self)
|
||||
@params.each &.accept(v)
|
||||
v.finish(self)
|
||||
end
|
||||
|
||||
def apply(t : Transformer)
|
||||
def apply(t)
|
||||
@params.map! do |param|
|
||||
param.apply(t)
|
||||
end
|
||||
|
@ -64,17 +64,17 @@ module Chalk
|
|||
property left : Tree
|
||||
property right : Tree
|
||||
|
||||
def initialize(@op : TokenType, @left : Tree, @right : Tree)
|
||||
def initialize(@op, @left, @right)
|
||||
end
|
||||
|
||||
def accept(v : Visitor)
|
||||
def accept(v)
|
||||
v.visit(self)
|
||||
@left.accept(v)
|
||||
@right.accept(v)
|
||||
v.finish(self)
|
||||
end
|
||||
|
||||
def apply(t : Transformer)
|
||||
def apply(t)
|
||||
@left = @left.apply(t)
|
||||
@right = @right.apply(t)
|
||||
return t.transform(self)
|
||||
|
@ -84,16 +84,16 @@ module Chalk
|
|||
class TreeBlock < Tree
|
||||
property children : Array(Tree)
|
||||
|
||||
def initialize(@children : Array(Tree))
|
||||
def initialize(@children)
|
||||
end
|
||||
|
||||
def accept(v : Visitor)
|
||||
def accept(v)
|
||||
v.visit(self)
|
||||
@children.each &.accept(v)
|
||||
v.finish(self)
|
||||
end
|
||||
|
||||
def apply(t : Transformer)
|
||||
def apply(t)
|
||||
@children.map! do |child|
|
||||
child.apply(t)
|
||||
end
|
||||
|
@ -106,16 +106,16 @@ module Chalk
|
|||
property params : Array(String)
|
||||
property block : Tree
|
||||
|
||||
def initialize(@name : String, @params : Array(String), @block : Tree)
|
||||
def initialize(@name, @params, @block)
|
||||
end
|
||||
|
||||
def accept(v : Visitor)
|
||||
def accept(v)
|
||||
v.visit(self)
|
||||
@block.accept(v)
|
||||
v.finish(self)
|
||||
end
|
||||
|
||||
def apply(t : Transformer)
|
||||
def apply(t)
|
||||
@block = @block.apply(t)
|
||||
return t.transform(self)
|
||||
end
|
||||
|
@ -125,16 +125,16 @@ module Chalk
|
|||
property name : String
|
||||
property expr : Tree
|
||||
|
||||
def initialize(@name : String, @expr : Tree)
|
||||
def initialize(@name, @expr)
|
||||
end
|
||||
|
||||
def accept(v : Visitor)
|
||||
def accept(v)
|
||||
v.visit(self)
|
||||
@expr.accept(v)
|
||||
v.finish(self)
|
||||
end
|
||||
|
||||
def apply(t : Transformer)
|
||||
def apply(t)
|
||||
@expr = @expr.apply(t)
|
||||
return t.transform(self)
|
||||
end
|
||||
|
@ -144,16 +144,16 @@ module Chalk
|
|||
property name : String
|
||||
property expr : Tree
|
||||
|
||||
def initialize(@name : String, @expr : Tree)
|
||||
def initialize(@name, @expr)
|
||||
end
|
||||
|
||||
def accept(v : Visitor)
|
||||
def accept(v)
|
||||
v.visit(self)
|
||||
@expr.accept(v)
|
||||
v.finish(self)
|
||||
end
|
||||
|
||||
def apply(t : Transformer)
|
||||
def apply(t)
|
||||
@expr = @expr.apply(t)
|
||||
return t.transform(self)
|
||||
end
|
||||
|
@ -164,10 +164,10 @@ module Chalk
|
|||
property block : Tree
|
||||
property otherwise : Tree?
|
||||
|
||||
def initialize(@condition : Tree, @block : Tree, @otherwise : Tree? = nil)
|
||||
def initialize(@condition, @block, @otherwise = nil)
|
||||
end
|
||||
|
||||
def accept(v : Visitor)
|
||||
def accept(v)
|
||||
v.visit(self)
|
||||
@condition.accept(v)
|
||||
@block.accept(v)
|
||||
|
@ -175,7 +175,7 @@ module Chalk
|
|||
v.finish(self)
|
||||
end
|
||||
|
||||
def apply(t : Transformer)
|
||||
def apply(t)
|
||||
@condition = @condition.apply(t)
|
||||
@block = @block.apply(t)
|
||||
@otherwise = @otherwise.try &.apply(t)
|
||||
|
@ -187,17 +187,17 @@ module Chalk
|
|||
property condition : Tree
|
||||
property block : Tree
|
||||
|
||||
def initialize(@condition : Tree, @block : Tree)
|
||||
def initialize(@condition, @block)
|
||||
end
|
||||
|
||||
def accept(v : Visitor)
|
||||
def accept(v)
|
||||
v.visit(self)
|
||||
@condition.accept(v)
|
||||
@block.accept(v)
|
||||
v.finish(self)
|
||||
end
|
||||
|
||||
def apply(t : Transformer)
|
||||
def apply(t)
|
||||
@condition = @condition.apply(t)
|
||||
@block = @block.apply(t)
|
||||
return t.transform(self)
|
||||
|
@ -207,16 +207,16 @@ module Chalk
|
|||
class TreeReturn < Tree
|
||||
property rvalue : Tree
|
||||
|
||||
def initialize(@rvalue : Tree)
|
||||
def initialize(@rvalue)
|
||||
end
|
||||
|
||||
def accept(v : Visitor)
|
||||
def accept(v)
|
||||
v.visit(self)
|
||||
@rvalue.accept(v)
|
||||
v.finish(self)
|
||||
end
|
||||
|
||||
def apply(t : Transformer)
|
||||
def apply(t)
|
||||
@rvalue = @rvalue.apply(t)
|
||||
return t.transform(self)
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ module Chalk
|
|||
property file : String
|
||||
property mode : OutputMode
|
||||
|
||||
def initialize(@file : String = "",
|
||||
def initialize(@file = "",
|
||||
@mode = OutputMode::Tree)
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user