152 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
| // 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.   For addr and copy, returns dst.
 | |
| 	ptr() nodeid
 | |
| 
 | |
| 	// renumber replaces each nodeid n in the constraint by mapping[n].
 | |
| 	renumber(mapping []nodeid)
 | |
| 
 | |
| 	// presolve is a hook for constraint-specific behaviour during
 | |
| 	// pre-solver optimization.  Typical implementations mark as
 | |
| 	// indirect the set of nodes to which the solver will add copy
 | |
| 	// edges or PTS labels.
 | |
| 	presolve(h *hvn)
 | |
| 
 | |
| 	// solve is called for complex constraints when the pts for
 | |
| 	// the node to which they are attached has changed.
 | |
| 	solve(a *analysis, 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 { return c.dst }
 | |
| 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 // (ptr)
 | |
| 	src nodeid
 | |
| }
 | |
| 
 | |
| func (c *copyConstraint) ptr() nodeid { return c.dst }
 | |
| 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
 | |
| 	src    nodeid // (ptr)
 | |
| }
 | |
| 
 | |
| func (c *loadConstraint) ptr() nodeid { return c.src }
 | |
| 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) 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
 | |
| 	src    nodeid // (ptr)
 | |
| }
 | |
| 
 | |
| func (c *offsetAddrConstraint) ptr() nodeid { return c.src }
 | |
| 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
 | |
| 	src nodeid // (ptr)
 | |
| }
 | |
| 
 | |
| func (c *typeFilterConstraint) ptr() nodeid { return c.src }
 | |
| 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
 | |
| 	src   nodeid // (ptr)
 | |
| 	exact bool
 | |
| }
 | |
| 
 | |
| func (c *untagConstraint) ptr() nodeid { return c.src }
 | |
| 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      // the start of the identity/params/results block
 | |
| }
 | |
| 
 | |
| func (c *invokeConstraint) ptr() nodeid { return c.iface }
 | |
| func (c *invokeConstraint) renumber(mapping []nodeid) {
 | |
| 	c.iface = mapping[c.iface]
 | |
| 	c.params = mapping[c.params]
 | |
| }
 |