blob: f43792e7f37887c8a9f4e6bf41814d466b35931c [file] [log] [blame]
Alan Donovan713699d2013-08-27 18:49:13 -04001// 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
Alan Donovan732dbe92013-07-16 13:50:08 -04005package ssa
6
7// This file defines the Const SSA value type.
8
9import (
10 "fmt"
Alan Donovane96c4e22018-08-10 12:49:16 -040011 "go/constant"
Alan Donovan732dbe92013-07-16 13:50:08 -040012 "go/token"
Alan Donovan542ffc72015-12-29 13:06:30 -050013 "go/types"
Alan Donovan732dbe92013-07-16 13:50:08 -040014 "strconv"
Alan Donovan732dbe92013-07-16 13:50:08 -040015)
16
17// NewConst returns a new constant of the specified value and type.
18// val must be valid according to the specification of Const.Value.
19//
Alan Donovane96c4e22018-08-10 12:49:16 -040020func NewConst(val constant.Value, typ types.Type) *Const {
Alan Donovan732dbe92013-07-16 13:50:08 -040021 return &Const{typ, val}
22}
23
Alan Donovanc846ece2013-12-04 13:59:55 -050024// intConst returns an 'int' constant that evaluates to i.
25// (i is an int64 in case the host is narrower than the target.)
Alan Donovan732dbe92013-07-16 13:50:08 -040026func intConst(i int64) *Const {
Alan Donovane96c4e22018-08-10 12:49:16 -040027 return NewConst(constant.MakeInt64(i), tInt)
Alan Donovan732dbe92013-07-16 13:50:08 -040028}
29
30// nilConst returns a nil constant of the specified type, which may
31// be any reference type, including interfaces.
32//
33func nilConst(typ types.Type) *Const {
Robert Griesemerf50f6c82013-10-09 14:17:25 -070034 return NewConst(nil, typ)
Alan Donovan732dbe92013-07-16 13:50:08 -040035}
36
Alan Donovande23e2b2014-06-13 17:34:07 -040037// stringConst returns a 'string' constant that evaluates to s.
38func stringConst(s string) *Const {
Alan Donovane96c4e22018-08-10 12:49:16 -040039 return NewConst(constant.MakeString(s), tString)
Alan Donovande23e2b2014-06-13 17:34:07 -040040}
41
Alan Donovan732dbe92013-07-16 13:50:08 -040042// 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.
45//
46func zeroConst(t types.Type) *Const {
47 switch t := t.(type) {
48 case *types.Basic:
49 switch {
50 case t.Info()&types.IsBoolean != 0:
Alan Donovane96c4e22018-08-10 12:49:16 -040051 return NewConst(constant.MakeBool(false), t)
Alan Donovan732dbe92013-07-16 13:50:08 -040052 case t.Info()&types.IsNumeric != 0:
Alan Donovane96c4e22018-08-10 12:49:16 -040053 return NewConst(constant.MakeInt64(0), t)
Alan Donovan732dbe92013-07-16 13:50:08 -040054 case t.Info()&types.IsString != 0:
Alan Donovane96c4e22018-08-10 12:49:16 -040055 return NewConst(constant.MakeString(""), t)
Alan Donovan732dbe92013-07-16 13:50:08 -040056 case t.Kind() == types.UnsafePointer:
57 fallthrough
58 case t.Kind() == types.UntypedNil:
59 return nilConst(t)
60 default:
61 panic(fmt.Sprint("zeroConst for unexpected type:", t))
62 }
63 case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature:
64 return nilConst(t)
65 case *types.Named:
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))
69 }
70 panic(fmt.Sprint("zeroConst: unexpected ", t))
71}
72
Alan Donovanb75a5a42014-01-15 13:51:50 -050073func (c *Const) RelString(from *types.Package) string {
74 var s string
Robert Griesemerf50f6c82013-10-09 14:17:25 -070075 if c.Value == nil {
Alan Donovanb75a5a42014-01-15 13:51:50 -050076 s = "nil"
Alan Donovane96c4e22018-08-10 12:49:16 -040077 } else if c.Value.Kind() == constant.String {
78 s = constant.StringVal(c.Value)
Alan Donovan732dbe92013-07-16 13:50:08 -040079 const max = 20
Alan Donovanba9c8012014-03-11 18:24:39 -040080 // TODO(adonovan): don't cut a rune in half.
Alan Donovan732dbe92013-07-16 13:50:08 -040081 if len(s) > max {
82 s = s[:max-3] + "..." // abbreviate
83 }
Alan Donovanb75a5a42014-01-15 13:51:50 -050084 s = strconv.Quote(s)
Alan Donovan732dbe92013-07-16 13:50:08 -040085 } else {
Alan Donovanb75a5a42014-01-15 13:51:50 -050086 s = c.Value.String()
Alan Donovan732dbe92013-07-16 13:50:08 -040087 }
Alan Donovanb75a5a42014-01-15 13:51:50 -050088 return s + ":" + relType(c.Type(), from)
Alan Donovan9fcd20e2013-11-15 09:21:48 -050089}
90
91func (c *Const) Name() string {
Alan Donovanb75a5a42014-01-15 13:51:50 -050092 return c.RelString(nil)
Alan Donovan9fcd20e2013-11-15 09:21:48 -050093}
94
Alan Donovanb75a5a42014-01-15 13:51:50 -050095func (c *Const) String() string {
96 return c.Name()
Alan Donovan732dbe92013-07-16 13:50:08 -040097}
98
99func (c *Const) Type() types.Type {
100 return c.typ
101}
102
103func (c *Const) Referrers() *[]Instruction {
104 return nil
105}
106
Alan Donovan04427c82014-06-11 13:14:06 -0400107func (c *Const) Parent() *Function { return nil }
108
Alan Donovan732dbe92013-07-16 13:50:08 -0400109func (c *Const) Pos() token.Pos {
110 return token.NoPos
111}
112
113// IsNil returns true if this constant represents a typed or untyped nil value.
114func (c *Const) IsNil() bool {
Robert Griesemerf50f6c82013-10-09 14:17:25 -0700115 return c.Value == nil
Alan Donovan732dbe92013-07-16 13:50:08 -0400116}
117
Alan Donovan542ffc72015-12-29 13:06:30 -0500118// TODO(adonovan): move everything below into golang.org/x/tools/go/ssa/interp.
119
Alan Donovan732dbe92013-07-16 13:50:08 -0400120// Int64 returns the numeric value of this constant truncated to fit
121// a signed 64-bit integer.
122//
123func (c *Const) Int64() int64 {
Alan Donovane96c4e22018-08-10 12:49:16 -0400124 switch x := constant.ToInt(c.Value); x.Kind() {
125 case constant.Int:
126 if i, ok := constant.Int64Val(x); ok {
Alan Donovan732dbe92013-07-16 13:50:08 -0400127 return i
128 }
129 return 0
Alan Donovane96c4e22018-08-10 12:49:16 -0400130 case constant.Float:
131 f, _ := constant.Float64Val(x)
Alan Donovan732dbe92013-07-16 13:50:08 -0400132 return int64(f)
133 }
134 panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
135}
136
137// Uint64 returns the numeric value of this constant truncated to fit
138// an unsigned 64-bit integer.
139//
140func (c *Const) Uint64() uint64 {
Alan Donovane96c4e22018-08-10 12:49:16 -0400141 switch x := constant.ToInt(c.Value); x.Kind() {
142 case constant.Int:
143 if u, ok := constant.Uint64Val(x); ok {
Alan Donovan732dbe92013-07-16 13:50:08 -0400144 return u
145 }
146 return 0
Alan Donovane96c4e22018-08-10 12:49:16 -0400147 case constant.Float:
148 f, _ := constant.Float64Val(x)
Alan Donovan732dbe92013-07-16 13:50:08 -0400149 return uint64(f)
150 }
151 panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
152}
153
154// Float64 returns the numeric value of this constant truncated to fit
155// a float64.
156//
157func (c *Const) Float64() float64 {
Alan Donovane96c4e22018-08-10 12:49:16 -0400158 f, _ := constant.Float64Val(c.Value)
Alan Donovan732dbe92013-07-16 13:50:08 -0400159 return f
160}
161
162// Complex128 returns the complex value of this constant truncated to
163// fit a complex128.
164//
165func (c *Const) Complex128() complex128 {
Alan Donovane96c4e22018-08-10 12:49:16 -0400166 re, _ := constant.Float64Val(constant.Real(c.Value))
167 im, _ := constant.Float64Val(constant.Imag(c.Value))
Alan Donovan732dbe92013-07-16 13:50:08 -0400168 return complex(re, im)
169}