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.
16 // NewConst returns a new constant of the specified value and type.
17 // val must be valid according to the specification of Const.Value.
19 func NewConst(val constant.Value, typ types.Type) *Const {
28 // intConst returns an 'int' constant that evaluates to i.
29 // (i is an int64 in case the host is narrower than the target.)
30 func intConst(i int64) *Const {
31 return NewConst(constant.MakeInt64(i), tInt)
34 // nilConst returns a nil constant of the specified type, which may
35 // be any reference type, including interfaces.
37 func nilConst(typ types.Type) *Const {
38 return NewConst(nil, typ)
41 // stringConst returns a 'string' constant that evaluates to s.
42 func stringConst(s string) *Const {
43 return NewConst(constant.MakeString(s), tString)
46 // zeroConst returns a new "zero" constant of the specified type,
47 // which must not be an array or struct type: the zero values of
48 // aggregates are well-defined but cannot be represented by Const.
50 func zeroConst(t types.Type) *Const {
51 switch t := t.(type) {
54 case t.Info()&types.IsBoolean != 0:
55 return NewConst(constant.MakeBool(false), t)
56 case t.Info()&types.IsNumeric != 0:
57 return NewConst(constant.MakeInt64(0), t)
58 case t.Info()&types.IsString != 0:
59 return NewConst(constant.MakeString(""), t)
60 case t.Kind() == types.UnsafePointer:
62 case t.Kind() == types.UntypedNil:
65 panic(fmt.Sprint("zeroConst for unexpected type:", t))
67 case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature:
70 return NewConst(zeroConst(t.Underlying()).Value, t)
71 case *types.Array, *types.Struct, *types.Tuple:
72 panic(fmt.Sprint("zeroConst applied to aggregate:", t))
74 panic(fmt.Sprint("zeroConst: unexpected ", t))
77 func (c *Const) RelString(from *types.Package) string {
81 } else if c.Value.Kind() == constant.String {
82 v := constant.StringVal(c.Value)
84 // TODO(adonovan): don't cut a rune in half.
86 v = v[:max-3] + "..." // abbreviate
92 return fmt.Sprintf("Const <%s> {%s}", relType(c.Type(), from), p)
95 func (c *Const) String() string {
96 return c.RelString(c.Parent().pkg())
99 // IsNil returns true if this constant represents a typed or untyped nil value.
100 func (c *Const) IsNil() bool {
101 return c.Value == nil
104 // Int64 returns the numeric value of this constant truncated to fit
105 // a signed 64-bit integer.
107 func (c *Const) Int64() int64 {
108 switch x := constant.ToInt(c.Value); x.Kind() {
110 if i, ok := constant.Int64Val(x); ok {
115 f, _ := constant.Float64Val(x)
118 panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
121 // Uint64 returns the numeric value of this constant truncated to fit
122 // an unsigned 64-bit integer.
124 func (c *Const) Uint64() uint64 {
125 switch x := constant.ToInt(c.Value); x.Kind() {
127 if u, ok := constant.Uint64Val(x); ok {
132 f, _ := constant.Float64Val(x)
135 panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
138 // Float64 returns the numeric value of this constant truncated to fit
141 func (c *Const) Float64() float64 {
142 f, _ := constant.Float64Val(c.Value)
146 // Complex128 returns the complex value of this constant truncated to
149 func (c *Const) Complex128() complex128 {
150 re, _ := constant.Float64Val(constant.Real(c.Value))
151 im, _ := constant.Float64Val(constant.Imag(c.Value))
152 return complex(re, im)