golang.org/x/tools@v0.21.1-0.20240520172518-788d39e776b1/go/ssa/lvalue.go (about) 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 }