1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
// 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
import (
"code.google.com/p/go.tools/go/types"
)
type constraint interface {
// For a complex constraint, returns the nodeid of the pointer
// to which it is attached.
ptr() nodeid
// indirect returns (by appending to the argument) the constraint's
// "indirect" nodes as defined in (Hardekopf 2007b):
// nodes whose points-to relations are not completely
// represented in the initial constraint graph.
//
// TODO(adonovan): I think we need >1 results in some obscure
// cases. If not, just return a nodeid, like ptr().
//
indirect(nodes []nodeid) []nodeid
// renumber replaces each nodeid n in the constraint by mapping[n].
renumber(mapping []nodeid)
// 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)
String() string
}
// dst = &src
// pts(dst) ⊇ {src}
// A base constraint used to initialize the solver's pt sets
type addrConstraint struct {
dst nodeid // (ptr)
src nodeid
}
func (c *addrConstraint) ptr() nodeid { panic("addrConstraint: not a complex constraint") }
func (c *addrConstraint) indirect(nodes []nodeid) []nodeid {
panic("addrConstraint: not a complex constraint")
}
func (c *addrConstraint) renumber(mapping []nodeid) {
c.dst = mapping[c.dst]
c.src = mapping[c.src]
}
// dst = src
// A simple constraint represented directly as a copyTo graph edge.
type copyConstraint struct {
dst nodeid
src nodeid // (ptr)
}
func (c *copyConstraint) ptr() nodeid { panic("copyConstraint: not a complex constraint") }
func (c *copyConstraint) indirect(nodes []nodeid) []nodeid {
panic("copyConstraint: not a complex constraint")
}
func (c *copyConstraint) renumber(mapping []nodeid) {
c.dst = mapping[c.dst]
c.src = mapping[c.src]
}
// dst = src[offset]
// A complex constraint attached to src (the pointer)
type loadConstraint struct {
offset uint32
dst nodeid // (indirect)
src nodeid // (ptr)
}
func (c *loadConstraint) ptr() nodeid { return c.src }
func (c *loadConstraint) indirect(nodes []nodeid) []nodeid { return append(nodes, c.dst) }
func (c *loadConstraint) renumber(mapping []nodeid) {
c.dst = mapping[c.dst]
c.src = mapping[c.src]
}
// dst[offset] = src
// A complex constraint attached to dst (the pointer)
type storeConstraint struct {
offset uint32
dst nodeid // (ptr)
src nodeid
}
func (c *storeConstraint) ptr() nodeid { return c.dst }
func (c *storeConstraint) indirect(nodes []nodeid) []nodeid { return nodes }
func (c *storeConstraint) renumber(mapping []nodeid) {
c.dst = mapping[c.dst]
c.src = mapping[c.src]
}
// dst = &src.f or dst = &src[0]
// A complex constraint attached to dst (the pointer)
type offsetAddrConstraint struct {
offset uint32
dst nodeid // (indirect)
src nodeid // (ptr)
}
func (c *offsetAddrConstraint) ptr() nodeid { return c.src }
func (c *offsetAddrConstraint) indirect(nodes []nodeid) []nodeid { return append(nodes, c.dst) }
func (c *offsetAddrConstraint) renumber(mapping []nodeid) {
c.dst = mapping[c.dst]
c.src = mapping[c.src]
}
// dst = src.(typ) where typ is an interface
// A complex constraint attached to src (the interface).
// No representation change: pts(dst) and pts(src) contains tagged objects.
type typeFilterConstraint struct {
typ types.Type // an interface type
dst nodeid // (indirect)
src nodeid // (ptr)
}
func (c *typeFilterConstraint) ptr() nodeid { return c.src }
func (c *typeFilterConstraint) indirect(nodes []nodeid) []nodeid { return append(nodes, c.dst) }
func (c *typeFilterConstraint) renumber(mapping []nodeid) {
c.dst = mapping[c.dst]
c.src = mapping[c.src]
}
// dst = src.(typ) where typ is a concrete type
// A complex constraint attached to src (the interface).
//
// If exact, only tagged objects identical to typ are untagged.
// If !exact, tagged objects assignable to typ are untagged too.
// The latter is needed for various reflect operators, e.g. Send.
//
// This entails a representation change:
// pts(src) contains tagged objects,
// pts(dst) contains their payloads.
type untagConstraint struct {
typ types.Type // a concrete type
dst nodeid // (indirect)
src nodeid // (ptr)
exact bool
}
func (c *untagConstraint) ptr() nodeid { return c.src }
func (c *untagConstraint) indirect(nodes []nodeid) []nodeid { return append(nodes, c.dst) }
func (c *untagConstraint) renumber(mapping []nodeid) {
c.dst = mapping[c.dst]
c.src = mapping[c.src]
}
// src.method(params...)
// A complex constraint attached to iface.
type invokeConstraint struct {
method *types.Func // the abstract method
iface nodeid // (ptr) the interface
params nodeid // (indirect) the first param in the params/results block
}
func (c *invokeConstraint) ptr() nodeid { return c.iface }
func (c *invokeConstraint) indirect(nodes []nodeid) []nodeid { return append(nodes, c.params) }
func (c *invokeConstraint) renumber(mapping []nodeid) {
c.iface = mapping[c.iface]
c.params = mapping[c.params]
}
|