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
|
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
|
```shell
|
||||||
q build examples/hello -v
|
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.
|
// ExpressionsToRegisters moves multiple expressions into the specified registers.
|
||||||
func (f *Function) ExpressionsToRegisters(expressions []*expression.Expression, registers []cpu.Register) error {
|
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-- {
|
for i := len(expressions) - 1; i >= 0; i-- {
|
||||||
expression := expressions[i]
|
expression := expressions[i]
|
||||||
register := registers[i]
|
register := registers[i]
|
||||||
|
@ -20,6 +20,7 @@ type Function struct {
|
|||||||
|
|
||||||
// Compile turns a function into machine code.
|
// Compile turns a function into machine code.
|
||||||
func (f *Function) Compile() {
|
func (f *Function) Compile() {
|
||||||
|
defer close(f.finished)
|
||||||
f.assembler.Label(f.Name)
|
f.assembler.Label(f.Name)
|
||||||
f.err = f.CompileTokens(f.Body)
|
f.err = f.CompileTokens(f.Body)
|
||||||
f.assembler.Return()
|
f.assembler.Return()
|
||||||
@ -124,6 +125,11 @@ func (f *Function) String() string {
|
|||||||
return f.Name
|
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.
|
// identifierExists returns true if the identifier has been defined.
|
||||||
func (f *Function) identifierExists(name string) bool {
|
func (f *Function) identifierExists(name string) bool {
|
||||||
_, exists := f.variables[name]
|
_, 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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function.functions = allFunctions
|
||||||
allFunctions[function.Name] = function
|
allFunctions[function.Name] = function
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,15 @@ import (
|
|||||||
|
|
||||||
// compiler is the data structure we embed in each function to preserve compilation state.
|
// compiler is the data structure we embed in each function to preserve compilation state.
|
||||||
type compiler struct {
|
type compiler struct {
|
||||||
assembler asm.Assembler
|
assembler asm.Assembler
|
||||||
count counter
|
count counter
|
||||||
cpu cpu.CPU
|
cpu cpu.CPU
|
||||||
debug []debug
|
debug []debug
|
||||||
err error
|
err error
|
||||||
variables map[string]*Variable
|
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.
|
// 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,
|
Return: x64.ReturnValueRegisters,
|
||||||
},
|
},
|
||||||
variables: map[string]*Variable{},
|
variables: map[string]*Variable{},
|
||||||
|
finished: make(chan struct{}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user