compiler: Fix package dependency order calculation

The algorithm is now simpler and seems to work better.
Этот коммит содержится в:
Ayke van Laethem 2018-05-05 18:29:23 +02:00
родитель 88f143f3e6
коммит db8b6c6900

31
tgo.go
Просмотреть файл

@ -124,7 +124,7 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
// TODO: pick the error of the first package, not a random package // TODO: pick the error of the first package, not a random package
for _, pkgInfo := range lprogram.AllPackages { for _, pkgInfo := range lprogram.AllPackages {
fmt.Println("package:", pkgInfo.Pkg.Name()) fmt.Println("package:", pkgInfo.Pkg.Path())
if len(pkgInfo.Errors) != 0 { if len(pkgInfo.Errors) != 0 {
return pkgInfo.Errors[0] return pkgInfo.Errors[0]
} }
@ -136,23 +136,24 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
// Make a list of packages in import order. // Make a list of packages in import order.
packageList := []*ssa.Package{} packageList := []*ssa.Package{}
packageSet := map[string]struct{}{} packageSet := map[string]struct{}{}
worklist := [][]string{{"runtime", mainPath}} worklist := []string{"runtime", mainPath}
for len(worklist) != 0 { for len(worklist) != 0 {
for _, pkgPath := range worklist[0] { pkgPath := worklist[0]
pkg := program.ImportedPackage(pkgPath) pkg := program.ImportedPackage(pkgPath)
if pkg == nil { if pkg == nil {
// Non-SSA package (e.g. cgo).
packageSet[pkgPath] = struct{}{} packageSet[pkgPath] = struct{}{}
continue // non-SSA package (e.g. cgo) worklist = worklist[1:]
continue
} }
if _, ok := packageSet[pkgPath]; ok { if _, ok := packageSet[pkgPath]; ok {
// Package already in the final package list.
worklist = worklist[1:]
continue continue
} }
unsatisfiedImports := make([]string, 0) unsatisfiedImports := make([]string, 0)
imports := pkg.Pkg.Imports() imports := pkg.Pkg.Imports()
if pkgPath != "runtime" && pkgPath != "unsafe" && pkgPath != "runtime/cgo" && pkgPath != "syscall" {
imports = append(imports, program.ImportedPackage("runtime").Pkg)
}
for _, pkg := range imports { for _, pkg := range imports {
if _, ok := packageSet[pkg.Path()]; ok { if _, ok := packageSet[pkg.Path()]; ok {
continue continue
@ -160,15 +161,17 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
unsatisfiedImports = append(unsatisfiedImports, pkg.Path()) unsatisfiedImports = append(unsatisfiedImports, pkg.Path())
} }
if len(unsatisfiedImports) == 0 { if len(unsatisfiedImports) == 0 {
// all dependencies are in packageList inserted // All dependencies of this package are satisfied, so add this
// package to the list.
packageList = append(packageList, pkg) packageList = append(packageList, pkg)
packageSet[pkgPath] = struct{}{} packageSet[pkgPath] = struct{}{}
} else {
unsatisfiedImports = append(unsatisfiedImports, pkgPath) // reconsider
worklist = append(worklist, unsatisfiedImports)
}
}
worklist = worklist[1:] worklist = worklist[1:]
} else {
// Prepend all dependencies to the worklist and reconsider this
// package (by not removing it from the worklist). At that point, it
// must be possible to add it to packageList.
worklist = append(unsatisfiedImports, worklist...)
}
} }
// Transform each package into LLVM IR. // Transform each package into LLVM IR.
@ -309,7 +312,7 @@ func (c *Compiler) getFunctionName(fn *ssa.Function) string {
} }
func (c *Compiler) parsePackage(program *ssa.Program, pkg *ssa.Package) error { func (c *Compiler) parsePackage(program *ssa.Program, pkg *ssa.Package) error {
fmt.Println("package:", pkg.Pkg.Path()) fmt.Println("\npackage:", pkg.Pkg.Path())
// Make sure we're walking through all members in a constant order every // Make sure we're walking through all members in a constant order every
// run. // run.