Fixed incorrect register move
This commit is contained in:
parent
34d865986a
commit
b1f0d20394
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
9
tests/programs/op-assign.q
Normal file
9
tests/programs/op-assign.q
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
main() {
|
||||||
|
f(10)
|
||||||
|
}
|
||||||
|
|
||||||
|
f(new) {
|
||||||
|
old := new
|
||||||
|
new -= 1
|
||||||
|
assert new != old
|
||||||
|
}
|
@ -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},
|
||||||
|
Loading…
Reference in New Issue
Block a user