github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/ir/const.go (about) 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 "math/big" 11 12 "github.com/go-asm/go/cmd/compile/base" 13 "github.com/go-asm/go/cmd/compile/types" 14 "github.com/go-asm/go/cmd/src" 15 ) 16 17 // NewBool returns an OLITERAL representing b as an untyped boolean. 18 func 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. 23 func 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. 28 func 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. 33 func 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. 38 func 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 61 var ( 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. 68 func 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 84 var ( 85 intOne = constant.MakeInt64(1) 86 floatOne = constant.ToFloat(intOne) 87 complexOne = constant.ToComplex(intOne) 88 ) 89 90 const ( 91 // Maximum size in bits for big.Ints before signaling 92 // overflow and also mantissa precision for big.Floats. 93 ConstPrec = 512 94 ) 95 96 func 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. 116 func 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. 151 func IsConstNode(n Node) bool { 152 return n.Op() == OLITERAL 153 } 154 155 func 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 }