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
5package pointer
6
7import "go/types"
8
9type 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
33type addrConstraint struct {
34	dst nodeid // (ptr)
35	src nodeid
36}
37
38func (c *addrConstraint) ptr() nodeid { return c.dst }
39func (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.
46type copyConstraint struct {
47	dst nodeid // (ptr)
48	src nodeid
49}
50
51func (c *copyConstraint) ptr() nodeid { return c.dst }
52func (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)
59type loadConstraint struct {
60	offset uint32
61	dst    nodeid
62	src    nodeid // (ptr)
63}
64
65func (c *loadConstraint) ptr() nodeid { return c.src }
66func (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)
73type storeConstraint struct {
74	offset uint32
75	dst    nodeid // (ptr)
76	src    nodeid
77}
78
79func (c *storeConstraint) ptr() nodeid { return c.dst }
80func (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)
87type offsetAddrConstraint struct {
88	offset uint32
89	dst    nodeid
90	src    nodeid // (ptr)
91}
92
93func (c *offsetAddrConstraint) ptr() nodeid { return c.src }
94func (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.
102type typeFilterConstraint struct {
103	typ types.Type // an interface type
104	dst nodeid
105	src nodeid // (ptr)
106}
107
108func (c *typeFilterConstraint) ptr() nodeid { return c.src }
109func (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.
124type untagConstraint struct {
125	typ   types.Type // a concrete type
126	dst   nodeid
127	src   nodeid // (ptr)
128	exact bool
129}
130
131func (c *untagConstraint) ptr() nodeid { return c.src }
132func (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.
139type 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
145func (c *invokeConstraint) ptr() nodeid { return c.iface }
146func (c *invokeConstraint) renumber(mapping []nodeid) {
147	c.iface = mapping[c.iface]
148	c.params = mapping[c.params]
149}
150