From: Josh Bleecher Snyder Date: Wed, 22 Jul 2015 20:13:53 +0000 (-0700) Subject: [dev.ssa] cmd/compile: add GOSSAFUNC and GOSSAPKG X-Git-Tag: go1.7beta1~1623^2^2~358 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=d298209b1c22e970adb19761c924f3301ca7e252;p=gostls13.git [dev.ssa] cmd/compile: add GOSSAFUNC and GOSSAPKG 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 [1] 8 genValue not implemented: MOVQstoreidx8 4 branch not implemented: If v -> b b. Control: SETG 3 branch not implemented: If v -> b b. Control: SETLE 2 load flags not implemented: LoadReg8 2 genValue not implemented: InvertFlags 1 store flags not implemented: StoreReg8 1 branch not implemented: If v -> b b. Control: SETGE Change-Id: Ib64809ac0c917e25bcae27829ae634c70d290c7f Reviewed-on: https://go-review.googlesource.com/12547 Reviewed-by: Keith Randall --- diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index d6c0bc7c59..6871fc48cd 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -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 diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index c9e543ba37..78e3295ed8 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -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?