some deletions
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / go / pointer / analysis.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/go/pointer/analysis.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/go/pointer/analysis.go
deleted file mode 100644 (file)
index 0abb04d..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package pointer
-
-// This file defines the main datatypes and Analyze function of the pointer analysis.
-
-import (
-       "fmt"
-       "go/token"
-       "go/types"
-       "io"
-       "os"
-       "reflect"
-       "runtime"
-       "runtime/debug"
-       "sort"
-
-       "golang.org/x/tools/go/callgraph"
-       "golang.org/x/tools/go/ssa"
-       "golang.org/x/tools/go/types/typeutil"
-)
-
-const (
-       // optimization options; enable all when committing
-       optRenumber = true // enable renumbering optimization (makes logs hard to read)
-       optHVN      = true // enable pointer equivalence via Hash-Value Numbering
-
-       // debugging options; disable all when committing
-       debugHVN           = false // enable assertions in HVN
-       debugHVNVerbose    = false // enable extra HVN logging
-       debugHVNCrossCheck = false // run solver with/without HVN and compare (caveats below)
-       debugTimers        = false // show running time of each phase
-)
-
-// object.flags bitmask values.
-const (
-       otTagged   = 1 << iota // type-tagged object
-       otIndirect             // type-tagged object with indirect payload
-       otFunction             // function object
-)
-
-// An object represents a contiguous block of memory to which some
-// (generalized) pointer may point.
-//
-// (Note: most variables called 'obj' are not *objects but nodeids
-// such that a.nodes[obj].obj != nil.)
-//
-type object struct {
-       // flags is a bitset of the node type (ot*) flags defined above.
-       flags uint32
-
-       // Number of following nodes belonging to the same "object"
-       // allocation.  Zero for all other nodes.
-       size uint32
-
-       // data describes this object; it has one of these types:
-       //
-       // ssa.Value    for an object allocated by an SSA operation.
-       // types.Type   for an rtype instance object or *rtype-tagged object.
-       // string       for an instrinsic object, e.g. the array behind os.Args.
-       // nil          for an object allocated by an instrinsic.
-       //              (cgn provides the identity of the intrinsic.)
-       data interface{}
-
-       // The call-graph node (=context) in which this object was allocated.
-       // May be nil for global objects: Global, Const, some Functions.
-       cgn *cgnode
-}
-
-// nodeid denotes a node.
-// It is an index within analysis.nodes.
-// We use small integers, not *node pointers, for many reasons:
-// - they are smaller on 64-bit systems.
-// - sets of them can be represented compactly in bitvectors or BDDs.
-// - order matters; a field offset can be computed by simple addition.
-type nodeid uint32
-
-// A node is an equivalence class of memory locations.
-// Nodes may be pointers, pointed-to locations, neither, or both.
-//
-// Nodes that are pointed-to locations ("labels") have an enclosing
-// object (see analysis.enclosingObject).
-//
-type node struct {
-       // If non-nil, this node is the start of an object
-       // (addressable memory location).
-       // The following obj.size nodes implicitly belong to the object;
-       // they locate their object by scanning back.
-       obj *object
-
-       // The type of the field denoted by this node.  Non-aggregate,
-       // unless this is an tagged.T node (i.e. the thing
-       // pointed to by an interface) in which case typ is that type.
-       typ types.Type
-
-       // subelement indicates which directly embedded subelement of
-       // an object of aggregate type (struct, tuple, array) this is.
-       subelement *fieldInfo // e.g. ".a.b[*].c"
-
-       // Solver state for the canonical node of this pointer-
-       // equivalence class.  Each node is created with its own state
-       // but they become shared after HVN.
-       solve *solverState
-}
-
-// An analysis instance holds the state of a single pointer analysis problem.
-type analysis struct {
-       config      *Config                     // the client's control/observer interface
-       prog        *ssa.Program                // the program being analyzed
-       log         io.Writer                   // log stream; nil to disable
-       panicNode   nodeid                      // sink for panic, source for recover
-       nodes       []*node                     // indexed by nodeid
-       flattenMemo map[types.Type][]*fieldInfo // memoization of flatten()
-       trackTypes  map[types.Type]bool         // memoization of shouldTrack()
-       constraints []constraint                // set of constraints
-       cgnodes     []*cgnode                   // all cgnodes
-       genq        []*cgnode                   // queue of functions to generate constraints for
-       intrinsics  map[*ssa.Function]intrinsic // non-nil values are summaries for intrinsic fns
-       globalval   map[ssa.Value]nodeid        // node for each global ssa.Value
-       globalobj   map[ssa.Value]nodeid        // maps v to sole member of pts(v), if singleton
-       localval    map[ssa.Value]nodeid        // node for each local ssa.Value
-       localobj    map[ssa.Value]nodeid        // maps v to sole member of pts(v), if singleton
-       atFuncs     map[*ssa.Function]bool      // address-taken functions (for presolver)
-       mapValues   []nodeid                    // values of makemap objects (indirect in HVN)
-       work        nodeset                     // solver's worklist
-       result      *Result                     // results of the analysis
-       track       track                       // pointerlike types whose aliasing we track
-       deltaSpace  []int                       // working space for iterating over PTS deltas
-
-       // Reflection & intrinsics:
-       hasher              typeutil.Hasher // cache of type hashes
-       reflectValueObj     types.Object    // type symbol for reflect.Value (if present)
-       reflectValueCall    *ssa.Function   // (reflect.Value).Call
-       reflectRtypeObj     types.Object    // *types.TypeName for reflect.rtype (if present)
-       reflectRtypePtr     *types.Pointer  // *reflect.rtype
-       reflectType         *types.Named    // reflect.Type
-       rtypes              typeutil.Map    // nodeid of canonical *rtype-tagged object for type T
-       reflectZeros        typeutil.Map    // nodeid of canonical T-tagged object for zero value
-       runtimeSetFinalizer *ssa.Function   // runtime.SetFinalizer
-}
-
-// enclosingObj returns the first node of the addressable memory
-// object that encloses node id.  Panic ensues if that node does not
-// belong to any object.
-func (a *analysis) enclosingObj(id nodeid) nodeid {
-       // Find previous node with obj != nil.
-       for i := id; i >= 0; i-- {
-               n := a.nodes[i]
-               if obj := n.obj; obj != nil {
-                       if i+nodeid(obj.size) <= id {
-                               break // out of bounds
-                       }
-                       return i
-               }
-       }
-       panic("node has no enclosing object")
-}
-
-// labelFor returns the Label for node id.
-// Panic ensues if that node is not addressable.
-func (a *analysis) labelFor(id nodeid) *Label {
-       return &Label{
-               obj:        a.nodes[a.enclosingObj(id)].obj,
-               subelement: a.nodes[id].subelement,
-       }
-}
-
-func (a *analysis) warnf(pos token.Pos, format string, args ...interface{}) {
-       msg := fmt.Sprintf(format, args...)
-       if a.log != nil {
-               fmt.Fprintf(a.log, "%s: warning: %s\n", a.prog.Fset.Position(pos), msg)
-       }
-       a.result.Warnings = append(a.result.Warnings, Warning{pos, msg})
-}
-
-// computeTrackBits sets a.track to the necessary 'track' bits for the pointer queries.
-func (a *analysis) computeTrackBits() {
-       if len(a.config.extendedQueries) != 0 {
-               // TODO(dh): only track the types necessary for the query.
-               a.track = trackAll
-               return
-       }
-       var queryTypes []types.Type
-       for v := range a.config.Queries {
-               queryTypes = append(queryTypes, v.Type())
-       }
-       for v := range a.config.IndirectQueries {
-               queryTypes = append(queryTypes, mustDeref(v.Type()))
-       }
-       for _, t := range queryTypes {
-               switch t.Underlying().(type) {
-               case *types.Chan:
-                       a.track |= trackChan
-               case *types.Map:
-                       a.track |= trackMap
-               case *types.Pointer:
-                       a.track |= trackPtr
-               case *types.Slice:
-                       a.track |= trackSlice
-               case *types.Interface:
-                       a.track = trackAll
-                       return
-               }
-               if rVObj := a.reflectValueObj; rVObj != nil && types.Identical(t, rVObj.Type()) {
-                       a.track = trackAll
-                       return
-               }
-       }
-}
-
-// Analyze runs the pointer analysis with the scope and options
-// specified by config, and returns the (synthetic) root of the callgraph.
-//
-// Pointer analysis of a transitively closed well-typed program should
-// always succeed.  An error can occur only due to an internal bug.
-//
-func Analyze(config *Config) (result *Result, err error) {
-       if config.Mains == nil {
-               return nil, fmt.Errorf("no main/test packages to analyze (check $GOROOT/$GOPATH)")
-       }
-       defer func() {
-               if p := recover(); p != nil {
-                       err = fmt.Errorf("internal error in pointer analysis: %v (please report this bug)", p)
-                       fmt.Fprintln(os.Stderr, "Internal panic in pointer analysis:")
-                       debug.PrintStack()
-               }
-       }()
-
-       a := &analysis{
-               config:      config,
-               log:         config.Log,
-               prog:        config.prog(),
-               globalval:   make(map[ssa.Value]nodeid),
-               globalobj:   make(map[ssa.Value]nodeid),
-               flattenMemo: make(map[types.Type][]*fieldInfo),
-               trackTypes:  make(map[types.Type]bool),
-               atFuncs:     make(map[*ssa.Function]bool),
-               hasher:      typeutil.MakeHasher(),
-               intrinsics:  make(map[*ssa.Function]intrinsic),
-               result: &Result{
-                       Queries:         make(map[ssa.Value]Pointer),
-                       IndirectQueries: make(map[ssa.Value]Pointer),
-               },
-               deltaSpace: make([]int, 0, 100),
-       }
-
-       if false {
-               a.log = os.Stderr // for debugging crashes; extremely verbose
-       }
-
-       if a.log != nil {
-               fmt.Fprintln(a.log, "==== Starting analysis")
-       }
-
-       // Pointer analysis requires a complete program for soundness.
-       // Check to prevent accidental misconfiguration.
-       for _, pkg := range a.prog.AllPackages() {
-               // (This only checks that the package scope is complete,
-               // not that func bodies exist, but it's a good signal.)
-               if !pkg.Pkg.Complete() {
-                       return nil, fmt.Errorf(`pointer analysis requires a complete program yet package %q was incomplete`, pkg.Pkg.Path())
-               }
-       }
-
-       if reflect := a.prog.ImportedPackage("reflect"); reflect != nil {
-               rV := reflect.Pkg.Scope().Lookup("Value")
-               a.reflectValueObj = rV
-               a.reflectValueCall = a.prog.LookupMethod(rV.Type(), nil, "Call")
-               a.reflectType = reflect.Pkg.Scope().Lookup("Type").Type().(*types.Named)
-               a.reflectRtypeObj = reflect.Pkg.Scope().Lookup("rtype")
-               a.reflectRtypePtr = types.NewPointer(a.reflectRtypeObj.Type())
-
-               // Override flattening of reflect.Value, treating it like a basic type.
-               tReflectValue := a.reflectValueObj.Type()
-               a.flattenMemo[tReflectValue] = []*fieldInfo{{typ: tReflectValue}}
-
-               // Override shouldTrack of reflect.Value and *reflect.rtype.
-               // Always track pointers of these types.
-               a.trackTypes[tReflectValue] = true
-               a.trackTypes[a.reflectRtypePtr] = true
-
-               a.rtypes.SetHasher(a.hasher)
-               a.reflectZeros.SetHasher(a.hasher)
-       }
-       if runtime := a.prog.ImportedPackage("runtime"); runtime != nil {
-               a.runtimeSetFinalizer = runtime.Func("SetFinalizer")
-       }
-       a.computeTrackBits()
-
-       a.generate()
-       a.showCounts()
-
-       if optRenumber {
-               a.renumber()
-       }
-
-       N := len(a.nodes) // excludes solver-created nodes
-
-       if optHVN {
-               if debugHVNCrossCheck {
-                       // Cross-check: run the solver once without
-                       // optimization, once with, and compare the
-                       // solutions.
-                       savedConstraints := a.constraints
-
-                       a.solve()
-                       a.dumpSolution("A.pts", N)
-
-                       // Restore.
-                       a.constraints = savedConstraints
-                       for _, n := range a.nodes {
-                               n.solve = new(solverState)
-                       }
-                       a.nodes = a.nodes[:N]
-
-                       // rtypes is effectively part of the solver state.
-                       a.rtypes = typeutil.Map{}
-                       a.rtypes.SetHasher(a.hasher)
-               }
-
-               a.hvn()
-       }
-
-       if debugHVNCrossCheck {
-               runtime.GC()
-               runtime.GC()
-       }
-
-       a.solve()
-
-       // Compare solutions.
-       if optHVN && debugHVNCrossCheck {
-               a.dumpSolution("B.pts", N)
-
-               if !diff("A.pts", "B.pts") {
-                       return nil, fmt.Errorf("internal error: optimization changed solution")
-               }
-       }
-
-       // Create callgraph.Nodes in deterministic order.
-       if cg := a.result.CallGraph; cg != nil {
-               for _, caller := range a.cgnodes {
-                       cg.CreateNode(caller.fn)
-               }
-       }
-
-       // Add dynamic edges to call graph.
-       var space [100]int
-       for _, caller := range a.cgnodes {
-               for _, site := range caller.sites {
-                       for _, callee := range a.nodes[site.targets].solve.pts.AppendTo(space[:0]) {
-                               a.callEdge(caller, site, nodeid(callee))
-                       }
-               }
-       }
-
-       return a.result, nil
-}
-
-// callEdge is called for each edge in the callgraph.
-// calleeid is the callee's object node (has otFunction flag).
-//
-func (a *analysis) callEdge(caller *cgnode, site *callsite, calleeid nodeid) {
-       obj := a.nodes[calleeid].obj
-       if obj.flags&otFunction == 0 {
-               panic(fmt.Sprintf("callEdge %s -> n%d: not a function object", site, calleeid))
-       }
-       callee := obj.cgn
-
-       if cg := a.result.CallGraph; cg != nil {
-               // TODO(adonovan): opt: I would expect duplicate edges
-               // (to wrappers) to arise due to the elimination of
-               // context information, but I haven't observed any.
-               // Understand this better.
-               callgraph.AddEdge(cg.CreateNode(caller.fn), site.instr, cg.CreateNode(callee.fn))
-       }
-
-       if a.log != nil {
-               fmt.Fprintf(a.log, "\tcall edge %s -> %s\n", site, callee)
-       }
-
-       // Warn about calls to non-intrinsic external functions.
-       // TODO(adonovan): de-dup these messages.
-       if fn := callee.fn; fn.Blocks == nil && a.findIntrinsic(fn) == nil {
-               a.warnf(site.pos(), "unsound call to unknown intrinsic: %s", fn)
-               a.warnf(fn.Pos(), " (declared here)")
-       }
-}
-
-// dumpSolution writes the PTS solution to the specified file.
-//
-// It only dumps the nodes that existed before solving.  The order in
-// which solver-created nodes are created depends on pre-solver
-// optimization, so we can't include them in the cross-check.
-//
-func (a *analysis) dumpSolution(filename string, N int) {
-       f, err := os.Create(filename)
-       if err != nil {
-               panic(err)
-       }
-       for id, n := range a.nodes[:N] {
-               if _, err := fmt.Fprintf(f, "pts(n%d) = {", id); err != nil {
-                       panic(err)
-               }
-               var sep string
-               for _, l := range n.solve.pts.AppendTo(a.deltaSpace) {
-                       if l >= N {
-                               break
-                       }
-                       fmt.Fprintf(f, "%s%d", sep, l)
-                       sep = " "
-               }
-               fmt.Fprintf(f, "} : %s\n", n.typ)
-       }
-       if err := f.Close(); err != nil {
-               panic(err)
-       }
-}
-
-// showCounts logs the size of the constraint system.  A typical
-// optimized distribution is 65% copy, 13% load, 11% addr, 5%
-// offsetAddr, 4% store, 2% others.
-//
-func (a *analysis) showCounts() {
-       if a.log != nil {
-               counts := make(map[reflect.Type]int)
-               for _, c := range a.constraints {
-                       counts[reflect.TypeOf(c)]++
-               }
-               fmt.Fprintf(a.log, "# constraints:\t%d\n", len(a.constraints))
-               var lines []string
-               for t, n := range counts {
-                       line := fmt.Sprintf("%7d  (%2d%%)\t%s", n, 100*n/len(a.constraints), t)
-                       lines = append(lines, line)
-               }
-               sort.Sort(sort.Reverse(sort.StringSlice(lines)))
-               for _, line := range lines {
-                       fmt.Fprintf(a.log, "\t%s\n", line)
-               }
-
-               fmt.Fprintf(a.log, "# nodes:\t%d\n", len(a.nodes))
-
-               // Show number of pointer equivalence classes.
-               m := make(map[*solverState]bool)
-               for _, n := range a.nodes {
-                       m[n.solve] = true
-               }
-               fmt.Fprintf(a.log, "# ptsets:\t%d\n", len(m))
-       }
-}