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 5package ir 6 7import ( 8 "go/constant" 9 "math" 10 11 "cmd/compile/internal/base" 12 "cmd/compile/internal/types" 13) 14 15func 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. 25func 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. 45func 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 59func 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 67func 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 73func 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. 94func NewLiteral(v constant.Value) Node { 95 return NewBasicLit(base.Pos, v) 96} 97 98func 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 115var OKForConst [types.NTYPE]bool 116 117// CanInt64 reports whether it is safe to call Int64Val() on n. 118func 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. 131func 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. 144func 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. 157func 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. 166func 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