From: Todd Neal Date: Tue, 8 Sep 2015 00:07:02 +0000 (-0500) Subject: [dev.ssa] cmd/compile/internal/ssa: implement OCFUNC X-Git-Tag: go1.7beta1~1623^2^2~179 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=def7c65b7062f5c087c4e348768ee4c464b79b91;p=gostls13.git [dev.ssa] cmd/compile/internal/ssa: implement OCFUNC Change-Id: Ieb9cddf8876bf8cd5ee1705d9210d22c3959e8cc Reviewed-on: https://go-review.googlesource.com/14329 Reviewed-by: Keith Randall Run-TryBot: Todd Neal --- diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 386420f26b..4fe8ba8836 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1203,6 +1203,9 @@ func (s *state) expr(n *Node) *ssa.Value { s.stmtList(n.Ninit) switch n.Op { + case OCFUNC: + aux := &ssa.ExternSymbol{n.Type, n.Left.Sym} + return s.entryNewValue1A(ssa.OpAddr, n.Type, aux, s.sb) case ONAME: if n.Class == PFUNC { // "value" of a function is the address of the function's closure @@ -1296,16 +1299,17 @@ func (s *state) expr(n *Node) *ssa.Value { case OCONVNOP: to := n.Type from := n.Left.Type - if to.Etype == TFUNC { - s.Unimplementedf("CONVNOP closure") - return nil - } // Assume everything will work out, so set up our return value. // Anything interesting that happens from here is a fatal. x := s.expr(n.Left) v := s.newValue1(ssa.OpCopy, to, x) // ensure that v has the right type + // CONVNOP closure + if to.Etype == TFUNC && from.IsPtr() { + return v + } + // named <--> unnamed type or typed <--> untyped const if from.Etype == to.Etype { return v diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index 0bce902982..feaea8b463 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -78,3 +78,6 @@ func TestRegalloc(t *testing.T) { runTest(t, "regalloc_ssa.go") } func TestString(t *testing.T) { runTest(t, "string_ssa.go") } func TestDeferNoReturn(t *testing.T) { buildTest(t, "deferNoReturn_ssa.go") } + +// TestClosure tests closure related behavior. +func TestClosure(t *testing.T) { runTest(t, "closure_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/closure_ssa.go b/src/cmd/compile/internal/gc/testdata/closure_ssa.go new file mode 100644 index 0000000000..ac1e51a23e --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/closure_ssa.go @@ -0,0 +1,39 @@ +// Copyright 2015 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. + +// map_ssa.go tests map operations. +package main + +import "fmt" + +var failed = false + +func testCFunc_ssa() int { + switch { // prevent inlining + } + a := 0 + b := func() { + switch { + } + a++ + } + b() + b() + return a +} + +func testCFunc() { + if want, got := 2, testCFunc_ssa(); got != want { + fmt.Printf("expected %d, got %d", want, got) + failed = true + } +} + +func main() { + testCFunc() + + if failed { + panic("failed") + } +}