mirror of
https://github.com/golang/go.git
synced 2025-05-29 03:11:26 +00:00
[dev.ssa] cmd/compile/internal/ssa: implement OCFUNC
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>
This commit is contained in:
parent
adba6c4fdf
commit
def7c65b70
@ -1203,6 +1203,9 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||||||
|
|
||||||
s.stmtList(n.Ninit)
|
s.stmtList(n.Ninit)
|
||||||
switch n.Op {
|
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:
|
case ONAME:
|
||||||
if n.Class == PFUNC {
|
if n.Class == PFUNC {
|
||||||
// "value" of a function is the address of the function's closure
|
// "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:
|
case OCONVNOP:
|
||||||
to := n.Type
|
to := n.Type
|
||||||
from := n.Left.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.
|
// Assume everything will work out, so set up our return value.
|
||||||
// Anything interesting that happens from here is a fatal.
|
// Anything interesting that happens from here is a fatal.
|
||||||
x := s.expr(n.Left)
|
x := s.expr(n.Left)
|
||||||
v := s.newValue1(ssa.OpCopy, to, x) // ensure that v has the right type
|
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
|
// named <--> unnamed type or typed <--> untyped const
|
||||||
if from.Etype == to.Etype {
|
if from.Etype == to.Etype {
|
||||||
return v
|
return v
|
||||||
|
@ -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 TestString(t *testing.T) { runTest(t, "string_ssa.go") }
|
||||||
|
|
||||||
func TestDeferNoReturn(t *testing.T) { buildTest(t, "deferNoReturn_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") }
|
||||||
|
39
src/cmd/compile/internal/gc/testdata/closure_ssa.go
vendored
Normal file
39
src/cmd/compile/internal/gc/testdata/closure_ssa.go
vendored
Normal file
@ -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")
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user