Implemented compilation finished events

This commit is contained in:
Eduard Urbach 2024-06-30 11:41:59 +02:00
parent 3fe2cd1da2
commit 247b82b529
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
8 changed files with 72 additions and 50 deletions

View File

@ -51,7 +51,13 @@ q build examples/hello
q build examples/hello --dry
```
To produce verbose output, add the `-v` flag which shows the generated assembly instructions:
Adding the `-a` or `--assembler` flag shows the generated assembly instructions:
```shell
q build examples/hello -a
```
Adding the `-v` or `--verbose` flag shows verbose compiler information:
```shell
q build examples/hello -v

44
src/build/Call.go Normal file
View File

@ -0,0 +1,44 @@
package build
import (
"git.akyoto.dev/cli/q/src/build/config"
"git.akyoto.dev/cli/q/src/build/expression"
)
// CompileFunctionCall executes a function call.
func (f *Function) CompileFunctionCall(expr *expression.Expression) error {
funcName := expr.Children[0].Token.Text()
if funcName == "syscall" {
return f.CompileSyscall(expr)
}
function := f.functions[funcName]
if function != f {
function.Wait()
}
parameters := expr.Children[1:]
registers := f.cpu.Call[:len(parameters)]
err := f.ExpressionsToRegisters(parameters, registers)
if config.Verbose {
f.Logf("call: %s", funcName)
}
f.assembler.Call(funcName)
f.sideEffects += function.sideEffects
return err
}
// CompileSyscall executes a syscall.
func (f *Function) CompileSyscall(expr *expression.Expression) error {
parameters := expr.Children[1:]
registers := f.cpu.Syscall[:len(parameters)]
err := f.ExpressionsToRegisters(parameters, registers)
f.assembler.Syscall()
f.sideEffects++
return err
}

View File

@ -166,6 +166,10 @@ func (f *Function) ExpressionToRegister(root *expression.Expression, register cp
// ExpressionsToRegisters moves multiple expressions into the specified registers.
func (f *Function) ExpressionsToRegisters(expressions []*expression.Expression, registers []cpu.Register) error {
for _, register := range registers {
f.SaveRegister(register)
}
for i := len(expressions) - 1; i >= 0; i-- {
expression := expressions[i]
register := registers[i]

View File

@ -20,6 +20,7 @@ type Function struct {
// Compile turns a function into machine code.
func (f *Function) Compile() {
defer close(f.finished)
f.assembler.Label(f.Name)
f.err = f.CompileTokens(f.Body)
f.assembler.Return()
@ -124,6 +125,11 @@ func (f *Function) String() string {
return f.Name
}
// Wait will block until the compilation finishes.
func (f *Function) Wait() {
<-f.finished
}
// identifierExists returns true if the identifier has been defined.
func (f *Function) identifierExists(name string) bool {
_, exists := f.variables[name]

View File

@ -1,43 +0,0 @@
package build
import (
"git.akyoto.dev/cli/q/src/build/config"
"git.akyoto.dev/cli/q/src/build/cpu"
"git.akyoto.dev/cli/q/src/build/expression"
)
// CompileFunctionCall executes a function call.
func (f *Function) CompileFunctionCall(expr *expression.Expression) error {
var (
funcName = expr.Children[0].Token.Text()
parameters = expr.Children[1:]
isSyscall = funcName == "syscall"
registers []cpu.Register
)
if isSyscall {
registers = f.cpu.Syscall
} else {
registers = f.cpu.Call
}
registers = registers[:len(parameters)]
for _, register := range registers {
f.SaveRegister(register)
}
err := f.ExpressionsToRegisters(parameters, registers)
if config.Verbose {
f.Logf("call: %s", funcName)
}
if isSyscall {
f.assembler.Syscall()
} else {
f.assembler.Call(funcName)
}
return err
}

View File

@ -27,6 +27,7 @@ func compile(functions <-chan *Function, errs <-chan error) (Result, error) {
continue
}
function.functions = allFunctions
allFunctions[function.Name] = function
}
}

View File

@ -11,12 +11,15 @@ import (
// compiler is the data structure we embed in each function to preserve compilation state.
type compiler struct {
assembler asm.Assembler
count counter
cpu cpu.CPU
debug []debug
err error
variables map[string]*Variable
assembler asm.Assembler
count counter
cpu cpu.CPU
debug []debug
err error
variables map[string]*Variable
functions map[string]*Function
sideEffects int
finished chan struct{}
}
// counter stores how often a certain statement appeared so we can generate a unique label from it.

View File

@ -251,6 +251,7 @@ func scanFile(path string, functions chan<- *Function) error {
Return: x64.ReturnValueRegisters,
},
variables: map[string]*Variable{},
finished: make(chan struct{}),
},
}