]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile/internal/ssa: implement OCFUNC
authorTodd Neal <todd@tneal.org>
Tue, 8 Sep 2015 00:07:02 +0000 (19:07 -0500)
committerTodd Neal <todd@tneal.org>
Thu, 10 Sep 2015 00:25:31 +0000 (00:25 +0000)
Change-Id: Ieb9cddf8876bf8cd5ee1705d9210d22c3959e8cc
Reviewed-on: https://go-review.googlesource.com/14329
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Todd Neal <todd@tneal.org>

src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/ssa_test.go
src/cmd/compile/internal/gc/testdata/closure_ssa.go [new file with mode: 0644]

index 386420f26b56654eb56bd098445a842a5dd9ea82..4fe8ba88366662e6dad60241b086ecb6950cc281 100644 (file)
@@ -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
index 0bce902982a9c11ebb366460828036b54fd31d47..feaea8b463dfda180a016edf5545ef87ca88b4f7 100644 (file)
@@ -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 (file)
index 0000000..ac1e51a
--- /dev/null
@@ -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")
+       }
+}