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 }