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 ssa
6 7 // lvalues are the union of addressable expressions and map-index
8 // expressions.
9 10 import (
11 "go/ast"
12 "go/token"
13 "go/types"
14 15 "golang.org/x/tools/internal/typeparams"
16 )
17 18 // An lvalue represents an assignable location that may appear on the
19 // left-hand side of an assignment. This is a generalization of a
20 // pointer to permit updates to elements of maps.
21 type lvalue interface {
22 store(fn *Function, v Value) // stores v into the location
23 load(fn *Function) Value // loads the contents of the location
24 address(fn *Function) Value // address of the location
25 typ() types.Type // returns the type of the location
26 }
27 28 // An address is an lvalue represented by a true pointer.
29 type address struct {
30 addr Value // must have a pointer core type.
31 pos token.Pos // source position
32 expr ast.Expr // source syntax of the value (not address) [debug mode]
33 }
34 35 func (a *address) load(fn *Function) Value {
36 load := emitLoad(fn, a.addr)
37 load.pos = a.pos
38 return load
39 }
40 41 func (a *address) store(fn *Function, v Value) {
42 store := emitStore(fn, a.addr, v, a.pos)
43 if a.expr != nil {
44 // store.Val is v, converted for assignability.
45 emitDebugRef(fn, a.expr, store.Val, false)
46 }
47 }
48 49 func (a *address) address(fn *Function) Value {
50 if a.expr != nil {
51 emitDebugRef(fn, a.expr, a.addr, true)
52 }
53 return a.addr
54 }
55 56 func (a *address) typ() types.Type {
57 return typeparams.MustDeref(a.addr.Type())
58 }
59 60 // An element is an lvalue represented by m[k], the location of an
61 // element of a map. These locations are not addressable
62 // since pointers cannot be formed from them, but they do support
63 // load() and store().
64 type element struct {
65 m, k Value // map
66 t types.Type // map element type
67 pos token.Pos // source position of colon ({k:v}) or lbrack (m[k]=v)
68 }
69 70 func (e *element) load(fn *Function) Value {
71 l := &Lookup{
72 X: e.m,
73 Index: e.k,
74 }
75 l.setPos(e.pos)
76 l.setType(e.t)
77 return fn.emit(l)
78 }
79 80 func (e *element) store(fn *Function, v Value) {
81 up := &MapUpdate{
82 Map: e.m,
83 Key: e.k,
84 Value: emitConv(fn, v, e.t),
85 }
86 up.pos = e.pos
87 fn.emit(up)
88 }
89 90 func (e *element) address(fn *Function) Value {
91 panic("map elements are not addressable")
92 }
93 94 func (e *element) typ() types.Type {
95 return e.t
96 }
97 98 // A lazyAddress is an lvalue whose address is the result of an instruction.
99 // These work like an *address except a new address.address() Value
100 // is created on each load, store and address call.
101 // A lazyAddress can be used to control when a side effect (nil pointer
102 // dereference, index out of bounds) of using a location happens.
103 type lazyAddress struct {
104 addr func(fn *Function) Value // emit to fn the computation of the address
105 t types.Type // type of the location
106 pos token.Pos // source position
107 expr ast.Expr // source syntax of the value (not address) [debug mode]
108 }
109 110 func (l *lazyAddress) load(fn *Function) Value {
111 load := emitLoad(fn, l.addr(fn))
112 load.pos = l.pos
113 return load
114 }
115 116 func (l *lazyAddress) store(fn *Function, v Value) {
117 store := emitStore(fn, l.addr(fn), v, l.pos)
118 if l.expr != nil {
119 // store.Val is v, converted for assignability.
120 emitDebugRef(fn, l.expr, store.Val, false)
121 }
122 }
123 124 func (l *lazyAddress) address(fn *Function) Value {
125 addr := l.addr(fn)
126 if l.expr != nil {
127 emitDebugRef(fn, l.expr, addr, true)
128 }
129 return addr
130 }
131 132 func (l *lazyAddress) typ() types.Type { return l.t }
133 134 // A blank is a dummy variable whose name is "_".
135 // It is not reified: loads are illegal and stores are ignored.
136 type blank struct{}
137 138 func (bl blank) load(fn *Function) Value {
139 panic("blank.load is illegal")
140 }
141 142 func (bl blank) store(fn *Function, v Value) {
143 // no-op
144 }
145 146 func (bl blank) address(fn *Function) Value {
147 panic("blank var is not addressable")
148 }
149 150 func (bl blank) typ() types.Type {
151 // This should be the type of the blank Ident; the typechecker
152 // doesn't provide this yet, but fortunately, we don't need it
153 // yet either.
154 panic("blank.typ is unimplemented")
155 }
156