// 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 entry points into the pointer analysis.

import (
	"fmt"
	"go/token"
	"io"
	"os"

	"code.google.com/p/go.tools/go/types"
	"code.google.com/p/go.tools/ssa"
)

// 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

// node.flags bitmask values.
const (
	ntObject    = 1 << iota // start of an object (addressable memory location)
	ntInterface             // conctype node of interface object (=> ntObject)
	ntFunction              // identity node of function object (=> ntObject)
)

// A node is an equivalence class of memory locations.
// Nodes may be pointers, pointed-to locations, neither, or both.
type node struct {
	// flags is a bitset of the node type (nt*) flags defined above.
	flags uint32

	// Number of following words belonging to the same "object" allocation.
	// (Set by endObject.)  Zero for all other nodes.
	size uint32

	// The type of the field denoted by this node.  Non-aggregate,
	// unless this is an iface.conctype node (i.e. the thing
	// pointed to by an interface) in which case typ is that type.
	typ types.Type

	// data holds additional attributes of this node, depending on
	// its flags.
	//
	// If ntObject is set, data is the ssa.Value of the
	// instruction that allocated this memory, or nil if it was
	// implicit.
	//
	// Special cases:
	// - If ntInterface is also set, data will be a *ssa.MakeInterface.
	// - If ntFunction is also set, this node is the first word of a
	//   function block, and data is a *cgnode (not an ssa.Value)
	//   representing this function.
	data interface{}

	// subelement indicates which directly embedded subelement of
	// an object of aggregate type (struct, tuple, array) this is.
	subelement *fieldInfo // e.g. ".a.b[*].c"

	// Points-to sets.
	pts     nodeset // points-to set of this node
	prevPts nodeset // pts(n) in previous iteration (for difference propagation)

	// Graph edges
	copyTo nodeset // simple copy constraint edges

	// Complex constraints attached to this node (x).
	// - *loadConstraint       y=*x
	// - *offsetAddrConstraint y=&x.f or y=&x[0]
	// - *storeConstraint      *x=z
	// - *typeAssertConstraint y=x.(T)
	// - *invokeConstraint     y=x.f(params...)
	complex constraintset
}

type constraint interface {
	String() string

	// Called by solver to prepare a constraint, e.g. to
	// - initialize a points-to set (addrConstraint).
	// - attach it to a pointer node (complex constraints).
	init(a *analysis)

	// solve is called for complex constraints when the pts for
	// the node to which they are attached has changed.
	solve(a *analysis, n *node, delta nodeset)
}

// dst = &src
// pts(dst) ⊇ {src}
// A base constraint used to initialize the solver's pt sets
type addrConstraint struct {
	dst nodeid
	src nodeid
}

// dst = src
// A simple constraint represented directly as a copyTo graph edge.
type copyConstraint struct {
	dst nodeid
	src nodeid
}

// dst = src[offset]
// A complex constraint attached to src (the pointer)
type loadConstraint struct {
	offset uint32
	dst    nodeid
	src    nodeid
}

// dst[offset] = src
// A complex constraint attached to dst (the pointer)
type storeConstraint struct {
	offset uint32
	dst    nodeid
	src    nodeid
}

// dst = &src.f  or  dst = &src[0]
// A complex constraint attached to dst (the pointer)
type offsetAddrConstraint struct {
	offset uint32
	dst    nodeid
	src    nodeid
}

// dst = src.(typ)
// A complex constraint attached to src (the interface).
type typeAssertConstraint struct {
	typ types.Type
	dst nodeid
	src nodeid
}

// src.method(params...)
// A complex constraint attached to iface.
type invokeConstraint struct {
	method *types.Func // the abstract method
	iface  nodeid      // the interface
	params nodeid      // the first parameter in the params/results block
}

// 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()
	constraints     []constraint                // set of constraints
	callsites       []*callsite                 // all callsites
	genq            []*cgnode                   // queue of functions to generate constraints for
	intrinsics      map[*ssa.Function]intrinsic // non-nil values are summaries for intrinsic fns
	reflectValueObj types.Object                // type symbol for reflect.Value (if present)
	reflectRtypeObj types.Object                // type symbol for reflect.rtype (if present)
	reflectRtype    *types.Pointer              // *reflect.rtype
	funcObj         map[*ssa.Function]nodeid    // default function object for each func
	probes          map[*ssa.CallCommon]nodeid  // maps call to print() to argument variable
	valNode         map[ssa.Value]nodeid        // node for each ssa.Value
	work            worklist                    // solver's worklist
}

func (a *analysis) warnf(pos token.Pos, format string, args ...interface{}) {
	if Warn := a.config.Warn; Warn != nil {
		Warn(pos, format, args...)
	} else {
		fmt.Fprintf(os.Stderr, "%s: warning: ", a.prog.Fset.Position(pos))
		fmt.Fprintf(os.Stderr, format, args...)
		fmt.Fprintln(os.Stderr)
	}
}

// Analyze runs the pointer analysis with the scope and options
// specified by config, and returns the (synthetic) root of the callgraph.
//
func Analyze(config *Config) CallGraphNode {
	a := &analysis{
		config:      config,
		log:         config.Log,
		prog:        config.prog(),
		valNode:     make(map[ssa.Value]nodeid),
		flattenMemo: make(map[types.Type][]*fieldInfo),
		intrinsics:  make(map[*ssa.Function]intrinsic),
		funcObj:     make(map[*ssa.Function]nodeid),
		probes:      make(map[*ssa.CallCommon]nodeid),
		work:        makeMapWorklist(),
	}

	if reflect := a.prog.ImportedPackage("reflect"); reflect != nil {
		a.reflectValueObj = reflect.Object.Scope().Lookup("Value")
		a.reflectRtypeObj = reflect.Object.Scope().Lookup("rtype")
		a.reflectRtype = types.NewPointer(a.reflectRtypeObj.Type())
	}

	if false {
		a.log = os.Stderr // for debugging crashes; extremely verbose
	}

	if a.log != nil {
		fmt.Fprintln(a.log, "======== NEW ANALYSIS ========")
	}

	root := a.generate()

	// ---------- Presolver ----------

	// TODO(adonovan): opt: presolver optimisations.

	// ---------- Solver ----------

	a.solve()

	if a.log != nil {
		// Dump solution.
		for i, n := range a.nodes {
			if n.pts != nil {
				fmt.Fprintf(a.log, "pts(n%d) = %s : %s\n", i, n.pts, n.typ)
			}
		}
	}

	// Notify the client of the callsites if they're interested.
	if CallSite := a.config.CallSite; CallSite != nil {
		for _, site := range a.callsites {
			CallSite(site)
		}
	}

	Call := a.config.Call
	for _, site := range a.callsites {
		for nid := range a.nodes[site.targets].pts {
			cgn := a.nodes[nid].data.(*cgnode)

			// Notify the client of the call graph, if
			// they're interested.
			if Call != nil {
				Call(site, cgn)
			}

			// Warn about calls to non-intrinsic external functions.

			if fn := cgn.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)")
			}
		}
	}

	return root
}
