| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package ir | |
| import ( | |
| "go/constant" | |
| "math" | |
| "math/big" | |
| "cmd/compile/internal/base" | |
| "cmd/compile/internal/types" | |
| ) | |
| func NewBool(b bool) Node { | |
| return NewLiteral(constant.MakeBool(b)) | |
| } | |
| func NewInt(v int64) Node { | |
| return NewLiteral(constant.MakeInt64(v)) | |
| } | |
| func NewString(s string) Node { | |
| return NewLiteral(constant.MakeString(s)) | |
| } | |
| const ( | |
| // Maximum size in bits for big.Ints before signaling | |
| // overflow and also mantissa precision for big.Floats. | |
| ConstPrec = 512 | |
| ) | |
| func BigFloat(v constant.Value) *big.Float { | |
| f := new(big.Float) | |
| f.SetPrec(ConstPrec) | |
| switch u := constant.Val(v).(type) { | |
| case int64: | |
| f.SetInt64(u) | |
| case *big.Int: | |
| f.SetInt(u) | |
| case *big.Float: | |
| f.Set(u) | |
| case *big.Rat: | |
| f.SetRat(u) | |
| default: | |
| base.Fatalf("unexpected: %v", u) | |
| } | |
| return f | |
| } | |
| // ConstOverflow reports whether constant value v is too large | |
| // to represent with type t. | |
| func ConstOverflow(v constant.Value, t *types.Type) bool { | |
| switch { | |
| case t.IsInteger(): | |
| bits := uint(8 * t.Size()) | |
| if t.IsUnsigned() { | |
| x, ok := constant.Uint64Val(v) | |
| return !ok || x>>bits != 0 | |
| } | |
| x, ok := constant.Int64Val(v) | |
| if x < 0 { | |
| x = ^x | |
| } | |
| return !ok || x>>(bits-1) != 0 | |
| case t.IsFloat(): | |
| switch t.Size() { | |
| case 4: | |
| f, _ := constant.Float32Val(v) | |
| return math.IsInf(float64(f), 0) | |
| case 8: | |
| f, _ := constant.Float64Val(v) | |
| return math.IsInf(f, 0) | |
| } | |
| case t.IsComplex(): | |
| ft := types.FloatForComplex(t) | |
| return ConstOverflow(constant.Real(v), ft) || ConstOverflow(constant.Imag(v), ft) | |
| } | |
| base.Fatalf("ConstOverflow: %v, %v", v, t) | |
| panic("unreachable") | |
| } | |
| // IsConstNode reports whether n is a Go language constant (as opposed to a | |
| // compile-time constant). | |
| // | |
| // Expressions derived from nil, like string([]byte(nil)), while they | |
| // may be known at compile time, are not Go language constants. | |
| func IsConstNode(n Node) bool { | |
| return n.Op() == OLITERAL | |
| } | |
| func IsSmallIntConst(n Node) bool { | |
| if n.Op() == OLITERAL { | |
| v, ok := constant.Int64Val(n.Val()) | |
| return ok && int64(int32(v)) == v | |
| } | |
| return false | |
| } |