Add support for binary generation.
This commit is contained in:
		
							parent
							
								
									99a47be826
								
							
						
					
					
						commit
						cc82894454
					
				@ -131,7 +131,8 @@ module Chalk
 | 
				
			|||||||
        call tree.name
 | 
					        call tree.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Reduce stack pointer
 | 
					        # Reduce stack pointer
 | 
				
			||||||
        op TokenType::OpSub, STACK_REG, start_at
 | 
					        load free, start_at
 | 
				
			||||||
 | 
					        opr TokenType::OpSub, STACK_REG, free
 | 
				
			||||||
        # Move I to stack
 | 
					        # Move I to stack
 | 
				
			||||||
        setis
 | 
					        setis
 | 
				
			||||||
        # Get to correct stack position
 | 
					        # Get to correct stack position
 | 
				
			||||||
 | 
				
			|||||||
@ -58,11 +58,15 @@ module Chalk
 | 
				
			|||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private def run_intermediate
 | 
					    private def generate_ir
 | 
				
			||||||
      trees = create_trees(@config.file)
 | 
					      trees = create_trees(@config.file)
 | 
				
			||||||
      table = process_initial(trees)
 | 
					      table = process_initial(trees)
 | 
				
			||||||
      raise "No main function!" unless table["main"]?
 | 
					      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|
 | 
					      code.each do |name, insts|
 | 
				
			||||||
        puts "Code for #{name}:"
 | 
					        puts "Code for #{name}:"
 | 
				
			||||||
        insts.each { |it| puts it }
 | 
					        insts.each { |it| puts it }
 | 
				
			||||||
@ -70,7 +74,31 @@ module Chalk
 | 
				
			|||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private def generate_binary(instructions)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private def run_binary
 | 
					    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
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def run
 | 
					    def run
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										109
									
								
								src/chalk/ir.cr
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								src/chalk/ir.cr
									
									
									
									
									
								
							@ -2,6 +2,17 @@ require "./lexer.cr"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
module Chalk
 | 
					module Chalk
 | 
				
			||||||
  class Instruction
 | 
					  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
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class LoadInstruction < Instruction
 | 
					  class LoadInstruction < Instruction
 | 
				
			||||||
@ -16,6 +27,10 @@ module Chalk
 | 
				
			|||||||
      @register.to_s(16, io)
 | 
					      @register.to_s(16, io)
 | 
				
			||||||
      io << " " << @value
 | 
					      io << " " << @value
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_bin(i, index)
 | 
				
			||||||
 | 
					        0x6000 | (register << 8) | value
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class LoadRegInstruction < Instruction
 | 
					  class LoadRegInstruction < Instruction
 | 
				
			||||||
@ -31,6 +46,10 @@ module Chalk
 | 
				
			|||||||
      io << " R"
 | 
					      io << " R"
 | 
				
			||||||
      @from.to_s(16, io)
 | 
					      @from.to_s(16, io)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_bin(i, index)
 | 
				
			||||||
 | 
					        0x8000 | (into << 8) | (from << 4)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class OpInstruction < Instruction
 | 
					  class OpInstruction < Instruction
 | 
				
			||||||
@ -46,6 +65,15 @@ module Chalk
 | 
				
			|||||||
      @into.to_s(16, io)
 | 
					      @into.to_s(16, io)
 | 
				
			||||||
      io << " " << @value
 | 
					      io << " " << @value
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_bin(i, index)
 | 
				
			||||||
 | 
					        case op
 | 
				
			||||||
 | 
					        when TokenType::OpAdd
 | 
				
			||||||
 | 
					            return 0x7000 | (into << 8) | value
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            raise "Invalid instruction"
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class OpRegInstruction < Instruction
 | 
					  class OpRegInstruction < Instruction
 | 
				
			||||||
@ -62,6 +90,25 @@ module Chalk
 | 
				
			|||||||
      io << " R"
 | 
					      io << " R"
 | 
				
			||||||
      @from.to_s(16, io)
 | 
					      @from.to_s(16, io)
 | 
				
			||||||
    end
 | 
					    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
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class StoreInstruction < Instruction
 | 
					  class StoreInstruction < Instruction
 | 
				
			||||||
@ -74,6 +121,10 @@ module Chalk
 | 
				
			|||||||
      io << "store R"
 | 
					      io << "store R"
 | 
				
			||||||
      @up_to.to_s(16, io)
 | 
					      @up_to.to_s(16, io)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_bin(i, index)
 | 
				
			||||||
 | 
					        return 0xf055 | (up_to << 8)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class RestoreInstruction < Instruction
 | 
					  class RestoreInstruction < Instruction
 | 
				
			||||||
@ -86,6 +137,10 @@ module Chalk
 | 
				
			|||||||
      io << "restore R"
 | 
					      io << "restore R"
 | 
				
			||||||
      @up_to.to_s(16, io)
 | 
					      @up_to.to_s(16, io)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_bin(i, index)
 | 
				
			||||||
 | 
					        return 0xf065 | (up_to << 8)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class ReturnInstruction < Instruction
 | 
					  class ReturnInstruction < Instruction
 | 
				
			||||||
@ -95,20 +150,9 @@ module Chalk
 | 
				
			|||||||
    def to_s(io)
 | 
					    def to_s(io)
 | 
				
			||||||
      io << "return"
 | 
					      io << "return"
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class JumpEqInstruction < Instruction
 | 
					    def to_bin(i, index)
 | 
				
			||||||
    property offset : Int32
 | 
					        return 0x00ee
 | 
				
			||||||
    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
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -121,6 +165,10 @@ module Chalk
 | 
				
			|||||||
    def to_s(io)
 | 
					    def to_s(io)
 | 
				
			||||||
      io << "jr " << @offset
 | 
					      io << "jr " << @offset
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_bin(i, index)
 | 
				
			||||||
 | 
					        return 0x1000 | ((offset + index) * 2 + 0x200)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class SkipEqInstruction < Instruction
 | 
					  class SkipEqInstruction < Instruction
 | 
				
			||||||
@ -135,6 +183,10 @@ module Chalk
 | 
				
			|||||||
      @left.to_s(16, io)
 | 
					      @left.to_s(16, io)
 | 
				
			||||||
      io << " " << right
 | 
					      io << " " << right
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_bin(i, index)
 | 
				
			||||||
 | 
					        return 0x3000 | (left << 8) | right
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class SkipNeInstruction < Instruction
 | 
					  class SkipNeInstruction < Instruction
 | 
				
			||||||
@ -149,6 +201,10 @@ module Chalk
 | 
				
			|||||||
      @left.to_s(16, io)
 | 
					      @left.to_s(16, io)
 | 
				
			||||||
      io << " " << right
 | 
					      io << " " << right
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_bin(i, index)
 | 
				
			||||||
 | 
					        return 0x4000 | (left << 8) | right
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class SkipRegEqInstruction < Instruction
 | 
					  class SkipRegEqInstruction < Instruction
 | 
				
			||||||
@ -164,6 +220,10 @@ module Chalk
 | 
				
			|||||||
      io << " R"
 | 
					      io << " R"
 | 
				
			||||||
      @right.to_s(16, io)
 | 
					      @right.to_s(16, io)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_bin(i, index)
 | 
				
			||||||
 | 
					        return 0x5000 | (left << 8) | (right << 4)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class SkipRegNeInstruction < Instruction
 | 
					  class SkipRegNeInstruction < Instruction
 | 
				
			||||||
@ -179,6 +239,10 @@ module Chalk
 | 
				
			|||||||
      io << " R"
 | 
					      io << " R"
 | 
				
			||||||
      @right.to_s(16, io)
 | 
					      @right.to_s(16, io)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_bin(i, index)
 | 
				
			||||||
 | 
					        return 0x9000 | (left << 8) | (right << 4)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class CallInstruction < Instruction
 | 
					  class CallInstruction < Instruction
 | 
				
			||||||
@ -190,16 +254,9 @@ module Chalk
 | 
				
			|||||||
    def to_s(io)
 | 
					    def to_s(io)
 | 
				
			||||||
      io << "call " << @name
 | 
					      io << "call " << @name
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class SetIInstruction < Instruction
 | 
					    def to_bin(i, index)
 | 
				
			||||||
    property value : Int32
 | 
					        return 0x2000 | (i.table[name]?.as(FunctionEntry).addr * 2 + 0x200)
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def initialize(@value)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def to_s(io)
 | 
					 | 
				
			||||||
      io << "seti " << @value
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
@ -207,6 +264,10 @@ module Chalk
 | 
				
			|||||||
    def to_s(io)
 | 
					    def to_s(io)
 | 
				
			||||||
      io << "setis"
 | 
					      io << "setis"
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_bin(i, index)
 | 
				
			||||||
 | 
					        return 0xa000 | (i.stack * 2 + 0x200)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class AddIRegInstruction < Instruction
 | 
					  class AddIRegInstruction < Instruction
 | 
				
			||||||
@ -219,5 +280,9 @@ module Chalk
 | 
				
			|||||||
      io << "addi R"
 | 
					      io << "addi R"
 | 
				
			||||||
      reg.to_s(16, io)
 | 
					      reg.to_s(16, io)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_bin(i, index)
 | 
				
			||||||
 | 
					        return 0xf000 | (reg << 8) | 0x1e
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user