diff --git a/compiler/compiler.go b/compiler/compiler.go index d349cbdb..b56962fe 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -177,50 +177,8 @@ func (c *Compiler) Parse(mainPath string) error { c.ir = ir.NewProgram(lprogram, mainPath) - // Make a list of packages in import order. - packageList := []*ssa.Package{} - packageSet := map[string]struct{}{} - worklist := []string{"runtime", mainPath} - for len(worklist) != 0 { - pkgPath := worklist[0] - pkg := c.ir.Program.ImportedPackage(pkgPath) - if pkg == nil { - // Non-SSA package (e.g. cgo). - packageSet[pkgPath] = struct{}{} - worklist = worklist[1:] - continue - } - if _, ok := packageSet[pkgPath]; ok { - // Package already in the final package list. - worklist = worklist[1:] - continue - } - - unsatisfiedImports := make([]string, 0) - imports := pkg.Pkg.Imports() - for _, pkg := range imports { - if _, ok := packageSet[pkg.Path()]; ok { - continue - } - unsatisfiedImports = append(unsatisfiedImports, pkg.Path()) - } - if len(unsatisfiedImports) == 0 { - // All dependencies of this package are satisfied, so add this - // package to the list. - packageList = append(packageList, pkg) - packageSet[pkgPath] = struct{}{} - 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...) - } - } - - for _, pkg := range packageList { - c.ir.AddPackage(pkg) - } + // Run some DCE and analysis passes. The results are later used by the + // compiler. c.ir.SimpleDCE() // remove most dead code c.ir.AnalyseCallgraph() // set up callgraph c.ir.AnalyseInterfaceConversions() // determine which types are converted to an interface diff --git a/ir/ir.go b/ir/ir.go index 88a2a53b..b495f77c 100644 --- a/ir/ir.go +++ b/ir/ir.go @@ -109,7 +109,48 @@ func NewProgram(lprogram *loader.Program, mainPath string) *Program { program := ssautil.CreateProgram(lprogram, ssa.SanityCheckFunctions|ssa.BareInits|ssa.GlobalDebug) program.Build() - return &Program{ + // Make a list of packages in import order. + packageList := []*ssa.Package{} + packageSet := map[string]struct{}{} + worklist := []string{"runtime", mainPath} + for len(worklist) != 0 { + pkgPath := worklist[0] + pkg := program.ImportedPackage(pkgPath) + if pkg == nil { + // Non-SSA package (e.g. cgo). + packageSet[pkgPath] = struct{}{} + worklist = worklist[1:] + continue + } + if _, ok := packageSet[pkgPath]; ok { + // Package already in the final package list. + worklist = worklist[1:] + continue + } + + unsatisfiedImports := make([]string, 0) + imports := pkg.Pkg.Imports() + for _, pkg := range imports { + if _, ok := packageSet[pkg.Path()]; ok { + continue + } + unsatisfiedImports = append(unsatisfiedImports, pkg.Path()) + } + if len(unsatisfiedImports) == 0 { + // All dependencies of this package are satisfied, so add this + // package to the list. + packageList = append(packageList, pkg) + packageSet[pkgPath] = struct{}{} + 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...) + } + } + + p := &Program{ Program: program, mainPkg: program.ImportedPackage(mainPath), functionMap: make(map[*ssa.Function]*Function), @@ -118,6 +159,12 @@ func NewProgram(lprogram *loader.Program, mainPath string) *Program { interfaces: make(map[string]*Interface), comments: comments, } + + for _, pkg := range packageList { + p.AddPackage(pkg) + } + + return p } // Add a package to this Program. All packages need to be added first before any