github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gotools/go/ssa/const.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  // This file defines the Const SSA value type.
     8  
     9  import (
    10  	"fmt"
    11  	"go/token"
    12  	"strconv"
    13  
    14  	"llvm.org/llgo/third_party/gotools/go/exact"
    15  	"llvm.org/llgo/third_party/gotools/go/types"
    16  )
    17  
    18  // NewConst returns a new constant of the specified value and type.
    19  // val must be valid according to the specification of Const.Value.
    20  //
    21  func NewConst(val exact.Value, typ types.Type) *Const {
    22  	return &Const{typ, val}
    23  }
    24  
    25  // intConst returns an 'int' constant that evaluates to i.
    26  // (i is an int64 in case the host is narrower than the target.)
    27  func intConst(i int64) *Const {
    28  	return NewConst(exact.MakeInt64(i), tInt)
    29  }
    30  
    31  // nilConst returns a nil constant of the specified type, which may
    32  // be any reference type, including interfaces.
    33  //
    34  func nilConst(typ types.Type) *Const {
    35  	return NewConst(nil, typ)
    36  }
    37  
    38  // stringConst returns a 'string' constant that evaluates to s.
    39  func stringConst(s string) *Const {
    40  	return NewConst(exact.MakeString(s), tString)
    41  }
    42  
    43  // zeroConst returns a new "zero" constant of the specified type,
    44  // which must not be an array or struct type: the zero values of
    45  // aggregates are well-defined but cannot be represented by Const.
    46  //
    47  func zeroConst(t types.Type) *Const {
    48  	switch t := t.(type) {
    49  	case *types.Basic:
    50  		switch {
    51  		case t.Info()&types.IsBoolean != 0:
    52  			return NewConst(exact.MakeBool(false), t)
    53  		case t.Info()&types.IsNumeric != 0:
    54  			return NewConst(exact.MakeInt64(0), t)
    55  		case t.Info()&types.IsString != 0:
    56  			return NewConst(exact.MakeString(""), t)
    57  		case t.Kind() == types.UnsafePointer:
    58  			fallthrough
    59  		case t.Kind() == types.UntypedNil:
    60  			return nilConst(t)
    61  		default:
    62  			panic(fmt.Sprint("zeroConst for unexpected type:", t))
    63  		}
    64  	case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature:
    65  		return nilConst(t)
    66  	case *types.Named:
    67  		return NewConst(zeroConst(t.Underlying()).Value, t)
    68  	case *types.Array, *types.Struct, *types.Tuple:
    69  		panic(fmt.Sprint("zeroConst applied to aggregate:", t))
    70  	}
    71  	panic(fmt.Sprint("zeroConst: unexpected ", t))
    72  }
    73  
    74  func (c *Const) RelString(from *types.Package) string {
    75  	var s string
    76  	if c.Value == nil {
    77  		s = "nil"
    78  	} else if c.Value.Kind() == exact.String {
    79  		s = exact.StringVal(c.Value)
    80  		const max = 20
    81  		// TODO(adonovan): don't cut a rune in half.
    82  		if len(s) > max {
    83  			s = s[:max-3] + "..." // abbreviate
    84  		}
    85  		s = strconv.Quote(s)
    86  	} else {
    87  		s = c.Value.String()
    88  	}
    89  	return s + ":" + relType(c.Type(), from)
    90  }
    91  
    92  func (c *Const) Name() string {
    93  	return c.RelString(nil)
    94  }
    95  
    96  func (c *Const) String() string {
    97  	return c.Name()
    98  }
    99  
   100  func (c *Const) Type() types.Type {
   101  	return c.typ
   102  }
   103  
   104  func (c *Const) Referrers() *[]Instruction {
   105  	return nil
   106  }
   107  
   108  func (c *Const) Parent() *Function { return nil }
   109  
   110  func (c *Const) Pos() token.Pos {
   111  	return token.NoPos
   112  }
   113  
   114  // IsNil returns true if this constant represents a typed or untyped nil value.
   115  func (c *Const) IsNil() bool {
   116  	return c.Value == nil
   117  }
   118  
   119  // Int64 returns the numeric value of this constant truncated to fit
   120  // a signed 64-bit integer.
   121  //
   122  func (c *Const) Int64() int64 {
   123  	switch x := c.Value; x.Kind() {
   124  	case exact.Int:
   125  		if i, ok := exact.Int64Val(x); ok {
   126  			return i
   127  		}
   128  		return 0
   129  	case exact.Float:
   130  		f, _ := exact.Float64Val(x)
   131  		return int64(f)
   132  	}
   133  	panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
   134  }
   135  
   136  // Uint64 returns the numeric value of this constant truncated to fit
   137  // an unsigned 64-bit integer.
   138  //
   139  func (c *Const) Uint64() uint64 {
   140  	switch x := c.Value; x.Kind() {
   141  	case exact.Int:
   142  		if u, ok := exact.Uint64Val(x); ok {
   143  			return u
   144  		}
   145  		return 0
   146  	case exact.Float:
   147  		f, _ := exact.Float64Val(x)
   148  		return uint64(f)
   149  	}
   150  	panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
   151  }
   152  
   153  // Float64 returns the numeric value of this constant truncated to fit
   154  // a float64.
   155  //
   156  func (c *Const) Float64() float64 {
   157  	f, _ := exact.Float64Val(c.Value)
   158  	return f
   159  }
   160  
   161  // Complex128 returns the complex value of this constant truncated to
   162  // fit a complex128.
   163  //
   164  func (c *Const) Complex128() complex128 {
   165  	re, _ := exact.Float64Val(exact.Real(c.Value))
   166  	im, _ := exact.Float64Val(exact.Imag(c.Value))
   167  	return complex(re, im)
   168  }