mirror of
https://github.com/golang/go.git
synced 2024-09-21 10:28:27 +00:00
[dev.regabi] cmd/compile: replace Val with go/constant.Value
This replaces the compiler's legacy constant representation with go/constant, which is used by go/types. This should ease integrating with the new go/types-based type checker in the future. Performance difference is mixed, but there's still room for improvement. name old time/op new time/op delta Template 280ms ± 6% 281ms ± 6% ~ (p=0.488 n=592+587) Unicode 132ms ±11% 129ms ±11% -2.61% (p=0.000 n=592+591) GoTypes 865ms ± 3% 866ms ± 3% +0.16% (p=0.019 n=572+577) Compiler 3.60s ± 3% 3.60s ± 3% ~ (p=0.083 n=578+582) SSA 8.27s ± 2% 8.28s ± 2% +0.14% (p=0.002 n=575+580) Flate 177ms ± 8% 176ms ± 8% ~ (p=0.133 n=580+590) GoParser 238ms ± 7% 237ms ± 6% ~ (p=0.569 n=587+591) Reflect 542ms ± 4% 543ms ± 4% ~ (p=0.064 n=581+579) Tar 244ms ± 6% 244ms ± 6% ~ (p=0.880 n=586+584) XML 322ms ± 5% 322ms ± 5% ~ (p=0.449 n=589+590) LinkCompiler 454ms ± 6% 453ms ± 6% ~ (p=0.249 n=585+583) ExternalLinkCompiler 1.35s ± 4% 1.35s ± 4% ~ (p=0.968 n=590+588) LinkWithoutDebugCompiler 279ms ± 7% 280ms ± 7% ~ (p=0.270 n=589+586) [Geo mean] 535ms 534ms -0.17% name old user-time/op new user-time/op delta Template 599ms ±22% 602ms ±21% ~ (p=0.377 n=588+590) Unicode 410ms ±43% 376ms ±39% -8.36% (p=0.000 n=596+586) GoTypes 1.96s ±15% 1.97s ±17% +0.70% (p=0.031 n=596+594) Compiler 7.47s ± 9% 7.50s ± 8% +0.38% (p=0.031 n=591+583) SSA 16.2s ± 4% 16.2s ± 5% ~ (p=0.617 n=531+531) Flate 298ms ±25% 292ms ±30% -2.14% (p=0.001 n=594+596) GoParser 379ms ±20% 381ms ±21% ~ (p=0.312 n=578+584) Reflect 1.24s ±20% 1.25s ±23% +0.88% (p=0.031 n=592+596) Tar 471ms ±23% 473ms ±21% ~ (p=0.616 n=593+587) XML 674ms ±20% 681ms ±21% +1.03% (p=0.050 n=584+587) LinkCompiler 842ms ±10% 839ms ±10% ~ (p=0.074 n=587+590) ExternalLinkCompiler 1.65s ± 7% 1.65s ± 7% ~ (p=0.767 n=590+585) LinkWithoutDebugCompiler 378ms ±11% 379ms ±12% ~ (p=0.677 n=591+586) [Geo mean] 1.02s 1.02s -0.52% name old alloc/op new alloc/op delta Template 37.4MB ± 0% 37.4MB ± 0% +0.06% (p=0.000 n=589+585) Unicode 29.6MB ± 0% 28.6MB ± 0% -3.11% (p=0.000 n=574+566) GoTypes 120MB ± 0% 120MB ± 0% -0.01% (p=0.000 n=594+593) Compiler 568MB ± 0% 568MB ± 0% -0.02% (p=0.000 n=588+591) SSA 1.45GB ± 0% 1.45GB ± 0% -0.16% (p=0.000 n=596+592) Flate 22.6MB ± 0% 22.5MB ± 0% -0.36% (p=0.000 n=593+595) GoParser 30.1MB ± 0% 30.1MB ± 0% -0.01% (p=0.000 n=590+594) Reflect 77.8MB ± 0% 77.8MB ± 0% ~ (p=0.631 n=584+591) Tar 34.1MB ± 0% 34.1MB ± 0% -0.04% (p=0.000 n=584+588) XML 43.6MB ± 0% 43.6MB ± 0% +0.07% (p=0.000 n=593+591) LinkCompiler 98.6MB ± 0% 98.6MB ± 0% ~ (p=0.096 n=590+589) ExternalLinkCompiler 89.6MB ± 0% 89.6MB ± 0% ~ (p=0.695 n=590+587) LinkWithoutDebugCompiler 57.2MB ± 0% 57.2MB ± 0% ~ (p=0.674 n=590+589) [Geo mean] 78.5MB 78.3MB -0.28% name old allocs/op new allocs/op delta Template 379k ± 0% 380k ± 0% +0.33% (p=0.000 n=593+590) Unicode 344k ± 0% 338k ± 0% -1.67% (p=0.000 n=594+589) GoTypes 1.30M ± 0% 1.31M ± 0% +0.19% (p=0.000 n=592+591) Compiler 5.40M ± 0% 5.41M ± 0% +0.23% (p=0.000 n=587+585) SSA 14.2M ± 0% 14.2M ± 0% +0.08% (p=0.000 n=594+591) Flate 231k ± 0% 230k ± 0% -0.42% (p=0.000 n=588+589) GoParser 314k ± 0% 315k ± 0% +0.16% (p=0.000 n=587+594) Reflect 975k ± 0% 976k ± 0% +0.10% (p=0.000 n=590+594) Tar 344k ± 0% 345k ± 0% +0.24% (p=0.000 n=595+590) XML 422k ± 0% 424k ± 0% +0.57% (p=0.000 n=590+589) LinkCompiler 538k ± 0% 538k ± 0% -0.00% (p=0.045 n=592+587) ExternalLinkCompiler 593k ± 0% 593k ± 0% ~ (p=0.171 n=588+587) LinkWithoutDebugCompiler 172k ± 0% 172k ± 0% ~ (p=0.996 n=590+585) [Geo mean] 685k 685k -0.02% name old maxRSS/op new maxRSS/op delta Template 53.7M ± 8% 53.8M ± 8% ~ (p=0.666 n=576+574) Unicode 54.4M ±12% 55.0M ±10% +1.15% (p=0.000 n=591+588) GoTypes 95.1M ± 4% 95.1M ± 4% ~ (p=0.948 n=589+591) Compiler 334M ± 6% 334M ± 6% ~ (p=0.875 n=592+593) SSA 792M ± 5% 791M ± 5% ~ (p=0.067 n=592+591) Flate 39.9M ±11% 40.0M ±10% ~ (p=0.131 n=596+596) GoParser 45.2M ±11% 45.3M ±11% ~ (p=0.353 n=592+590) Reflect 76.1M ± 5% 76.2M ± 5% ~ (p=0.114 n=594+594) Tar 49.4M ±10% 49.6M ± 9% +0.57% (p=0.015 n=590+593) XML 57.4M ± 9% 57.7M ± 8% +0.67% (p=0.000 n=592+580) LinkCompiler 183M ± 2% 183M ± 2% ~ (p=0.229 n=587+591) ExternalLinkCompiler 187M ± 2% 187M ± 3% ~ (p=0.362 n=571+562) LinkWithoutDebugCompiler 143M ± 3% 143M ± 3% ~ (p=0.350 n=584+586) [Geo mean] 103M 103M +0.23% Passes toolstash-check. Fixes #4617. Change-Id: Id4f6759b4afc5e002770091d0d4f6e272ee6cbdd Reviewed-on: https://go-review.googlesource.com/c/go/+/272654 Reviewed-by: Robert Griesemer <gri@golang.org> Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
6826287c6b
commit
7d72951229
@ -22,8 +22,6 @@ package main_test
|
||||
var knownFormats = map[string]string{
|
||||
"*bytes.Buffer %s": "",
|
||||
"*cmd/compile/internal/gc.EscLocation %v": "",
|
||||
"*cmd/compile/internal/gc.Mpflt %v": "",
|
||||
"*cmd/compile/internal/gc.Mpint %v": "",
|
||||
"*cmd/compile/internal/gc.Node %#v": "",
|
||||
"*cmd/compile/internal/gc.Node %+S": "",
|
||||
"*cmd/compile/internal/gc.Node %+v": "",
|
||||
@ -60,9 +58,7 @@ var knownFormats = map[string]string{
|
||||
"*cmd/internal/obj.Addr %v": "",
|
||||
"*cmd/internal/obj.LSym %v": "",
|
||||
"*math/big.Float %f": "",
|
||||
"*math/big.Int %#x": "",
|
||||
"*math/big.Int %s": "",
|
||||
"*math/big.Int %v": "",
|
||||
"[16]byte %x": "",
|
||||
"[]*cmd/compile/internal/ssa.Block %v": "",
|
||||
"[]*cmd/compile/internal/ssa.Value %v": "",
|
||||
@ -91,9 +87,6 @@ var knownFormats = map[string]string{
|
||||
"cmd/compile/internal/gc.Nodes %v": "",
|
||||
"cmd/compile/internal/gc.Op %#v": "",
|
||||
"cmd/compile/internal/gc.Op %v": "",
|
||||
"cmd/compile/internal/gc.Val %#v": "",
|
||||
"cmd/compile/internal/gc.Val %T": "",
|
||||
"cmd/compile/internal/gc.Val %v": "",
|
||||
"cmd/compile/internal/gc.fmtMode %d": "",
|
||||
"cmd/compile/internal/gc.initKind %d": "",
|
||||
"cmd/compile/internal/gc.itag %v": "",
|
||||
@ -134,10 +127,10 @@ var knownFormats = map[string]string{
|
||||
"error %v": "",
|
||||
"float64 %.2f": "",
|
||||
"float64 %.3f": "",
|
||||
"float64 %.6g": "",
|
||||
"float64 %g": "",
|
||||
"go/constant.Kind %d": "",
|
||||
"go/constant.Kind %v": "",
|
||||
"go/constant.Value %#v": "",
|
||||
"go/constant.Value %v": "",
|
||||
"int %#x": "",
|
||||
"int %-12d": "",
|
||||
"int %-6d": "",
|
||||
@ -155,7 +148,6 @@ var knownFormats = map[string]string{
|
||||
"int32 %v": "",
|
||||
"int32 %x": "",
|
||||
"int64 %#x": "",
|
||||
"int64 %+d": "",
|
||||
"int64 %-10d": "",
|
||||
"int64 %.5d": "",
|
||||
"int64 %d": "",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -553,7 +553,7 @@ func structfield(n *Node) *types.Field {
|
||||
f.Embedded = 1
|
||||
}
|
||||
if n.HasVal() {
|
||||
f.Note = n.Val().U.(string)
|
||||
f.Note = constant.StringVal(n.Val())
|
||||
}
|
||||
|
||||
lineno = lno
|
||||
@ -638,7 +638,7 @@ func interfacefield(n *Node) *types.Field {
|
||||
Fatalf("interfacefield: oops %v\n", n)
|
||||
}
|
||||
|
||||
if n.Val().Kind() != constant.Unknown {
|
||||
if n.HasVal() {
|
||||
yyerror("interface method cannot have annotation")
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op, ctxt Class, t
|
||||
|
||||
// importconst declares symbol s as an imported constant with type t and value val.
|
||||
// ipkg is the package being imported
|
||||
func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val Val) {
|
||||
func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val constant.Value) {
|
||||
n := importobj(ipkg, pos, s, OLITERAL, PEXTERN, t)
|
||||
if n == nil { // TODO: Check that value matches.
|
||||
return
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/src"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -334,7 +335,7 @@ func (m fmtMode) prepareArgs(args []interface{}) {
|
||||
args[i] = (*fmtSymErr)(arg)
|
||||
case Nodes:
|
||||
args[i] = fmtNodesErr(arg)
|
||||
case Val, int32, int64, string, types.EType:
|
||||
case int32, int64, string, types.EType, constant.Value:
|
||||
// OK: printing these types doesn't depend on mode
|
||||
default:
|
||||
Fatalf("mode.prepareArgs type %T", arg)
|
||||
@ -353,7 +354,7 @@ func (m fmtMode) prepareArgs(args []interface{}) {
|
||||
args[i] = (*fmtSymDbg)(arg)
|
||||
case Nodes:
|
||||
args[i] = fmtNodesDbg(arg)
|
||||
case Val, int32, int64, string, types.EType:
|
||||
case int32, int64, string, types.EType, constant.Value:
|
||||
// OK: printing these types doesn't depend on mode
|
||||
default:
|
||||
Fatalf("mode.prepareArgs type %T", arg)
|
||||
@ -372,7 +373,7 @@ func (m fmtMode) prepareArgs(args []interface{}) {
|
||||
args[i] = (*fmtSymTypeId)(arg)
|
||||
case Nodes:
|
||||
args[i] = fmtNodesTypeId(arg)
|
||||
case Val, int32, int64, string, types.EType:
|
||||
case int32, int64, string, types.EType, constant.Value:
|
||||
// OK: printing these types doesn't depend on mode
|
||||
default:
|
||||
Fatalf("mode.prepareArgs type %T", arg)
|
||||
@ -391,7 +392,7 @@ func (m fmtMode) prepareArgs(args []interface{}) {
|
||||
args[i] = (*fmtSymTypeIdName)(arg)
|
||||
case Nodes:
|
||||
args[i] = fmtNodesTypeIdName(arg)
|
||||
case Val, int32, int64, string, types.EType:
|
||||
case int32, int64, string, types.EType, constant.Value:
|
||||
// OK: printing these types doesn't depend on mode
|
||||
default:
|
||||
Fatalf("mode.prepareArgs type %T", arg)
|
||||
@ -513,51 +514,37 @@ func (n *Node) jconv(s fmt.State, flag FmtFlag) {
|
||||
}
|
||||
}
|
||||
|
||||
func (v Val) Format(s fmt.State, verb rune) {
|
||||
switch verb {
|
||||
case 'v':
|
||||
v.vconv(s, fmtFlag(s, verb))
|
||||
func vconv(v constant.Value, flag FmtFlag) string {
|
||||
if flag&FmtSharp == 0 && v.Kind() == constant.Complex {
|
||||
real, imag := constant.Real(v), constant.Imag(v)
|
||||
|
||||
default:
|
||||
fmt.Fprintf(s, "%%!%c(Val=%T)", verb, v)
|
||||
var re string
|
||||
sre := constant.Sign(real)
|
||||
if sre != 0 {
|
||||
re = real.String()
|
||||
}
|
||||
|
||||
var im string
|
||||
sim := constant.Sign(imag)
|
||||
if sim != 0 {
|
||||
im = imag.String()
|
||||
}
|
||||
|
||||
switch {
|
||||
case sre == 0 && sim == 0:
|
||||
return "0"
|
||||
case sre == 0:
|
||||
return im + "i"
|
||||
case sim == 0:
|
||||
return re
|
||||
case sim < 0:
|
||||
return fmt.Sprintf("(%s%si)", re, im)
|
||||
default:
|
||||
return fmt.Sprintf("(%s+%si)", re, im)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (v Val) vconv(s fmt.State, flag FmtFlag) {
|
||||
switch u := v.U.(type) {
|
||||
case *Mpint:
|
||||
if flag&FmtSharp != 0 {
|
||||
fmt.Fprint(s, u.String())
|
||||
return
|
||||
}
|
||||
fmt.Fprint(s, u.GoString())
|
||||
return
|
||||
|
||||
case *Mpflt:
|
||||
if flag&FmtSharp != 0 {
|
||||
fmt.Fprint(s, u.String())
|
||||
return
|
||||
}
|
||||
fmt.Fprint(s, u.GoString())
|
||||
return
|
||||
|
||||
case *Mpcplx:
|
||||
if flag&FmtSharp != 0 {
|
||||
fmt.Fprint(s, u.String())
|
||||
return
|
||||
}
|
||||
fmt.Fprint(s, u.GoString())
|
||||
return
|
||||
|
||||
case string:
|
||||
fmt.Fprint(s, strconv.Quote(u))
|
||||
|
||||
case bool:
|
||||
fmt.Fprint(s, u)
|
||||
|
||||
default:
|
||||
fmt.Fprintf(s, "<ctype=%d>", v.Kind())
|
||||
}
|
||||
return v.String()
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1333,8 +1320,12 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
|
||||
}
|
||||
|
||||
if n.Type == types.UntypedRune {
|
||||
u := n.Val().U.(*Mpint)
|
||||
switch x := u.Int64(); {
|
||||
switch x, ok := constant.Int64Val(n.Val()); {
|
||||
case !ok:
|
||||
fallthrough
|
||||
default:
|
||||
fmt.Fprintf(s, "('\\x00' + %v)", n.Val())
|
||||
|
||||
case ' ' <= x && x < utf8.RuneSelf && x != '\\' && x != '\'':
|
||||
fmt.Fprintf(s, "'%c'", int(x))
|
||||
|
||||
@ -1343,12 +1334,9 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
|
||||
|
||||
case 0 <= x && x <= utf8.MaxRune:
|
||||
fmt.Fprintf(s, "'\\U%08x'", uint64(x))
|
||||
|
||||
default:
|
||||
fmt.Fprintf(s, "('\\x00' + %v)", u)
|
||||
}
|
||||
} else {
|
||||
mode.Fprintf(s, "%v", n.Val())
|
||||
fmt.Fprint(s, vconv(n.Val(), fmtFlag(s, 'v')))
|
||||
}
|
||||
|
||||
if needUnparen {
|
||||
|
@ -178,14 +178,6 @@ var (
|
||||
iscmp [OEND]bool
|
||||
)
|
||||
|
||||
var minintval [NTYPE]*Mpint
|
||||
|
||||
var maxintval [NTYPE]*Mpint
|
||||
|
||||
var minfltval [NTYPE]*Mpflt
|
||||
|
||||
var maxfltval [NTYPE]*Mpflt
|
||||
|
||||
var xtop []*Node
|
||||
|
||||
var exportlist []*Node
|
||||
|
@ -777,7 +777,7 @@ func constTypeOf(typ *types.Type) constant.Kind {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (w *exportWriter) value(typ *types.Type, v Val) {
|
||||
func (w *exportWriter) value(typ *types.Type, v constant.Value) {
|
||||
assertRepresents(typ, v)
|
||||
w.typ(typ)
|
||||
|
||||
@ -788,17 +788,16 @@ func (w *exportWriter) value(typ *types.Type, v Val) {
|
||||
|
||||
switch constTypeOf(typ) {
|
||||
case constant.Bool:
|
||||
w.bool(v.U.(bool))
|
||||
w.bool(constant.BoolVal(v))
|
||||
case constant.String:
|
||||
w.string(v.U.(string))
|
||||
w.string(constant.StringVal(v))
|
||||
case constant.Int:
|
||||
w.mpint(&v.U.(*Mpint).Val, typ)
|
||||
w.mpint(v, typ)
|
||||
case constant.Float:
|
||||
w.mpfloat(&v.U.(*Mpflt).Val, typ)
|
||||
w.mpfloat(v, typ)
|
||||
case constant.Complex:
|
||||
x := v.U.(*Mpcplx)
|
||||
w.mpfloat(&x.Real.Val, typ)
|
||||
w.mpfloat(&x.Imag.Val, typ)
|
||||
w.mpfloat(constant.Real(v), typ)
|
||||
w.mpfloat(constant.Imag(v), typ)
|
||||
}
|
||||
}
|
||||
|
||||
@ -847,15 +846,19 @@ func intSize(typ *types.Type) (signed bool, maxBytes uint) {
|
||||
// single byte.
|
||||
//
|
||||
// TODO(mdempsky): Is this level of complexity really worthwhile?
|
||||
func (w *exportWriter) mpint(x *big.Int, typ *types.Type) {
|
||||
func (w *exportWriter) mpint(x constant.Value, typ *types.Type) {
|
||||
signed, maxBytes := intSize(typ)
|
||||
|
||||
negative := x.Sign() < 0
|
||||
negative := constant.Sign(x) < 0
|
||||
if !signed && negative {
|
||||
Fatalf("negative unsigned integer; type %v, value %v", typ, x)
|
||||
}
|
||||
|
||||
b := x.Bytes()
|
||||
b := constant.Bytes(x) // little endian
|
||||
for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
if len(b) > 0 && b[0] == 0 {
|
||||
Fatalf("leading zeros")
|
||||
}
|
||||
@ -910,7 +913,8 @@ func (w *exportWriter) mpint(x *big.Int, typ *types.Type) {
|
||||
// mantissa is an integer. The value is written out as mantissa (as a
|
||||
// multi-precision integer) and then the exponent, except exponent is
|
||||
// omitted if mantissa is zero.
|
||||
func (w *exportWriter) mpfloat(f *big.Float, typ *types.Type) {
|
||||
func (w *exportWriter) mpfloat(v constant.Value, typ *types.Type) {
|
||||
f := bigFloatVal(v)
|
||||
if f.IsInf() {
|
||||
Fatalf("infinite constant")
|
||||
}
|
||||
@ -928,7 +932,7 @@ func (w *exportWriter) mpfloat(f *big.Float, typ *types.Type) {
|
||||
if acc != big.Exact {
|
||||
Fatalf("mantissa scaling failed for %f (%s)", f, acc)
|
||||
}
|
||||
w.mpint(manti, typ)
|
||||
w.mpint(makeInt(manti), typ)
|
||||
if manti.Sign() != 0 {
|
||||
w.int64(exp)
|
||||
}
|
||||
|
@ -356,27 +356,24 @@ func (r *importReader) doDecl(n *Node) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *importReader) value(typ *types.Type) (v Val) {
|
||||
func (p *importReader) value(typ *types.Type) constant.Value {
|
||||
switch constTypeOf(typ) {
|
||||
case constant.Bool:
|
||||
v.U = p.bool()
|
||||
return constant.MakeBool(p.bool())
|
||||
case constant.String:
|
||||
v.U = p.string()
|
||||
return constant.MakeString(p.string())
|
||||
case constant.Int:
|
||||
x := new(Mpint)
|
||||
p.mpint(&x.Val, typ)
|
||||
v.U = x
|
||||
var i big.Int
|
||||
p.mpint(&i, typ)
|
||||
return makeInt(&i)
|
||||
case constant.Float:
|
||||
x := newMpflt()
|
||||
p.float(x, typ)
|
||||
v.U = x
|
||||
return p.float(typ)
|
||||
case constant.Complex:
|
||||
x := newMpcmplx()
|
||||
p.float(&x.Real, typ)
|
||||
p.float(&x.Imag, typ)
|
||||
v.U = x
|
||||
return makeComplex(p.float(typ), p.float(typ))
|
||||
}
|
||||
return
|
||||
|
||||
Fatalf("unexpected value type: %v", typ)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func (p *importReader) mpint(x *big.Int, typ *types.Type) {
|
||||
@ -418,14 +415,15 @@ func (p *importReader) mpint(x *big.Int, typ *types.Type) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *importReader) float(x *Mpflt, typ *types.Type) {
|
||||
func (p *importReader) float(typ *types.Type) constant.Value {
|
||||
var mant big.Int
|
||||
p.mpint(&mant, typ)
|
||||
m := x.Val.SetInt(&mant)
|
||||
if m.Sign() == 0 {
|
||||
return
|
||||
var f big.Float
|
||||
f.SetInt(&mant)
|
||||
if f.Sign() != 0 {
|
||||
f.SetMantExp(&f, int(p.int64()))
|
||||
}
|
||||
m.SetMantExp(m, int(p.int64()))
|
||||
return constant.Make(&f)
|
||||
}
|
||||
|
||||
func (r *importReader) ident() *types.Sym {
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"cmd/internal/sys"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"internal/goversion"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@ -1135,13 +1136,13 @@ func loadsys() {
|
||||
// imported so far.
|
||||
var myheight int
|
||||
|
||||
func importfile(f *Val) *types.Pkg {
|
||||
path_, ok := f.U.(string)
|
||||
if !ok {
|
||||
func importfile(f constant.Value) *types.Pkg {
|
||||
if f.Kind() != constant.String {
|
||||
yyerror("import path must be a string")
|
||||
return nil
|
||||
}
|
||||
|
||||
path_ := constant.StringVal(f)
|
||||
if len(path_) == 0 {
|
||||
yyerror("import path is empty")
|
||||
return nil
|
||||
|
@ -1,357 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// implements float arithmetic
|
||||
|
||||
const (
|
||||
// Maximum size in bits for Mpints before signalling
|
||||
// overflow and also mantissa precision for Mpflts.
|
||||
Mpprec = 512
|
||||
// Turn on for constant arithmetic debugging output.
|
||||
Mpdebug = false
|
||||
)
|
||||
|
||||
// Mpflt represents a floating-point constant.
|
||||
type Mpflt struct {
|
||||
Val big.Float
|
||||
}
|
||||
|
||||
// Mpcplx represents a complex constant.
|
||||
type Mpcplx struct {
|
||||
Real Mpflt
|
||||
Imag Mpflt
|
||||
}
|
||||
|
||||
// Use newMpflt (not new(Mpflt)!) to get the correct default precision.
|
||||
func newMpflt() *Mpflt {
|
||||
var a Mpflt
|
||||
a.Val.SetPrec(Mpprec)
|
||||
return &a
|
||||
}
|
||||
|
||||
// Use newMpcmplx (not new(Mpcplx)!) to get the correct default precision.
|
||||
func newMpcmplx() *Mpcplx {
|
||||
var a Mpcplx
|
||||
a.Real = *newMpflt()
|
||||
a.Imag = *newMpflt()
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a *Mpflt) SetInt(b *Mpint) {
|
||||
if b.checkOverflow(0) {
|
||||
// sign doesn't really matter but copy anyway
|
||||
a.Val.SetInf(b.Val.Sign() < 0)
|
||||
return
|
||||
}
|
||||
a.Val.SetInt(&b.Val)
|
||||
}
|
||||
|
||||
func (a *Mpflt) Set(b *Mpflt) {
|
||||
a.Val.Set(&b.Val)
|
||||
}
|
||||
|
||||
func (a *Mpflt) Add(b *Mpflt) {
|
||||
if Mpdebug {
|
||||
fmt.Printf("\n%v + %v", a, b)
|
||||
}
|
||||
|
||||
a.Val.Add(&a.Val, &b.Val)
|
||||
|
||||
if Mpdebug {
|
||||
fmt.Printf(" = %v\n\n", a)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Mpflt) AddFloat64(c float64) {
|
||||
var b Mpflt
|
||||
|
||||
b.SetFloat64(c)
|
||||
a.Add(&b)
|
||||
}
|
||||
|
||||
func (a *Mpflt) Sub(b *Mpflt) {
|
||||
if Mpdebug {
|
||||
fmt.Printf("\n%v - %v", a, b)
|
||||
}
|
||||
|
||||
a.Val.Sub(&a.Val, &b.Val)
|
||||
|
||||
if Mpdebug {
|
||||
fmt.Printf(" = %v\n\n", a)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Mpflt) Mul(b *Mpflt) {
|
||||
if Mpdebug {
|
||||
fmt.Printf("%v\n * %v\n", a, b)
|
||||
}
|
||||
|
||||
a.Val.Mul(&a.Val, &b.Val)
|
||||
|
||||
if Mpdebug {
|
||||
fmt.Printf(" = %v\n\n", a)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Mpflt) MulFloat64(c float64) {
|
||||
var b Mpflt
|
||||
|
||||
b.SetFloat64(c)
|
||||
a.Mul(&b)
|
||||
}
|
||||
|
||||
func (a *Mpflt) Quo(b *Mpflt) {
|
||||
if Mpdebug {
|
||||
fmt.Printf("%v\n / %v\n", a, b)
|
||||
}
|
||||
|
||||
a.Val.Quo(&a.Val, &b.Val)
|
||||
|
||||
if Mpdebug {
|
||||
fmt.Printf(" = %v\n\n", a)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Mpflt) Cmp(b *Mpflt) int {
|
||||
return a.Val.Cmp(&b.Val)
|
||||
}
|
||||
|
||||
func (a *Mpflt) CmpFloat64(c float64) int {
|
||||
if c == 0 {
|
||||
return a.Val.Sign() // common case shortcut
|
||||
}
|
||||
return a.Val.Cmp(big.NewFloat(c))
|
||||
}
|
||||
|
||||
func (a *Mpflt) Float64() float64 {
|
||||
x, _ := a.Val.Float64()
|
||||
|
||||
// check for overflow
|
||||
if math.IsInf(x, 0) && Errors() == 0 {
|
||||
Fatalf("ovf in Mpflt Float64")
|
||||
}
|
||||
|
||||
return x + 0 // avoid -0 (should not be needed, but be conservative)
|
||||
}
|
||||
|
||||
func (a *Mpflt) Float32() float64 {
|
||||
x32, _ := a.Val.Float32()
|
||||
x := float64(x32)
|
||||
|
||||
// check for overflow
|
||||
if math.IsInf(x, 0) && Errors() == 0 {
|
||||
Fatalf("ovf in Mpflt Float32")
|
||||
}
|
||||
|
||||
return x + 0 // avoid -0 (should not be needed, but be conservative)
|
||||
}
|
||||
|
||||
func (a *Mpflt) SetFloat64(c float64) {
|
||||
if Mpdebug {
|
||||
fmt.Printf("\nconst %g", c)
|
||||
}
|
||||
|
||||
// convert -0 to 0
|
||||
if c == 0 {
|
||||
c = 0
|
||||
}
|
||||
a.Val.SetFloat64(c)
|
||||
|
||||
if Mpdebug {
|
||||
fmt.Printf(" = %v\n", a)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Mpflt) Neg() {
|
||||
// avoid -0
|
||||
if a.Val.Sign() != 0 {
|
||||
a.Val.Neg(&a.Val)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Mpflt) SetString(as string) {
|
||||
f, _, err := a.Val.Parse(as, 0)
|
||||
if err != nil {
|
||||
yyerror("malformed constant: %s (%v)", as, err)
|
||||
a.Val.SetFloat64(0)
|
||||
return
|
||||
}
|
||||
|
||||
if f.IsInf() {
|
||||
yyerror("constant too large: %s", as)
|
||||
a.Val.SetFloat64(0)
|
||||
return
|
||||
}
|
||||
|
||||
// -0 becomes 0
|
||||
if f.Sign() == 0 && f.Signbit() {
|
||||
a.Val.SetFloat64(0)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Mpflt) String() string {
|
||||
return f.Val.Text('b', 0)
|
||||
}
|
||||
|
||||
func (fvp *Mpflt) GoString() string {
|
||||
// determine sign
|
||||
sign := ""
|
||||
f := &fvp.Val
|
||||
if f.Sign() < 0 {
|
||||
sign = "-"
|
||||
f = new(big.Float).Abs(f)
|
||||
}
|
||||
|
||||
// Don't try to convert infinities (will not terminate).
|
||||
if f.IsInf() {
|
||||
return sign + "Inf"
|
||||
}
|
||||
|
||||
// Use exact fmt formatting if in float64 range (common case):
|
||||
// proceed if f doesn't underflow to 0 or overflow to inf.
|
||||
if x, _ := f.Float64(); f.Sign() == 0 == (x == 0) && !math.IsInf(x, 0) {
|
||||
return fmt.Sprintf("%s%.6g", sign, x)
|
||||
}
|
||||
|
||||
// Out of float64 range. Do approximate manual to decimal
|
||||
// conversion to avoid precise but possibly slow Float
|
||||
// formatting.
|
||||
// f = mant * 2**exp
|
||||
var mant big.Float
|
||||
exp := f.MantExp(&mant) // 0.5 <= mant < 1.0
|
||||
|
||||
// approximate float64 mantissa m and decimal exponent d
|
||||
// f ~ m * 10**d
|
||||
m, _ := mant.Float64() // 0.5 <= m < 1.0
|
||||
d := float64(exp) * (math.Ln2 / math.Ln10) // log_10(2)
|
||||
|
||||
// adjust m for truncated (integer) decimal exponent e
|
||||
e := int64(d)
|
||||
m *= math.Pow(10, d-float64(e))
|
||||
|
||||
// ensure 1 <= m < 10
|
||||
switch {
|
||||
case m < 1-0.5e-6:
|
||||
// The %.6g format below rounds m to 5 digits after the
|
||||
// decimal point. Make sure that m*10 < 10 even after
|
||||
// rounding up: m*10 + 0.5e-5 < 10 => m < 1 - 0.5e6.
|
||||
m *= 10
|
||||
e--
|
||||
case m >= 10:
|
||||
m /= 10
|
||||
e++
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s%.6ge%+d", sign, m, e)
|
||||
}
|
||||
|
||||
// complex multiply v *= rv
|
||||
// (a, b) * (c, d) = (a*c - b*d, b*c + a*d)
|
||||
func (v *Mpcplx) Mul(rv *Mpcplx) {
|
||||
var ac, ad, bc, bd Mpflt
|
||||
|
||||
ac.Set(&v.Real)
|
||||
ac.Mul(&rv.Real) // ac
|
||||
|
||||
bd.Set(&v.Imag)
|
||||
bd.Mul(&rv.Imag) // bd
|
||||
|
||||
bc.Set(&v.Imag)
|
||||
bc.Mul(&rv.Real) // bc
|
||||
|
||||
ad.Set(&v.Real)
|
||||
ad.Mul(&rv.Imag) // ad
|
||||
|
||||
v.Real.Set(&ac)
|
||||
v.Real.Sub(&bd) // ac-bd
|
||||
|
||||
v.Imag.Set(&bc)
|
||||
v.Imag.Add(&ad) // bc+ad
|
||||
}
|
||||
|
||||
// complex divide v /= rv
|
||||
// (a, b) / (c, d) = ((a*c + b*d), (b*c - a*d))/(c*c + d*d)
|
||||
func (v *Mpcplx) Div(rv *Mpcplx) bool {
|
||||
if rv.Real.CmpFloat64(0) == 0 && rv.Imag.CmpFloat64(0) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var ac, ad, bc, bd, cc_plus_dd Mpflt
|
||||
|
||||
cc_plus_dd.Set(&rv.Real)
|
||||
cc_plus_dd.Mul(&rv.Real) // cc
|
||||
|
||||
ac.Set(&rv.Imag)
|
||||
ac.Mul(&rv.Imag) // dd
|
||||
cc_plus_dd.Add(&ac) // cc+dd
|
||||
|
||||
// We already checked that c and d are not both zero, but we can't
|
||||
// assume that c²+d² != 0 follows, because for tiny values of c
|
||||
// and/or d c²+d² can underflow to zero. Check that c²+d² is
|
||||
// nonzero, return if it's not.
|
||||
if cc_plus_dd.CmpFloat64(0) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
ac.Set(&v.Real)
|
||||
ac.Mul(&rv.Real) // ac
|
||||
|
||||
bd.Set(&v.Imag)
|
||||
bd.Mul(&rv.Imag) // bd
|
||||
|
||||
bc.Set(&v.Imag)
|
||||
bc.Mul(&rv.Real) // bc
|
||||
|
||||
ad.Set(&v.Real)
|
||||
ad.Mul(&rv.Imag) // ad
|
||||
|
||||
v.Real.Set(&ac)
|
||||
v.Real.Add(&bd) // ac+bd
|
||||
v.Real.Quo(&cc_plus_dd) // (ac+bd)/(cc+dd)
|
||||
|
||||
v.Imag.Set(&bc)
|
||||
v.Imag.Sub(&ad) // bc-ad
|
||||
v.Imag.Quo(&cc_plus_dd) // (bc+ad)/(cc+dd)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (v *Mpcplx) String() string {
|
||||
return fmt.Sprintf("(%s+%si)", v.Real.String(), v.Imag.String())
|
||||
}
|
||||
|
||||
func (v *Mpcplx) GoString() string {
|
||||
var re string
|
||||
sre := v.Real.CmpFloat64(0)
|
||||
if sre != 0 {
|
||||
re = v.Real.GoString()
|
||||
}
|
||||
|
||||
var im string
|
||||
sim := v.Imag.CmpFloat64(0)
|
||||
if sim != 0 {
|
||||
im = v.Imag.GoString()
|
||||
}
|
||||
|
||||
switch {
|
||||
case sre == 0 && sim == 0:
|
||||
return "0"
|
||||
case sre == 0:
|
||||
return im + "i"
|
||||
case sim == 0:
|
||||
return re
|
||||
case sim < 0:
|
||||
return fmt.Sprintf("(%s%si)", re, im)
|
||||
default:
|
||||
return fmt.Sprintf("(%s+%si)", re, im)
|
||||
}
|
||||
}
|
@ -1,303 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// implements integer arithmetic
|
||||
|
||||
// Mpint represents an integer constant.
|
||||
type Mpint struct {
|
||||
Val big.Int
|
||||
Ovf bool // set if Val overflowed compiler limit (sticky)
|
||||
}
|
||||
|
||||
func (a *Mpint) SetOverflow() {
|
||||
a.Val.SetUint64(1) // avoid spurious div-zero errors
|
||||
a.Ovf = true
|
||||
}
|
||||
|
||||
func (a *Mpint) checkOverflow(extra int) bool {
|
||||
// We don't need to be precise here, any reasonable upper limit would do.
|
||||
// For now, use existing limit so we pass all the tests unchanged.
|
||||
if a.Val.BitLen()+extra > Mpprec {
|
||||
a.SetOverflow()
|
||||
}
|
||||
return a.Ovf
|
||||
}
|
||||
|
||||
func (a *Mpint) Set(b *Mpint) {
|
||||
a.Val.Set(&b.Val)
|
||||
}
|
||||
|
||||
func (a *Mpint) SetFloat(b *Mpflt) bool {
|
||||
// avoid converting huge floating-point numbers to integers
|
||||
// (2*Mpprec is large enough to permit all tests to pass)
|
||||
if b.Val.MantExp(nil) > 2*Mpprec {
|
||||
a.SetOverflow()
|
||||
return false
|
||||
}
|
||||
|
||||
if _, acc := b.Val.Int(&a.Val); acc == big.Exact {
|
||||
return true
|
||||
}
|
||||
|
||||
const delta = 16 // a reasonably small number of bits > 0
|
||||
var t big.Float
|
||||
t.SetPrec(Mpprec - delta)
|
||||
|
||||
// try rounding down a little
|
||||
t.SetMode(big.ToZero)
|
||||
t.Set(&b.Val)
|
||||
if _, acc := t.Int(&a.Val); acc == big.Exact {
|
||||
return true
|
||||
}
|
||||
|
||||
// try rounding up a little
|
||||
t.SetMode(big.AwayFromZero)
|
||||
t.Set(&b.Val)
|
||||
if _, acc := t.Int(&a.Val); acc == big.Exact {
|
||||
return true
|
||||
}
|
||||
|
||||
a.Ovf = false
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *Mpint) Add(b *Mpint) {
|
||||
if a.Ovf || b.Ovf {
|
||||
if Errors() == 0 {
|
||||
Fatalf("ovf in Mpint Add")
|
||||
}
|
||||
a.SetOverflow()
|
||||
return
|
||||
}
|
||||
|
||||
a.Val.Add(&a.Val, &b.Val)
|
||||
|
||||
if a.checkOverflow(0) {
|
||||
yyerror("constant addition overflow")
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Mpint) Sub(b *Mpint) {
|
||||
if a.Ovf || b.Ovf {
|
||||
if Errors() == 0 {
|
||||
Fatalf("ovf in Mpint Sub")
|
||||
}
|
||||
a.SetOverflow()
|
||||
return
|
||||
}
|
||||
|
||||
a.Val.Sub(&a.Val, &b.Val)
|
||||
|
||||
if a.checkOverflow(0) {
|
||||
yyerror("constant subtraction overflow")
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Mpint) Mul(b *Mpint) {
|
||||
if a.Ovf || b.Ovf {
|
||||
if Errors() == 0 {
|
||||
Fatalf("ovf in Mpint Mul")
|
||||
}
|
||||
a.SetOverflow()
|
||||
return
|
||||
}
|
||||
|
||||
a.Val.Mul(&a.Val, &b.Val)
|
||||
|
||||
if a.checkOverflow(0) {
|
||||
yyerror("constant multiplication overflow")
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Mpint) Quo(b *Mpint) {
|
||||
if a.Ovf || b.Ovf {
|
||||
if Errors() == 0 {
|
||||
Fatalf("ovf in Mpint Quo")
|
||||
}
|
||||
a.SetOverflow()
|
||||
return
|
||||
}
|
||||
|
||||
a.Val.Quo(&a.Val, &b.Val)
|
||||
|
||||
if a.checkOverflow(0) {
|
||||
// can only happen for div-0 which should be checked elsewhere
|
||||
yyerror("constant division overflow")
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Mpint) Rem(b *Mpint) {
|
||||
if a.Ovf || b.Ovf {
|
||||
if Errors() == 0 {
|
||||
Fatalf("ovf in Mpint Rem")
|
||||
}
|
||||
a.SetOverflow()
|
||||
return
|
||||
}
|
||||
|
||||
a.Val.Rem(&a.Val, &b.Val)
|
||||
|
||||
if a.checkOverflow(0) {
|
||||
// should never happen
|
||||
yyerror("constant modulo overflow")
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Mpint) Or(b *Mpint) {
|
||||
if a.Ovf || b.Ovf {
|
||||
if Errors() == 0 {
|
||||
Fatalf("ovf in Mpint Or")
|
||||
}
|
||||
a.SetOverflow()
|
||||
return
|
||||
}
|
||||
|
||||
a.Val.Or(&a.Val, &b.Val)
|
||||
}
|
||||
|
||||
func (a *Mpint) And(b *Mpint) {
|
||||
if a.Ovf || b.Ovf {
|
||||
if Errors() == 0 {
|
||||
Fatalf("ovf in Mpint And")
|
||||
}
|
||||
a.SetOverflow()
|
||||
return
|
||||
}
|
||||
|
||||
a.Val.And(&a.Val, &b.Val)
|
||||
}
|
||||
|
||||
func (a *Mpint) AndNot(b *Mpint) {
|
||||
if a.Ovf || b.Ovf {
|
||||
if Errors() == 0 {
|
||||
Fatalf("ovf in Mpint AndNot")
|
||||
}
|
||||
a.SetOverflow()
|
||||
return
|
||||
}
|
||||
|
||||
a.Val.AndNot(&a.Val, &b.Val)
|
||||
}
|
||||
|
||||
func (a *Mpint) Xor(b *Mpint) {
|
||||
if a.Ovf || b.Ovf {
|
||||
if Errors() == 0 {
|
||||
Fatalf("ovf in Mpint Xor")
|
||||
}
|
||||
a.SetOverflow()
|
||||
return
|
||||
}
|
||||
|
||||
a.Val.Xor(&a.Val, &b.Val)
|
||||
}
|
||||
|
||||
func (a *Mpint) Lsh(b *Mpint) {
|
||||
if a.Ovf || b.Ovf {
|
||||
if Errors() == 0 {
|
||||
Fatalf("ovf in Mpint Lsh")
|
||||
}
|
||||
a.SetOverflow()
|
||||
return
|
||||
}
|
||||
|
||||
s := b.Int64()
|
||||
if s < 0 || s >= Mpprec {
|
||||
msg := "shift count too large"
|
||||
if s < 0 {
|
||||
msg = "invalid negative shift count"
|
||||
}
|
||||
yyerror("%s: %d", msg, s)
|
||||
a.SetInt64(0)
|
||||
return
|
||||
}
|
||||
|
||||
if a.checkOverflow(int(s)) {
|
||||
yyerror("constant shift overflow")
|
||||
return
|
||||
}
|
||||
a.Val.Lsh(&a.Val, uint(s))
|
||||
}
|
||||
|
||||
func (a *Mpint) Rsh(b *Mpint) {
|
||||
if a.Ovf || b.Ovf {
|
||||
if Errors() == 0 {
|
||||
Fatalf("ovf in Mpint Rsh")
|
||||
}
|
||||
a.SetOverflow()
|
||||
return
|
||||
}
|
||||
|
||||
s := b.Int64()
|
||||
if s < 0 {
|
||||
yyerror("invalid negative shift count: %d", s)
|
||||
if a.Val.Sign() < 0 {
|
||||
a.SetInt64(-1)
|
||||
} else {
|
||||
a.SetInt64(0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
a.Val.Rsh(&a.Val, uint(s))
|
||||
}
|
||||
|
||||
func (a *Mpint) Cmp(b *Mpint) int {
|
||||
return a.Val.Cmp(&b.Val)
|
||||
}
|
||||
|
||||
func (a *Mpint) CmpInt64(c int64) int {
|
||||
if c == 0 {
|
||||
return a.Val.Sign() // common case shortcut
|
||||
}
|
||||
return a.Val.Cmp(big.NewInt(c))
|
||||
}
|
||||
|
||||
func (a *Mpint) Neg() {
|
||||
a.Val.Neg(&a.Val)
|
||||
}
|
||||
|
||||
func (a *Mpint) Int64() int64 {
|
||||
if a.Ovf {
|
||||
if Errors() == 0 {
|
||||
Fatalf("constant overflow")
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
return a.Val.Int64()
|
||||
}
|
||||
|
||||
func (a *Mpint) SetInt64(c int64) {
|
||||
a.Val.SetInt64(c)
|
||||
}
|
||||
|
||||
func (a *Mpint) SetString(as string) {
|
||||
_, ok := a.Val.SetString(as, 0)
|
||||
if !ok {
|
||||
// The lexer checks for correct syntax of the literal
|
||||
// and reports detailed errors. Thus SetString should
|
||||
// never fail (in theory it might run out of memory,
|
||||
// but that wouldn't be reported as an error here).
|
||||
Fatalf("malformed integer constant: %s", as)
|
||||
return
|
||||
}
|
||||
if a.checkOverflow(0) {
|
||||
yyerror("constant too large: %s", as)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Mpint) GoString() string {
|
||||
return a.Val.String()
|
||||
}
|
||||
|
||||
func (a *Mpint) String() string {
|
||||
return fmt.Sprintf("%#x", &a.Val)
|
||||
}
|
@ -7,6 +7,7 @@ package gc
|
||||
import (
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@ -331,8 +332,7 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) {
|
||||
p.checkUnused(pragma)
|
||||
}
|
||||
|
||||
val := p.basicLit(imp.Path)
|
||||
ipkg := importfile(&val)
|
||||
ipkg := importfile(p.basicLit(imp.Path))
|
||||
if ipkg == nil {
|
||||
if Errors() == 0 {
|
||||
Fatalf("phase error in import")
|
||||
@ -824,7 +824,7 @@ func (p *noder) sum(x syntax.Expr) *Node {
|
||||
chunks = append(chunks, nstr.StringVal())
|
||||
} else {
|
||||
if len(chunks) > 1 {
|
||||
nstr.SetVal(Val{U: strings.Join(chunks, "")})
|
||||
nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
|
||||
}
|
||||
nstr = nil
|
||||
chunks = chunks[:0]
|
||||
@ -832,7 +832,7 @@ func (p *noder) sum(x syntax.Expr) *Node {
|
||||
n = p.nod(add, OADD, n, r)
|
||||
}
|
||||
if len(chunks) > 1 {
|
||||
nstr.SetVal(Val{U: strings.Join(chunks, "")})
|
||||
nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
|
||||
}
|
||||
|
||||
return n
|
||||
@ -1400,64 +1400,43 @@ func checkLangCompat(lit *syntax.BasicLit) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *noder) basicLit(lit *syntax.BasicLit) Val {
|
||||
func (p *noder) basicLit(lit *syntax.BasicLit) constant.Value {
|
||||
// We don't use the errors of the conversion routines to determine
|
||||
// if a literal string is valid because the conversion routines may
|
||||
// accept a wider syntax than the language permits. Rely on lit.Bad
|
||||
// instead.
|
||||
switch s := lit.Value; lit.Kind {
|
||||
case syntax.IntLit:
|
||||
checkLangCompat(lit)
|
||||
x := new(Mpint)
|
||||
if !lit.Bad {
|
||||
x.SetString(s)
|
||||
}
|
||||
return Val{U: x}
|
||||
|
||||
case syntax.FloatLit:
|
||||
checkLangCompat(lit)
|
||||
x := newMpflt()
|
||||
if !lit.Bad {
|
||||
x.SetString(s)
|
||||
}
|
||||
return Val{U: x}
|
||||
|
||||
case syntax.ImagLit:
|
||||
checkLangCompat(lit)
|
||||
x := newMpcmplx()
|
||||
if !lit.Bad {
|
||||
x.Imag.SetString(strings.TrimSuffix(s, "i"))
|
||||
}
|
||||
return Val{U: x}
|
||||
|
||||
case syntax.RuneLit:
|
||||
x := new(Mpint)
|
||||
if !lit.Bad {
|
||||
u, _ := strconv.Unquote(s)
|
||||
var r rune
|
||||
if len(u) == 1 {
|
||||
r = rune(u[0])
|
||||
} else {
|
||||
r, _ = utf8.DecodeRuneInString(u)
|
||||
}
|
||||
x.SetInt64(int64(r))
|
||||
}
|
||||
return Val{U: x}
|
||||
|
||||
case syntax.StringLit:
|
||||
var x string
|
||||
if !lit.Bad {
|
||||
if len(s) > 0 && s[0] == '`' {
|
||||
// strip carriage returns from raw string
|
||||
s = strings.Replace(s, "\r", "", -1)
|
||||
}
|
||||
x, _ = strconv.Unquote(s)
|
||||
}
|
||||
return Val{U: x}
|
||||
|
||||
default:
|
||||
panic("unhandled BasicLit kind")
|
||||
if lit.Bad {
|
||||
return constant.MakeUnknown()
|
||||
}
|
||||
|
||||
switch lit.Kind {
|
||||
case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
|
||||
checkLangCompat(lit)
|
||||
}
|
||||
|
||||
v := constant.MakeFromLiteral(lit.Value, tokenForLitKind[lit.Kind], 0)
|
||||
if v.Kind() == constant.Unknown {
|
||||
// TODO(mdempsky): Better error message?
|
||||
p.yyerrorpos(lit.Pos(), "malformed constant: %s", lit.Value)
|
||||
}
|
||||
|
||||
// go/constant uses big.Rat by default, which is more precise, but
|
||||
// causes toolstash -cmp and some tests to fail. For now, convert
|
||||
// to big.Float to match cmd/compile's historical precision.
|
||||
// TODO(mdempsky): Remove.
|
||||
if v.Kind() == constant.Float {
|
||||
v = constant.Make(bigFloatVal(v))
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
var tokenForLitKind = [...]token.Token{
|
||||
syntax.IntLit: token.INT,
|
||||
syntax.RuneLit: token.CHAR,
|
||||
syntax.FloatLit: token.FLOAT,
|
||||
syntax.ImagLit: token.IMAG,
|
||||
syntax.StringLit: token.STRING,
|
||||
}
|
||||
|
||||
func (p *noder) name(name *syntax.Name) *types.Sym {
|
||||
|
@ -250,33 +250,18 @@ func dumpGlobalConst(n *Node) {
|
||||
return
|
||||
}
|
||||
// only export integer constants for now
|
||||
switch t.Etype {
|
||||
case TINT8:
|
||||
case TINT16:
|
||||
case TINT32:
|
||||
case TINT64:
|
||||
case TINT:
|
||||
case TUINT8:
|
||||
case TUINT16:
|
||||
case TUINT32:
|
||||
case TUINT64:
|
||||
case TUINT:
|
||||
case TUINTPTR:
|
||||
// ok
|
||||
case TIDEAL:
|
||||
if !Isconst(n, constant.Int) {
|
||||
return
|
||||
}
|
||||
x := n.Val().U.(*Mpint)
|
||||
if x.Cmp(minintval[TINT]) < 0 || x.Cmp(maxintval[TINT]) > 0 {
|
||||
return
|
||||
}
|
||||
// Ideal integers we export as int (if they fit).
|
||||
t = types.Types[TINT]
|
||||
default:
|
||||
if !t.IsInteger() {
|
||||
return
|
||||
}
|
||||
Ctxt.DwarfIntConst(myimportpath, n.Sym.Name, typesymname(t), n.Int64Val())
|
||||
v := n.Val()
|
||||
if t.IsUntyped() {
|
||||
// Export untyped integers as int (if they fit).
|
||||
t = types.Types[TINT]
|
||||
if doesoverflow(v, t) {
|
||||
return
|
||||
}
|
||||
}
|
||||
Ctxt.DwarfIntConst(myimportpath, n.Sym.Name, typesymname(t), int64Val(t, v))
|
||||
}
|
||||
|
||||
func dumpglobls() {
|
||||
@ -595,6 +580,9 @@ func litsym(n, c *Node, wid int) {
|
||||
if n.Sym == nil {
|
||||
Fatalf("litsym nil n sym")
|
||||
}
|
||||
if !types.Identical(n.Type, c.Type) {
|
||||
Fatalf("litsym: type mismatch: %v has type %v, but %v has type %v", n, n.Type, c, c.Type)
|
||||
}
|
||||
if c.Op == ONIL {
|
||||
return
|
||||
}
|
||||
@ -602,16 +590,16 @@ func litsym(n, c *Node, wid int) {
|
||||
Fatalf("litsym c op %v", c.Op)
|
||||
}
|
||||
s := n.Sym.Linksym()
|
||||
switch u := c.Val().U.(type) {
|
||||
case bool:
|
||||
i := int64(obj.Bool2int(u))
|
||||
switch u := c.Val(); u.Kind() {
|
||||
case constant.Bool:
|
||||
i := int64(obj.Bool2int(constant.BoolVal(u)))
|
||||
s.WriteInt(Ctxt, n.Xoffset, wid, i)
|
||||
|
||||
case *Mpint:
|
||||
s.WriteInt(Ctxt, n.Xoffset, wid, u.Int64())
|
||||
case constant.Int:
|
||||
s.WriteInt(Ctxt, n.Xoffset, wid, int64Val(n.Type, u))
|
||||
|
||||
case *Mpflt:
|
||||
f := u.Float64()
|
||||
case constant.Float:
|
||||
f, _ := constant.Float64Val(u)
|
||||
switch n.Type.Etype {
|
||||
case TFLOAT32:
|
||||
s.WriteFloat32(Ctxt, n.Xoffset, float32(f))
|
||||
@ -619,22 +607,23 @@ func litsym(n, c *Node, wid int) {
|
||||
s.WriteFloat64(Ctxt, n.Xoffset, f)
|
||||
}
|
||||
|
||||
case *Mpcplx:
|
||||
r := u.Real.Float64()
|
||||
i := u.Imag.Float64()
|
||||
case constant.Complex:
|
||||
re, _ := constant.Float64Val(constant.Real(u))
|
||||
im, _ := constant.Float64Val(constant.Imag(u))
|
||||
switch n.Type.Etype {
|
||||
case TCOMPLEX64:
|
||||
s.WriteFloat32(Ctxt, n.Xoffset, float32(r))
|
||||
s.WriteFloat32(Ctxt, n.Xoffset+4, float32(i))
|
||||
s.WriteFloat32(Ctxt, n.Xoffset, float32(re))
|
||||
s.WriteFloat32(Ctxt, n.Xoffset+4, float32(im))
|
||||
case TCOMPLEX128:
|
||||
s.WriteFloat64(Ctxt, n.Xoffset, r)
|
||||
s.WriteFloat64(Ctxt, n.Xoffset+8, i)
|
||||
s.WriteFloat64(Ctxt, n.Xoffset, re)
|
||||
s.WriteFloat64(Ctxt, n.Xoffset+8, im)
|
||||
}
|
||||
|
||||
case string:
|
||||
symdata := stringsym(n.Pos, u)
|
||||
case constant.String:
|
||||
i := constant.StringVal(u)
|
||||
symdata := stringsym(n.Pos, i)
|
||||
s.WriteAddr(Ctxt, n.Xoffset, Widthptr, symdata, 0)
|
||||
s.WriteInt(Ctxt, n.Xoffset+int64(Widthptr), Widthptr, int64(len(u)))
|
||||
s.WriteInt(Ctxt, n.Xoffset+int64(Widthptr), Widthptr, int64(len(i)))
|
||||
|
||||
default:
|
||||
Fatalf("litsym unhandled OLITERAL %v", c)
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/obj"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
)
|
||||
|
||||
type InitEntry struct {
|
||||
@ -1116,20 +1117,13 @@ func isZero(n *Node) bool {
|
||||
return true
|
||||
|
||||
case OLITERAL:
|
||||
switch u := n.Val().U.(type) {
|
||||
switch u := n.Val(); u.Kind() {
|
||||
case constant.String:
|
||||
return constant.StringVal(u) == ""
|
||||
case constant.Bool:
|
||||
return !constant.BoolVal(u)
|
||||
default:
|
||||
Dump("unexpected literal", n)
|
||||
Fatalf("isZero")
|
||||
case string:
|
||||
return u == ""
|
||||
case bool:
|
||||
return !u
|
||||
case *Mpint:
|
||||
return u.CmpInt64(0) == 0
|
||||
case *Mpflt:
|
||||
return u.CmpFloat64(0) == 0
|
||||
case *Mpcplx:
|
||||
return u.Real.CmpFloat64(0) == 0 && u.Imag.CmpFloat64(0) == 0
|
||||
return constant.Sign(u) == 0
|
||||
}
|
||||
|
||||
case OARRAYLIT:
|
||||
|
@ -2044,9 +2044,9 @@ func (s *state) expr(n *Node) *ssa.Value {
|
||||
return s.constNil(t)
|
||||
}
|
||||
case OLITERAL:
|
||||
switch u := n.Val().U.(type) {
|
||||
case *Mpint:
|
||||
i := u.Int64()
|
||||
switch u := n.Val(); u.Kind() {
|
||||
case constant.Int:
|
||||
i := int64Val(n.Type, u)
|
||||
switch n.Type.Size() {
|
||||
case 1:
|
||||
return s.constInt8(n.Type, int8(i))
|
||||
@ -2060,44 +2060,45 @@ func (s *state) expr(n *Node) *ssa.Value {
|
||||
s.Fatalf("bad integer size %d", n.Type.Size())
|
||||
return nil
|
||||
}
|
||||
case string:
|
||||
if u == "" {
|
||||
case constant.String:
|
||||
i := constant.StringVal(u)
|
||||
if i == "" {
|
||||
return s.constEmptyString(n.Type)
|
||||
}
|
||||
return s.entryNewValue0A(ssa.OpConstString, n.Type, u)
|
||||
case bool:
|
||||
return s.constBool(u)
|
||||
case *Mpflt:
|
||||
return s.entryNewValue0A(ssa.OpConstString, n.Type, i)
|
||||
case constant.Bool:
|
||||
return s.constBool(constant.BoolVal(u))
|
||||
case constant.Float:
|
||||
f, _ := constant.Float64Val(u)
|
||||
switch n.Type.Size() {
|
||||
case 4:
|
||||
return s.constFloat32(n.Type, u.Float32())
|
||||
return s.constFloat32(n.Type, f)
|
||||
case 8:
|
||||
return s.constFloat64(n.Type, u.Float64())
|
||||
return s.constFloat64(n.Type, f)
|
||||
default:
|
||||
s.Fatalf("bad float size %d", n.Type.Size())
|
||||
return nil
|
||||
}
|
||||
case *Mpcplx:
|
||||
r := &u.Real
|
||||
i := &u.Imag
|
||||
case constant.Complex:
|
||||
re, _ := constant.Float64Val(constant.Real(u))
|
||||
im, _ := constant.Float64Val(constant.Imag(u))
|
||||
switch n.Type.Size() {
|
||||
case 8:
|
||||
pt := types.Types[TFLOAT32]
|
||||
return s.newValue2(ssa.OpComplexMake, n.Type,
|
||||
s.constFloat32(pt, r.Float32()),
|
||||
s.constFloat32(pt, i.Float32()))
|
||||
s.constFloat32(pt, re),
|
||||
s.constFloat32(pt, im))
|
||||
case 16:
|
||||
pt := types.Types[TFLOAT64]
|
||||
return s.newValue2(ssa.OpComplexMake, n.Type,
|
||||
s.constFloat64(pt, r.Float64()),
|
||||
s.constFloat64(pt, i.Float64()))
|
||||
s.constFloat64(pt, re),
|
||||
s.constFloat64(pt, im))
|
||||
default:
|
||||
s.Fatalf("bad float size %d", n.Type.Size())
|
||||
s.Fatalf("bad complex size %d", n.Type.Size())
|
||||
return nil
|
||||
}
|
||||
|
||||
default:
|
||||
s.Fatalf("unhandled OLITERAL %v", n.Val().Kind())
|
||||
s.Fatalf("unhandled OLITERAL %v", u.Kind())
|
||||
return nil
|
||||
}
|
||||
case OCONVNOP:
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"crypto/md5"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -252,9 +253,7 @@ func (x methcmp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
func (x methcmp) Less(i, j int) bool { return x[i].Sym.Less(x[j].Sym) }
|
||||
|
||||
func nodintconst(v int64) *Node {
|
||||
u := new(Mpint)
|
||||
u.SetInt64(v)
|
||||
return nodlit(Val{u})
|
||||
return nodlit(constant.MakeInt64(v))
|
||||
}
|
||||
|
||||
func nodnil() *Node {
|
||||
@ -264,11 +263,11 @@ func nodnil() *Node {
|
||||
}
|
||||
|
||||
func nodbool(b bool) *Node {
|
||||
return nodlit(Val{b})
|
||||
return nodlit(constant.MakeBool(b))
|
||||
}
|
||||
|
||||
func nodstr(s string) *Node {
|
||||
return nodlit(Val{s})
|
||||
return nodlit(constant.MakeString(s))
|
||||
}
|
||||
|
||||
// treecopy recursively copies n, with the exception of
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/src"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"sort"
|
||||
)
|
||||
|
||||
@ -400,7 +401,7 @@ func (s *exprSwitch) flush() {
|
||||
}
|
||||
|
||||
sort.Slice(cc, func(i, j int) bool {
|
||||
return compareOp(cc[i].lo.Val(), OLT, cc[j].lo.Val())
|
||||
return constant.Compare(cc[i].lo.Val(), token.LSS, cc[j].lo.Val())
|
||||
})
|
||||
|
||||
// Merge consecutive integer cases.
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/objabi"
|
||||
"cmd/internal/src"
|
||||
"go/constant"
|
||||
"sort"
|
||||
)
|
||||
|
||||
@ -236,16 +237,17 @@ func (n *Node) MarkReadonly() {
|
||||
n.Sym.Linksym().Type = objabi.SRODATA
|
||||
}
|
||||
|
||||
// Val returns the Val for the node.
|
||||
func (n *Node) Val() Val {
|
||||
// Val returns the constant.Value for the node.
|
||||
func (n *Node) Val() constant.Value {
|
||||
if !n.HasVal() {
|
||||
return Val{}
|
||||
return constant.MakeUnknown()
|
||||
}
|
||||
return Val{n.E}
|
||||
return *n.E.(*constant.Value)
|
||||
}
|
||||
|
||||
// SetVal sets the Val for the node, which must not have been used with SetOpt.
|
||||
func (n *Node) SetVal(v Val) {
|
||||
// SetVal sets the constant.Value for the node,
|
||||
// which must not have been used with SetOpt.
|
||||
func (n *Node) SetVal(v constant.Value) {
|
||||
if n.HasOpt() {
|
||||
Debug.h = 1
|
||||
Dump("have Opt", n)
|
||||
@ -255,7 +257,7 @@ func (n *Node) SetVal(v Val) {
|
||||
assertRepresents(n.Type, v)
|
||||
}
|
||||
n.SetHasVal(true)
|
||||
n.E = v.U
|
||||
n.E = &v
|
||||
}
|
||||
|
||||
// Opt returns the optimizer data for the node.
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"cmd/compile/internal/types"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -361,7 +362,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||
ok |= ctxExpr
|
||||
|
||||
if n.Type == nil && n.Val().Kind() == constant.String {
|
||||
n.Type = types.UntypedString
|
||||
Fatalf("string literal missing type")
|
||||
}
|
||||
|
||||
case ONIL, ONONAME:
|
||||
@ -446,12 +447,13 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||
return n
|
||||
}
|
||||
|
||||
bound := v.U.(*Mpint).Int64()
|
||||
if bound < 0 {
|
||||
if constant.Sign(v) < 0 {
|
||||
yyerror("array bound must be non-negative")
|
||||
n.Type = nil
|
||||
return n
|
||||
}
|
||||
|
||||
bound, _ := constant.Int64Val(v)
|
||||
t = types.NewArray(r.Type, bound)
|
||||
}
|
||||
|
||||
@ -776,8 +778,9 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||
}
|
||||
|
||||
if iscmp[n.Op] {
|
||||
n = evalConst(n)
|
||||
t = types.UntypedBool
|
||||
n.Type = t
|
||||
n = evalConst(n)
|
||||
if n.Op != OLITERAL {
|
||||
l, r = defaultlit2(l, r, true)
|
||||
n.Left = l
|
||||
@ -803,7 +806,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||
}
|
||||
|
||||
if (op == ODIV || op == OMOD) && Isconst(r, constant.Int) {
|
||||
if r.Val().U.(*Mpint).CmpInt64(0) == 0 {
|
||||
if constant.Sign(r.Val()) == 0 {
|
||||
yyerror("division by zero")
|
||||
n.Type = nil
|
||||
return n
|
||||
@ -1045,14 +1048,14 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||
}
|
||||
|
||||
if !n.Bounded() && Isconst(n.Right, constant.Int) {
|
||||
x := n.Right.Int64Val()
|
||||
if x < 0 {
|
||||
x := n.Right.Val()
|
||||
if constant.Sign(x) < 0 {
|
||||
yyerror("invalid %s index %v (index must be non-negative)", why, n.Right)
|
||||
} else if t.IsArray() && x >= t.NumElem() {
|
||||
} else if t.IsArray() && constant.Compare(x, token.GEQ, constant.MakeInt64(t.NumElem())) {
|
||||
yyerror("invalid array index %v (out of bounds for %d-element array)", n.Right, t.NumElem())
|
||||
} else if Isconst(n.Left, constant.String) && x >= int64(len(n.Left.StringVal())) {
|
||||
} else if Isconst(n.Left, constant.String) && constant.Compare(x, token.GEQ, constant.MakeInt64(int64(len(n.Left.StringVal())))) {
|
||||
yyerror("invalid string index %v (out of bounds for %d-byte string)", n.Right, len(n.Left.StringVal()))
|
||||
} else if doesoverflow(n.Right.Val(), types.Types[TINT]) {
|
||||
} else if doesoverflow(x, types.Types[TINT]) {
|
||||
yyerror("invalid %s index %v (index too large)", why, n.Right)
|
||||
}
|
||||
}
|
||||
@ -1155,7 +1158,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||
Fatalf("cap for OSLICEHEADER must be non-negative")
|
||||
}
|
||||
|
||||
if Isconst(l, constant.Int) && Isconst(c, constant.Int) && compareOp(l.Val(), OGT, c.Val()) {
|
||||
if Isconst(l, constant.Int) && Isconst(c, constant.Int) && constant.Compare(l.Val(), token.GTR, c.Val()) {
|
||||
Fatalf("len larger than cap for OSLICEHEADER")
|
||||
}
|
||||
|
||||
@ -1200,7 +1203,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||
if doesoverflow(n.Left.Val(), types.Types[TINT]) {
|
||||
Fatalf("len for OMAKESLICECOPY too large")
|
||||
}
|
||||
if n.Left.Int64Val() < 0 {
|
||||
if constant.Sign(n.Left.Val()) < 0 {
|
||||
Fatalf("len for OMAKESLICECOPY must be non-negative")
|
||||
}
|
||||
}
|
||||
@ -1773,7 +1776,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||
n.Type = nil
|
||||
return n
|
||||
}
|
||||
if Isconst(l, constant.Int) && r != nil && Isconst(r, constant.Int) && compareOp(l.Val(), OGT, r.Val()) {
|
||||
if Isconst(l, constant.Int) && r != nil && Isconst(r, constant.Int) && constant.Compare(l.Val(), token.GTR, r.Val()) {
|
||||
yyerror("len larger than cap in make(%v)", t)
|
||||
n.Type = nil
|
||||
return n
|
||||
@ -2181,16 +2184,17 @@ func checksliceindex(l *Node, r *Node, tp *types.Type) bool {
|
||||
}
|
||||
|
||||
if r.Op == OLITERAL {
|
||||
if r.Int64Val() < 0 {
|
||||
x := r.Val()
|
||||
if constant.Sign(x) < 0 {
|
||||
yyerror("invalid slice index %v (index must be non-negative)", r)
|
||||
return false
|
||||
} else if tp != nil && tp.NumElem() >= 0 && r.Int64Val() > tp.NumElem() {
|
||||
} else if tp != nil && tp.NumElem() >= 0 && constant.Compare(x, token.GTR, constant.MakeInt64(tp.NumElem())) {
|
||||
yyerror("invalid slice index %v (out of bounds for %d-element array)", r, tp.NumElem())
|
||||
return false
|
||||
} else if Isconst(l, constant.String) && r.Int64Val() > int64(len(l.StringVal())) {
|
||||
} else if Isconst(l, constant.String) && constant.Compare(x, token.GTR, constant.MakeInt64(int64(len(l.StringVal())))) {
|
||||
yyerror("invalid slice index %v (out of bounds for %d-byte string)", r, len(l.StringVal()))
|
||||
return false
|
||||
} else if doesoverflow(r.Val(), types.Types[TINT]) {
|
||||
} else if doesoverflow(x, types.Types[TINT]) {
|
||||
yyerror("invalid slice index %v (index too large)", r)
|
||||
return false
|
||||
}
|
||||
@ -2200,7 +2204,7 @@ func checksliceindex(l *Node, r *Node, tp *types.Type) bool {
|
||||
}
|
||||
|
||||
func checksliceconst(lo *Node, hi *Node) bool {
|
||||
if lo != nil && hi != nil && lo.Op == OLITERAL && hi.Op == OLITERAL && compareOp(lo.Val(), OGT, hi.Val()) {
|
||||
if lo != nil && hi != nil && lo.Op == OLITERAL && hi.Op == OLITERAL && constant.Compare(lo.Val(), token.GTR, hi.Val()) {
|
||||
yyerror("invalid slice index: %v > %v", lo, hi)
|
||||
return false
|
||||
}
|
||||
@ -3192,7 +3196,7 @@ func samesafeexpr(l *Node, r *Node) bool {
|
||||
return samesafeexpr(l.Left, r.Left) && samesafeexpr(l.Right, r.Right)
|
||||
|
||||
case OLITERAL:
|
||||
return eqval(l.Val(), r.Val())
|
||||
return constant.Compare(l.Val(), token.EQL, r.Val())
|
||||
|
||||
case ONIL:
|
||||
return true
|
||||
@ -3625,7 +3629,9 @@ func typecheckdef(n *Node) {
|
||||
}
|
||||
|
||||
n.Type = e.Type
|
||||
n.SetVal(e.Val())
|
||||
if n.Type != nil {
|
||||
n.SetVal(e.Val())
|
||||
}
|
||||
|
||||
case ONAME:
|
||||
if n.Name.Param.Ntype != nil {
|
||||
@ -3723,14 +3729,13 @@ func checkmake(t *types.Type, arg string, np **Node) bool {
|
||||
|
||||
// Do range checks for constants before defaultlit
|
||||
// to avoid redundant "constant NNN overflows int" errors.
|
||||
switch consttype(n) {
|
||||
case constant.Int, constant.Float, constant.Complex:
|
||||
v := toint(n.Val()).U.(*Mpint)
|
||||
if v.CmpInt64(0) < 0 {
|
||||
if n.Op == OLITERAL {
|
||||
v := toint(n.Val())
|
||||
if constant.Sign(v) < 0 {
|
||||
yyerror("negative %s argument in make(%v)", arg, t)
|
||||
return false
|
||||
}
|
||||
if v.Cmp(maxintval[TINT]) > 0 {
|
||||
if doesoverflow(v, types.Types[TINT]) {
|
||||
yyerror("%s argument too large in make(%v)", arg, t)
|
||||
return false
|
||||
}
|
||||
|
@ -209,8 +209,6 @@ func typeinit() {
|
||||
okforand[et] = true
|
||||
okforconst[et] = true
|
||||
issimple[et] = true
|
||||
minintval[et] = new(Mpint)
|
||||
maxintval[et] = new(Mpint)
|
||||
}
|
||||
|
||||
if isFloat[et] {
|
||||
@ -220,8 +218,6 @@ func typeinit() {
|
||||
okforarith[et] = true
|
||||
okforconst[et] = true
|
||||
issimple[et] = true
|
||||
minfltval[et] = newMpflt()
|
||||
maxfltval[et] = newMpflt()
|
||||
}
|
||||
|
||||
if isComplex[et] {
|
||||
@ -310,31 +306,6 @@ func typeinit() {
|
||||
iscmp[OEQ] = true
|
||||
iscmp[ONE] = true
|
||||
|
||||
maxintval[TINT8].SetString("0x7f")
|
||||
minintval[TINT8].SetString("-0x80")
|
||||
maxintval[TINT16].SetString("0x7fff")
|
||||
minintval[TINT16].SetString("-0x8000")
|
||||
maxintval[TINT32].SetString("0x7fffffff")
|
||||
minintval[TINT32].SetString("-0x80000000")
|
||||
maxintval[TINT64].SetString("0x7fffffffffffffff")
|
||||
minintval[TINT64].SetString("-0x8000000000000000")
|
||||
|
||||
maxintval[TUINT8].SetString("0xff")
|
||||
maxintval[TUINT16].SetString("0xffff")
|
||||
maxintval[TUINT32].SetString("0xffffffff")
|
||||
maxintval[TUINT64].SetString("0xffffffffffffffff")
|
||||
|
||||
// f is valid float if min < f < max. (min and max are not themselves valid.)
|
||||
maxfltval[TFLOAT32].SetString("33554431p103") // 2^24-1 p (127-23) + 1/2 ulp
|
||||
minfltval[TFLOAT32].SetString("-33554431p103")
|
||||
maxfltval[TFLOAT64].SetString("18014398509481983p970") // 2^53-1 p (1023-52) + 1/2 ulp
|
||||
minfltval[TFLOAT64].SetString("-18014398509481983p970")
|
||||
|
||||
maxfltval[TCOMPLEX64] = maxfltval[TFLOAT32]
|
||||
minfltval[TCOMPLEX64] = minfltval[TFLOAT32]
|
||||
maxfltval[TCOMPLEX128] = maxfltval[TFLOAT64]
|
||||
minfltval[TCOMPLEX128] = minfltval[TFLOAT64]
|
||||
|
||||
types.Types[TINTER] = types.New(TINTER) // empty interface
|
||||
|
||||
// simple aliases
|
||||
@ -410,10 +381,6 @@ func lexinit1() {
|
||||
}
|
||||
|
||||
simtype[s.etype] = sameas
|
||||
minfltval[s.etype] = minfltval[sameas]
|
||||
maxfltval[s.etype] = maxfltval[sameas]
|
||||
minintval[s.etype] = minintval[sameas]
|
||||
maxintval[s.etype] = maxintval[sameas]
|
||||
|
||||
t := types.New(s.etype)
|
||||
t.Sym = s1
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -1002,7 +1003,7 @@ opswitch:
|
||||
break opswitch
|
||||
}
|
||||
case TUINT64:
|
||||
c := uint64(n.Right.Int64Val())
|
||||
c := n.Right.Uint64Val()
|
||||
if c < 1<<16 {
|
||||
break opswitch
|
||||
}
|
||||
@ -1062,7 +1063,7 @@ opswitch:
|
||||
}
|
||||
|
||||
if Isconst(n.Right, constant.Int) {
|
||||
if n.Right.Val().U.(*Mpint).CmpInt64(0) < 0 || doesoverflow(n.Right.Val(), types.Types[TINT]) {
|
||||
if v := n.Right.Val(); constant.Sign(v) < 0 || doesoverflow(v, types.Types[TINT]) {
|
||||
yyerror("index out of bounds")
|
||||
}
|
||||
}
|
||||
@ -1223,7 +1224,7 @@ opswitch:
|
||||
// Maximum key and elem size is 128 bytes, larger objects
|
||||
// are stored with an indirection. So max bucket size is 2048+eps.
|
||||
if !Isconst(hint, constant.Int) ||
|
||||
hint.Val().U.(*Mpint).CmpInt64(BUCKETSIZE) <= 0 {
|
||||
constant.Compare(hint.Val(), token.LEQ, constant.MakeInt64(BUCKETSIZE)) {
|
||||
|
||||
// In case hint is larger than BUCKETSIZE runtime.makemap
|
||||
// will allocate the buckets on the heap, see #20184
|
||||
@ -1256,7 +1257,7 @@ opswitch:
|
||||
}
|
||||
}
|
||||
|
||||
if Isconst(hint, constant.Int) && hint.Val().U.(*Mpint).CmpInt64(BUCKETSIZE) <= 0 {
|
||||
if Isconst(hint, constant.Int) && constant.Compare(hint.Val(), token.LEQ, constant.MakeInt64(BUCKETSIZE)) {
|
||||
// Handling make(map[any]any) and
|
||||
// make(map[any]any, hint) where hint <= BUCKETSIZE
|
||||
// special allows for faster map initialization and
|
||||
@ -1588,8 +1589,8 @@ opswitch:
|
||||
n = typecheck(n, ctxExpr)
|
||||
// Emit string symbol now to avoid emitting
|
||||
// any concurrently during the backend.
|
||||
if s, ok := n.Val().U.(string); ok {
|
||||
_ = stringsym(n.Pos, s)
|
||||
if v := n.Val(); v.Kind() == constant.String {
|
||||
_ = stringsym(n.Pos, constant.StringVal(v))
|
||||
}
|
||||
}
|
||||
|
||||
@ -3841,17 +3842,14 @@ func candiscard(n *Node) bool {
|
||||
|
||||
// Discardable as long as we know it's not division by zero.
|
||||
case ODIV, OMOD:
|
||||
if Isconst(n.Right, constant.Int) && n.Right.Val().U.(*Mpint).CmpInt64(0) != 0 {
|
||||
break
|
||||
}
|
||||
if Isconst(n.Right, constant.Float) && n.Right.Val().U.(*Mpflt).CmpFloat64(0) != 0 {
|
||||
if n.Right.Op == OLITERAL && constant.Sign(n.Right.Val()) != 0 {
|
||||
break
|
||||
}
|
||||
return false
|
||||
|
||||
// Discardable as long as we know it won't fail because of a bad size.
|
||||
case OMAKECHAN, OMAKEMAP:
|
||||
if Isconst(n.Left, constant.Int) && n.Left.Val().U.(*Mpint).CmpInt64(0) == 0 {
|
||||
if Isconst(n.Left, constant.Int) && constant.Sign(n.Left.Val()) == 0 {
|
||||
break
|
||||
}
|
||||
return false
|
||||
|
@ -1212,7 +1212,7 @@ func (t *Type) IsInteger() bool {
|
||||
case TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TINT, TUINT, TUINTPTR:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return t == UntypedInt || t == UntypedRune
|
||||
}
|
||||
|
||||
func (t *Type) IsSigned() bool {
|
||||
@ -1223,12 +1223,20 @@ func (t *Type) IsSigned() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *Type) IsUnsigned() bool {
|
||||
switch t.Etype {
|
||||
case TUINT8, TUINT16, TUINT32, TUINT64, TUINT, TUINTPTR:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *Type) IsFloat() bool {
|
||||
return t.Etype == TFLOAT32 || t.Etype == TFLOAT64
|
||||
return t.Etype == TFLOAT32 || t.Etype == TFLOAT64 || t == UntypedFloat
|
||||
}
|
||||
|
||||
func (t *Type) IsComplex() bool {
|
||||
return t.Etype == TCOMPLEX64 || t.Etype == TCOMPLEX128
|
||||
return t.Etype == TCOMPLEX64 || t.Etype == TCOMPLEX128 || t == UntypedComplex
|
||||
}
|
||||
|
||||
// IsPtr reports whether t is a regular Go pointer type.
|
||||
|
@ -6,6 +6,6 @@
|
||||
|
||||
package main
|
||||
|
||||
const _ = 6e5518446744 // ERROR "malformed constant: 6e5518446744 \(exponent overflow\)"
|
||||
const _ = 6e5518446744 // ERROR "malformed constant: 6e5518446744"
|
||||
const _ = 1e-1000000000
|
||||
const _ = 1e+1000000000 // ERROR "constant too large"
|
||||
const _ = 1e+1000000000
|
||||
|
Loading…
Reference in New Issue
Block a user