]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile: add GOSSAFUNC and GOSSAPKG
authorJosh Bleecher Snyder <josharian@gmail.com>
Wed, 22 Jul 2015 20:13:53 +0000 (13:13 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Thu, 23 Jul 2015 18:08:17 +0000 (18:08 +0000)
These temporary environment variables make it
possible to enable using SSA-generated code
for a particular function or package without
having to rebuild the compiler.

This makes it possible to start bulk testing
SSA generated code.

First, bump up the default stack size
(_StackMin in runtime/stack2.go) to something
large like 32768, because without stackmaps
we can't grow stacks.

Then run something like:

for pkg in `go list std`
do
  GOGC=off GOSSAPKG=`basename $pkg` go test -a $pkg
done

When a test fails, you can re-run those tests,
selectively enabling one function after another,
until you find the one that is causing trouble.

Doing this right now yields some interesting results:

* There are several packages for which we generate
  some code and whose tests pass. Yay!

* We can generate code for encoding/base64, but
  tests there fail, so there's a bug to fix.

* Attempting to build the runtime yields a panic during codegen:
  panic: interface conversion: ssa.Location is nil, not *ssa.LocalSlot

* The top unimplemented codegen items are (simplified):
  59 genValue not implemented: REPMOVSB
  18 genValue not implemented: REPSTOSQ
  14 genValue not implemented: SUBQ
   9 branch not implemented: If v -> b b. Control: XORQconst <bool> [1]
   8 genValue not implemented: MOVQstoreidx8
   4 branch not implemented: If v -> b b. Control: SETG <bool>
   3 branch not implemented: If v -> b b. Control: SETLE <bool>
   2 load flags not implemented: LoadReg8 <flags>
   2 genValue not implemented: InvertFlags <flags>
   1 store flags not implemented: StoreReg8 <flags>
   1 branch not implemented: If v -> b b. Control: SETGE <bool>

Change-Id: Ib64809ac0c917e25bcae27829ae634c70d290c7f
Reviewed-on: https://go-review.googlesource.com/12547
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/config.go

index d6c0bc7c592c67cb4f6a8cfd7f1d9c31c62399d0..6871fc48cd552aaaf151c412a1f8f9d492de7d76 100644 (file)
@@ -6,6 +6,7 @@ package gc
 
 import (
        "fmt"
+       "os"
        "strings"
 
        "cmd/compile/internal/ssa"
@@ -146,7 +147,10 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
        if e.unimplemented {
                return nil, false
        }
-       return s.f, usessa // TODO: return s.f, true once runtime support is in (gc maps, write barriers, etc.)
+
+       // TODO: enable codegen more broadly once the codegen stabilizes
+       // and runtime support is in (gc maps, write barriers, etc.)
+       return s.f, usessa || name == os.Getenv("GOSSAFUNC") || localpkg.Name == os.Getenv("GOSSAPKG")
 }
 
 type state struct {
@@ -1321,6 +1325,12 @@ func genssa(f *ssa.Func, ptxt *obj.Prog, gcargs, gclocals *Sym) {
                return
        }
 
+       e := f.Config.Frontend().(*ssaExport)
+       // We're about to emit a bunch of Progs.
+       // Since the only way to get here is to explicitly request it,
+       // just fail on unimplemented instead of trying to unwind our mess.
+       e.mustImplement = true
+
        ptxt.To.Type = obj.TYPE_TEXTSIZE
        ptxt.To.Val = int32(Rnd(Curfn.Type.Argwid, int64(Widthptr))) // arg size
        ptxt.To.Offset = f.FrameSize - 8                             // TODO: arch-dependent
@@ -1688,7 +1698,7 @@ func genValue(v *ssa.Value) {
                p.To.Type = obj.TYPE_REG
                p.To.Reg = regnum(v)
        default:
-               v.Unimplementedf("value %s not implemented", v.LongString())
+               v.Unimplementedf("genValue not implemented: %s", v.LongString())
        }
 }
 
@@ -1810,7 +1820,7 @@ func genBlock(b, next *ssa.Block, branches []branch) []branch {
                }
 
        default:
-               b.Unimplementedf("branch %s not implemented", b.LongString())
+               b.Unimplementedf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
        }
        return branches
 }
@@ -1900,6 +1910,7 @@ func localOffset(v *ssa.Value) int64 {
 type ssaExport struct {
        log           bool
        unimplemented bool
+       mustImplement bool
 }
 
 // StringSym returns a symbol (a *Sym wrapped in an interface) which
@@ -1929,6 +1940,9 @@ func (e *ssaExport) Fatalf(msg string, args ...interface{}) {
 // Unimplemented reports that the function cannot be compiled.
 // It will be removed once SSA work is complete.
 func (e *ssaExport) Unimplementedf(msg string, args ...interface{}) {
+       if e.mustImplement {
+               Fatal(msg, args...)
+       }
        const alwaysLog = false // enable to calculate top unimplemented features
        if !e.unimplemented && (e.log || alwaysLog) {
                // first implementation failure, print explanation
index c9e543ba37873561979d683c37b711f3294baf75..78e3295ed8a58d4a3ef6edab8c81e89fdc8ec6b4 100644 (file)
@@ -60,6 +60,8 @@ func NewConfig(arch string, fe Frontend) *Config {
        return c
 }
 
+func (c *Config) Frontend() Frontend { return c.fe }
+
 // NewFunc returns a new, empty function object
 func (c *Config) NewFunc() *Func {
        // TODO(khr): should this function take name, type, etc. as arguments?