GoPLS Viewer

Home|gopls/go/ssa/ssautil/load.go
1// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package ssautil
6
7// This file defines utility functions for constructing programs in SSA form.
8
9import (
10    "go/ast"
11    "go/token"
12    "go/types"
13
14    "golang.org/x/tools/go/loader"
15    "golang.org/x/tools/go/packages"
16    "golang.org/x/tools/go/ssa"
17    "golang.org/x/tools/internal/typeparams"
18)
19
20// Packages creates an SSA program for a set of packages.
21//
22// The packages must have been loaded from source syntax using the
23// golang.org/x/tools/go/packages.Load function in LoadSyntax or
24// LoadAllSyntax mode.
25//
26// Packages creates an SSA package for each well-typed package in the
27// initial list, plus all their dependencies. The resulting list of
28// packages corresponds to the list of initial packages, and may contain
29// a nil if SSA code could not be constructed for the corresponding initial
30// package due to type errors.
31//
32// Code for bodies of functions is not built until Build is called on
33// the resulting Program. SSA code is constructed only for the initial
34// packages with well-typed syntax trees.
35//
36// The mode parameter controls diagnostics and checking during SSA construction.
37func Packages(initial []*packages.Packagemode ssa.BuilderMode) (*ssa.Program, []*ssa.Package) {
38    return doPackages(initialmodefalse)
39}
40
41// AllPackages creates an SSA program for a set of packages plus all
42// their dependencies.
43//
44// The packages must have been loaded from source syntax using the
45// golang.org/x/tools/go/packages.Load function in LoadAllSyntax mode.
46//
47// AllPackages creates an SSA package for each well-typed package in the
48// initial list, plus all their dependencies. The resulting list of
49// packages corresponds to the list of initial packages, and may contain
50// a nil if SSA code could not be constructed for the corresponding
51// initial package due to type errors.
52//
53// Code for bodies of functions is not built until Build is called on
54// the resulting Program. SSA code is constructed for all packages with
55// well-typed syntax trees.
56//
57// The mode parameter controls diagnostics and checking during SSA construction.
58func AllPackages(initial []*packages.Packagemode ssa.BuilderMode) (*ssa.Program, []*ssa.Package) {
59    return doPackages(initialmodetrue)
60}
61
62func doPackages(initial []*packages.Packagemode ssa.BuilderModedeps bool) (*ssa.Program, []*ssa.Package) {
63
64    var fset *token.FileSet
65    if len(initial) > 0 {
66        fset = initial[0].Fset
67    }
68
69    prog := ssa.NewProgram(fsetmode)
70
71    isInitial := make(map[*packages.Package]boollen(initial))
72    for _p := range initial {
73        isInitial[p] = true
74    }
75
76    ssamap := make(map[*packages.Package]*ssa.Package)
77    packages.Visit(initialnil, func(p *packages.Package) {
78        if p.Types != nil && !p.IllTyped {
79            var files []*ast.File
80            var info *types.Info
81            if deps || isInitial[p] {
82                files = p.Syntax
83                info = p.TypesInfo
84            }
85            ssamap[p] = prog.CreatePackage(p.Typesfilesinfotrue)
86        }
87    })
88
89    var ssapkgs []*ssa.Package
90    for _p := range initial {
91        ssapkgs = append(ssapkgsssamap[p]) // may be nil
92    }
93    return progssapkgs
94}
95
96// CreateProgram returns a new program in SSA form, given a program
97// loaded from source.  An SSA package is created for each transitively
98// error-free package of lprog.
99//
100// Code for bodies of functions is not built until Build is called
101// on the result.
102//
103// The mode parameter controls diagnostics and checking during SSA construction.
104//
105// Deprecated: Use golang.org/x/tools/go/packages and the Packages
106// function instead; see ssa.Example_loadPackages.
107func CreateProgram(lprog *loader.Programmode ssa.BuilderMode) *ssa.Program {
108    prog := ssa.NewProgram(lprog.Fsetmode)
109
110    for _info := range lprog.AllPackages {
111        if info.TransitivelyErrorFree {
112            prog.CreatePackage(info.Pkginfo.Files, &info.Infoinfo.Importable)
113        }
114    }
115
116    return prog
117}
118
119// BuildPackage builds an SSA program with IR for a single package.
120//
121// It populates pkg by type-checking the specified file ASTs.  All
122// dependencies are loaded using the importer specified by tc, which
123// typically loads compiler export data; SSA code cannot be built for
124// those packages.  BuildPackage then constructs an ssa.Program with all
125// dependency packages created, and builds and returns the SSA package
126// corresponding to pkg.
127//
128// The caller must have set pkg.Path() to the import path.
129//
130// The operation fails if there were any type-checking or import errors.
131//
132// See ../example_test.go for an example.
133func BuildPackage(tc *types.Configfset *token.FileSetpkg *types.Packagefiles []*ast.Filemode ssa.BuilderMode) (*ssa.Package, *types.Infoerror) {
134    if fset == nil {
135        panic("no token.FileSet")
136    }
137    if pkg.Path() == "" {
138        panic("package has no import path")
139    }
140
141    info := &types.Info{
142        Types:      make(map[ast.Expr]types.TypeAndValue),
143        Defs:       make(map[*ast.Ident]types.Object),
144        Uses:       make(map[*ast.Ident]types.Object),
145        Implicits:  make(map[ast.Node]types.Object),
146        Scopes:     make(map[ast.Node]*types.Scope),
147        Selectionsmake(map[*ast.SelectorExpr]*types.Selection),
148    }
149    typeparams.InitInstanceInfo(info)
150    if err := types.NewChecker(tcfsetpkginfo).Files(files); err != nil {
151        return nilnilerr
152    }
153
154    prog := ssa.NewProgram(fsetmode)
155
156    // Create SSA packages for all imports.
157    // Order is not significant.
158    created := make(map[*types.Package]bool)
159    var createAll func(pkgs []*types.Package)
160    createAll = func(pkgs []*types.Package) {
161        for _p := range pkgs {
162            if !created[p] {
163                created[p] = true
164                prog.CreatePackage(pnilniltrue)
165                createAll(p.Imports())
166            }
167        }
168    }
169    createAll(pkg.Imports())
170
171    // Create and build the primary package.
172    ssapkg := prog.CreatePackage(pkgfilesinfofalse)
173    ssapkg.Build()
174    return ssapkginfonil
175}
176
MembersX
BuildPackage.mode
packages
CreateProgram.mode
BuildPackage.tc
BuildPackage.BlockStmt.RangeStmt_5537.p
Packages.initial
doPackages.fset
doPackages.ssamap
doPackages.RangeStmt_2636.p
CreateProgram.prog
BuildPackage
BuildPackage.files
BuildPackage.ssapkg
Packages
doPackages
doPackages.prog
doPackages.mode
doPackages.BlockStmt.BlockStmt.info
doPackages.ssapkgs
BuildPackage.err
types
AllPackages.initial
doPackages.initial
doPackages.deps
doPackages.isInitial
doPackages.RangeStmt_3064.p
BuildPackage.pkg
token
loader
Packages.mode
AllPackages.mode
CreateProgram.lprog
CreateProgram.RangeStmt_3761.info
BuildPackage.info
ssa
typeparams
AllPackages
doPackages.BlockStmt.BlockStmt.files
BuildPackage.prog
BuildPackage.created
ast
CreateProgram
BuildPackage.fset
Members
X