Skip to content

Commit

Permalink
[dev.typeparams] cmd/compile/internal/importer: adjust importer to ma…
Browse files Browse the repository at this point in the history
…tch 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>
  • Loading branch information
griesemer committed Feb 3, 2021
1 parent 3f845b3 commit bb53a5a
Showing 1 changed file with 20 additions and 32 deletions.
52 changes: 20 additions & 32 deletions src/cmd/compile/internal/importer/iimport.go
Expand Up @@ -17,6 +17,7 @@ import (
"go/constant"
"go/token"
"io"
"math/big"
"sort"
)

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand All @@ -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
Expand All @@ -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 {
Expand Down

0 comments on commit bb53a5a

Please sign in to comment.