github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gotools/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  
    14  	"llvm.org/llgo/third_party/gotools/go/types"
    15  )
    16  
    17  // An lvalue represents an assignable location that may appear on the
    18  // left-hand side of an assignment.  This is a generalization of a
    19  // pointer to permit updates to elements of maps.
    20  //
    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
    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 deref(a.addr.Type())
    58  }
    59  
    60  // An element is an lvalue represented by m[k], the location of an
    61  // element of a map or string.  These locations are not addressable
    62  // since pointers cannot be formed from them, but they do support
    63  // load(), and in the case of maps, store().
    64  //
    65  type element struct {
    66  	m, k Value      // map or string
    67  	t    types.Type // map element type or string byte type
    68  	pos  token.Pos  // source position of colon ({k:v}) or lbrack (m[k]=v)
    69  }
    70  
    71  func (e *element) load(fn *Function) Value {
    72  	l := &Lookup{
    73  		X:     e.m,
    74  		Index: e.k,
    75  	}
    76  	l.setPos(e.pos)
    77  	l.setType(e.t)
    78  	return fn.emit(l)
    79  }
    80  
    81  func (e *element) store(fn *Function, v Value) {
    82  	up := &MapUpdate{
    83  		Map:   e.m,
    84  		Key:   e.k,
    85  		Value: emitConv(fn, v, e.t),
    86  	}
    87  	up.pos = e.pos
    88  	fn.emit(up)
    89  }
    90  
    91  func (e *element) address(fn *Function) Value {
    92  	panic("map/string elements are not addressable")
    93  }
    94  
    95  func (e *element) typ() types.Type {
    96  	return e.t
    97  }
    98  
    99  // A blank is a dummy variable whose name is "_".
   100  // It is not reified: loads are illegal and stores are ignored.
   101  //
   102  type blank struct{}
   103  
   104  func (bl blank) load(fn *Function) Value {
   105  	panic("blank.load is illegal")
   106  }
   107  
   108  func (bl blank) store(fn *Function, v Value) {
   109  	// no-op
   110  }
   111  
   112  func (bl blank) address(fn *Function) Value {
   113  	panic("blank var is not addressable")
   114  }
   115  
   116  func (bl blank) typ() types.Type {
   117  	// This should be the type of the blank Ident; the typechecker
   118  	// doesn't provide this yet, but fortunately, we don't need it
   119  	// yet either.
   120  	panic("blank.typ is unimplemented")
   121  }