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.
7 // This file defines the Const SSA value type.
17 // NewConst returns a new constant of the specified value and type.
18 // val must be valid according to the specification of Const.Value.
20 func NewConst(val constant.Value, typ types.Type) *Const {
21 return &Const{typ, val}
24 // intConst returns an 'int' constant that evaluates to i.
25 // (i is an int64 in case the host is narrower than the target.)
26 func intConst(i int64) *Const {
27 return NewConst(constant.MakeInt64(i), tInt)
30 // nilConst returns a nil constant of the specified type, which may
31 // be any reference type, including interfaces.
33 func nilConst(typ types.Type) *Const {
34 return NewConst(nil, typ)
37 // stringConst returns a 'string' constant that evaluates to s.
38 func stringConst(s string) *Const {
39 return NewConst(constant.MakeString(s), tString)
42 // zeroConst returns a new "zero" constant of the specified type,
43 // which must not be an array or struct type: the zero values of
44 // aggregates are well-defined but cannot be represented by Const.
46 func zeroConst(t types.Type) *Const {
47 switch t := t.(type) {
50 case t.Info()&types.IsBoolean != 0:
51 return NewConst(constant.MakeBool(false), t)
52 case t.Info()&types.IsNumeric != 0:
53 return NewConst(constant.MakeInt64(0), t)
54 case t.Info()&types.IsString != 0:
55 return NewConst(constant.MakeString(""), t)
56 case t.Kind() == types.UnsafePointer:
58 case t.Kind() == types.UntypedNil:
61 panic(fmt.Sprint("zeroConst for unexpected type:", t))
63 case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature:
66 return NewConst(zeroConst(t.Underlying()).Value, t)
67 case *types.Array, *types.Struct, *types.Tuple:
68 panic(fmt.Sprint("zeroConst applied to aggregate:", t))
70 panic(fmt.Sprint("zeroConst: unexpected ", t))
73 func (c *Const) RelString(from *types.Package) string {
77 } else if c.Value.Kind() == constant.String {
78 s = constant.StringVal(c.Value)
80 // TODO(adonovan): don't cut a rune in half.
82 s = s[:max-3] + "..." // abbreviate
88 return s + ":" + relType(c.Type(), from)
91 func (c *Const) Name() string {
92 return c.RelString(nil)
95 func (c *Const) String() string {
99 func (c *Const) Type() types.Type {
103 func (c *Const) Referrers() *[]Instruction {
107 func (c *Const) Parent() *Function { return nil }
109 func (c *Const) Pos() token.Pos {
113 // IsNil returns true if this constant represents a typed or untyped nil value.
114 func (c *Const) IsNil() bool {
115 return c.Value == nil
118 // TODO(adonovan): move everything below into golang.org/x/tools/go/ssa/interp.
120 // Int64 returns the numeric value of this constant truncated to fit
121 // a signed 64-bit integer.
123 func (c *Const) Int64() int64 {
124 switch x := constant.ToInt(c.Value); x.Kind() {
126 if i, ok := constant.Int64Val(x); ok {
131 f, _ := constant.Float64Val(x)
134 panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
137 // Uint64 returns the numeric value of this constant truncated to fit
138 // an unsigned 64-bit integer.
140 func (c *Const) Uint64() uint64 {
141 switch x := constant.ToInt(c.Value); x.Kind() {
143 if u, ok := constant.Uint64Val(x); ok {
148 f, _ := constant.Float64Val(x)
151 panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
154 // Float64 returns the numeric value of this constant truncated to fit
157 func (c *Const) Float64() float64 {
158 f, _ := constant.Float64Val(c.Value)
162 // Complex128 returns the complex value of this constant truncated to
165 func (c *Const) Complex128() complex128 {
166 re, _ := constant.Float64Val(constant.Real(c.Value))
167 im, _ := constant.Float64Val(constant.Imag(c.Value))
168 return complex(re, im)