Implemented compilation finished events
This commit is contained in:
parent
3fe2cd1da2
commit
247b82b529
@ -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
44
src/build/Call.go
Normal 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
|
||||
}
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
}
|
@ -27,6 +27,7 @@ func compile(functions <-chan *Function, errs <-chan error) (Result, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
function.functions = allFunctions
|
||||
allFunctions[function.Name] = function
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -251,6 +251,7 @@ func scanFile(path string, functions chan<- *Function) error {
|
||||
Return: x64.ReturnValueRegisters,
|
||||
},
|
||||
variables: map[string]*Variable{},
|
||||
finished: make(chan struct{}),
|
||||
},
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user