]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/ir/const.go
cmd/compile/internal/noder: handle unsafe.Sizeof, etc in unified IR
[gostls13.git] / src / cmd / compile / internal / ir / const.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         "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.
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 // NewOne returns an OLITERAL representing 1 with the given type.
38 func NewOne(pos src.XPos, typ *types.Type) Node {
39         var val constant.Value
40         switch {
41         case typ.IsInteger():
42                 val = intOne
43         case typ.IsFloat():
44                 val = floatOne
45         case typ.IsComplex():
46                 val = complexOne
47         default:
48                 base.FatalfAt(pos, "%v cannot represent 1", typ)
49         }
50
51         return NewBasicLit(pos, typ, val)
52 }
53
54 var (
55         intOne     = constant.MakeInt64(1)
56         floatOne   = constant.ToFloat(intOne)
57         complexOne = constant.ToComplex(intOne)
58 )
59
60 const (
61         // Maximum size in bits for big.Ints before signaling
62         // overflow and also mantissa precision for big.Floats.
63         ConstPrec = 512
64 )
65
66 func BigFloat(v constant.Value) *big.Float {
67         f := new(big.Float)
68         f.SetPrec(ConstPrec)
69         switch u := constant.Val(v).(type) {
70         case int64:
71                 f.SetInt64(u)
72         case *big.Int:
73                 f.SetInt(u)
74         case *big.Float:
75                 f.Set(u)
76         case *big.Rat:
77                 f.SetRat(u)
78         default:
79                 base.Fatalf("unexpected: %v", u)
80         }
81         return f
82 }
83
84 // ConstOverflow reports whether constant value v is too large
85 // to represent with type t.
86 func ConstOverflow(v constant.Value, t *types.Type) bool {
87         switch {
88         case t.IsInteger():
89                 bits := uint(8 * t.Size())
90                 if t.IsUnsigned() {
91                         x, ok := constant.Uint64Val(v)
92                         return !ok || x>>bits != 0
93                 }
94                 x, ok := constant.Int64Val(v)
95                 if x < 0 {
96                         x = ^x
97                 }
98                 return !ok || x>>(bits-1) != 0
99         case t.IsFloat():
100                 switch t.Size() {
101                 case 4:
102                         f, _ := constant.Float32Val(v)
103                         return math.IsInf(float64(f), 0)
104                 case 8:
105                         f, _ := constant.Float64Val(v)
106                         return math.IsInf(f, 0)
107                 }
108         case t.IsComplex():
109                 ft := types.FloatForComplex(t)
110                 return ConstOverflow(constant.Real(v), ft) || ConstOverflow(constant.Imag(v), ft)
111         }
112         base.Fatalf("ConstOverflow: %v, %v", v, t)
113         panic("unreachable")
114 }
115
116 // IsConstNode reports whether n is a Go language constant (as opposed to a
117 // compile-time constant).
118 //
119 // Expressions derived from nil, like string([]byte(nil)), while they
120 // may be known at compile time, are not Go language constants.
121 func IsConstNode(n Node) bool {
122         return n.Op() == OLITERAL
123 }
124
125 func IsSmallIntConst(n Node) bool {
126         if n.Op() == OLITERAL {
127                 v, ok := constant.Int64Val(n.Val())
128                 return ok && int64(int32(v)) == v
129         }
130         return false
131 }