GoPLS Viewer

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