diff --git a/src/asmc/move.go b/src/asmc/move.go index 11742b3..b4f76ae 100644 --- a/src/asmc/move.go +++ b/src/asmc/move.go @@ -23,7 +23,7 @@ func (c *compiler) move(x asm.Instruction) { opSize := len(c.code) - size - start regLabel := x.Data.(*asm.RegisterLabel) - if strings.HasPrefix(regLabel.Label, "data_") { + if strings.HasPrefix(regLabel.Label, "data ") { c.dataPointers = append(c.dataPointers, &pointer{ Position: Address(len(c.code) - size), OpSize: uint8(opSize), diff --git a/src/core/AddBytes.go b/src/core/AddBytes.go index bd620e0..a6c3955 100644 --- a/src/core/AddBytes.go +++ b/src/core/AddBytes.go @@ -1,13 +1,9 @@ package core -import ( - "fmt" -) - // AddBytes adds a sequence of bytes and returns its address as a label. func (f *Function) AddBytes(value []byte) string { f.count.data++ - label := fmt.Sprintf("data_%s_%d", f.UniqueName, f.count.data) + label := f.CreateLabel("data", f.count.data) f.Assembler.SetData(label, value) return label } diff --git a/src/core/ArrayElementToRegister.go b/src/core/ArrayElementToRegister.go index 66777b9..924f16f 100644 --- a/src/core/ArrayElementToRegister.go +++ b/src/core/ArrayElementToRegister.go @@ -20,6 +20,7 @@ func (f *Function) ArrayElementToRegister(node *expression.Expression, register return nil, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, node.Children[0].Token.Position) } + defer f.UseVariable(array) index := node.Children[1] memory := asm.Memory{ diff --git a/src/core/CompileAssert.go b/src/core/CompileAssert.go index f8608e0..f3db795 100644 --- a/src/core/CompileAssert.go +++ b/src/core/CompileAssert.go @@ -1,8 +1,6 @@ package core import ( - "fmt" - "git.akyoto.dev/cli/q/src/asm" "git.akyoto.dev/cli/q/src/ast" ) @@ -10,8 +8,8 @@ import ( // CompileAssert compiles an assertion. func (f *Function) CompileAssert(assert *ast.Assert) error { f.count.assert++ - success := fmt.Sprintf("%s_assert_%d_true", f.UniqueName, f.count.assert) - fail := fmt.Sprintf("%s_assert_%d_false", f.UniqueName, f.count.assert) + success := f.CreateLabel("assert true", f.count.assert) + fail := f.CreateLabel("assert false", f.count.assert) err := f.CompileCondition(assert.Condition, success, fail) if err != nil { diff --git a/src/core/CompileAssignDivision.go b/src/core/CompileAssignDivision.go index d9f5f5c..c427b04 100644 --- a/src/core/CompileAssignDivision.go +++ b/src/core/CompileAssignDivision.go @@ -38,7 +38,9 @@ func (f *Function) CompileAssignDivision(node *ast.Assign) error { divisor := right.Children[1] err = f.Execute(right.Token, dividendRegister, divisor) f.RegisterRegister(asm.MOVE, quotientVariable.Register, x86.RAX) + f.UseVariable(quotientVariable) f.RegisterRegister(asm.MOVE, remainderVariable.Register, x86.RDX) + f.UseVariable(remainderVariable) if isTemporary { f.FreeRegister(dividendRegister) diff --git a/src/core/CompileCondition.go b/src/core/CompileCondition.go index 28b16b9..0a31b5a 100644 --- a/src/core/CompileCondition.go +++ b/src/core/CompileCondition.go @@ -1,8 +1,6 @@ package core import ( - "fmt" - "git.akyoto.dev/cli/q/src/expression" "git.akyoto.dev/cli/q/src/token" ) @@ -12,7 +10,7 @@ func (f *Function) CompileCondition(condition *expression.Expression, successLab switch condition.Token.Kind { case token.LogicalOr: f.count.subBranch++ - leftFailLabel := fmt.Sprintf("%s_false_%d", f.UniqueName, f.count.subBranch) + leftFailLabel := f.CreateLabel("false", f.count.subBranch) // Left left := condition.Children[0] @@ -39,7 +37,7 @@ func (f *Function) CompileCondition(condition *expression.Expression, successLab case token.LogicalAnd: f.count.subBranch++ - leftSuccessLabel := fmt.Sprintf("%s_true_%d", f.UniqueName, f.count.subBranch) + leftSuccessLabel := f.CreateLabel("true", f.count.subBranch) // Left left := condition.Children[0] diff --git a/src/core/CompileFor.go b/src/core/CompileFor.go index 6cfde4c..b9a6d7f 100644 --- a/src/core/CompileFor.go +++ b/src/core/CompileFor.go @@ -1,8 +1,6 @@ package core import ( - "fmt" - "git.akyoto.dev/cli/q/src/asm" "git.akyoto.dev/cli/q/src/ast" "git.akyoto.dev/cli/q/src/cpu" @@ -19,8 +17,8 @@ func (f *Function) CompileFor(loop *ast.For) error { f.count.loop++ var ( - label = fmt.Sprintf("%s_loop_%d", f.UniqueName, f.count.loop) - labelEnd = fmt.Sprintf("%s_loop_%d_end", f.UniqueName, f.count.loop) + label = f.CreateLabel("for", f.count.loop) + labelEnd = f.CreateLabel("for end", f.count.loop) counter cpu.Register from *expression.Expression to *expression.Expression diff --git a/src/core/CompileIf.go b/src/core/CompileIf.go index 029d7e1..61fb3c6 100644 --- a/src/core/CompileIf.go +++ b/src/core/CompileIf.go @@ -1,8 +1,6 @@ package core import ( - "fmt" - "git.akyoto.dev/cli/q/src/asm" "git.akyoto.dev/cli/q/src/ast" ) @@ -17,8 +15,8 @@ func (f *Function) CompileIf(branch *ast.If) error { var ( end string - success = fmt.Sprintf("%s_if_%d_true", f.UniqueName, f.count.branch) - fail = fmt.Sprintf("%s_if_%d_false", f.UniqueName, f.count.branch) + success = f.CreateLabel("if true", f.count.branch) + fail = f.CreateLabel("if false", f.count.branch) err = f.CompileCondition(branch.Condition, success, fail) ) @@ -35,7 +33,7 @@ func (f *Function) CompileIf(branch *ast.If) error { } if branch.Else != nil { - end = fmt.Sprintf("%s_if_%d_end", f.UniqueName, f.count.branch) + end = f.CreateLabel("if end", f.count.branch) f.Jump(asm.JUMP, end) } diff --git a/src/core/CompileLoop.go b/src/core/CompileLoop.go index ea9aea7..13ccf90 100644 --- a/src/core/CompileLoop.go +++ b/src/core/CompileLoop.go @@ -1,8 +1,6 @@ package core import ( - "fmt" - "git.akyoto.dev/cli/q/src/asm" "git.akyoto.dev/cli/q/src/ast" ) @@ -14,7 +12,7 @@ func (f *Function) CompileLoop(loop *ast.Loop) error { } f.count.loop++ - label := fmt.Sprintf("%s_loop_%d", f.UniqueName, f.count.loop) + label := f.CreateLabel("loop", f.count.loop) f.AddLabel(label) scope := f.PushScope(loop.Body, f.File.Bytes) scope.InLoop = true diff --git a/src/core/CompileSwitch.go b/src/core/CompileSwitch.go index 7a08153..e62b8ca 100644 --- a/src/core/CompileSwitch.go +++ b/src/core/CompileSwitch.go @@ -1,8 +1,6 @@ package core import ( - "fmt" - "git.akyoto.dev/cli/q/src/asm" "git.akyoto.dev/cli/q/src/ast" ) @@ -10,7 +8,7 @@ import ( // CompileSwitch compiles a multi-branch instruction. func (f *Function) CompileSwitch(s *ast.Switch) error { f.count.multiBranch++ - end := fmt.Sprintf("%s_switch_%d_end", f.UniqueName, f.count.multiBranch) + end := f.CreateLabel("switch end", f.count.multiBranch) for _, branch := range s.Cases { if branch.Condition == nil { @@ -28,8 +26,8 @@ func (f *Function) CompileSwitch(s *ast.Switch) error { f.count.branch++ var ( - success = fmt.Sprintf("%s_case_%d_true", f.UniqueName, f.count.branch) - fail = fmt.Sprintf("%s_case_%d_false", f.UniqueName, f.count.branch) + success = f.CreateLabel("case true", f.count.branch) + fail = f.CreateLabel("case false", f.count.branch) err = f.CompileCondition(branch.Condition, success, fail) ) diff --git a/src/core/CreateLabel.go b/src/core/CreateLabel.go new file mode 100644 index 0000000..8ee8eb4 --- /dev/null +++ b/src/core/CreateLabel.go @@ -0,0 +1,18 @@ +package core + +import ( + "strconv" + "strings" +) + +// CreateLabel creates a label that is tied to this function by using a suffix. +func (f *Function) CreateLabel(prefix string, count int) string { + tmp := strings.Builder{} + tmp.WriteString(prefix) + tmp.WriteString(" ") + tmp.WriteString(strconv.Itoa(count)) + tmp.WriteString(" [") + tmp.WriteString(f.UniqueName) + tmp.WriteString("]") + return tmp.String() +}