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 "math/big" 11 12 "cmd/compile/internal/base" 13 "cmd/compile/internal/types" 14 "cmd/internal/src" 15) 16 17// NewBool returns an OLITERAL representing b as an untyped boolean. 18func NewBool(pos src.XPos, b bool) Node { 19 return NewBasicLit(pos, types.UntypedBool, constant.MakeBool(b)) 20} 21 22// NewInt returns an OLITERAL representing v as an untyped integer. 23func NewInt(pos src.XPos, v int64) Node { 24 return NewBasicLit(pos, types.UntypedInt, constant.MakeInt64(v)) 25} 26 27// NewString returns an OLITERAL representing s as an untyped string. 28func NewString(pos src.XPos, s string) Node { 29 return NewBasicLit(pos, types.UntypedString, constant.MakeString(s)) 30} 31 32// NewUintptr returns an OLITERAL representing v as a uintptr. 33func NewUintptr(pos src.XPos, v int64) Node { 34 return NewBasicLit(pos, types.Types[types.TUINTPTR], constant.MakeInt64(v)) 35} 36 37// NewZero returns a zero value of the given type. 38func NewZero(pos src.XPos, typ *types.Type) Node { 39 switch { 40 case typ.HasNil(): 41 return NewNilExpr(pos, typ) 42 case typ.IsInteger(): 43 return NewBasicLit(pos, typ, intZero) 44 case typ.IsFloat(): 45 return NewBasicLit(pos, typ, floatZero) 46 case typ.IsComplex(): 47 return NewBasicLit(pos, typ, complexZero) 48 case typ.IsBoolean(): 49 return NewBasicLit(pos, typ, constant.MakeBool(false)) 50 case typ.IsString(): 51 return NewBasicLit(pos, typ, constant.MakeString("")) 52 case typ.IsArray() || typ.IsStruct(): 53 // TODO(mdempsky): Return a typechecked expression instead. 54 return NewCompLitExpr(pos, OCOMPLIT, typ, nil) 55 } 56 57 base.FatalfAt(pos, "unexpected type: %v", typ) 58 panic("unreachable") 59} 60 61var ( 62 intZero = constant.MakeInt64(0) 63 floatZero = constant.ToFloat(intZero) 64 complexZero = constant.ToComplex(intZero) 65) 66 67// NewOne returns an OLITERAL representing 1 with the given type. 68func NewOne(pos src.XPos, typ *types.Type) Node { 69 var val constant.Value 70 switch { 71 case typ.IsInteger(): 72 val = intOne 73 case typ.IsFloat(): 74 val = floatOne 75 case typ.IsComplex(): 76 val = complexOne 77 default: 78 base.FatalfAt(pos, "%v cannot represent 1", typ) 79 } 80 81 return NewBasicLit(pos, typ, val) 82} 83 84var ( 85 intOne = constant.MakeInt64(1) 86 floatOne = constant.ToFloat(intOne) 87 complexOne = constant.ToComplex(intOne) 88) 89 90const ( 91 // Maximum size in bits for big.Ints before signaling 92 // overflow and also mantissa precision for big.Floats. 93 ConstPrec = 512 94) 95 96func BigFloat(v constant.Value) *big.Float { 97 f := new(big.Float) 98 f.SetPrec(ConstPrec) 99 switch u := constant.Val(v).(type) { 100 case int64: 101 f.SetInt64(u) 102 case *big.Int: 103 f.SetInt(u) 104 case *big.Float: 105 f.Set(u) 106 case *big.Rat: 107 f.SetRat(u) 108 default: 109 base.Fatalf("unexpected: %v", u) 110 } 111 return f 112} 113 114// ConstOverflow reports whether constant value v is too large 115// to represent with type t. 116func ConstOverflow(v constant.Value, t *types.Type) bool { 117 switch { 118 case t.IsInteger(): 119 bits := uint(8 * t.Size()) 120 if t.IsUnsigned() { 121 x, ok := constant.Uint64Val(v) 122 return !ok || x>>bits != 0 123 } 124 x, ok := constant.Int64Val(v) 125 if x < 0 { 126 x = ^x 127 } 128 return !ok || x>>(bits-1) != 0 129 case t.IsFloat(): 130 switch t.Size() { 131 case 4: 132 f, _ := constant.Float32Val(v) 133 return math.IsInf(float64(f), 0) 134 case 8: 135 f, _ := constant.Float64Val(v) 136 return math.IsInf(f, 0) 137 } 138 case t.IsComplex(): 139 ft := types.FloatForComplex(t) 140 return ConstOverflow(constant.Real(v), ft) || ConstOverflow(constant.Imag(v), ft) 141 } 142 base.Fatalf("ConstOverflow: %v, %v", v, t) 143 panic("unreachable") 144} 145 146// IsConstNode reports whether n is a Go language constant (as opposed to a 147// compile-time constant). 148// 149// Expressions derived from nil, like string([]byte(nil)), while they 150// may be known at compile time, are not Go language constants. 151func IsConstNode(n Node) bool { 152 return n.Op() == OLITERAL 153} 154 155func IsSmallIntConst(n Node) bool { 156 if n.Op() == OLITERAL { 157 v, ok := constant.Int64Val(n.Val()) 158 return ok && int64(int32(v)) == v 159 } 160 return false 161} 162