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.
|
||||
func (f *Function) ExecuteRegisterNumber(operation token.Token, register cpu.Register, number int) error {
|
||||
if !operation.IsAssignment() && !operation.IsComparison() {
|
||||
f.SaveRegister(register)
|
||||
}
|
||||
|
||||
switch operation.Kind {
|
||||
case token.Add, token.AddAssign:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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.
|
||||
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 {
|
||||
case token.Add, token.AddAssign:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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.
|
||||
func (f *Function) ExpressionToRegister(node *expression.Expression, register cpu.Register) error {
|
||||
if node.IsFolded {
|
||||
f.SaveRegister(register)
|
||||
f.RegisterNumber(asm.MOVE, register, node.Value)
|
||||
return nil
|
||||
}
|
||||
@ -24,6 +25,7 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp
|
||||
err := f.CompileCall(node)
|
||||
|
||||
if register != f.CPU.Output[0] {
|
||||
f.SaveRegister(register)
|
||||
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)
|
||||
|
||||
if register != final {
|
||||
f.SaveRegister(final)
|
||||
f.RegisterRegister(asm.MOVE, final, register)
|
||||
f.FreeRegister(register)
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
|
||||
}
|
||||
|
||||
f.UseVariable(variable)
|
||||
f.SaveRegister(register)
|
||||
f.RegisterRegister(asm.MOVE, register, variable.Register)
|
||||
return nil
|
||||
|
||||
@ -30,6 +31,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
|
||||
return err
|
||||
}
|
||||
|
||||
f.SaveRegister(register)
|
||||
f.RegisterNumber(asm.MOVE, register, number)
|
||||
return nil
|
||||
|
||||
@ -37,6 +39,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
|
||||
data := t.Bytes(f.File.Bytes)
|
||||
data = String(data)
|
||||
label := f.AddBytes(data)
|
||||
f.SaveRegister(register)
|
||||
f.RegisterLabel(asm.MOVE, register, label)
|
||||
return nil
|
||||
|
||||
|
@ -6,10 +6,6 @@ import (
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
if mnemonic == asm.MOVE {
|
||||
|
@ -7,10 +7,6 @@ import (
|
||||
)
|
||||
|
||||
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.
|
||||
if mnemonic == asm.MOVE {
|
||||
f.Assembler.RegisterNumber(mnemonic, a, b)
|
||||
|
@ -10,10 +10,6 @@ func (f *Machine) RegisterRegister(mnemonic asm.Mnemonic, a cpu.Register, b cpu.
|
||||
return
|
||||
}
|
||||
|
||||
if f.RegisterIsUsed(a) && isDestructive(mnemonic) {
|
||||
f.SaveRegister(a)
|
||||
}
|
||||
|
||||
f.Assembler.RegisterRegister(mnemonic, a, b)
|
||||
|
||||
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 // >>
|
||||
LogicalAnd // &&
|
||||
LogicalOr // ||
|
||||
_comparisons // <comparisons>
|
||||
Equal // ==
|
||||
NotEqual // !=
|
||||
Less // <
|
||||
Greater // >
|
||||
NotEqual // !=
|
||||
LessEqual // <=
|
||||
GreaterEqual // >=
|
||||
_comparisonsEnd // </comparisons>
|
||||
Define // :=
|
||||
Period // .
|
||||
Call // x()
|
||||
|
@ -28,6 +28,11 @@ func (t Token) IsAssignment() bool {
|
||||
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.
|
||||
func (t Token) IsExpressionStart() bool {
|
||||
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},
|
||||
{"math", "", "", 0},
|
||||
{"precedence", "", "", 0},
|
||||
{"op-assign", "", "", 0},
|
||||
{"binary", "", "", 0},
|
||||
{"octal", "", "", 0},
|
||||
{"hexadecimal", "", "", 0},
|
||||
|
Loading…
Reference in New Issue
Block a user