aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/importer
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2021-02-01 15:39:42 -0800
committerRobert Griesemer <gri@golang.org>2021-02-03 02:21:24 +0000
commitbb53a5ad43732893da095e82334fb9f0ea912878 (patch)
tree1f3043eef4011a1d28181c947c9ab4e7f84e4126 /src/cmd/compile/internal/importer
parent3f845b3b45a2aba58e3412f31fd1b4bd6c581d04 (diff)
downloadgo-bb53a5ad43732893da095e82334fb9f0ea912878.tar.gz
go-bb53a5ad43732893da095e82334fb9f0ea912878.zip
[dev.typeparams] cmd/compile/internal/importer: adjust importer to match compiler importer
The compiler chooses the literal value export format by type not by constant.Kind. That is, a floating-point constant is always exported as a (big) float value, not a (big) rational value, even though the internal representation may be that of a rational number. (This is a possibility now that the compiler also uses the go/constant package.) Naturally, during import, a floating-point value is read as a float and represented as a (big) float in go/constant. The types2 importer (based on the go/types importer) read the floating-point number elements (mantissa, exponent) but then constructed the float go/constant value through a series of elementary operations, typically leading to a rational, but sometimes even an integer number (e.g. for math.MaxFloat64). There is no problem with that (the value is the same) but if we want to impose bitsize limits on overlarge integer values we quickly run into trouble with large floats represented as integers. This change matches the code importing float literals with the code used by the compiler. Note: At some point we may want to relax the import/export code for constant values and export them by representation rather than by type. As is, we lose accuracy since all floating-point point values, even the ones internally represented as rational numbers end up being exported as floating-point numbers. Change-Id: Ic751b2046a0fd047f751da3d35cbef0a1b5fea3e Reviewed-on: https://go-review.googlesource.com/c/go/+/288632 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
Diffstat (limited to 'src/cmd/compile/internal/importer')
-rw-r--r--src/cmd/compile/internal/importer/iimport.go52
1 files changed, 20 insertions, 32 deletions
diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go
index 6cb8e9377d..33c46a0f90 100644
--- a/src/cmd/compile/internal/importer/iimport.go
+++ b/src/cmd/compile/internal/importer/iimport.go
@@ -17,6 +17,7 @@ import (
"go/constant"
"go/token"
"io"
+ "math/big"
"sort"
)
@@ -324,7 +325,9 @@ func (r *importReader) value() (typ types2.Type, val constant.Value) {
val = constant.MakeString(r.string())
case types2.IsInteger:
- val = r.mpint(b)
+ var x big.Int
+ r.mpint(&x, b)
+ val = constant.Make(&x)
case types2.IsFloat:
val = r.mpfloat(b)
@@ -369,8 +372,8 @@ func intSize(b *types2.Basic) (signed bool, maxBytes uint) {
return
}
-func (r *importReader) mpint(b *types2.Basic) constant.Value {
- signed, maxBytes := intSize(b)
+func (r *importReader) mpint(x *big.Int, typ *types2.Basic) {
+ signed, maxBytes := intSize(typ)
maxSmall := 256 - maxBytes
if signed {
@@ -389,7 +392,8 @@ func (r *importReader) mpint(b *types2.Basic) constant.Value {
v = ^v
}
}
- return constant.MakeInt64(v)
+ x.SetInt64(v)
+ return
}
v := -n
@@ -399,39 +403,23 @@ func (r *importReader) mpint(b *types2.Basic) constant.Value {
if v < 1 || uint(v) > maxBytes {
errorf("weird decoding: %v, %v => %v", n, signed, v)
}
-
- buf := make([]byte, v)
- io.ReadFull(&r.declReader, buf)
-
- // convert to little endian
- // TODO(gri) go/constant should have a more direct conversion function
- // (e.g., once it supports a big.Float based implementation)
- for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
- buf[i], buf[j] = buf[j], buf[i]
- }
-
- x := constant.MakeFromBytes(buf)
+ b := make([]byte, v)
+ io.ReadFull(&r.declReader, b)
+ x.SetBytes(b)
if signed && n&1 != 0 {
- x = constant.UnaryOp(token.SUB, x, 0)
+ x.Neg(x)
}
- return x
}
-func (r *importReader) mpfloat(b *types2.Basic) constant.Value {
- x := r.mpint(b)
- if constant.Sign(x) == 0 {
- return x
- }
-
- exp := r.int64()
- switch {
- case exp > 0:
- x = constant.Shift(x, token.SHL, uint(exp))
- case exp < 0:
- d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
- x = constant.BinaryOp(x, token.QUO, d)
+func (r *importReader) mpfloat(typ *types2.Basic) constant.Value {
+ var mant big.Int
+ r.mpint(&mant, typ)
+ var f big.Float
+ f.SetInt(&mant)
+ if f.Sign() != 0 {
+ f.SetMantExp(&f, int(r.int64()))
}
- return x
+ return constant.Make(&f)
}
func (r *importReader) ident() string {