Added label type
This commit is contained in:
@ -2,12 +2,12 @@ package asm
|
|||||||
|
|
||||||
// Comment adds a comment at the current position.
|
// Comment adds a comment at the current position.
|
||||||
func (a *Assembler) Comment(text string) {
|
func (a *Assembler) Comment(text string) {
|
||||||
a.Label(COMMENT, text)
|
a.Label(COMMENT, Label{Name: text, Type: CommentLabel})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DLLCall calls a function in a DLL file.
|
// DLLCall calls a function in a DLL file.
|
||||||
func (a *Assembler) DLLCall(name string) {
|
func (a *Assembler) DLLCall(name string) {
|
||||||
a.Label(DLLCALL, name)
|
a.Label(DLLCALL, Label{Name: name, Type: ExternLabel})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return returns back to the caller.
|
// Return returns back to the caller.
|
||||||
|
@ -3,6 +3,7 @@ package asm
|
|||||||
// Label represents a jump label.
|
// Label represents a jump label.
|
||||||
type Label struct {
|
type Label struct {
|
||||||
Name string
|
Name string
|
||||||
|
Type LabelType
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a human readable version.
|
// String returns a human readable version.
|
||||||
@ -11,14 +12,12 @@ func (data *Label) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Label adds an instruction using a label.
|
// Label adds an instruction using a label.
|
||||||
func (a *Assembler) Label(mnemonic Mnemonic, name string) {
|
func (a *Assembler) Label(mnemonic Mnemonic, label Label) {
|
||||||
a.Instructions = append(a.Instructions, Instruction{
|
a.Instructions = append(a.Instructions, Instruction{
|
||||||
Mnemonic: mnemonic,
|
Mnemonic: mnemonic,
|
||||||
Type: TypeLabel,
|
Type: TypeLabel,
|
||||||
Index: Index(len(a.Param.Label)),
|
Index: Index(len(a.Param.Label)),
|
||||||
})
|
})
|
||||||
|
|
||||||
a.Param.Label = append(a.Param.Label, Label{
|
a.Param.Label = append(a.Param.Label, label)
|
||||||
Name: name,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
13
src/asm/LabelType.go
Normal file
13
src/asm/LabelType.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package asm
|
||||||
|
|
||||||
|
// LabelType shows what the label was used for.
|
||||||
|
type LabelType uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
UnknownLabel LabelType = iota
|
||||||
|
CommentLabel
|
||||||
|
ControlLabel
|
||||||
|
DataLabel
|
||||||
|
FunctionLabel
|
||||||
|
ExternLabel
|
||||||
|
)
|
@ -2,17 +2,17 @@ package asm
|
|||||||
|
|
||||||
// MemoryLabel operates with a memory address and a number.
|
// MemoryLabel operates with a memory address and a number.
|
||||||
type MemoryLabel struct {
|
type MemoryLabel struct {
|
||||||
Label string
|
Label Label
|
||||||
Address Memory
|
Address Memory
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a human readable version.
|
// String returns a human readable version.
|
||||||
func (data *MemoryLabel) String() string {
|
func (data *MemoryLabel) String() string {
|
||||||
return data.Address.Format(data.Label)
|
return data.Address.Format(data.Label.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MemoryLabel adds an instruction with a memory address and a label.
|
// MemoryLabel adds an instruction with a memory address and a label.
|
||||||
func (a *Assembler) MemoryLabel(mnemonic Mnemonic, address Memory, label string) {
|
func (a *Assembler) MemoryLabel(mnemonic Mnemonic, address Memory, label Label) {
|
||||||
a.Instructions = append(a.Instructions, Instruction{
|
a.Instructions = append(a.Instructions, Instruction{
|
||||||
Mnemonic: mnemonic,
|
Mnemonic: mnemonic,
|
||||||
Type: TypeMemoryLabel,
|
Type: TypeMemoryLabel,
|
||||||
|
@ -8,17 +8,17 @@ import (
|
|||||||
|
|
||||||
// RegisterLabel operates with a register and a label.
|
// RegisterLabel operates with a register and a label.
|
||||||
type RegisterLabel struct {
|
type RegisterLabel struct {
|
||||||
Label string
|
Label Label
|
||||||
Register cpu.Register
|
Register cpu.Register
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a human readable version.
|
// String returns a human readable version.
|
||||||
func (data *RegisterLabel) String() string {
|
func (data *RegisterLabel) String() string {
|
||||||
return fmt.Sprintf("%s, %s", data.Register, data.Label)
|
return fmt.Sprintf("%s, %s", data.Register, data.Label.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterLabel adds an instruction with a register and a label.
|
// RegisterLabel adds an instruction with a register and a label.
|
||||||
func (a *Assembler) RegisterLabel(mnemonic Mnemonic, register cpu.Register, label string) {
|
func (a *Assembler) RegisterLabel(mnemonic Mnemonic, register cpu.Register, label Label) {
|
||||||
a.Instructions = append(a.Instructions, Instruction{
|
a.Instructions = append(a.Instructions, Instruction{
|
||||||
Mnemonic: mnemonic,
|
Mnemonic: mnemonic,
|
||||||
Type: TypeRegisterLabel,
|
Type: TypeRegisterLabel,
|
||||||
|
@ -3,7 +3,6 @@ package asmc
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.urbach.dev/cli/q/src/arm"
|
"git.urbach.dev/cli/q/src/arm"
|
||||||
"git.urbach.dev/cli/q/src/asm"
|
"git.urbach.dev/cli/q/src/asm"
|
||||||
@ -44,8 +43,11 @@ func (c *compiler) compileARM(x asm.Instruction) {
|
|||||||
case asm.LABEL:
|
case asm.LABEL:
|
||||||
label := c.assembler.Param.Label[x.Index]
|
label := c.assembler.Param.Label[x.Index]
|
||||||
c.codeLabels[label.Name] = Address(len(c.code))
|
c.codeLabels[label.Name] = Address(len(c.code))
|
||||||
c.append(arm.StorePair(arm.FP, arm.LR, arm.SP, -16))
|
|
||||||
c.append(arm.MoveRegisterRegister(arm.FP, arm.SP))
|
if label.Type == asm.FunctionLabel {
|
||||||
|
c.append(arm.StorePair(arm.FP, arm.LR, arm.SP, -16))
|
||||||
|
c.append(arm.MoveRegisterRegister(arm.FP, arm.SP))
|
||||||
|
}
|
||||||
|
|
||||||
case asm.LOAD:
|
case asm.LOAD:
|
||||||
switch x.Type {
|
switch x.Type {
|
||||||
@ -140,13 +142,13 @@ func (c *compiler) compileARM(x asm.Instruction) {
|
|||||||
position := Address(len(c.code))
|
position := Address(len(c.code))
|
||||||
c.append(arm.LoadAddress(operands.Register, 0))
|
c.append(arm.LoadAddress(operands.Register, 0))
|
||||||
|
|
||||||
if strings.HasPrefix(operands.Label, "data ") {
|
if operands.Label.Type == asm.DataLabel {
|
||||||
c.dataPointers = append(c.dataPointers, &pointer{
|
c.dataPointers = append(c.dataPointers, &pointer{
|
||||||
Position: position,
|
Position: position,
|
||||||
OpSize: 0,
|
OpSize: 0,
|
||||||
Size: 4,
|
Size: 4,
|
||||||
Resolve: func() Address {
|
Resolve: func() Address {
|
||||||
destination, exists := c.dataLabels[operands.Label]
|
destination, exists := c.dataLabels[operands.Label.Name]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
panic("unknown label")
|
panic("unknown label")
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package asmc
|
package asmc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.urbach.dev/cli/q/src/asm"
|
"git.urbach.dev/cli/q/src/asm"
|
||||||
"git.urbach.dev/cli/q/src/x86"
|
"git.urbach.dev/cli/q/src/x86"
|
||||||
)
|
)
|
||||||
@ -25,13 +23,13 @@ func (c *compiler) move(x asm.Instruction) {
|
|||||||
position := end - 4
|
position := end - 4
|
||||||
opSize := position - start
|
opSize := position - start
|
||||||
|
|
||||||
if strings.HasPrefix(operands.Label, "data ") {
|
if operands.Label.Type == asm.DataLabel {
|
||||||
c.dataPointers = append(c.dataPointers, &pointer{
|
c.dataPointers = append(c.dataPointers, &pointer{
|
||||||
Position: position,
|
Position: position,
|
||||||
OpSize: uint8(opSize),
|
OpSize: uint8(opSize),
|
||||||
Size: uint8(4),
|
Size: uint8(4),
|
||||||
Resolve: func() Address {
|
Resolve: func() Address {
|
||||||
destination, exists := c.dataLabels[operands.Label]
|
destination, exists := c.dataLabels[operands.Label.Name]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
panic("unknown label")
|
panic("unknown label")
|
||||||
@ -48,7 +46,7 @@ func (c *compiler) move(x asm.Instruction) {
|
|||||||
OpSize: uint8(opSize),
|
OpSize: uint8(opSize),
|
||||||
Size: uint8(4),
|
Size: uint8(4),
|
||||||
Resolve: func() Address {
|
Resolve: func() Address {
|
||||||
destination, exists := c.codeLabels[operands.Label]
|
destination, exists := c.codeLabels[operands.Label.Name]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
panic("unknown label")
|
panic("unknown label")
|
||||||
|
@ -34,7 +34,7 @@ func (c *compiler) store(x asm.Instruction) {
|
|||||||
OpSize: uint8(opSize),
|
OpSize: uint8(opSize),
|
||||||
Size: uint8(size),
|
Size: uint8(size),
|
||||||
Resolve: func() Address {
|
Resolve: func() Address {
|
||||||
destination, exists := c.codeLabels[operands.Label]
|
destination, exists := c.codeLabels[operands.Label.Name]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
panic("unknown label")
|
panic("unknown label")
|
||||||
|
@ -45,7 +45,10 @@ func (r *Result) finalize() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
final.Label(asm.LABEL, "_crash")
|
final.Label(asm.LABEL, asm.Label{
|
||||||
|
Name: "_crash",
|
||||||
|
Type: asm.ControlLabel,
|
||||||
|
})
|
||||||
|
|
||||||
switch config.TargetOS {
|
switch config.TargetOS {
|
||||||
case config.Linux:
|
case config.Linux:
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
|
import "git.urbach.dev/cli/q/src/asm"
|
||||||
|
|
||||||
// AddBytes adds a sequence of bytes and returns its address as a label.
|
// AddBytes adds a sequence of bytes and returns its address as a label.
|
||||||
func (f *Function) AddBytes(value []byte) string {
|
func (f *Function) AddBytes(value []byte) asm.Label {
|
||||||
f.count.data++
|
f.count.data++
|
||||||
label := f.CreateLabel("data", f.count.data)
|
label := f.CreateLabel("data", f.count.data, asm.DataLabel)
|
||||||
f.Assembler.SetData(label, value)
|
f.Assembler.SetData(label.Name, value)
|
||||||
return label
|
return label
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
|
import "git.urbach.dev/cli/q/src/asm"
|
||||||
|
|
||||||
// Compile turns a function into machine code.
|
// Compile turns a function into machine code.
|
||||||
func (f *Function) Compile() {
|
func (f *Function) Compile() {
|
||||||
f.AddLabel(f.UniqueName)
|
f.AddLabel(asm.Label{
|
||||||
|
Name: f.UniqueName,
|
||||||
|
Type: asm.FunctionLabel,
|
||||||
|
})
|
||||||
|
|
||||||
f.Err = f.CompileTokens(f.Body)
|
f.Err = f.CompileTokens(f.Body)
|
||||||
f.Return()
|
f.Return()
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ import (
|
|||||||
// CompileAssert compiles an assertion.
|
// CompileAssert compiles an assertion.
|
||||||
func (f *Function) CompileAssert(assert *ast.Assert) error {
|
func (f *Function) CompileAssert(assert *ast.Assert) error {
|
||||||
f.count.assert++
|
f.count.assert++
|
||||||
success := f.CreateLabel("assert true", f.count.assert)
|
success := f.CreateLabel("assert true", f.count.assert, asm.ControlLabel)
|
||||||
fail := f.CreateLabel("assert false", f.count.assert)
|
fail := f.CreateLabel("assert false", f.count.assert, asm.ControlLabel)
|
||||||
err := f.CompileCondition(assert.Condition, success, fail)
|
err := f.CompileCondition(assert.Condition, success, fail)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -20,7 +20,7 @@ func (f *Function) CompileAssert(assert *ast.Assert) error {
|
|||||||
|
|
||||||
f.Defer(func() {
|
f.Defer(func() {
|
||||||
f.AddLabel(fail)
|
f.AddLabel(fail)
|
||||||
f.Jump(asm.JUMP, "_crash")
|
f.Jump(asm.JUMP, asm.Label{Name: "_crash", Type: asm.ControlLabel})
|
||||||
})
|
})
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -58,7 +58,7 @@ func (f *Function) CompileCall(root *expression.Expression) ([]*Parameter, error
|
|||||||
|
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case *eval.Label:
|
case *eval.Label:
|
||||||
fn := f.All.Functions[value.Label]
|
fn := f.All.Functions[value.Label.Name]
|
||||||
|
|
||||||
if len(parameters) != len(fn.Input) {
|
if len(parameters) != len(fn.Input) {
|
||||||
return nil, errors.New(&errors.ParameterCountMismatch{Function: fn.Name, Count: len(parameters), ExpectedCount: len(fn.Input)}, f.File, root.Children[0].Token.End())
|
return nil, errors.New(&errors.ParameterCountMismatch{Function: fn.Name, Count: len(parameters), ExpectedCount: len(fn.Input)}, f.File, root.Children[0].Token.End())
|
||||||
|
@ -12,11 +12,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// CompileCondition inserts code to jump to the start label or end label depending on the truth of the condition.
|
// CompileCondition inserts code to jump to the start label or end label depending on the truth of the condition.
|
||||||
func (f *Function) CompileCondition(condition *expression.Expression, successLabel string, failLabel string) error {
|
func (f *Function) CompileCondition(condition *expression.Expression, successLabel asm.Label, failLabel asm.Label) error {
|
||||||
switch condition.Token.Kind {
|
switch condition.Token.Kind {
|
||||||
case token.LogicalOr:
|
case token.LogicalOr:
|
||||||
f.count.subBranch++
|
f.count.subBranch++
|
||||||
leftFailLabel := f.CreateLabel("false", f.count.subBranch)
|
leftFailLabel := f.CreateLabel("false", f.count.subBranch, asm.ControlLabel)
|
||||||
|
|
||||||
// Left
|
// Left
|
||||||
left := condition.Children[0]
|
left := condition.Children[0]
|
||||||
@ -43,7 +43,7 @@ func (f *Function) CompileCondition(condition *expression.Expression, successLab
|
|||||||
|
|
||||||
case token.LogicalAnd:
|
case token.LogicalAnd:
|
||||||
f.count.subBranch++
|
f.count.subBranch++
|
||||||
leftSuccessLabel := f.CreateLabel("true", f.count.subBranch)
|
leftSuccessLabel := f.CreateLabel("true", f.count.subBranch, asm.ControlLabel)
|
||||||
|
|
||||||
// Left
|
// Left
|
||||||
left := condition.Children[0]
|
left := condition.Children[0]
|
||||||
|
@ -24,7 +24,7 @@ func (f *Function) CompileDelete(root *expression.Expression) error {
|
|||||||
f.RegisterNumber(asm.MOVE, f.CPU.Input[1], variable.Value.Typ.(*types.Pointer).To.Size())
|
f.RegisterNumber(asm.MOVE, f.CPU.Input[1], variable.Value.Typ.(*types.Pointer).To.Size())
|
||||||
free := f.All.Functions["mem.free"]
|
free := f.All.Functions["mem.free"]
|
||||||
f.BeforeCall()
|
f.BeforeCall()
|
||||||
f.Label(asm.CALL, "mem.free")
|
f.Label(asm.CALL, asm.Label{Name: "mem.free", Type: asm.FunctionLabel})
|
||||||
f.AfterCall(f.CPU.Input[:2])
|
f.AfterCall(f.CPU.Input[:2])
|
||||||
f.Dependencies = append(f.Dependencies, free)
|
f.Dependencies = append(f.Dependencies, free)
|
||||||
return nil
|
return nil
|
||||||
|
@ -23,8 +23,8 @@ func (f *Function) CompileFor(loop *ast.For) error {
|
|||||||
f.count.loop++
|
f.count.loop++
|
||||||
|
|
||||||
var (
|
var (
|
||||||
label = f.CreateLabel("for", f.count.loop)
|
label = f.CreateLabel("for", f.count.loop, asm.ControlLabel)
|
||||||
labelEnd = f.CreateLabel("for end", f.count.loop)
|
labelEnd = f.CreateLabel("for end", f.count.loop, asm.ControlLabel)
|
||||||
counter cpu.Register
|
counter cpu.Register
|
||||||
from *expression.Expression
|
from *expression.Expression
|
||||||
to *expression.Expression
|
to *expression.Expression
|
||||||
|
@ -14,9 +14,9 @@ func (f *Function) CompileIf(branch *ast.If) error {
|
|||||||
f.count.branch++
|
f.count.branch++
|
||||||
|
|
||||||
var (
|
var (
|
||||||
end string
|
end asm.Label
|
||||||
success = f.CreateLabel("if true", f.count.branch)
|
success = f.CreateLabel("if true", f.count.branch, asm.ControlLabel)
|
||||||
fail = f.CreateLabel("if false", f.count.branch)
|
fail = f.CreateLabel("if false", f.count.branch, asm.ControlLabel)
|
||||||
err = f.CompileCondition(branch.Condition, success, fail)
|
err = f.CompileCondition(branch.Condition, success, fail)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ func (f *Function) CompileIf(branch *ast.If) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if branch.Else != nil {
|
if branch.Else != nil {
|
||||||
end = f.CreateLabel("if end", f.count.branch)
|
end = f.CreateLabel("if end", f.count.branch, asm.ControlLabel)
|
||||||
f.Jump(asm.JUMP, end)
|
f.Jump(asm.JUMP, end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ func (f *Function) CompileLoop(loop *ast.Loop) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
f.count.loop++
|
f.count.loop++
|
||||||
label := f.CreateLabel("loop", f.count.loop)
|
label := f.CreateLabel("loop", f.count.loop, asm.ControlLabel)
|
||||||
f.AddLabel(label)
|
f.AddLabel(label)
|
||||||
scope := f.PushScope(loop.Body, f.File.Bytes)
|
scope := f.PushScope(loop.Body, f.File.Bytes)
|
||||||
scope.InLoop = true
|
scope.InLoop = true
|
||||||
|
@ -47,7 +47,7 @@ func (f *Function) CompileNew(root *expression.Expression) (types.Type, error) {
|
|||||||
f.RegisterNumber(asm.MOVE, f.CPU.Input[0], typ.Size())
|
f.RegisterNumber(asm.MOVE, f.CPU.Input[0], typ.Size())
|
||||||
alloc := f.All.Functions["mem.alloc"]
|
alloc := f.All.Functions["mem.alloc"]
|
||||||
f.BeforeCall()
|
f.BeforeCall()
|
||||||
f.Label(asm.CALL, "mem.alloc")
|
f.Label(asm.CALL, asm.Label{Name: "mem.alloc", Type: asm.FunctionLabel})
|
||||||
f.AfterCall(f.CPU.Input[:1])
|
f.AfterCall(f.CPU.Input[:1])
|
||||||
f.Dependencies = append(f.Dependencies, alloc)
|
f.Dependencies = append(f.Dependencies, alloc)
|
||||||
return &types.Pointer{To: typ}, nil
|
return &types.Pointer{To: typ}, nil
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
// CompileSwitch compiles a multi-branch instruction.
|
// CompileSwitch compiles a multi-branch instruction.
|
||||||
func (f *Function) CompileSwitch(s *ast.Switch) error {
|
func (f *Function) CompileSwitch(s *ast.Switch) error {
|
||||||
f.count.multiBranch++
|
f.count.multiBranch++
|
||||||
end := f.CreateLabel("switch end", f.count.multiBranch)
|
end := f.CreateLabel("switch end", f.count.multiBranch, asm.ControlLabel)
|
||||||
|
|
||||||
for _, branch := range s.Cases {
|
for _, branch := range s.Cases {
|
||||||
if branch.Condition == nil {
|
if branch.Condition == nil {
|
||||||
@ -26,8 +26,8 @@ func (f *Function) CompileSwitch(s *ast.Switch) error {
|
|||||||
f.count.branch++
|
f.count.branch++
|
||||||
|
|
||||||
var (
|
var (
|
||||||
success = f.CreateLabel("case true", f.count.branch)
|
success = f.CreateLabel("case true", f.count.branch, asm.ControlLabel)
|
||||||
fail = f.CreateLabel("case false", f.count.branch)
|
fail = f.CreateLabel("case false", f.count.branch, asm.ControlLabel)
|
||||||
err = f.CompileCondition(branch.Condition, success, fail)
|
err = f.CompileCondition(branch.Condition, success, fail)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -3,10 +3,12 @@ package core
|
|||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"git.urbach.dev/cli/q/src/asm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateLabel creates a label that is tied to this function by using a suffix.
|
// CreateLabel creates a label that is tied to this function by using a suffix.
|
||||||
func (f *Function) CreateLabel(prefix string, count counter) string {
|
func (f *Function) CreateLabel(prefix string, count counter, typ asm.LabelType) asm.Label {
|
||||||
tmp := strings.Builder{}
|
tmp := strings.Builder{}
|
||||||
tmp.WriteString(prefix)
|
tmp.WriteString(prefix)
|
||||||
tmp.WriteString(" ")
|
tmp.WriteString(" ")
|
||||||
@ -14,5 +16,9 @@ func (f *Function) CreateLabel(prefix string, count counter) string {
|
|||||||
tmp.WriteString(" [")
|
tmp.WriteString(" [")
|
||||||
tmp.WriteString(f.UniqueName)
|
tmp.WriteString(f.UniqueName)
|
||||||
tmp.WriteString("]")
|
tmp.WriteString("]")
|
||||||
return tmp.String()
|
|
||||||
|
return asm.Label{
|
||||||
|
Name: tmp.String(),
|
||||||
|
Type: typ,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,8 +79,11 @@ func (f *Function) EvaluateDot(expr *expression.Expression) (eval.Value, error)
|
|||||||
f.Dependencies = append(f.Dependencies, function)
|
f.Dependencies = append(f.Dependencies, function)
|
||||||
|
|
||||||
value := &eval.Label{
|
value := &eval.Label{
|
||||||
Typ: types.AnyPointer,
|
Typ: types.AnyPointer,
|
||||||
Label: label,
|
Label: asm.Label{
|
||||||
|
Name: label,
|
||||||
|
Type: asm.FunctionLabel,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return value, nil
|
return value, nil
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"git.urbach.dev/cli/q/src/asm"
|
||||||
"git.urbach.dev/cli/q/src/errors"
|
"git.urbach.dev/cli/q/src/errors"
|
||||||
"git.urbach.dev/cli/q/src/eval"
|
"git.urbach.dev/cli/q/src/eval"
|
||||||
"git.urbach.dev/cli/q/src/token"
|
"git.urbach.dev/cli/q/src/token"
|
||||||
@ -48,8 +49,11 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
|
|||||||
f.Dependencies = append(f.Dependencies, function)
|
f.Dependencies = append(f.Dependencies, function)
|
||||||
|
|
||||||
value := &eval.Label{
|
value := &eval.Label{
|
||||||
Typ: types.AnyPointer,
|
Typ: types.AnyPointer,
|
||||||
Label: function.UniqueName,
|
Label: asm.Label{
|
||||||
|
Name: function.UniqueName,
|
||||||
|
Type: asm.FunctionLabel,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return value, nil
|
return value, nil
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// JumpIfFalse jumps to the label if the previous comparison was false.
|
// JumpIfFalse jumps to the label if the previous comparison was false.
|
||||||
func (f *Function) JumpIfFalse(operator token.Kind, label string) {
|
func (f *Function) JumpIfFalse(operator token.Kind, label asm.Label) {
|
||||||
switch operator {
|
switch operator {
|
||||||
case token.Equal:
|
case token.Equal:
|
||||||
f.Jump(asm.JNE, label)
|
f.Jump(asm.JNE, label)
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// JumpIfTrue jumps to the label if the previous comparison was true.
|
// JumpIfTrue jumps to the label if the previous comparison was true.
|
||||||
func (f *Function) JumpIfTrue(operator token.Kind, label string) {
|
func (f *Function) JumpIfTrue(operator token.Kind, label asm.Label) {
|
||||||
switch operator {
|
switch operator {
|
||||||
case token.Equal:
|
case token.Equal:
|
||||||
f.Jump(asm.JE, label)
|
f.Jump(asm.JE, label)
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package eval
|
package eval
|
||||||
|
|
||||||
import "git.urbach.dev/cli/q/src/types"
|
import (
|
||||||
|
"git.urbach.dev/cli/q/src/asm"
|
||||||
|
"git.urbach.dev/cli/q/src/types"
|
||||||
|
)
|
||||||
|
|
||||||
// Label is a named pointer to a code or data section.
|
// Label is a named pointer to a code or data section.
|
||||||
type Label struct {
|
type Label struct {
|
||||||
Typ types.Type
|
Typ types.Type
|
||||||
Label string
|
Label asm.Label
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Label) String() string {
|
func (v *Label) String() string {
|
||||||
|
@ -2,7 +2,7 @@ package register
|
|||||||
|
|
||||||
import "git.urbach.dev/cli/q/src/asm"
|
import "git.urbach.dev/cli/q/src/asm"
|
||||||
|
|
||||||
func (f *Machine) AddLabel(label string) {
|
func (f *Machine) AddLabel(label asm.Label) {
|
||||||
f.Assembler.Label(asm.LABEL, label)
|
f.Assembler.Label(asm.LABEL, label)
|
||||||
f.postInstruction()
|
f.postInstruction()
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package register
|
|||||||
import "git.urbach.dev/cli/q/src/asm"
|
import "git.urbach.dev/cli/q/src/asm"
|
||||||
|
|
||||||
func (f *Machine) DLLCall(label string) {
|
func (f *Machine) DLLCall(label string) {
|
||||||
f.Assembler.Label(asm.DLLCALL, label)
|
f.Assembler.Label(asm.DLLCALL, asm.Label{Name: label, Type: asm.UnknownLabel})
|
||||||
f.UseRegister(f.CPU.Output[0])
|
f.UseRegister(f.CPU.Output[0])
|
||||||
f.postInstruction()
|
f.postInstruction()
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package register
|
|||||||
|
|
||||||
import "git.urbach.dev/cli/q/src/asm"
|
import "git.urbach.dev/cli/q/src/asm"
|
||||||
|
|
||||||
func (f *Machine) Jump(mnemonic asm.Mnemonic, label string) {
|
func (f *Machine) Jump(mnemonic asm.Mnemonic, label asm.Label) {
|
||||||
f.Assembler.Label(mnemonic, label)
|
f.Assembler.Label(mnemonic, label)
|
||||||
f.postInstruction()
|
f.postInstruction()
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package register
|
|||||||
|
|
||||||
import "git.urbach.dev/cli/q/src/asm"
|
import "git.urbach.dev/cli/q/src/asm"
|
||||||
|
|
||||||
func (f *Machine) Label(mnemonic asm.Mnemonic, label string) {
|
func (f *Machine) Label(mnemonic asm.Mnemonic, label asm.Label) {
|
||||||
f.Assembler.Label(mnemonic, label)
|
f.Assembler.Label(mnemonic, label)
|
||||||
f.postInstruction()
|
f.postInstruction()
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package register
|
|||||||
|
|
||||||
import "git.urbach.dev/cli/q/src/asm"
|
import "git.urbach.dev/cli/q/src/asm"
|
||||||
|
|
||||||
func (f *Machine) MemoryLabel(mnemonic asm.Mnemonic, a asm.Memory, b string) {
|
func (f *Machine) MemoryLabel(mnemonic asm.Mnemonic, a asm.Memory, b asm.Label) {
|
||||||
f.Assembler.MemoryLabel(mnemonic, a, b)
|
f.Assembler.MemoryLabel(mnemonic, a, b)
|
||||||
f.postInstruction()
|
f.postInstruction()
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"git.urbach.dev/cli/q/src/cpu"
|
"git.urbach.dev/cli/q/src/cpu"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (f *Machine) RegisterLabel(mnemonic asm.Mnemonic, register cpu.Register, label string) {
|
func (f *Machine) RegisterLabel(mnemonic asm.Mnemonic, register cpu.Register, label asm.Label) {
|
||||||
f.Assembler.RegisterLabel(mnemonic, register, label)
|
f.Assembler.RegisterLabel(mnemonic, register, label)
|
||||||
|
|
||||||
if mnemonic == asm.MOVE {
|
if mnemonic == asm.MOVE {
|
||||||
|
Reference in New Issue
Block a user