From cc8289445453582ecd800c71ba47316d9b32c63d Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 27 Jul 2018 19:56:26 -0700 Subject: [PATCH] Add support for binary generation. --- src/chalk/codegen.cr | 3 +- src/chalk/compiler.cr | 32 +++++++++++- src/chalk/ir.cr | 113 +++++++++++++++++++++++++++++++++--------- 3 files changed, 121 insertions(+), 27 deletions(-) diff --git a/src/chalk/codegen.cr b/src/chalk/codegen.cr index 183f592..3f1b0f7 100644 --- a/src/chalk/codegen.cr +++ b/src/chalk/codegen.cr @@ -131,7 +131,8 @@ module Chalk call tree.name # Reduce stack pointer - op TokenType::OpSub, STACK_REG, start_at + load free, start_at + opr TokenType::OpSub, STACK_REG, free # Move I to stack setis # Get to correct stack position diff --git a/src/chalk/compiler.cr b/src/chalk/compiler.cr index 0ad5f9f..c933f68 100644 --- a/src/chalk/compiler.cr +++ b/src/chalk/compiler.cr @@ -58,11 +58,15 @@ module Chalk end end - private def run_intermediate + private def generate_ir trees = create_trees(@config.file) table = process_initial(trees) raise "No main function!" unless table["main"]? - code = generate_code(trees, table) + return { table, generate_code(trees, table) } + end + + private def run_intermediate + table, code = generate_ir code.each do |name, insts| puts "Code for #{name}:" insts.each { |it| puts it } @@ -70,7 +74,31 @@ module Chalk end end + private def generate_binary(instructions) + end + private def run_binary + all_instructions = [] of Instruction + table, code = generate_ir + all_instructions.concat code["main"] + table["main"]?.as(FunctionEntry).addr = 0 + all_instructions << JumpRelativeInstruction.new 0 + code.delete "main" + code.each do |key, value| + table[key]?.as(FunctionEntry).addr = all_instructions.size + all_instructions.concat(value) + all_instructions << ReturnInstruction.new + end + context = InstructionContext.new table, all_instructions.size + binary = all_instructions.map_with_index { |it, i| it.to_bin(context, i).to_u16 } + file = File.open("out.ch8", "w") + binary.each do |inst| + first = (inst >> 8).to_u8 + file.write_byte(first) + second = (inst & 0xff).to_u8 + file.write_byte(second) + end + file.close end def run diff --git a/src/chalk/ir.cr b/src/chalk/ir.cr index ded53bf..a10dfbb 100644 --- a/src/chalk/ir.cr +++ b/src/chalk/ir.cr @@ -2,6 +2,17 @@ require "./lexer.cr" module Chalk class Instruction + def to_bin(i, index) + return 0 + end + end + + class InstructionContext + property table : Table + property stack : Int32 + + def initialize(@table, @stack) + end end class LoadInstruction < Instruction @@ -16,6 +27,10 @@ module Chalk @register.to_s(16, io) io << " " << @value end + + def to_bin(i, index) + 0x6000 | (register << 8) | value + end end class LoadRegInstruction < Instruction @@ -31,6 +46,10 @@ module Chalk io << " R" @from.to_s(16, io) end + + def to_bin(i, index) + 0x8000 | (into << 8) | (from << 4) + end end class OpInstruction < Instruction @@ -46,6 +65,15 @@ module Chalk @into.to_s(16, io) io << " " << @value end + + def to_bin(i, index) + case op + when TokenType::OpAdd + return 0x7000 | (into << 8) | value + else + raise "Invalid instruction" + end + end end class OpRegInstruction < Instruction @@ -62,6 +90,25 @@ module Chalk io << " R" @from.to_s(16, io) end + + def to_bin(i, index) + code = 0 + case op + when TokenType::OpAdd + code = 4 + when TokenType::OpSub + code = 5 + when TokenType::OpOr + code = 1 + when TokenType::OpAnd + code = 2 + when TokenType::OpXor + code = 3 + else + raise "Invalid instruction" + end + return 0x8000 | (into << 8) | (from << 4) | code + end end class StoreInstruction < Instruction @@ -74,6 +121,10 @@ module Chalk io << "store R" @up_to.to_s(16, io) end + + def to_bin(i, index) + return 0xf055 | (up_to << 8) + end end class RestoreInstruction < Instruction @@ -86,6 +137,10 @@ module Chalk io << "restore R" @up_to.to_s(16, io) end + + def to_bin(i, index) + return 0xf065 | (up_to << 8) + end end class ReturnInstruction < Instruction @@ -95,20 +150,9 @@ module Chalk def to_s(io) io << "return" 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 + def to_bin(i, index) + return 0x00ee end end @@ -121,6 +165,10 @@ module Chalk def to_s(io) io << "jr " << @offset end + + def to_bin(i, index) + return 0x1000 | ((offset + index) * 2 + 0x200) + end end class SkipEqInstruction < Instruction @@ -135,6 +183,10 @@ module Chalk @left.to_s(16, io) io << " " << right end + + def to_bin(i, index) + return 0x3000 | (left << 8) | right + end end class SkipNeInstruction < Instruction @@ -149,6 +201,10 @@ module Chalk @left.to_s(16, io) io << " " << right end + + def to_bin(i, index) + return 0x4000 | (left << 8) | right + end end class SkipRegEqInstruction < Instruction @@ -164,6 +220,10 @@ module Chalk io << " R" @right.to_s(16, io) end + + def to_bin(i, index) + return 0x5000 | (left << 8) | (right << 4) + end end class SkipRegNeInstruction < Instruction @@ -179,6 +239,10 @@ module Chalk io << " R" @right.to_s(16, io) end + + def to_bin(i, index) + return 0x9000 | (left << 8) | (right << 4) + end end class CallInstruction < Instruction @@ -190,23 +254,20 @@ module Chalk def to_s(io) io << "call " << @name end + + def to_bin(i, index) + return 0x2000 | (i.table[name]?.as(FunctionEntry).addr * 2 + 0x200) + end end - class SetIInstruction < Instruction - property value : Int32 - - def initialize(@value) - end - - def to_s(io) - io << "seti " << @value - end - end - class SetIStackInstruction < Instruction def to_s(io) io << "setis" end + + def to_bin(i, index) + return 0xa000 | (i.stack * 2 + 0x200) + end end class AddIRegInstruction < Instruction @@ -219,5 +280,9 @@ module Chalk io << "addi R" reg.to_s(16, io) end + + def to_bin(i, index) + return 0xf000 | (reg << 8) | 0x1e + end end end