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