Improved code generation

This commit is contained in:
Eduard Urbach 2024-07-03 16:37:59 +02:00
parent 5ca086f177
commit 75672c1e16
Signed by: eduard
GPG key ID: 49226B848C78F6C8
15 changed files with 215 additions and 275 deletions

View file

@ -1,123 +0,0 @@
package core
import (
"git.akyoto.dev/cli/q/src/build/asm"
"git.akyoto.dev/cli/q/src/build/ast"
"git.akyoto.dev/cli/q/src/build/cpu"
"git.akyoto.dev/cli/q/src/build/expression"
"git.akyoto.dev/cli/q/src/build/token"
)
// Evaluate evaluates the result of an expression and saves it into a temporary register.
func (f *Function) Evaluate(root *expression.Expression) (*Variable, error) {
if root.IsLeaf() {
return f.EvaluateLeaf(root)
}
if ast.IsFunctionCall(root) {
return f.EvaluateCall(root)
}
left := root.Children[0]
right := root.Children[1]
tmpLeft, err := f.Evaluate(left)
if err != nil {
return nil, err
}
tmpLeftExpr := expression.NewLeaf(token.Token{
Kind: token.Identifier,
Position: left.Token.Position,
Bytes: []byte(tmpLeft.Name),
})
tmpLeftExpr.Parent = root
root.Children[0].Parent = nil
root.Children[0] = tmpLeftExpr
tmpRight, err := f.Evaluate(right)
if err != nil {
return nil, err
}
tmpRightExpr := expression.NewLeaf(token.Token{
Kind: token.Identifier,
Position: left.Token.Position,
Bytes: []byte(tmpRight.Name),
})
tmpRightExpr.Parent = root
root.Children[1].Parent = nil
root.Children[1] = tmpRightExpr
tmp := f.addTemporary(root)
f.assembler.RegisterRegister(asm.MOVE, tmp.Register, tmpLeft.Register)
f.useVariable(tmpLeft)
err = f.opRegisterRegister(root.Token, tmp.Register, tmpRight.Register)
f.useVariable(tmpRight)
return tmp, err
}
func (f *Function) EvaluateCall(root *expression.Expression) (*Variable, error) {
funcName := root.Children[0].Token.Text()
parameters := root.Children[1:]
registers := f.cpu.Call[:len(parameters)]
isSyscall := funcName == "syscall"
if isSyscall {
registers = f.cpu.Syscall[:len(parameters)]
}
err := f.ExpressionsToRegisters(parameters, registers)
for _, register := range f.cpu.General {
if !f.cpu.IsFree(register) {
f.assembler.Register(asm.PUSH, register)
}
}
if isSyscall {
f.assembler.Syscall()
} else {
f.assembler.Call(funcName)
}
for i := len(f.cpu.General) - 1; i >= 0; i-- {
register := f.cpu.General[i]
if !f.cpu.IsFree(register) {
f.assembler.Register(asm.POP, register)
}
}
tmp := f.addTemporary(root)
f.assembler.RegisterRegister(asm.MOVE, tmp.Register, f.cpu.Return[0])
return tmp, err
}
func (f *Function) EvaluateLeaf(root *expression.Expression) (*Variable, error) {
tmp := f.addTemporary(root)
err := f.TokenToRegister(root.Token, tmp.Register)
return tmp, err
}
func (f *Function) EvaluateTo(root *expression.Expression, register cpu.Register) error {
tmp, err := f.Evaluate(root)
if err != nil {
return err
}
if register != tmp.Register {
f.assembler.RegisterRegister(asm.MOVE, register, tmp.Register)
}
f.useVariable(tmp)
return nil
}