Source file src/cmd/compile/internal/ir/val.go

     1  // Copyright 2009 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  
     5  package ir
     6  
     7  import (
     8  	"go/constant"
     9  	"math"
    10  
    11  	"cmd/compile/internal/base"
    12  	"cmd/compile/internal/types"
    13  )
    14  
    15  func ConstType(n Node) constant.Kind {
    16  	if n == nil || n.Op() != OLITERAL {
    17  		return constant.Unknown
    18  	}
    19  	return n.Val().Kind()
    20  }
    21  
    22  // ConstValue returns the constant value stored in n as an interface{}.
    23  // It returns int64s for ints and runes, float64s for floats,
    24  // and complex128s for complex values.
    25  func ConstValue(n Node) interface{} {
    26  	switch v := n.Val(); v.Kind() {
    27  	default:
    28  		base.Fatalf("unexpected constant: %v", v)
    29  		panic("unreachable")
    30  	case constant.Bool:
    31  		return constant.BoolVal(v)
    32  	case constant.String:
    33  		return constant.StringVal(v)
    34  	case constant.Int:
    35  		return IntVal(n.Type(), v)
    36  	case constant.Float:
    37  		return Float64Val(v)
    38  	case constant.Complex:
    39  		return complex(Float64Val(constant.Real(v)), Float64Val(constant.Imag(v)))
    40  	}
    41  }
    42  
    43  // IntVal returns v converted to int64.
    44  // Note: if t is uint64, very large values will be converted to negative int64.
    45  func IntVal(t *types.Type, v constant.Value) int64 {
    46  	if t.IsUnsigned() {
    47  		if x, ok := constant.Uint64Val(v); ok {
    48  			return int64(x)
    49  		}
    50  	} else {
    51  		if x, ok := constant.Int64Val(v); ok {
    52  			return x
    53  		}
    54  	}
    55  	base.Fatalf("%v out of range for %v", v, t)
    56  	panic("unreachable")
    57  }
    58  
    59  func Float64Val(v constant.Value) float64 {
    60  	if x, _ := constant.Float64Val(v); !math.IsInf(x, 0) {
    61  		return x + 0 // avoid -0 (should not be needed, but be conservative)
    62  	}
    63  	base.Fatalf("bad float64 value: %v", v)
    64  	panic("unreachable")
    65  }
    66  
    67  func AssertValidTypeForConst(t *types.Type, v constant.Value) {
    68  	if !ValidTypeForConst(t, v) {
    69  		base.Fatalf("%v (%v) does not represent %v (%v)", t, t.Kind(), v, v.Kind())
    70  	}
    71  }
    72  
    73  func ValidTypeForConst(t *types.Type, v constant.Value) bool {
    74  	switch v.Kind() {
    75  	case constant.Unknown:
    76  		return OKForConst[t.Kind()]
    77  	case constant.Bool:
    78  		return t.IsBoolean()
    79  	case constant.String:
    80  		return t.IsString()
    81  	case constant.Int:
    82  		return t.IsInteger()
    83  	case constant.Float:
    84  		return t.IsFloat()
    85  	case constant.Complex:
    86  		return t.IsComplex()
    87  	}
    88  
    89  	base.Fatalf("unexpected constant kind: %v", v)
    90  	panic("unreachable")
    91  }
    92  
    93  // NewLiteral returns a new untyped constant with value v.
    94  func NewLiteral(v constant.Value) Node {
    95  	return NewBasicLit(base.Pos, v)
    96  }
    97  
    98  func idealType(ct constant.Kind) *types.Type {
    99  	switch ct {
   100  	case constant.String:
   101  		return types.UntypedString
   102  	case constant.Bool:
   103  		return types.UntypedBool
   104  	case constant.Int:
   105  		return types.UntypedInt
   106  	case constant.Float:
   107  		return types.UntypedFloat
   108  	case constant.Complex:
   109  		return types.UntypedComplex
   110  	}
   111  	base.Fatalf("unexpected Ctype: %v", ct)
   112  	return nil
   113  }
   114  
   115  var OKForConst [types.NTYPE]bool
   116  
   117  // CanInt64 reports whether it is safe to call Int64Val() on n.
   118  func CanInt64(n Node) bool {
   119  	if !IsConst(n, constant.Int) {
   120  		return false
   121  	}
   122  
   123  	// if the value inside n cannot be represented as an int64, the
   124  	// return value of Int64 is undefined
   125  	_, ok := constant.Int64Val(n.Val())
   126  	return ok
   127  }
   128  
   129  // Int64Val returns n as an int64.
   130  // n must be an integer or rune constant.
   131  func Int64Val(n Node) int64 {
   132  	if !IsConst(n, constant.Int) {
   133  		base.Fatalf("Int64Val(%v)", n)
   134  	}
   135  	x, ok := constant.Int64Val(n.Val())
   136  	if !ok {
   137  		base.Fatalf("Int64Val(%v)", n)
   138  	}
   139  	return x
   140  }
   141  
   142  // Uint64Val returns n as an uint64.
   143  // n must be an integer or rune constant.
   144  func Uint64Val(n Node) uint64 {
   145  	if !IsConst(n, constant.Int) {
   146  		base.Fatalf("Uint64Val(%v)", n)
   147  	}
   148  	x, ok := constant.Uint64Val(n.Val())
   149  	if !ok {
   150  		base.Fatalf("Uint64Val(%v)", n)
   151  	}
   152  	return x
   153  }
   154  
   155  // BoolVal returns n as a bool.
   156  // n must be a boolean constant.
   157  func BoolVal(n Node) bool {
   158  	if !IsConst(n, constant.Bool) {
   159  		base.Fatalf("BoolVal(%v)", n)
   160  	}
   161  	return constant.BoolVal(n.Val())
   162  }
   163  
   164  // StringVal returns the value of a literal string Node as a string.
   165  // n must be a string constant.
   166  func StringVal(n Node) string {
   167  	if !IsConst(n, constant.String) {
   168  		base.Fatalf("StringVal(%v)", n)
   169  	}
   170  	return constant.StringVal(n.Val())
   171  }
   172  

View as plain text