Make inline functions more high level.

This commit is contained in:
Danila Fedorin 2018-08-03 16:09:09 -07:00
parent ecbe84134d
commit 4de89d98a1
4 changed files with 62 additions and 41 deletions

View File

@ -8,11 +8,6 @@ module Chalk
class CodeGenerator
include Emitter
# The register into which the return value of a function is stored.
RETURN_REG = 14
# The register into which the "stack pointer" is stored.
STACK_REG = 13
# Gets the instructions currently emitted by this code generator.
getter instructions
@ -42,10 +37,7 @@ module Chalk
# `#generate!` call.
def generate!(tree, function : Trees::TreeFunction | Builtin::BuiltinFunction, table, target, free)
start_at = free
# Move I to stack
setis
# Get to correct stack position
addi STACK_REG
to_stack
# Store variables
store (start_at - 1) unless start_at == 0
# Increment I and stack position
@ -67,10 +59,7 @@ module Chalk
# Reduce stack pointer
load free, start_at
opr TokenType::OpSub, STACK_REG, free
# Move I to stack
setis
# Get to correct stack position
addi STACK_REG
to_stack
# Restore
restore (start_at - 1) unless start_at == 0
# Get call value into target

View File

@ -53,11 +53,11 @@ module Chalk
end
@logger.debug("Done creating symbol table")
table["draw"] = FunctionEntry.new Builtin::InlineDrawFunction.new
table["get_key"] = FunctionEntry.new Builtin::InlineAwaitKeyFunction.new
table["get_font"] = FunctionEntry.new Builtin::InlineGetFontFunction.new
table["set_delay"] = FunctionEntry.new Builtin::InlineSetDelayFunction.new
table["get_delay"] = FunctionEntry.new Builtin::InlineGetDelayFunction.new
table["set_sound"] = FunctionEntry.new Builtin::InlineSetSoundFunction.new
table["draw_number"] = FunctionEntry.new Builtin::InlineDrawNumberFunction.new
return table
end

View File

@ -1,8 +1,19 @@
module Chalk
module Compiler
# The register into which the return value of a function is stored.
RETURN_REG = 14
# The register into which the "stack pointer" is stored.
STACK_REG = 13
# Module to emit instructions and store
# them into an existing array.
module Emitter
# Moves I to the next available value on the stack.
def to_stack
setis
addi STACK_REG
end
# Emits an instruction to load a *value* into a register, *into*.
def load(into, value)
inst = Ir::LoadInstruction.new into, value.to_i32

View File

@ -3,21 +3,6 @@ require "./type"
module Chalk
module Builtin
# Inline function to draw sprite at address I.
class InlineDrawFunction < InlineFunction
def generate!(emitter, params, table, target, free)
if !params[2].is_a?(Trees::TreeLit)
raise "Third parameter must be a constant."
end
emitter.generate! params[0], table, free, free + 1
emitter.generate! params[1], table, free + 1, free + 2
emitter.instructions << Ir::DrawInstruction.new free, free + 1, params[2].as(Trees::TreeLit).lit.to_i32
end
def type
return Compiler::FunctionType.new([Compiler::Type::U8] * 3, Compiler::Type::U0)
end
end
# Inline function to await for a key and return it.
class InlineAwaitKeyFunction < InlineFunction
def generate!(emitter, params, table, target, free)
@ -28,17 +13,6 @@ module Chalk
end
end
# Inline function to get font for a given value.
class InlineGetFontFunction < InlineFunction
def generate!(emitter, params, table, target, free)
emitter.generate! params[0], table, free, free + 1
emitter.instructions << Ir::GetFontInstruction.new free
end
def type
return Compiler::FunctionType.new([Compiler::Type::U8], Compiler::Type::U0)
end
end
# Inline function to set the delay timer.
class InlineSetDelayFunction < InlineFunction
def generate!(emitter, params, table, target, free)
@ -60,5 +34,52 @@ module Chalk
return Compiler::FunctionType.new(([] of Compiler::Type), Compiler::Type::U8)
end
end
# Function to set the sound timer.
class InlineSetSoundFunction < InlineFunction
def generate!(emitter, params, table, target, free)
emitter.generate! params[0], table, free, free + 1
emitter.instructions << Ir::SetSoundTimerInstruction.new free
end
def type
return Compiler::FunctionType.new([Compiler::Type::U8], Compiler::Type::U0)
end
end
# Function to draw numbers.
class InlineDrawNumberFunction < InlineFunction
def generate!(emitter, params, table, target, free)
emitter.to_stack
# Save variables from R0-R2
emitter.store 0x2
emitter.load free, 0x3
emitter.addi free
# Write BCD values to I
emitter.generate! params[0], table, free, free + 1
emitter.instructions << Ir::BCDInstruction.new free
emitter.restore 0x2
# Get the coordinates
free = 3 if free < 3
emitter.generate! params[1], table, free, free + 1
emitter.generate! params[2], table, free + 1, free + 2
# Draw
emitter.instructions << Ir::GetFontInstruction.new 0x0
emitter.instructions << Ir::DrawInstruction.new free, free + 1, 5
emitter.op(Compiler::TokenType::OpAdd, free, 6)
emitter.instructions << Ir::GetFontInstruction.new 0x1
emitter.instructions << Ir::DrawInstruction.new free, free + 1, 5
emitter.op(Compiler::TokenType::OpAdd, free, 6)
emitter.instructions << Ir::GetFontInstruction.new 0x2
emitter.instructions << Ir::DrawInstruction.new free, free + 1, 5
# Load variables from RO-R2 back
emitter.to_stack
emitter.restore 0x2
end
def type
return Compiler::FunctionType.new([Compiler::Type::U8] * 3, Compiler::Type::U0)
end
end
end
end