// 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 constraint generation phase.

import (
	"fmt"
	"go/ast"
	"go/token"

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

var (
	tEface     = types.NewInterface(nil)
	tInvalid   = types.Typ[types.Invalid]
	tUnsafePtr = types.Typ[types.UnsafePointer]
)

// ---------- Node creation ----------

// nextNode returns the index of the next unused node.
func (a *analysis) nextNode() nodeid {
	return nodeid(len(a.nodes))
}

// addNodes creates nodes for all scalar elements in type typ, and
// returns the id of the first one, or zero if the type was
// analytically uninteresting.
//
// comment explains the origin of the nodes, as a debugging aid.
//
func (a *analysis) addNodes(typ types.Type, comment string) nodeid {
	id := a.nextNode()
	for _, fi := range a.flatten(typ) {
		a.addOneNode(fi.typ, comment, fi)
	}
	if id == a.nextNode() {
		return 0 // type contained no pointers
	}
	return id
}

// addOneNode creates a single node with type typ, and returns its id.
//
// typ should generally be scalar (except for interface.conctype nodes
// and struct/array identity nodes).  Use addNodes for non-scalar types.
//
// comment explains the origin of the nodes, as a debugging aid.
// subelement indicates the subelement, e.g. ".a.b[*].c".
//
func (a *analysis) addOneNode(typ types.Type, comment string, subelement *fieldInfo) nodeid {
	id := a.nextNode()
	a.nodes = append(a.nodes, &node{typ: typ, subelement: subelement})
	if a.log != nil {
		fmt.Fprintf(a.log, "\tcreate n%d %s for %s%s\n",
			id, typ, comment, subelement.path())
	}
	return id
}

// setValueNode associates node id with the value v.
// TODO(adonovan): disambiguate v by its CallGraphNode, if it's a local.
func (a *analysis) setValueNode(v ssa.Value, id nodeid) {
	a.valNode[v] = id
	if a.log != nil {
		fmt.Fprintf(a.log, "\tval[%s] = n%d  (%T)\n", v.Name(), id, v)
	}

	// Record the (v, id) relation if the client has queried v.
	if indirect, ok := a.config.QueryValues[v]; ok {
		if indirect {
			tmp := a.addNodes(v.Type(), "query.indirect")
			a.load(tmp, id, a.sizeof(v.Type()))
			id = tmp
		}
		ptrs := a.config.QueryResults
		if ptrs == nil {
			ptrs = make(map[ssa.Value][]Pointer)
			a.config.QueryResults = ptrs
		}
		ptrs[v] = append(ptrs[v], ptr{a, id})
	}
}

// endObject marks the end of a sequence of calls to addNodes denoting
// a single object allocation.
//
// obj is the start node of the object, from a prior call to nextNode.
// Its size, flags and (optionally) data will be updated.
//
func (a *analysis) endObject(obj nodeid, data ssa.Value) {
	// Ensure object is non-empty by padding;
	// the pad will be the object node.
	size := uint32(a.nextNode() - obj)
	if size == 0 {
		a.addOneNode(tInvalid, "padding", nil)
	}
	objNode := a.nodes[obj]
	objNode.size = size // excludes padding
	objNode.flags = ntObject

	if data != nil {
		objNode.data = data
		if a.log != nil {
			fmt.Fprintf(a.log, "\tobj[%s] = n%d\n", data, obj)
		}
	}
}

// makeFunctionObject creates and returns a new function object for
// fn, and returns the id of its first node.  It also enqueues fn for
// subsequent constraint generation.
//
func (a *analysis) makeFunctionObject(fn *ssa.Function) nodeid {
	if a.log != nil {
		fmt.Fprintf(a.log, "\t---- makeFunctionObject %s\n", fn)
	}

	// obj is the function object (identity, params, results).
	obj := a.nextNode()
	sig := fn.Signature
	a.addOneNode(sig, "func.cgnode", nil) // (scalar with Signature type)
	if recv := sig.Recv(); recv != nil {
		a.addNodes(recv.Type(), "func.recv")
	}
	a.addNodes(sig.Params(), "func.params")
	a.addNodes(sig.Results(), "func.results")
	a.endObject(obj, fn)

	if a.log != nil {
		fmt.Fprintf(a.log, "\t----\n")
	}

	cgn := &cgnode{fn: fn, obj: obj}
	a.nodes[obj].flags |= ntFunction
	a.nodes[obj].data = cgn

	// Queue it up for constraint processing.
	a.genq = append(a.genq, cgn)

	return obj
}

// makeFunction creates the shared function object (aka contour) for
// function fn and returns a 'func' value node that points to it.
//
func (a *analysis) makeFunction(fn *ssa.Function) nodeid {
	obj := a.makeFunctionObject(fn)
	a.funcObj[fn] = obj

	var comment string
	if a.log != nil {
		comment = fn.String()
	}
	id := a.addOneNode(fn.Type(), comment, nil)
	a.addressOf(id, obj)
	return id
}

// makeGlobal creates the value node and object node for global g,
// and returns the value node.
//
// The value node represents the address of the global variable, and
// points to the object (and nothing else).
//
// The object consists of the global variable itself (conceptually,
// the BSS address).
//
func (a *analysis) makeGlobal(g *ssa.Global) nodeid {
	var comment string
	if a.log != nil {
		fmt.Fprintf(a.log, "\t---- makeGlobal %s\n", g)
		comment = g.FullName()
	}

	// The nodes representing the object itself.
	obj := a.nextNode()
	a.addNodes(mustDeref(g.Type()), "global")
	a.endObject(obj, g)

	if a.log != nil {
		fmt.Fprintf(a.log, "\t----\n")
	}

	// The node representing the address of the global.
	id := a.addOneNode(g.Type(), comment, nil)
	a.addressOf(id, obj)

	return id
}

// makeConstant creates the value node and object node (if needed) for
// constant c, and returns the value node.
// An object node is created only for []byte or []rune constants.
// The value node points to the object node, iff present.
//
func (a *analysis) makeConstant(l *ssa.Const) nodeid {
	id := a.addNodes(l.Type(), "const")
	if !l.IsNil() {
		// []byte or []rune?
		if t, ok := l.Type().Underlying().(*types.Slice); ok {
			// Treat []T like *[1]T, 'make []T' like new([1]T).
			obj := a.nextNode()
			a.addNodes(sliceToArray(t), "array in slice constant")
			a.endObject(obj, l)

			a.addressOf(id, obj)
		}
	}
	return id
}

// valueNode returns the id of the value node for v, creating it (and
// the association) as needed.  It may return zero for uninteresting
// values containing no pointers.
//
// Nodes for locals are created en masse during genFunc and are
// implicitly contextualized by the function currently being analyzed
// (i.e. parameter to genFunc).
//
func (a *analysis) valueNode(v ssa.Value) nodeid {
	id, ok := a.valNode[v]
	if !ok {
		switch v := v.(type) {
		case *ssa.Function:
			id = a.makeFunction(v)

		case *ssa.Global:
			id = a.makeGlobal(v)

		case *ssa.Const:
			id = a.makeConstant(v)

		case *ssa.Capture:
			// TODO(adonovan): treat captures context-sensitively.
			id = a.addNodes(v.Type(), "capture")

		default:
			// *ssa.Parameters and ssa.Instruction values
			// are created by genFunc.
			// *Builtins are not true values.
			panic(v)
		}
		a.setValueNode(v, id)
	}
	return id
}

// valueOffsetNode ascertains the node for tuple/struct value v,
// then returns the node for its subfield #index.
//
func (a *analysis) valueOffsetNode(v ssa.Value, index int) nodeid {
	id := a.valueNode(v)
	if id == 0 {
		panic(fmt.Sprintf("cannot offset within n0: %s = %s", v.Name(), v))
	}
	return id + nodeid(a.offsetOf(v.Type(), index))
}

// interfaceValue returns the (first node of) the value, and the
// concrete type, of the interface object (flags&ntInterface) starting
// at id.
//
func (a *analysis) interfaceValue(id nodeid) (nodeid, types.Type) {
	n := a.nodes[id]
	if n.flags&ntInterface == 0 {
		panic(fmt.Sprintf("interfaceValue(n%d): not an interface object; typ=%s", id, n.typ))
	}
	return id + 1, n.typ
}

// funcParams returns the first node of the params block of the
// function whose object node (flags&ntFunction) is id.
//
func (a *analysis) funcParams(id nodeid) nodeid {
	if a.nodes[id].flags&ntFunction == 0 {
		panic(fmt.Sprintf("funcParams(n%d): not a function object block", id))
	}
	return id + 1
}

// funcResults returns the first node of the results block of the
// function whose object node (flags&ntFunction) is id.
//
func (a *analysis) funcResults(id nodeid) nodeid {
	n := a.nodes[id]
	if n.flags&ntFunction == 0 {
		panic(fmt.Sprintf("funcResults(n%d): not a function object block", id))
	}
	sig := n.typ.(*types.Signature)
	id += 1 + nodeid(a.sizeof(sig.Params()))
	if sig.Recv() != nil {
		id += nodeid(a.sizeof(sig.Recv().Type()))
	}
	return id
}

// ---------- Constraint creation ----------

// copy creates a constraint of the form dst = src.
// sizeof is the width (in logical fields) of the copied type.
//
func (a *analysis) copy(dst, src nodeid, sizeof uint32) {
	if src == dst || sizeof == 0 {
		return // trivial
	}
	if src == 0 || dst == 0 {
		panic(fmt.Sprintf("ill-typed copy dst=n%d src=n%d", dst, src))
	}
	for i := uint32(0); i < sizeof; i++ {
		a.addConstraint(&copyConstraint{dst, src})
		src++
		dst++
	}
}

// addressOf creates a constraint of the form id = &obj.
func (a *analysis) addressOf(id, obj nodeid) {
	if id == 0 {
		panic("addressOf: zero id")
	}
	if obj == 0 {
		panic("addressOf: zero obj")
	}
	a.addConstraint(&addrConstraint{id, obj})
}

// load creates a load constraint of the form dst = *src.
// sizeof is the width (in logical fields) of the loaded type.
//
func (a *analysis) load(dst, src nodeid, sizeof uint32) {
	a.loadOffset(dst, src, 0, sizeof)
}

// loadOffset creates a load constraint of the form dst = src[offset].
// offset is the pointer offset in logical fields.
// sizeof is the width (in logical fields) of the loaded type.
//
func (a *analysis) loadOffset(dst, src nodeid, offset uint32, sizeof uint32) {
	if dst == 0 {
		return // load of non-pointerlike value
	}
	if src == 0 && dst == 0 {
		return // non-pointerlike operation
	}
	if src == 0 || dst == 0 {
		panic(fmt.Sprintf("ill-typed load dst=n%d src=n%d", dst, src))
	}
	for i := uint32(0); i < sizeof; i++ {
		a.addConstraint(&loadConstraint{offset, dst, src})
		offset++
		dst++
	}
}

// store creates a store constraint of the form *dst = src.
// sizeof is the width (in logical fields) of the stored type.
//
func (a *analysis) store(dst, src nodeid, sizeof uint32) {
	a.storeOffset(dst, src, 0, sizeof)
}

// storeOffset creates a store constraint of the form dst[offset] = src.
// offset is the pointer offset in logical fields.
// sizeof is the width (in logical fields) of the stored type.
//
func (a *analysis) storeOffset(dst, src nodeid, offset uint32, sizeof uint32) {
	if src == 0 {
		return // store of non-pointerlike value
	}
	if src == 0 && dst == 0 {
		return // non-pointerlike operation
	}
	if src == 0 || dst == 0 {
		panic(fmt.Sprintf("ill-typed store dst=n%d src=n%d", dst, src))
	}
	for i := uint32(0); i < sizeof; i++ {
		a.addConstraint(&storeConstraint{offset, dst, src})
		offset++
		src++
	}
}

// offsetAddr creates an offsetAddr constraint of the form dst = &src.#offset.
// offset is the field offset in logical fields.
//
func (a *analysis) offsetAddr(dst, src nodeid, offset uint32) {
	if offset == 0 {
		// Simplify  dst = &src->f0
		//       to  dst = src
		// (NB: this optimisation is defeated by the identity
		// field prepended to struct and array objects.)
		a.copy(dst, src, 1)
	} else {
		a.addConstraint(&offsetAddrConstraint{offset, dst, src})
	}
}

// addConstraint adds c to the constraint set.
func (a *analysis) addConstraint(c constraint) {
	a.constraints = append(a.constraints, c)
	if a.log != nil {
		fmt.Fprintf(a.log, "\t%s\n", c)
	}
}

// copyElems generates load/store constraints for *dst = *src,
// where src and dst are slices or *arrays.
// (If pts(·) of either is a known singleton, this is suboptimal.)
//
func (a *analysis) copyElems(typ types.Type, dst, src nodeid) {
	tmp := a.addNodes(typ, "copy")
	sz := a.sizeof(typ)
	a.loadOffset(tmp, src, 1, sz)
	a.storeOffset(dst, tmp, 1, sz)
}

// ---------- Constraint generation ----------

// genConv generates constraints for the conversion operation conv.
func (a *analysis) genConv(conv *ssa.Convert) {
	res := a.valueNode(conv)
	if res == 0 {
		return // result is non-pointerlike
	}

	tSrc := conv.X.Type()
	tDst := conv.Type()

	switch utSrc := tSrc.Underlying().(type) {
	case *types.Slice:
		// []byte/[]rune -> string?
		return

	case *types.Pointer:
		// *T -> unsafe.Pointer?
		if tDst == tUnsafePtr {
			// ignore for now
			// a.copy(res, a.valueNode(conv.X), 1)
			return
		}

	case *types.Basic:
		switch utDst := tDst.Underlying().(type) {
		case *types.Pointer:
			// unsafe.Pointer -> *T?  (currently unsound)
			if utSrc == tUnsafePtr {
				// For now, suppress unsafe.Pointer conversion
				// warnings on "syscall" package.
				// TODO(adonovan): audit for soundness.
				if conv.Parent().Pkg.Object.Path() != "syscall" {
					a.warnf(conv.Pos(),
						"unsound: %s contains an unsafe.Pointer conversion (to %s)",
						conv.Parent(), tDst)
				}

				// For now, we treat unsafe.Pointer->*T
				// conversion like new(T) and create an
				// unaliased object.  In future we may handle
				// unsafe conversions soundly; see TODO file.
				obj := a.addNodes(mustDeref(tDst), "unsafe.Pointer conversion")
				a.endObject(obj, conv)
				a.addressOf(res, obj)
				return
			}

		case *types.Slice:
			// string -> []byte/[]rune (or named aliases)?
			if utSrc.Info()&types.IsString != 0 {
				obj := a.addNodes(sliceToArray(tDst), "convert")
				a.endObject(obj, conv)
				a.addressOf(res, obj)
				return
			}

		case *types.Basic:
			// TODO(adonovan):
			// unsafe.Pointer -> uintptr?
			// uintptr -> unsafe.Pointer
			//
			// The language doesn't adequately specify the
			// behaviour of these operations, but almost
			// all uses of these conversions (even in the
			// spec) seem to imply a non-moving garbage
			// collection strategy, or implicit "pinning"
			// semantics for unsafe.Pointer conversions.

			// TODO(adonovan): we need more work before we can handle
			// cryptopointers well.
			if utSrc == tUnsafePtr || utDst == tUnsafePtr {
				// Ignore for now.  See TODO file for ideas.
				return
			}

			return // ignore all other basic type conversions
		}
	}

	panic(fmt.Sprintf("illegal *ssa.Convert %s -> %s: %s", tSrc, tDst, conv.Parent()))
}

// genAppend generates constraints for a call to append.
func (a *analysis) genAppend(instr *ssa.Call) {
	// Consider z = append(x, y).   y is optional.
	// This may allocate a new [1]T array; call its object w.
	// We get the following constraints:
	// 	z = x
	// 	z = &w
	//     *z = *y

	x := a.valueNode(instr.Call.Args[0])

	z := a.valueNode(instr)
	a.copy(z, x, 1) // z = x

	if len(instr.Call.Args) == 1 {
		return // no allocation for z = append(x) or _ = append(x).
	}

	// TODO(adonovan): test append([]byte, ...string) []byte.

	y := a.valueNode(instr.Call.Args[1])
	tArray := sliceToArray(instr.Call.Args[0].Type())

	var w nodeid
	w = a.nextNode()
	a.addNodes(tArray, "append")
	a.endObject(w, instr)

	a.copyElems(tArray.Elem(), z, y) // *z = *y
	a.addressOf(z, w)                //  z = &w
}

// genBuiltinCall generates contraints for a call to a built-in.
func (a *analysis) genBuiltinCall(instr ssa.CallInstruction) {
	call := instr.Common()
	switch call.Value.(*ssa.Builtin).Object().Name() {
	case "append":
		// Safe cast: append cannot appear in a go or defer statement.
		a.genAppend(instr.(*ssa.Call))

	case "copy":
		tElem := call.Args[0].Type().Underlying().(*types.Slice).Elem()
		a.copyElems(tElem, a.valueNode(call.Args[0]), a.valueNode(call.Args[1]))

	case "panic":
		a.copy(a.panicNode, a.valueNode(call.Args[0]), 1)

	case "recover":
		if v := instr.Value(); v != nil {
			a.copy(a.valueNode(v), a.panicNode, 1)
		}

	case "print":
		// Analytically print is a no-op, but it's a convenient hook
		// for testing the pts of an expression, so we notify the client.
		// Existing uses in Go core libraries are few and harmless.
		if Print := a.config.Print; Print != nil {
			// Due to context-sensitivity, we may encounter
			// the same print() call in many contexts, so
			// we merge them to a canonical node.
			probe := a.probes[call]
			t := call.Args[0].Type()

			// First time?  Create the canonical probe node.
			if probe == 0 {
				probe = a.addNodes(t, "print")
				a.probes[call] = probe
				Print(call, ptr{a, probe}) // notify client
			}

			a.copy(probe, a.valueNode(call.Args[0]), a.sizeof(t))
		}

	default:
		// No-ops: close len cap real imag complex println delete.
	}
}

// shouldUseContext defines the context-sensitivity policy.  It
// returns true if we should analyse all static calls to fn anew.
//
// Obviously this interface rather limits how much freedom we have to
// choose a policy.  The current policy, rather arbitrarily, is true
// for intrinsics and accessor methods (actually: short, single-block,
// call-free functions).  This is just a starting point.
//
func (a *analysis) shouldUseContext(fn *ssa.Function) bool {
	if a.findIntrinsic(fn) != nil {
		return true // treat intrinsics context-sensitively
	}
	if len(fn.Blocks) != 1 {
		return false // too expensive
	}
	blk := fn.Blocks[0]
	if len(blk.Instrs) > 10 {
		return false // too expensive
	}
	if fn.Synthetic != "" && (fn.Pkg == nil || fn != fn.Pkg.Func("init")) {
		return true // treat synthetic wrappers context-sensitively
	}
	for _, instr := range blk.Instrs {
		switch instr := instr.(type) {
		case ssa.CallInstruction:
			// Disallow function calls (except to built-ins)
			// because of the danger of unbounded recursion.
			if _, ok := instr.Common().Value.(*ssa.Builtin); !ok {
				return false
			}
		}
	}
	return true
}

// genStaticCall generates constraints for a statically dispatched
// function call.  It returns a node whose pts() will be the set of
// possible call targets (in this case, a singleton).
//
func (a *analysis) genStaticCall(call *ssa.CallCommon, result nodeid) nodeid {
	// Ascertain the context (contour/CGNode) for a particular call.
	var obj nodeid
	fn := call.StaticCallee()
	if a.shouldUseContext(fn) {
		obj = a.makeFunctionObject(fn) // new contour for this call
	} else {
		a.valueNode(fn)     // ensure shared contour was created
		obj = a.funcObj[fn] // ordinary (shared) contour.
	}

	sig := call.Signature()
	targets := a.addOneNode(sig, "call.targets", nil)
	a.addressOf(targets, obj) // (a singleton)

	// Copy receiver, if any.
	params := a.funcParams(obj)
	args := call.Args
	if sig.Recv() != nil {
		sz := a.sizeof(sig.Recv().Type())
		a.copy(params, a.valueNode(args[0]), sz)
		params += nodeid(sz)
		args = args[1:]
	}

	// Copy actual parameters into formal params block.
	// Must loop, since the actuals aren't contiguous.
	for i, arg := range args {
		sz := a.sizeof(sig.Params().At(i).Type())
		a.copy(params, a.valueNode(arg), sz)
		params += nodeid(sz)
	}

	// Copy formal results block to actual result.
	if result != 0 {
		a.copy(result, a.funcResults(obj), a.sizeof(sig.Results()))
	}

	return targets
}

// genDynamicCall generates constraints for a dynamic function call.
// It returns a node whose pts() will be the set of possible call targets.
//
func (a *analysis) genDynamicCall(call *ssa.CallCommon, result nodeid) nodeid {
	fn := a.valueNode(call.Value)
	sig := call.Signature()

	// We add dynamic closure rules that store the arguments into,
	// and load the results from, the P/R block of each function
	// discovered in pts(fn).

	var offset uint32 = 1 // P/R block starts at offset 1
	for i, arg := range call.Args {
		sz := a.sizeof(sig.Params().At(i).Type())
		a.storeOffset(fn, a.valueNode(arg), offset, sz)
		offset += sz
	}
	if result != 0 {
		a.loadOffset(result, fn, offset, a.sizeof(sig.Results()))
	}
	return fn
}

// genInvoke generates constraints for a dynamic method invocation.
// It returns a node whose pts() will be the set of possible call targets.
//
func (a *analysis) genInvoke(call *ssa.CallCommon, result nodeid) nodeid {
	sig := call.Signature()

	// Allocate a contiguous targets/params/results block for this call.
	block := a.nextNode()
	targets := a.addOneNode(sig, "invoke.targets", nil)
	p := a.addNodes(sig.Params(), "invoke.params")
	r := a.addNodes(sig.Results(), "invoke.results")

	// Copy the actual parameters into the call's params block.
	for i, n := 0, sig.Params().Len(); i < n; i++ {
		sz := a.sizeof(sig.Params().At(i).Type())
		a.copy(p, a.valueNode(call.Args[i]), sz)
		p += nodeid(sz)
	}
	// Copy the call's results block to the actual results.
	if result != 0 {
		a.copy(result, r, a.sizeof(sig.Results()))
	}

	// We add a dynamic invoke constraint that will add
	// edges from the caller's P/R block to the callee's
	// P/R block for each discovered call target.
	a.addConstraint(&invokeConstraint{call.Method, a.valueNode(call.Value), block})

	return targets
}

// genCall generates contraints for call instruction instr.
func (a *analysis) genCall(caller *cgnode, instr ssa.CallInstruction) {
	call := instr.Common()

	// Intrinsic implementations of built-in functions.
	if _, ok := call.Value.(*ssa.Builtin); ok {
		a.genBuiltinCall(instr)
		return
	}

	var result nodeid
	if v := instr.Value(); v != nil {
		result = a.valueNode(v)
	}

	// The node whose pts(·) will contain all targets of the call.
	var targets nodeid
	switch {
	case call.StaticCallee() != nil:
		targets = a.genStaticCall(call, result)
	case call.IsInvoke():
		targets = a.genInvoke(call, result)
	default:
		targets = a.genDynamicCall(call, result)
	}

	site := &callsite{
		caller:  caller,
		targets: targets,
		instr:   instr,
		pos:     instr.Pos(),
	}
	a.callsites = append(a.callsites, site)
	if a.log != nil {
		fmt.Fprintf(a.log, "\t%s to targets %s from %s\n",
			site.Description(), site.targets, site.caller)
	}
}

// genInstr generates contraints for instruction instr in context cgn.
func (a *analysis) genInstr(cgn *cgnode, instr ssa.Instruction) {
	if a.log != nil {
		var prefix string
		if val, ok := instr.(ssa.Value); ok {
			prefix = val.Name() + " = "
		}
		fmt.Fprintf(a.log, "; %s%s\n", prefix, instr)
	}

	switch instr := instr.(type) {
	case *ssa.DebugRef:
		// no-op.

	case *ssa.UnOp:
		switch instr.Op {
		case token.ARROW: // <-x
			// We can ignore instr.CommaOk because the node we're
			// altering is always at zero offset relative to instr.
			a.load(a.valueNode(instr), a.valueNode(instr.X), a.sizeof(instr.Type()))

		case token.MUL: // *x
			a.load(a.valueNode(instr), a.valueNode(instr.X), a.sizeof(instr.Type()))

		default:
			// NOT, SUB, XOR: no-op.
		}

	case *ssa.BinOp:
		// All no-ops.

	case ssa.CallInstruction: // *ssa.Call, *ssa.Go, *ssa.Defer
		a.genCall(cgn, instr)

	case *ssa.ChangeType:
		a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)

	case *ssa.Convert:
		a.genConv(instr)

	case *ssa.Extract:
		a.copy(a.valueNode(instr),
			a.valueOffsetNode(instr.Tuple, instr.Index),
			a.sizeof(instr.Type()))

	case *ssa.FieldAddr:
		a.offsetAddr(a.valueNode(instr), a.valueNode(instr.X),
			a.offsetOf(mustDeref(instr.X.Type()), instr.Field))

	case *ssa.IndexAddr:
		a.offsetAddr(a.valueNode(instr), a.valueNode(instr.X), 1)

	case *ssa.Field:
		a.copy(a.valueNode(instr),
			a.valueOffsetNode(instr.X, instr.Field),
			a.sizeof(instr.Type()))

	case *ssa.Index:
		a.copy(a.valueNode(instr), 1+a.valueNode(instr.X), a.sizeof(instr.Type()))

	case *ssa.Select:
		recv := a.valueOffsetNode(instr, 2) // instr : (index, recvOk, recv0, ... recv_n-1)
		for _, st := range instr.States {
			elemSize := a.sizeof(st.Chan.Type().Underlying().(*types.Chan).Elem())
			switch st.Dir {
			case ast.RECV:
				a.load(recv, a.valueNode(st.Chan), elemSize)
				recv++

			case ast.SEND:
				a.store(a.valueNode(st.Chan), a.valueNode(st.Send), elemSize)
			}
		}

	case *ssa.Ret:
		results := a.funcResults(cgn.obj)
		for _, r := range instr.Results {
			sz := a.sizeof(r.Type())
			a.copy(results, a.valueNode(r), sz)
			results += nodeid(sz)
		}

	case *ssa.Send:
		a.store(a.valueNode(instr.Chan), a.valueNode(instr.X), a.sizeof(instr.X.Type()))

	case *ssa.Store:
		a.store(a.valueNode(instr.Addr), a.valueNode(instr.Val), a.sizeof(instr.Val.Type()))

	case *ssa.Alloc:
		obj := a.nextNode()
		a.addNodes(mustDeref(instr.Type()), "alloc")
		a.endObject(obj, instr)
		a.addressOf(a.valueNode(instr), obj)

	case *ssa.MakeSlice:
		obj := a.nextNode()
		a.addNodes(sliceToArray(instr.Type()), "makeslice")
		a.endObject(obj, instr)
		a.addressOf(a.valueNode(instr), obj)

	case *ssa.MakeChan:
		obj := a.nextNode()
		a.addNodes(instr.Type().Underlying().(*types.Chan).Elem(), "makechan")
		a.endObject(obj, instr)
		a.addressOf(a.valueNode(instr), obj)

	case *ssa.MakeMap:
		obj := a.nextNode()
		tmap := instr.Type().Underlying().(*types.Map)
		a.addNodes(tmap.Key(), "makemap.key")
		a.addNodes(tmap.Elem(), "makemap.value")
		a.endObject(obj, instr)
		a.addressOf(a.valueNode(instr), obj)

	case *ssa.MakeInterface:
		tConc := instr.X.Type()
		// Create nodes and constraints for all methods of the type.
		// Ascertaining which will be needed is undecidable in general.
		mset := tConc.MethodSet()
		for i, n := 0, mset.Len(); i < n; i++ {
			a.valueNode(a.prog.Method(mset.At(i)))
		}
		obj := a.addOneNode(tConc, "iface.conctype", nil) // NB: type may be non-scalar!
		vnode := a.addNodes(tConc, "iface.value")
		a.endObject(obj, instr)
		a.nodes[obj].flags |= ntInterface
		// Copy the value into it, if nontrivial.
		if x := a.valueNode(instr.X); x != 0 {
			a.copy(vnode, x, a.sizeof(tConc))
		}
		a.addressOf(a.valueNode(instr), obj)

	case *ssa.ChangeInterface:
		a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)

	case *ssa.TypeAssert:
		dst, src := a.valueNode(instr), a.valueNode(instr.X)
		a.addConstraint(&typeAssertConstraint{instr.AssertedType, dst, src})

	case *ssa.Slice:
		a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)

	case *ssa.If, *ssa.Jump:
		// no-op.

	case *ssa.Phi:
		sz := a.sizeof(instr.Type())
		for _, e := range instr.Edges {
			a.copy(a.valueNode(instr), a.valueNode(e), sz)
		}

	case *ssa.MakeClosure:
		fn := instr.Fn.(*ssa.Function)
		a.copy(a.valueNode(instr), a.valueNode(fn), 1)
		// Free variables are treated like global variables.
		for i, b := range instr.Bindings {
			a.copy(a.valueNode(fn.FreeVars[i]), a.valueNode(b), a.sizeof(b.Type()))
		}

	case *ssa.RunDefers:
		// The analysis is flow insensitive, so we just "call"
		// defers as we encounter them.

	case *ssa.Range:
		// Do nothing.  Next{Iter: *ssa.Range} handles this case.

	case *ssa.Next:
		if !instr.IsString { // map
			// Assumes that Next is always directly applied to a Range result.
			theMap := instr.Iter.(*ssa.Range).X
			tMap := theMap.Type().Underlying().(*types.Map)
			ksize := a.sizeof(tMap.Key())
			vsize := a.sizeof(tMap.Elem())

			// Load from the map's (k,v) into the tuple's (ok, k, v).
			a.load(a.valueNode(instr)+1, a.valueNode(theMap), ksize+vsize)
		}

	case *ssa.Lookup:
		if tMap, ok := instr.X.Type().Underlying().(*types.Map); ok {
			// CommaOk can be ignored: field 0 is a no-op.
			ksize := a.sizeof(tMap.Key())
			vsize := a.sizeof(tMap.Elem())
			a.loadOffset(a.valueNode(instr), a.valueNode(instr.X), ksize, vsize)
		}

	case *ssa.MapUpdate:
		tmap := instr.Map.Type().Underlying().(*types.Map)
		ksize := a.sizeof(tmap.Key())
		vsize := a.sizeof(tmap.Elem())
		m := a.valueNode(instr.Map)
		a.store(m, a.valueNode(instr.Key), ksize)
		a.storeOffset(m, a.valueNode(instr.Value), ksize, vsize)

	case *ssa.Panic:
		a.copy(a.panicNode, a.valueNode(instr.X), 1)

	default:
		panic(fmt.Sprintf("unimplemented: %T", instr))
	}
}

// genRootCalls generates the synthetic root of the callgraph and the
// initial calls from it to the analysis scope, such as main, a test
// or a library.
//
func (a *analysis) genRootCalls() *cgnode {
	r := ssa.NewFunction("<root>", new(types.Signature), "root of callgraph")
	r.Prog = a.prog // hack.
	r.Enclosing = r // hack, so Function.String() doesn't crash
	r.String()      // (asserts that it doesn't crash)
	root := &cgnode{fn: r}

	// For each main package, call main.init(), main.main().
	for _, mainPkg := range a.config.Mains {
		main := mainPkg.Func("main")
		if main == nil {
			panic(fmt.Sprintf("%s has no main function", mainPkg))
		}

		targets := a.addOneNode(main.Signature, "root.targets", nil)
		site := &callsite{
			caller:  root,
			targets: targets,
		}
		a.callsites = append(a.callsites, site)
		for _, fn := range [2]*ssa.Function{mainPkg.Func("init"), main} {
			if a.log != nil {
				fmt.Fprintf(a.log, "\troot call to %s:\n", fn)
			}
			a.copy(targets, a.valueNode(fn), 1)
		}
	}

	return root
}

// genFunc generates constraints for function fn.
func (a *analysis) genFunc(cgn *cgnode) {
	fn := cgn.fn
	if a.log != nil {
		fmt.Fprintln(a.log)
		fmt.Fprintln(a.log)
		cgn.fn.DumpTo(a.log)
	}

	if impl := a.findIntrinsic(fn); impl != nil {
		impl(a, cgn)
		return
	}

	if fn.Blocks == nil {
		// External function with no intrinsic treatment.
		// We'll warn about calls to such functions at the end.
		return
	}

	// The value nodes for the params are in the func object block.
	params := a.funcParams(cgn.obj)
	for _, p := range fn.Params {
		// TODO(adonovan): record the context (cgn) too.
		a.setValueNode(p, params)
		params += nodeid(a.sizeof(p.Type()))
	}

	// Free variables are treated like global variables:
	// the outer function sets them with MakeClosure;
	// the inner function accesses them with Capture.

	// Create value nodes for all value instructions.
	// (Clobbers any previous nodes from same fn in different context.)
	if a.log != nil {
		fmt.Fprintln(a.log, "; Creating instruction values")
	}
	for _, b := range fn.Blocks {
		for _, instr := range b.Instrs {
			switch instr := instr.(type) {
			case *ssa.Range:
				// do nothing: it has a funky type.

			case ssa.Value:
				var comment string
				if a.log != nil {
					comment = instr.Name()
				}
				id := a.addNodes(instr.Type(), comment)
				// TODO(adonovan): record the context (cgn) too.
				a.setValueNode(instr, id)
			}
		}
	}

	// Generate constraints for instructions.
	for _, b := range fn.Blocks {
		for _, instr := range b.Instrs {
			a.genInstr(cgn, instr)
		}
	}

	// (Instruction Values will hang around in the environment.)
}

// generate generates offline constraints for the entire program.
// It returns the synthetic root of the callgraph.
//
func (a *analysis) generate() *cgnode {
	// Create a dummy node since we use the nodeid 0 for
	// non-pointerlike variables.
	a.addNodes(tInvalid, "(zero)")

	// Create the global node for panic values.
	a.panicNode = a.addNodes(tEface, "panic")

	root := a.genRootCalls()

	// Generate constraints for entire program.
	// (Actually just the RTA-reachable portion of the program.
	// See Bacon & Sweeney, OOPSLA'96).
	for len(a.genq) > 0 {
		cgn := a.genq[0]
		a.genq = a.genq[1:]
		a.genFunc(cgn)
	}

	// Create a dummy node to avoid out-of-range indexing in case
	// the last allocated type was of zero length.
	a.addNodes(tInvalid, "(max)")

	return root
}
