Fixed incorrect register move

This commit is contained in:
Eduard Urbach 2024-08-02 12:55:25 +02:00
parent 34d865986a
commit b1f0d20394
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
12 changed files with 38 additions and 31 deletions

View File

@ -9,6 +9,10 @@ import (
// ExecuteRegisterNumber performs an operation on a register and a number. // ExecuteRegisterNumber performs an operation on a register and a number.
func (f *Function) ExecuteRegisterNumber(operation token.Token, register cpu.Register, number int) error { func (f *Function) ExecuteRegisterNumber(operation token.Token, register cpu.Register, number int) error {
if !operation.IsAssignment() && !operation.IsComparison() {
f.SaveRegister(register)
}
switch operation.Kind { switch operation.Kind {
case token.Add, token.AddAssign: case token.Add, token.AddAssign:
f.RegisterNumber(asm.ADD, register, number) f.RegisterNumber(asm.ADD, register, number)
@ -40,12 +44,12 @@ func (f *Function) ExecuteRegisterNumber(operation token.Token, register cpu.Reg
case token.Shr, token.ShrAssign: case token.Shr, token.ShrAssign:
f.RegisterNumber(asm.SHIFTRS, register, number) f.RegisterNumber(asm.SHIFTRS, register, number)
case token.Equal, token.NotEqual, token.Less, token.LessEqual, token.Greater, token.GreaterEqual:
f.RegisterNumber(asm.COMPARE, register, number)
case token.Assign: case token.Assign:
f.RegisterNumber(asm.MOVE, register, number) f.RegisterNumber(asm.MOVE, register, number)
case token.Equal, token.NotEqual, token.Less, token.LessEqual, token.Greater, token.GreaterEqual:
f.RegisterNumber(asm.COMPARE, register, number)
default: default:
return errors.New(&errors.InvalidOperator{Operator: operation.Text(f.File.Bytes)}, f.File, operation.Position) return errors.New(&errors.InvalidOperator{Operator: operation.Text(f.File.Bytes)}, f.File, operation.Position)
} }

View File

@ -9,6 +9,10 @@ import (
// ExecuteRegisterRegister performs an operation on two registers. // ExecuteRegisterRegister performs an operation on two registers.
func (f *Function) ExecuteRegisterRegister(operation token.Token, register cpu.Register, operand cpu.Register) error { func (f *Function) ExecuteRegisterRegister(operation token.Token, register cpu.Register, operand cpu.Register) error {
if !operation.IsAssignment() && !operation.IsComparison() {
f.SaveRegister(register)
}
switch operation.Kind { switch operation.Kind {
case token.Add, token.AddAssign: case token.Add, token.AddAssign:
f.RegisterRegister(asm.ADD, register, operand) f.RegisterRegister(asm.ADD, register, operand)
@ -34,12 +38,12 @@ func (f *Function) ExecuteRegisterRegister(operation token.Token, register cpu.R
case token.Xor, token.XorAssign: case token.Xor, token.XorAssign:
f.RegisterRegister(asm.XOR, register, operand) f.RegisterRegister(asm.XOR, register, operand)
case token.Equal, token.NotEqual, token.Less, token.LessEqual, token.Greater, token.GreaterEqual:
f.RegisterRegister(asm.COMPARE, register, operand)
case token.Assign: case token.Assign:
f.RegisterRegister(asm.MOVE, register, operand) f.RegisterRegister(asm.MOVE, register, operand)
case token.Equal, token.NotEqual, token.Less, token.LessEqual, token.Greater, token.GreaterEqual:
f.RegisterRegister(asm.COMPARE, register, operand)
default: default:
return errors.New(&errors.InvalidOperator{Operator: operation.Text(f.File.Bytes)}, f.File, operation.Position) return errors.New(&errors.InvalidOperator{Operator: operation.Text(f.File.Bytes)}, f.File, operation.Position)
} }

View File

@ -12,6 +12,7 @@ import (
// ExpressionToRegister puts the result of an expression into the specified register. // ExpressionToRegister puts the result of an expression into the specified register.
func (f *Function) ExpressionToRegister(node *expression.Expression, register cpu.Register) error { func (f *Function) ExpressionToRegister(node *expression.Expression, register cpu.Register) error {
if node.IsFolded { if node.IsFolded {
f.SaveRegister(register)
f.RegisterNumber(asm.MOVE, register, node.Value) f.RegisterNumber(asm.MOVE, register, node.Value)
return nil return nil
} }
@ -24,6 +25,7 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp
err := f.CompileCall(node) err := f.CompileCall(node)
if register != f.CPU.Output[0] { if register != f.CPU.Output[0] {
f.SaveRegister(register)
f.RegisterRegister(asm.MOVE, register, f.CPU.Output[0]) f.RegisterRegister(asm.MOVE, register, f.CPU.Output[0])
} }
@ -68,6 +70,7 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp
err = f.Execute(node.Token, register, right) err = f.Execute(node.Token, register, right)
if register != final { if register != final {
f.SaveRegister(final)
f.RegisterRegister(asm.MOVE, final, register) f.RegisterRegister(asm.MOVE, final, register)
f.FreeRegister(register) f.FreeRegister(register)
} }

View File

@ -20,6 +20,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
} }
f.UseVariable(variable) f.UseVariable(variable)
f.SaveRegister(register)
f.RegisterRegister(asm.MOVE, register, variable.Register) f.RegisterRegister(asm.MOVE, register, variable.Register)
return nil return nil
@ -30,6 +31,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
return err return err
} }
f.SaveRegister(register)
f.RegisterNumber(asm.MOVE, register, number) f.RegisterNumber(asm.MOVE, register, number)
return nil return nil
@ -37,6 +39,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
data := t.Bytes(f.File.Bytes) data := t.Bytes(f.File.Bytes)
data = String(data) data = String(data)
label := f.AddBytes(data) label := f.AddBytes(data)
f.SaveRegister(register)
f.RegisterLabel(asm.MOVE, register, label) f.RegisterLabel(asm.MOVE, register, label)
return nil return nil

View File

@ -6,10 +6,6 @@ import (
) )
func (f *Machine) RegisterLabel(mnemonic asm.Mnemonic, register cpu.Register, label string) { func (f *Machine) RegisterLabel(mnemonic asm.Mnemonic, register cpu.Register, label string) {
if f.RegisterIsUsed(register) && isDestructive(mnemonic) {
f.SaveRegister(register)
}
f.Assembler.RegisterLabel(mnemonic, register, label) f.Assembler.RegisterLabel(mnemonic, register, label)
if mnemonic == asm.MOVE { if mnemonic == asm.MOVE {

View File

@ -7,10 +7,6 @@ import (
) )
func (f *Machine) RegisterNumber(mnemonic asm.Mnemonic, a cpu.Register, b int) { func (f *Machine) RegisterNumber(mnemonic asm.Mnemonic, a cpu.Register, b int) {
if f.RegisterIsUsed(a) && isDestructive(mnemonic) {
f.SaveRegister(a)
}
// The `MOVE` operation is very flexible and works with any type of immediate number. // The `MOVE` operation is very flexible and works with any type of immediate number.
if mnemonic == asm.MOVE { if mnemonic == asm.MOVE {
f.Assembler.RegisterNumber(mnemonic, a, b) f.Assembler.RegisterNumber(mnemonic, a, b)

View File

@ -10,10 +10,6 @@ func (f *Machine) RegisterRegister(mnemonic asm.Mnemonic, a cpu.Register, b cpu.
return return
} }
if f.RegisterIsUsed(a) && isDestructive(mnemonic) {
f.SaveRegister(a)
}
f.Assembler.RegisterRegister(mnemonic, a, b) f.Assembler.RegisterRegister(mnemonic, a, b)
if mnemonic == asm.MOVE { if mnemonic == asm.MOVE {

View File

@ -1,12 +0,0 @@
package register
import "git.akyoto.dev/cli/q/src/build/asm"
func isDestructive(mnemonic asm.Mnemonic) bool {
switch mnemonic {
case asm.MOVE, asm.ADD, asm.SUB, asm.MUL, asm.DIV, asm.MODULO, asm.AND, asm.OR, asm.XOR, asm.SHIFTL, asm.SHIFTRS, asm.NEGATE:
return true
default:
return false
}
}

View File

@ -31,12 +31,14 @@ const (
Shr // >> Shr // >>
LogicalAnd // && LogicalAnd // &&
LogicalOr // || LogicalOr // ||
_comparisons // <comparisons>
Equal // == Equal // ==
NotEqual // !=
Less // < Less // <
Greater // > Greater // >
NotEqual // !=
LessEqual // <= LessEqual // <=
GreaterEqual // >= GreaterEqual // >=
_comparisonsEnd // </comparisons>
Define // := Define // :=
Period // . Period // .
Call // x() Call // x()

View File

@ -28,6 +28,11 @@ func (t Token) IsAssignment() bool {
return t.Kind > _assignments && t.Kind < _assignmentsEnd return t.Kind > _assignments && t.Kind < _assignmentsEnd
} }
// IsComparison returns true if the token is a comparison operator.
func (t Token) IsComparison() bool {
return t.Kind > _comparisons && t.Kind < _comparisonsEnd
}
// IsExpressionStart returns true if the token starts an expression. // IsExpressionStart returns true if the token starts an expression.
func (t Token) IsExpressionStart() bool { func (t Token) IsExpressionStart() bool {
return t.Kind == GroupStart || t.Kind == ArrayStart || t.Kind == BlockStart return t.Kind == GroupStart || t.Kind == ArrayStart || t.Kind == BlockStart

View File

@ -0,0 +1,9 @@
main() {
f(10)
}
f(new) {
old := new
new -= 1
assert new != old
}

View File

@ -26,6 +26,7 @@ var programs = []struct {
{"return", "", "", 0}, {"return", "", "", 0},
{"math", "", "", 0}, {"math", "", "", 0},
{"precedence", "", "", 0}, {"precedence", "", "", 0},
{"op-assign", "", "", 0},
{"binary", "", "", 0}, {"binary", "", "", 0},
{"octal", "", "", 0}, {"octal", "", "", 0},
{"hexadecimal", "", "", 0}, {"hexadecimal", "", "", 0},