Implemented dependency tracking
This commit is contained in:
parent
08660ad845
commit
751614e7c0
@ -1,6 +1,8 @@
|
|||||||
package asmc
|
package asmc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"git.urbach.dev/cli/q/src/asm"
|
"git.urbach.dev/cli/q/src/asm"
|
||||||
"git.urbach.dev/cli/q/src/x86"
|
"git.urbach.dev/cli/q/src/x86"
|
||||||
)
|
)
|
||||||
@ -21,7 +23,7 @@ func (c *compiler) call(x asm.Instruction) {
|
|||||||
destination, exists := c.codeLabels[data.Name]
|
destination, exists := c.codeLabels[data.Name]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
panic("unknown jump label")
|
panic(fmt.Sprintf("unknown jump label %s", data.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
distance := destination - (pointer.Position + Address(pointer.Size))
|
distance := destination - (pointer.Position + Address(pointer.Size))
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package asmc
|
package asmc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"git.urbach.dev/cli/q/src/asm"
|
"git.urbach.dev/cli/q/src/asm"
|
||||||
"git.urbach.dev/cli/q/src/x86"
|
"git.urbach.dev/cli/q/src/x86"
|
||||||
)
|
)
|
||||||
@ -36,7 +38,7 @@ func (c *compiler) jump(x asm.Instruction) {
|
|||||||
destination, exists := c.codeLabels[label.Name]
|
destination, exists := c.codeLabels[label.Name]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
panic("unknown jump label")
|
panic(fmt.Sprintf("unknown jump label %s", label.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
distance := destination - (pointer.Position + Address(pointer.Size))
|
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
|
// Start parallel compilation
|
||||||
CompileFunctions(all.Functions)
|
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.Init = init
|
||||||
result.Main = main
|
result.Main = main
|
||||||
result.Functions = all.Functions
|
result.Functions = all.Functions
|
||||||
|
@ -1,37 +1,20 @@
|
|||||||
package compiler
|
package compiler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.urbach.dev/cli/q/src/asm"
|
|
||||||
"git.urbach.dev/cli/q/src/core"
|
"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.
|
// 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)) {
|
func (r *Result) eachFunction(caller *core.Function, traversed map[*core.Function]bool, call func(*core.Function)) {
|
||||||
call(caller)
|
call(caller)
|
||||||
traversed[caller] = true
|
traversed[caller] = true
|
||||||
|
|
||||||
for _, x := range caller.Assembler.Instructions {
|
for _, function := range caller.Dependencies {
|
||||||
if x.Mnemonic != asm.CALL {
|
if traversed[function] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
label, isLabel := x.Data.(*asm.Label)
|
r.eachFunction(function, traversed, call)
|
||||||
|
|
||||||
if !isLabel {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
callee, exists := r.Functions[label.Name]
|
|
||||||
|
|
||||||
if !exists {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if traversed[callee] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
r.eachFunction(callee, traversed, call)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,16 +43,7 @@ func (f *Function) CompileCall(root *expression.Expression) ([]types.Type, error
|
|||||||
|
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case *eval.Label:
|
case *eval.Label:
|
||||||
fn, exists := f.All.Functions[value.Label]
|
fn := 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(parameters) != len(fn.Input) {
|
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())
|
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.SaveRegister(f.CPU.Input[1])
|
||||||
f.RegisterRegister(asm.MOVE, f.CPU.Input[0], variable.Value.Register)
|
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.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
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,8 @@ func (f *Function) CompileNew(root *expression.Expression) (types.Type, error) {
|
|||||||
|
|
||||||
f.SaveRegister(f.CPU.Input[0])
|
f.SaveRegister(f.CPU.Input[0])
|
||||||
f.RegisterNumber(asm.MOVE, f.CPU.Input[0], typ.Size())
|
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
|
return &types.Pointer{To: typ}, nil
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,8 @@ func (f *Function) EvaluateDot(expr *expression.Expression) (eval.Value, error)
|
|||||||
return value, nil
|
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 {
|
if isConst {
|
||||||
number, err := ToNumber(constant.Token, constant.File)
|
number, err := ToNumber(constant.Token, constant.File)
|
||||||
@ -73,10 +74,18 @@ func (f *Function) EvaluateDot(expr *expression.Expression) (eval.Value, error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function, exists := f.All.Functions[label]
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
f.Dependencies = append(f.Dependencies, function)
|
||||||
|
|
||||||
value := &eval.Label{
|
value := &eval.Label{
|
||||||
Typ: types.AnyPointer,
|
Typ: types.AnyPointer,
|
||||||
Label: fmt.Sprintf("%s.%s", leftText, rightText),
|
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 {
|
if function != nil {
|
||||||
|
f.Dependencies = append(f.Dependencies, function)
|
||||||
|
|
||||||
value := &eval.Label{
|
value := &eval.Label{
|
||||||
Typ: types.AnyPointer,
|
Typ: types.AnyPointer,
|
||||||
Label: function.UniqueName,
|
Label: function.UniqueName,
|
||||||
|
@ -20,6 +20,7 @@ type Function struct {
|
|||||||
Input []*Parameter
|
Input []*Parameter
|
||||||
Output []*Parameter
|
Output []*Parameter
|
||||||
OutputTypes []types.Type
|
OutputTypes []types.Type
|
||||||
|
Dependencies []*Function
|
||||||
DLLs dll.List
|
DLLs dll.List
|
||||||
Err error
|
Err error
|
||||||
deferred []func()
|
deferred []func()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import core
|
import sys
|
||||||
|
|
||||||
struct Struct {
|
struct Struct {
|
||||||
func *any
|
func *any
|
||||||
@ -6,6 +6,11 @@ struct Struct {
|
|||||||
|
|
||||||
main() {
|
main() {
|
||||||
s := new(Struct)
|
s := new(Struct)
|
||||||
s.func = core.exit
|
s.func = f
|
||||||
s.func()
|
s.func()
|
||||||
|
sys.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
f() {
|
||||||
|
sys.exit(0)
|
||||||
}
|
}
|
@ -1,6 +1,13 @@
|
|||||||
import core
|
import core
|
||||||
|
import sys
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
func := f
|
||||||
|
func()
|
||||||
|
sys.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
f() {
|
||||||
exit := core.exit
|
exit := core.exit
|
||||||
exit()
|
exit()
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user