You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
4.2 KiB

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