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.
19//
20type lvalue interface {
21	store(fn *Function, v Value) // stores v into the location
22	load(fn *Function) Value     // loads the contents of the location
23	address(fn *Function) Value  // address of the location
24	typ() types.Type             // returns the type of the location
25}
26
27// An address is an lvalue represented by a true pointer.
28type address struct {
29	addr Value
30	pos  token.Pos // source position
31	expr ast.Expr  // source syntax of the value (not address) [debug mode]
32}
33
34func (a *address) load(fn *Function) Value {
35	load := emitLoad(fn, a.addr)
36	load.pos = a.pos
37	return load
38}
39
40func (a *address) store(fn *Function, v Value) {
41	store := emitStore(fn, a.addr, v, a.pos)
42	if a.expr != nil {
43		// store.Val is v, converted for assignability.
44		emitDebugRef(fn, a.expr, store.Val, false)
45	}
46}
47
48func (a *address) address(fn *Function) Value {
49	if a.expr != nil {
50		emitDebugRef(fn, a.expr, a.addr, true)
51	}
52	return a.addr
53}
54
55func (a *address) typ() types.Type {
56	return deref(a.addr.Type())
57}
58
59// An element is an lvalue represented by m[k], the location of an
60// element of a map or string.  These locations are not addressable
61// since pointers cannot be formed from them, but they do support
62// load(), and in the case of maps, store().
63//
64type element struct {
65	m, k Value      // map or string
66	t    types.Type // map element type or string byte type
67	pos  token.Pos  // source position of colon ({k:v}) or lbrack (m[k]=v)
68}
69
70func (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
80func (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
90func (e *element) address(fn *Function) Value {
91	panic("map/string elements are not addressable")
92}
93
94func (e *element) typ() types.Type {
95	return e.t
96}
97
98// A blank is a dummy variable whose name is "_".
99// It is not reified: loads are illegal and stores are ignored.
100//
101type blank struct{}
102
103func (bl blank) load(fn *Function) Value {
104	panic("blank.load is illegal")
105}
106
107func (bl blank) store(fn *Function, v Value) {
108	// no-op
109}
110
111func (bl blank) address(fn *Function) Value {
112	panic("blank var is not addressable")
113}
114
115func (bl blank) typ() types.Type {
116	// This should be the type of the blank Ident; the typechecker
117	// doesn't provide this yet, but fortunately, we don't need it
118	// yet either.
119	panic("blank.typ is unimplemented")
120}
121