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 | package pointer |
6 | |
7 | import "go/types" |
8 | |
9 | type constraint interface { |
10 | // For a complex constraint, returns the nodeid of the pointer |
11 | // to which it is attached. For addr and copy, returns dst. |
12 | ptr() nodeid |
13 | |
14 | // renumber replaces each nodeid n in the constraint by mapping[n]. |
15 | renumber(mapping []nodeid) |
16 | |
17 | // presolve is a hook for constraint-specific behaviour during |
18 | // pre-solver optimization. Typical implementations mark as |
19 | // indirect the set of nodes to which the solver will add copy |
20 | // edges or PTS labels. |
21 | presolve(h *hvn) |
22 | |
23 | // solve is called for complex constraints when the pts for |
24 | // the node to which they are attached has changed. |
25 | solve(a *analysis, delta *nodeset) |
26 | |
27 | String() string |
28 | } |
29 | |
30 | // dst = &src |
31 | // pts(dst) ⊇ {src} |
32 | // A base constraint used to initialize the solver's pt sets |
33 | type addrConstraint struct { |
34 | dst nodeid // (ptr) |
35 | src nodeid |
36 | } |
37 | |
38 | func (c *addrConstraint) ptr() nodeid { return c.dst } |
39 | func (c *addrConstraint) renumber(mapping []nodeid) { |
40 | c.dst = mapping[c.dst] |
41 | c.src = mapping[c.src] |
42 | } |
43 | |
44 | // dst = src |
45 | // A simple constraint represented directly as a copyTo graph edge. |
46 | type copyConstraint struct { |
47 | dst nodeid // (ptr) |
48 | src nodeid |
49 | } |
50 | |
51 | func (c *copyConstraint) ptr() nodeid { return c.dst } |
52 | func (c *copyConstraint) renumber(mapping []nodeid) { |
53 | c.dst = mapping[c.dst] |
54 | c.src = mapping[c.src] |
55 | } |
56 | |
57 | // dst = src[offset] |
58 | // A complex constraint attached to src (the pointer) |
59 | type loadConstraint struct { |
60 | offset uint32 |
61 | dst nodeid |
62 | src nodeid // (ptr) |
63 | } |
64 | |
65 | func (c *loadConstraint) ptr() nodeid { return c.src } |
66 | func (c *loadConstraint) renumber(mapping []nodeid) { |
67 | c.dst = mapping[c.dst] |
68 | c.src = mapping[c.src] |
69 | } |
70 | |
71 | // dst[offset] = src |
72 | // A complex constraint attached to dst (the pointer) |
73 | type storeConstraint struct { |
74 | offset uint32 |
75 | dst nodeid // (ptr) |
76 | src nodeid |
77 | } |
78 | |
79 | func (c *storeConstraint) ptr() nodeid { return c.dst } |
80 | func (c *storeConstraint) renumber(mapping []nodeid) { |
81 | c.dst = mapping[c.dst] |
82 | c.src = mapping[c.src] |
83 | } |
84 | |
85 | // dst = &src.f or dst = &src[0] |
86 | // A complex constraint attached to dst (the pointer) |
87 | type offsetAddrConstraint struct { |
88 | offset uint32 |
89 | dst nodeid |
90 | src nodeid // (ptr) |
91 | } |
92 | |
93 | func (c *offsetAddrConstraint) ptr() nodeid { return c.src } |
94 | func (c *offsetAddrConstraint) renumber(mapping []nodeid) { |
95 | c.dst = mapping[c.dst] |
96 | c.src = mapping[c.src] |
97 | } |
98 | |
99 | // dst = src.(typ) where typ is an interface |
100 | // A complex constraint attached to src (the interface). |
101 | // No representation change: pts(dst) and pts(src) contains tagged objects. |
102 | type typeFilterConstraint struct { |
103 | typ types.Type // an interface type |
104 | dst nodeid |
105 | src nodeid // (ptr) |
106 | } |
107 | |
108 | func (c *typeFilterConstraint) ptr() nodeid { return c.src } |
109 | func (c *typeFilterConstraint) renumber(mapping []nodeid) { |
110 | c.dst = mapping[c.dst] |
111 | c.src = mapping[c.src] |
112 | } |
113 | |
114 | // dst = src.(typ) where typ is a concrete type |
115 | // A complex constraint attached to src (the interface). |
116 | // |
117 | // If exact, only tagged objects identical to typ are untagged. |
118 | // If !exact, tagged objects assignable to typ are untagged too. |
119 | // The latter is needed for various reflect operators, e.g. Send. |
120 | // |
121 | // This entails a representation change: |
122 | // pts(src) contains tagged objects, |
123 | // pts(dst) contains their payloads. |
124 | type untagConstraint struct { |
125 | typ types.Type // a concrete type |
126 | dst nodeid |
127 | src nodeid // (ptr) |
128 | exact bool |
129 | } |
130 | |
131 | func (c *untagConstraint) ptr() nodeid { return c.src } |
132 | func (c *untagConstraint) renumber(mapping []nodeid) { |
133 | c.dst = mapping[c.dst] |
134 | c.src = mapping[c.src] |
135 | } |
136 | |
137 | // src.method(params...) |
138 | // A complex constraint attached to iface. |
139 | type invokeConstraint struct { |
140 | method *types.Func // the abstract method |
141 | iface nodeid // (ptr) the interface |
142 | params nodeid // the start of the identity/params/results block |
143 | } |
144 | |
145 | func (c *invokeConstraint) ptr() nodeid { return c.iface } |
146 | func (c *invokeConstraint) renumber(mapping []nodeid) { |
147 | c.iface = mapping[c.iface] |
148 | c.params = mapping[c.params] |
149 | } |
150 |
Members