github.com/jd-ly/tools@v0.5.7/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 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 // 20 type 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. 28 type 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 34 func (a *address) load(fn *Function) Value { 35 load := emitLoad(fn, a.addr) 36 load.pos = a.pos 37 return load 38 } 39 40 func (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 48 func (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 55 func (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 // 64 type 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 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/string elements are not addressable") 92 } 93 94 func (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 // 101 type blank struct{} 102 103 func (bl blank) load(fn *Function) Value { 104 panic("blank.load is illegal") 105 } 106 107 func (bl blank) store(fn *Function, v Value) { 108 // no-op 109 } 110 111 func (bl blank) address(fn *Function) Value { 112 panic("blank var is not addressable") 113 } 114 115 func (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 }