]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add "surprised by IData of Arg" case for register args
authorDavid Chase <drchase@google.com>
Mon, 5 Apr 2021 13:47:22 +0000 (09:47 -0400)
committerDavid Chase <drchase@google.com>
Mon, 5 Apr 2021 20:11:08 +0000 (20:11 +0000)
This fixes a compile crash for
GOEXPERIMENT=regabi,regabiargs go test -c  go/constant

Updates #40724.

Change-Id: I238cef436e045647815326fc8fdb025c30ba1f5c
Reviewed-on: https://go-review.googlesource.com/c/go/+/307309
Trust: David Chase <drchase@google.com>
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/compile/internal/ssa/expand_calls.go
test/abi/idata.go [new file with mode: 0644]
test/abi/idata.out [new file with mode: 0644]

index b6683d076df16e4b239909d9ebcb3307af5c9370..6a6517deb89e11f5f9533061a947b7d3c4ebe7f4 100644 (file)
@@ -317,6 +317,15 @@ func (x *expandState) rewriteSelect(leaf *Value, selector *Value, offset int64,
                }
        }
        switch selector.Op {
+       case OpArgIntReg, OpArgFloatReg:
+               if leafType == selector.Type { // OpIData leads us here, sometimes.
+                       leaf.copyOf(selector)
+               } else {
+                       x.f.Fatalf("Unexpected %s type, selector=%s, leaf=%s\n", selector.Op.String(), selector.LongString(), leaf.LongString())
+               }
+               if x.debug {
+                       x.Printf("---%s, break\n", selector.Op.String())
+               }
        case OpArg:
                if !x.isAlreadyExpandedAggregateType(selector.Type) {
                        if leafType == selector.Type { // OpIData leads us here, sometimes.
diff --git a/test/abi/idata.go b/test/abi/idata.go
new file mode 100644 (file)
index 0000000..af2b87b
--- /dev/null
@@ -0,0 +1,97 @@
+// run
+
+// Copyright 2021 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.
+
+// Excerpted from go/constant/value.go to capture a bug from there.
+
+package main
+
+import (
+       "fmt"
+       "math"
+       "math/big"
+)
+
+type (
+       unknownVal struct{}
+       intVal     struct{ val *big.Int }   // Int values not representable as an int64
+       ratVal     struct{ val *big.Rat }   // Float values representable as a fraction
+       floatVal   struct{ val *big.Float } // Float values not representable as a fraction
+       complexVal struct{ re, im Value }
+)
+
+const prec = 512
+
+func (unknownVal) String() string { return "unknown" }
+
+func (x intVal) String() string   { return x.val.String() }
+func (x ratVal) String() string   { return rtof(x).String() }
+
+func (x floatVal) String() string {
+       f := x.val
+
+       // 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("%.6g", x)
+       }
+
+       return "OOPS"
+}
+
+func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) }
+
+func newFloat() *big.Float { return new(big.Float).SetPrec(prec) }
+
+//go:noinline
+//go:registerparams
+func itor(x intVal) ratVal       { return ratVal{nil} }
+
+//go:noinline
+//go:registerparams
+func itof(x intVal) floatVal     { return floatVal{nil} }
+func rtof(x ratVal) floatVal     { return floatVal{newFloat().SetRat(x.val)} }
+
+type Value interface {
+       String() string
+}
+
+//go:noinline
+//go:registerparams
+func ToFloat(x Value) Value {
+       switch x := x.(type) {
+       case intVal:
+               if smallInt(x.val) {
+                       return itor(x)
+               }
+               return itof(x)
+       case ratVal, floatVal:
+               return x
+       case complexVal:
+               if Sign(x.im) == 0 {
+                       return ToFloat(x.re)
+               }
+       }
+       return unknownVal{}
+}
+
+//go:noinline
+//go:registerparams
+func smallInt(x *big.Int) bool {
+       return false
+}
+
+//go:noinline
+//go:registerparams
+func Sign(x Value) int {
+       return 0
+}
+
+
+func main() {
+       v := ratVal{big.NewRat(22,7)}
+       s := ToFloat(v).String()
+       fmt.Printf("s=%s\n", s)
+}
diff --git a/test/abi/idata.out b/test/abi/idata.out
new file mode 100644 (file)
index 0000000..98190c2
--- /dev/null
@@ -0,0 +1 @@
+s=3.14286