Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / go / ssa / create.go
1 // Copyright 2013 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
5 package ssa
6
7 // This file implements the CREATE phase of SSA construction.
8 // See builder.go for explanation.
9
10 import (
11         "fmt"
12         "go/ast"
13         "go/token"
14         "go/types"
15         "os"
16         "sync"
17
18         "golang.org/x/tools/go/types/typeutil"
19 )
20
21 // NewProgram returns a new SSA Program.
22 //
23 // mode controls diagnostics and checking during SSA construction.
24 //
25 func NewProgram(fset *token.FileSet, mode BuilderMode) *Program {
26         prog := &Program{
27                 Fset:     fset,
28                 imported: make(map[string]*Package),
29                 packages: make(map[*types.Package]*Package),
30                 thunks:   make(map[selectionKey]*Function),
31                 bounds:   make(map[*types.Func]*Function),
32                 mode:     mode,
33         }
34
35         h := typeutil.MakeHasher() // protected by methodsMu, in effect
36         prog.methodSets.SetHasher(h)
37         prog.canon.SetHasher(h)
38
39         return prog
40 }
41
42 // memberFromObject populates package pkg with a member for the
43 // typechecker object obj.
44 //
45 // For objects from Go source code, syntax is the associated syntax
46 // tree (for funcs and vars only); it will be used during the build
47 // phase.
48 //
49 func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node) {
50         name := obj.Name()
51         switch obj := obj.(type) {
52         case *types.Builtin:
53                 if pkg.Pkg != types.Unsafe {
54                         panic("unexpected builtin object: " + obj.String())
55                 }
56
57         case *types.TypeName:
58                 pkg.Members[name] = &Type{
59                         object: obj,
60                         pkg:    pkg,
61                 }
62
63         case *types.Const:
64                 c := &NamedConst{
65                         object: obj,
66                         Value:  NewConst(obj.Val(), obj.Type()),
67                         pkg:    pkg,
68                 }
69                 pkg.values[obj] = c.Value
70                 pkg.Members[name] = c
71
72         case *types.Var:
73                 g := &Global{
74                         Pkg:    pkg,
75                         name:   name,
76                         object: obj,
77                         typ:    types.NewPointer(obj.Type()), // address
78                         pos:    obj.Pos(),
79                 }
80                 pkg.values[obj] = g
81                 pkg.Members[name] = g
82
83         case *types.Func:
84                 sig := obj.Type().(*types.Signature)
85                 if sig.Recv() == nil && name == "init" {
86                         pkg.ninit++
87                         name = fmt.Sprintf("init#%d", pkg.ninit)
88                 }
89                 fn := &Function{
90                         name:      name,
91                         object:    obj,
92                         Signature: sig,
93                         syntax:    syntax,
94                         pos:       obj.Pos(),
95                         Pkg:       pkg,
96                         Prog:      pkg.Prog,
97                 }
98                 if syntax == nil {
99                         fn.Synthetic = "loaded from gc object file"
100                 }
101
102                 pkg.values[obj] = fn
103                 if sig.Recv() == nil {
104                         pkg.Members[name] = fn // package-level function
105                 }
106
107         default: // (incl. *types.Package)
108                 panic("unexpected Object type: " + obj.String())
109         }
110 }
111
112 // membersFromDecl populates package pkg with members for each
113 // typechecker object (var, func, const or type) associated with the
114 // specified decl.
115 //
116 func membersFromDecl(pkg *Package, decl ast.Decl) {
117         switch decl := decl.(type) {
118         case *ast.GenDecl: // import, const, type or var
119                 switch decl.Tok {
120                 case token.CONST:
121                         for _, spec := range decl.Specs {
122                                 for _, id := range spec.(*ast.ValueSpec).Names {
123                                         if !isBlankIdent(id) {
124                                                 memberFromObject(pkg, pkg.info.Defs[id], nil)
125                                         }
126                                 }
127                         }
128
129                 case token.VAR:
130                         for _, spec := range decl.Specs {
131                                 for _, id := range spec.(*ast.ValueSpec).Names {
132                                         if !isBlankIdent(id) {
133                                                 memberFromObject(pkg, pkg.info.Defs[id], spec)
134                                         }
135                                 }
136                         }
137
138                 case token.TYPE:
139                         for _, spec := range decl.Specs {
140                                 id := spec.(*ast.TypeSpec).Name
141                                 if !isBlankIdent(id) {
142                                         memberFromObject(pkg, pkg.info.Defs[id], nil)
143                                 }
144                         }
145                 }
146
147         case *ast.FuncDecl:
148                 id := decl.Name
149                 if !isBlankIdent(id) {
150                         memberFromObject(pkg, pkg.info.Defs[id], decl)
151                 }
152         }
153 }
154
155 // CreatePackage constructs and returns an SSA Package from the
156 // specified type-checked, error-free file ASTs, and populates its
157 // Members mapping.
158 //
159 // importable determines whether this package should be returned by a
160 // subsequent call to ImportedPackage(pkg.Path()).
161 //
162 // The real work of building SSA form for each function is not done
163 // until a subsequent call to Package.Build().
164 //
165 func (prog *Program) CreatePackage(pkg *types.Package, files []*ast.File, info *types.Info, importable bool) *Package {
166         p := &Package{
167                 Prog:    prog,
168                 Members: make(map[string]Member),
169                 values:  make(map[types.Object]Value),
170                 Pkg:     pkg,
171                 info:    info,  // transient (CREATE and BUILD phases)
172                 files:   files, // transient (CREATE and BUILD phases)
173         }
174
175         // Add init() function.
176         p.init = &Function{
177                 name:      "init",
178                 Signature: new(types.Signature),
179                 Synthetic: "package initializer",
180                 Pkg:       p,
181                 Prog:      prog,
182         }
183         p.Members[p.init.name] = p.init
184
185         // CREATE phase.
186         // Allocate all package members: vars, funcs, consts and types.
187         if len(files) > 0 {
188                 // Go source package.
189                 for _, file := range files {
190                         for _, decl := range file.Decls {
191                                 membersFromDecl(p, decl)
192                         }
193                 }
194         } else {
195                 // GC-compiled binary package (or "unsafe")
196                 // No code.
197                 // No position information.
198                 scope := p.Pkg.Scope()
199                 for _, name := range scope.Names() {
200                         obj := scope.Lookup(name)
201                         memberFromObject(p, obj, nil)
202                         if obj, ok := obj.(*types.TypeName); ok {
203                                 if named, ok := obj.Type().(*types.Named); ok {
204                                         for i, n := 0, named.NumMethods(); i < n; i++ {
205                                                 memberFromObject(p, named.Method(i), nil)
206                                         }
207                                 }
208                         }
209                 }
210         }
211
212         if prog.mode&BareInits == 0 {
213                 // Add initializer guard variable.
214                 initguard := &Global{
215                         Pkg:  p,
216                         name: "init$guard",
217                         typ:  types.NewPointer(tBool),
218                 }
219                 p.Members[initguard.Name()] = initguard
220         }
221
222         if prog.mode&GlobalDebug != 0 {
223                 p.SetDebugMode(true)
224         }
225
226         if prog.mode&PrintPackages != 0 {
227                 printMu.Lock()
228                 p.WriteTo(os.Stdout)
229                 printMu.Unlock()
230         }
231
232         if importable {
233                 prog.imported[p.Pkg.Path()] = p
234         }
235         prog.packages[p.Pkg] = p
236
237         return p
238 }
239
240 // printMu serializes printing of Packages/Functions to stdout.
241 var printMu sync.Mutex
242
243 // AllPackages returns a new slice containing all packages in the
244 // program prog in unspecified order.
245 //
246 func (prog *Program) AllPackages() []*Package {
247         pkgs := make([]*Package, 0, len(prog.packages))
248         for _, pkg := range prog.packages {
249                 pkgs = append(pkgs, pkg)
250         }
251         return pkgs
252 }
253
254 // ImportedPackage returns the importable Package whose PkgPath
255 // is path, or nil if no such Package has been created.
256 //
257 // A parameter to CreatePackage determines whether a package should be
258 // considered importable. For example, no import declaration can resolve
259 // to the ad-hoc main package created by 'go build foo.go'.
260 //
261 // TODO(adonovan): rethink this function and the "importable" concept;
262 // most packages are importable. This function assumes that all
263 // types.Package.Path values are unique within the ssa.Program, which is
264 // false---yet this function remains very convenient.
265 // Clients should use (*Program).Package instead where possible.
266 // SSA doesn't really need a string-keyed map of packages.
267 //
268 func (prog *Program) ImportedPackage(path string) *Package {
269         return prog.imported[path]
270 }