Added CPU type
This commit is contained in:
parent
1058970be3
commit
4faa1641c6
@ -18,8 +18,8 @@ func TestErrors(t *testing.T) {
|
|||||||
{"ExpectedFunctionDefinition.q", errors.ExpectedFunctionDefinition},
|
{"ExpectedFunctionDefinition.q", errors.ExpectedFunctionDefinition},
|
||||||
{"ExpectedFunctionName.q", errors.ExpectedFunctionName},
|
{"ExpectedFunctionName.q", errors.ExpectedFunctionName},
|
||||||
{"ExpectedFunctionParameters.q", errors.ExpectedFunctionParameters},
|
{"ExpectedFunctionParameters.q", errors.ExpectedFunctionParameters},
|
||||||
{"InvalidInstruction-Identifier.q", &errors.InvalidInstruction{Instruction: "abc"}},
|
{"InvalidInstructionIdentifier.q", &errors.InvalidInstruction{Instruction: "abc"}},
|
||||||
{"InvalidInstruction-Number.q", &errors.InvalidInstruction{Instruction: "123"}},
|
{"InvalidInstructionNumber.q", &errors.InvalidInstruction{Instruction: "123"}},
|
||||||
{"MissingAssignValue.q", errors.MissingAssignValue},
|
{"MissingAssignValue.q", errors.MissingAssignValue},
|
||||||
{"MissingBlockEnd.q", errors.MissingBlockEnd},
|
{"MissingBlockEnd.q", errors.MissingBlockEnd},
|
||||||
{"MissingBlockStart.q", errors.MissingBlockStart},
|
{"MissingBlockStart.q", errors.MissingBlockStart},
|
||||||
|
@ -29,8 +29,8 @@ func Finalize(functions map[string]*Function) ([]byte, []byte) {
|
|||||||
func entry() *asm.Assembler {
|
func entry() *asm.Assembler {
|
||||||
entry := asm.New()
|
entry := asm.New()
|
||||||
entry.Call("main")
|
entry.Call("main")
|
||||||
entry.MoveRegisterNumber(x64.SyscallArgs[0], linux.Exit)
|
entry.MoveRegisterNumber(x64.SyscallRegisters[0], linux.Exit)
|
||||||
entry.MoveRegisterNumber(x64.SyscallArgs[1], 0)
|
entry.MoveRegisterNumber(x64.SyscallRegisters[1], 0)
|
||||||
entry.Syscall()
|
entry.Syscall()
|
||||||
return entry
|
return entry
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"git.akyoto.dev/cli/q/src/build/arch/x64"
|
|
||||||
"git.akyoto.dev/cli/q/src/build/asm"
|
"git.akyoto.dev/cli/q/src/build/asm"
|
||||||
|
"git.akyoto.dev/cli/q/src/build/cpu"
|
||||||
"git.akyoto.dev/cli/q/src/build/expression"
|
"git.akyoto.dev/cli/q/src/build/expression"
|
||||||
"git.akyoto.dev/cli/q/src/build/fs"
|
"git.akyoto.dev/cli/q/src/build/fs"
|
||||||
"git.akyoto.dev/cli/q/src/build/token"
|
"git.akyoto.dev/cli/q/src/build/token"
|
||||||
@ -21,6 +21,7 @@ type Function struct {
|
|||||||
Body token.List
|
Body token.List
|
||||||
Variables map[string]*Variable
|
Variables map[string]*Variable
|
||||||
Assembler asm.Assembler
|
Assembler asm.Assembler
|
||||||
|
CPU cpu.CPU
|
||||||
Error error
|
Error error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,12 +170,12 @@ func (f *Function) CompileFunctionCall(expr *expression.Expression) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
n, _ := strconv.Atoi(variable.Value.Token.Text())
|
n, _ := strconv.Atoi(variable.Value.Token.Text())
|
||||||
f.Assembler.MoveRegisterNumber(x64.SyscallArgs[i], uint64(n))
|
f.Assembler.MoveRegisterNumber(f.CPU.Syscall[i], uint64(n))
|
||||||
|
|
||||||
case token.Number:
|
case token.Number:
|
||||||
value := parameter.Token.Text()
|
value := parameter.Token.Text()
|
||||||
n, _ := strconv.Atoi(value)
|
n, _ := strconv.Atoi(value)
|
||||||
f.Assembler.MoveRegisterNumber(x64.SyscallArgs[i], uint64(n))
|
f.Assembler.MoveRegisterNumber(f.CPU.Syscall[i], uint64(n))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("Unknown expression")
|
panic("Unknown expression")
|
||||||
|
28
src/build/arch/x64/Registers.go
Normal file
28
src/build/arch/x64/Registers.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package x64
|
||||||
|
|
||||||
|
import "git.akyoto.dev/cli/q/src/build/cpu"
|
||||||
|
|
||||||
|
const (
|
||||||
|
rax = iota
|
||||||
|
rcx
|
||||||
|
rdx
|
||||||
|
rbx
|
||||||
|
rsp
|
||||||
|
rbp
|
||||||
|
rsi
|
||||||
|
rdi
|
||||||
|
r8
|
||||||
|
r9
|
||||||
|
r10
|
||||||
|
r11
|
||||||
|
r12
|
||||||
|
r13
|
||||||
|
r14
|
||||||
|
r15
|
||||||
|
)
|
||||||
|
|
||||||
|
const SyscallReturn = rax
|
||||||
|
|
||||||
|
var GeneralRegisters = []cpu.Register{rbx, rbp, r12, r13, r14, r15}
|
||||||
|
var SyscallRegisters = []cpu.Register{rax, rdi, rsi, rdx, r10, r8, r9}
|
||||||
|
var ReturnValueRegisters = []cpu.Register{rax, rcx, r11}
|
@ -1,13 +1,5 @@
|
|||||||
package x64
|
package x64
|
||||||
|
|
||||||
import "git.akyoto.dev/cli/q/src/build/cpu"
|
|
||||||
|
|
||||||
const (
|
|
||||||
SyscallReturn = 0 // rax
|
|
||||||
)
|
|
||||||
|
|
||||||
var SyscallArgs = []cpu.Register{0, 7, 6, 2, 10, 8, 9}
|
|
||||||
|
|
||||||
// Syscall is the primary way to communicate with the OS kernel.
|
// Syscall is the primary way to communicate with the OS kernel.
|
||||||
func Syscall(code []byte) []byte {
|
func Syscall(code []byte) []byte {
|
||||||
return append(code, 0x0f, 0x05)
|
return append(code, 0x0f, 0x05)
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// compile waits for all functions to finish compilation.
|
// compile waits for the scan to finish and compiles all functions.
|
||||||
func compile(functions <-chan *Function, errors <-chan error) (map[string]*Function, error) {
|
func compile(functions <-chan *Function, errors <-chan error) (map[string]*Function, error) {
|
||||||
allFunctions := map[string]*Function{}
|
allFunctions := map[string]*Function{}
|
||||||
|
|
||||||
@ -28,18 +28,7 @@ func compile(functions <-chan *Function, errors <-chan error) (map[string]*Funct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
compileFunctions(allFunctions)
|
||||||
|
|
||||||
for _, function := range allFunctions {
|
|
||||||
wg.Add(1)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
function.Compile()
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
for _, function := range allFunctions {
|
for _, function := range allFunctions {
|
||||||
if function.Error != nil {
|
if function.Error != nil {
|
||||||
@ -49,3 +38,19 @@ func compile(functions <-chan *Function, errors <-chan error) (map[string]*Funct
|
|||||||
|
|
||||||
return allFunctions, nil
|
return allFunctions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compileFunctions starts a goroutine for each function compilation and waits for completion.
|
||||||
|
func compileFunctions(functions map[string]*Function) {
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
|
||||||
|
for _, function := range functions {
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
function.Compile()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
31
src/build/cpu/CPU.go
Normal file
31
src/build/cpu/CPU.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package cpu
|
||||||
|
|
||||||
|
// CPU represents the processor.
|
||||||
|
type CPU struct {
|
||||||
|
General []Register
|
||||||
|
Syscall []Register
|
||||||
|
Return []Register
|
||||||
|
usage uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CPU) Use(reg Register) {
|
||||||
|
c.usage |= (1 << reg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CPU) Free(reg Register) {
|
||||||
|
c.usage &= ^(1 << reg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CPU) IsFree(reg Register) bool {
|
||||||
|
return c.usage&(1<<reg) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CPU) FindFree() (Register, bool) {
|
||||||
|
for _, reg := range c.General {
|
||||||
|
if c.IsFree(reg) {
|
||||||
|
return reg, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, false
|
||||||
|
}
|
@ -6,6 +6,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"git.akyoto.dev/cli/q/src/build/arch/x64"
|
||||||
|
"git.akyoto.dev/cli/q/src/build/cpu"
|
||||||
"git.akyoto.dev/cli/q/src/build/fs"
|
"git.akyoto.dev/cli/q/src/build/fs"
|
||||||
"git.akyoto.dev/cli/q/src/build/token"
|
"git.akyoto.dev/cli/q/src/build/token"
|
||||||
"git.akyoto.dev/cli/q/src/errors"
|
"git.akyoto.dev/cli/q/src/errors"
|
||||||
@ -225,6 +227,11 @@ func scanFile(path string, functions chan<- *Function) error {
|
|||||||
Head: tokens[paramsStart:bodyStart],
|
Head: tokens[paramsStart:bodyStart],
|
||||||
Body: tokens[bodyStart : i+1],
|
Body: tokens[bodyStart : i+1],
|
||||||
Variables: map[string]*Variable{},
|
Variables: map[string]*Variable{},
|
||||||
|
CPU: cpu.CPU{
|
||||||
|
General: x64.GeneralRegisters,
|
||||||
|
Syscall: x64.SyscallRegisters,
|
||||||
|
Return: x64.ReturnValueRegisters,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
nameStart = -1
|
nameStart = -1
|
||||||
|
Loading…
Reference in New Issue
Block a user