Implemented dependency tracking
This commit is contained in:
parent
08660ad845
commit
751614e7c0
@ -1,6 +1,8 @@
|
||||
package asmc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.urbach.dev/cli/q/src/asm"
|
||||
"git.urbach.dev/cli/q/src/x86"
|
||||
)
|
||||
@ -21,7 +23,7 @@ func (c *compiler) call(x asm.Instruction) {
|
||||
destination, exists := c.codeLabels[data.Name]
|
||||
|
||||
if !exists {
|
||||
panic("unknown jump label")
|
||||
panic(fmt.Sprintf("unknown jump label %s", data.Name))
|
||||
}
|
||||
|
||||
distance := destination - (pointer.Position + Address(pointer.Size))
|
||||
|
@ -1,6 +1,8 @@
|
||||
package asmc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.urbach.dev/cli/q/src/asm"
|
||||
"git.urbach.dev/cli/q/src/x86"
|
||||
)
|
||||
@ -36,7 +38,7 @@ func (c *compiler) jump(x asm.Instruction) {
|
||||
destination, exists := c.codeLabels[label.Name]
|
||||
|
||||
if !exists {
|
||||
panic("unknown jump label")
|
||||
panic(fmt.Sprintf("unknown jump label %s", label.Name))
|
||||
}
|
||||
|
||||
distance := destination - (pointer.Position + Address(pointer.Size))
|
||||
|
@ -82,6 +82,20 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
|
||||
}
|
||||
}
|
||||
|
||||
// Check for existence of `init`
|
||||
init, exists := all.Functions["core.init"]
|
||||
|
||||
if !exists {
|
||||
return result, errors.MissingInitFunction
|
||||
}
|
||||
|
||||
// Check for existence of `main`
|
||||
main, exists := all.Functions["main.main"]
|
||||
|
||||
if !exists {
|
||||
return result, errors.MissingMainFunction
|
||||
}
|
||||
|
||||
// Start parallel compilation
|
||||
CompileFunctions(all.Functions)
|
||||
|
||||
@ -104,20 +118,6 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
|
||||
}
|
||||
}
|
||||
|
||||
// Check for existence of `init`
|
||||
init, exists := all.Functions["core.init"]
|
||||
|
||||
if !exists {
|
||||
return result, errors.MissingInitFunction
|
||||
}
|
||||
|
||||
// Check for existence of `main`
|
||||
main, exists := all.Functions["main.main"]
|
||||
|
||||
if !exists {
|
||||
return result, errors.MissingMainFunction
|
||||
}
|
||||
|
||||
result.Init = init
|
||||
result.Main = main
|
||||
result.Functions = all.Functions
|
||||
|
@ -1,37 +1,20 @@
|
||||
package compiler
|
||||
|
||||
import (
|
||||
"git.urbach.dev/cli/q/src/asm"
|
||||
"git.urbach.dev/cli/q/src/core"
|
||||
)
|
||||
|
||||
// eachFunction recursively finds all the calls to external functions.
|
||||
// eachFunction recursively finds all the calls to other functions.
|
||||
// It avoids calling the same function twice with the help of a hashmap.
|
||||
func (r *Result) eachFunction(caller *core.Function, traversed map[*core.Function]bool, call func(*core.Function)) {
|
||||
call(caller)
|
||||
traversed[caller] = true
|
||||
|
||||
for _, x := range caller.Assembler.Instructions {
|
||||
if x.Mnemonic != asm.CALL {
|
||||
for _, function := range caller.Dependencies {
|
||||
if traversed[function] {
|
||||
continue
|
||||
}
|
||||
|
||||
label, isLabel := x.Data.(*asm.Label)
|
||||
|
||||
if !isLabel {
|
||||
continue
|
||||
}
|
||||
|
||||
callee, exists := r.Functions[label.Name]
|
||||
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
if traversed[callee] {
|
||||
continue
|
||||
}
|
||||
|
||||
r.eachFunction(callee, traversed, call)
|
||||
r.eachFunction(function, traversed, call)
|
||||
}
|
||||
}
|
||||
|
@ -43,16 +43,7 @@ func (f *Function) CompileCall(root *expression.Expression) ([]types.Type, error
|
||||
|
||||
switch value := value.(type) {
|
||||
case *eval.Label:
|
||||
fn, exists := f.All.Functions[value.Label]
|
||||
|
||||
if !exists {
|
||||
if value.Label == "main.main" && f.UniqueName == "core.init" {
|
||||
f.Label(asm.CALL, "main.main")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, errors.New(&errors.UnknownIdentifier{Name: value.Label}, f.File, root.Children[0].Token.Position)
|
||||
}
|
||||
fn := f.All.Functions[value.Label]
|
||||
|
||||
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())
|
||||
|
@ -22,6 +22,8 @@ func (f *Function) CompileDelete(root *expression.Expression) error {
|
||||
f.SaveRegister(f.CPU.Input[1])
|
||||
f.RegisterRegister(asm.MOVE, f.CPU.Input[0], variable.Value.Register)
|
||||
f.RegisterNumber(asm.MOVE, f.CPU.Input[1], variable.Value.Typ.(*types.Pointer).To.Size())
|
||||
f.CallSafe(f.All.Functions["mem.free"], f.CPU.Input[:2])
|
||||
free := f.All.Functions["mem.free"]
|
||||
f.CallSafe(free, f.CPU.Input[:2])
|
||||
f.Dependencies = append(f.Dependencies, free)
|
||||
return nil
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ func (f *Function) CompileNew(root *expression.Expression) (types.Type, error) {
|
||||
|
||||
f.SaveRegister(f.CPU.Input[0])
|
||||
f.RegisterNumber(asm.MOVE, f.CPU.Input[0], typ.Size())
|
||||
f.CallSafe(f.All.Functions["mem.alloc"], f.CPU.Input[:1])
|
||||
alloc := f.All.Functions["mem.alloc"]
|
||||
f.CallSafe(alloc, f.CPU.Input[:1])
|
||||
f.Dependencies = append(f.Dependencies, alloc)
|
||||
return &types.Pointer{To: typ}, nil
|
||||
}
|
||||
|
@ -42,7 +42,8 @@ func (f *Function) EvaluateDot(expr *expression.Expression) (eval.Value, error)
|
||||
return value, nil
|
||||
}
|
||||
|
||||
constant, isConst := f.All.Constants[f.Package+"."+leftText+"."+rightText]
|
||||
label := fmt.Sprintf("%s.%s", leftText, rightText)
|
||||
constant, isConst := f.All.Constants[f.Package+"."+label]
|
||||
|
||||
if isConst {
|
||||
number, err := ToNumber(constant.Token, constant.File)
|
||||
@ -73,10 +74,18 @@ func (f *Function) EvaluateDot(expr *expression.Expression) (eval.Value, error)
|
||||
}
|
||||
}
|
||||
|
||||
value := &eval.Label{
|
||||
Typ: types.AnyPointer,
|
||||
Label: fmt.Sprintf("%s.%s", leftText, rightText),
|
||||
function, exists := f.All.Functions[label]
|
||||
|
||||
if exists {
|
||||
f.Dependencies = append(f.Dependencies, function)
|
||||
|
||||
value := &eval.Label{
|
||||
Typ: types.AnyPointer,
|
||||
Label: label,
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
|
||||
return value, nil
|
||||
return nil, errors.New(&errors.UnknownIdentifier{Name: label}, f.File, left.Token.Position)
|
||||
}
|
||||
|
@ -41,6 +41,8 @@ func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
|
||||
}
|
||||
|
||||
if function != nil {
|
||||
f.Dependencies = append(f.Dependencies, function)
|
||||
|
||||
value := &eval.Label{
|
||||
Typ: types.AnyPointer,
|
||||
Label: function.UniqueName,
|
||||
|
@ -11,17 +11,18 @@ import (
|
||||
// Function represents the smallest unit of code.
|
||||
type Function struct {
|
||||
register.Machine
|
||||
Package string
|
||||
Name string
|
||||
UniqueName string
|
||||
All *Environment
|
||||
File *fs.File
|
||||
Body token.List
|
||||
Input []*Parameter
|
||||
Output []*Parameter
|
||||
OutputTypes []types.Type
|
||||
DLLs dll.List
|
||||
Err error
|
||||
deferred []func()
|
||||
count count
|
||||
Package string
|
||||
Name string
|
||||
UniqueName string
|
||||
All *Environment
|
||||
File *fs.File
|
||||
Body token.List
|
||||
Input []*Parameter
|
||||
Output []*Parameter
|
||||
OutputTypes []types.Type
|
||||
Dependencies []*Function
|
||||
DLLs dll.List
|
||||
Err error
|
||||
deferred []func()
|
||||
count count
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import core
|
||||
import sys
|
||||
|
||||
struct Struct {
|
||||
func *any
|
||||
@ -6,6 +6,11 @@ struct Struct {
|
||||
|
||||
main() {
|
||||
s := new(Struct)
|
||||
s.func = core.exit
|
||||
s.func = f
|
||||
s.func()
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
f() {
|
||||
sys.exit(0)
|
||||
}
|
@ -1,6 +1,13 @@
|
||||
import core
|
||||
import sys
|
||||
|
||||
main() {
|
||||
func := f
|
||||
func()
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
f() {
|
||||
exit := core.exit
|
||||
exit()
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user