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 5package ir 6 7// This file defines the Const SSA value type. 8 9import ( 10 "fmt" 11 "go/constant" 12 "go/types" 13 "strconv" 14) 15 16// NewConst returns a new constant of the specified value and type. 17// val must be valid according to the specification of Const.Value. 18// 19func NewConst(val constant.Value, typ types.Type) *Const { 20 return &Const{ 21 register: register{ 22 typ: typ, 23 }, 24 Value: val, 25 } 26} 27 28// intConst returns an 'int' constant that evaluates to i. 29// (i is an int64 in case the host is narrower than the target.) 30func intConst(i int64) *Const { 31 return NewConst(constant.MakeInt64(i), tInt) 32} 33 34// nilConst returns a nil constant of the specified type, which may 35// be any reference type, including interfaces. 36// 37func nilConst(typ types.Type) *Const { 38 return NewConst(nil, typ) 39} 40 41// stringConst returns a 'string' constant that evaluates to s. 42func stringConst(s string) *Const { 43 return NewConst(constant.MakeString(s), tString) 44} 45 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. 49// 50func zeroConst(t types.Type) *Const { 51 switch t := t.(type) { 52 case *types.Basic: 53 switch { 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: 61 fallthrough 62 case t.Kind() == types.UntypedNil: 63 return nilConst(t) 64 default: 65 panic(fmt.Sprint("zeroConst for unexpected type:", t)) 66 } 67 case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature: 68 return nilConst(t) 69 case *types.Named: 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)) 73 } 74 panic(fmt.Sprint("zeroConst: unexpected ", t)) 75} 76 77func (c *Const) RelString(from *types.Package) string { 78 var p string 79 if c.Value == nil { 80 p = "nil" 81 } else if c.Value.Kind() == constant.String { 82 v := constant.StringVal(c.Value) 83 const max = 20 84 // TODO(adonovan): don't cut a rune in half. 85 if len(v) > max { 86 v = v[:max-3] + "..." // abbreviate 87 } 88 p = strconv.Quote(v) 89 } else { 90 p = c.Value.String() 91 } 92 return fmt.Sprintf("Const <%s> {%s}", relType(c.Type(), from), p) 93} 94 95func (c *Const) String() string { 96 return c.RelString(c.Parent().pkg()) 97} 98 99// IsNil returns true if this constant represents a typed or untyped nil value. 100func (c *Const) IsNil() bool { 101 return c.Value == nil 102} 103 104// Int64 returns the numeric value of this constant truncated to fit 105// a signed 64-bit integer. 106// 107func (c *Const) Int64() int64 { 108 switch x := constant.ToInt(c.Value); x.Kind() { 109 case constant.Int: 110 if i, ok := constant.Int64Val(x); ok { 111 return i 112 } 113 return 0 114 case constant.Float: 115 f, _ := constant.Float64Val(x) 116 return int64(f) 117 } 118 panic(fmt.Sprintf("unexpected constant value: %T", c.Value)) 119} 120 121// Uint64 returns the numeric value of this constant truncated to fit 122// an unsigned 64-bit integer. 123// 124func (c *Const) Uint64() uint64 { 125 switch x := constant.ToInt(c.Value); x.Kind() { 126 case constant.Int: 127 if u, ok := constant.Uint64Val(x); ok { 128 return u 129 } 130 return 0 131 case constant.Float: 132 f, _ := constant.Float64Val(x) 133 return uint64(f) 134 } 135 panic(fmt.Sprintf("unexpected constant value: %T", c.Value)) 136} 137 138// Float64 returns the numeric value of this constant truncated to fit 139// a float64. 140// 141func (c *Const) Float64() float64 { 142 f, _ := constant.Float64Val(c.Value) 143 return f 144} 145 146// Complex128 returns the complex value of this constant truncated to 147// fit a complex128. 148// 149func (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) 153} 154