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  }