aboutsummaryrefslogtreecommitdiff
path: root/src/pkg
diff options
context:
space:
mode:
authorAlan Donovan <adonovan@google.com>2013-02-22 00:09:21 -0500
committerAlan Donovan <adonovan@google.com>2013-02-22 00:09:21 -0500
commitd9001ef012aabcd28c66a2d1f321078f45a2ffac (patch)
treeca132028b2b295b3a2d97801d7aac385f1e1d55e /src/pkg
parented1ac056735e67c0f6bc23c60a9c2a0f999c80cb (diff)
downloadgo-d9001ef012aabcd28c66a2d1f321078f45a2ffac.tar.xz
exp/ssa: cross off a few remaining TODO issues.
- append: nothing to do (nonsemantic change). - delete: now performs correct conversion (+ test). - emitCompare: nothing to do. - emitArith (shifts): nothing to do (+ test). - "banish untyped types": give up on that. - real, imag: now do correct conversions. - added comment to interp.go re zero-size values. R=gri CC=golang-dev https://golang.org/cl/7391046
Diffstat (limited to 'src/pkg')
-rw-r--r--src/pkg/exp/ssa/builder.go50
-rw-r--r--src/pkg/exp/ssa/emit.go2
-rw-r--r--src/pkg/exp/ssa/interp/interp.go4
-rw-r--r--src/pkg/exp/ssa/interp/testdata/coverage.go28
4 files changed, 63 insertions, 21 deletions
diff --git a/src/pkg/exp/ssa/builder.go b/src/pkg/exp/ssa/builder.go
index d8c17be500..a00a9e3443 100644
--- a/src/pkg/exp/ssa/builder.go
+++ b/src/pkg/exp/ssa/builder.go
@@ -31,15 +31,10 @@ package ssa
// It uses a mutex so that access from multiple threads is serialized.
// TODO(adonovan): fix the following:
-// - append, delete details.
// - support f(g()) where g has multiple result parameters.
-// - finish emitCompare, emitArith.
-// - banish "untyped" types everywhere except package/universal constants?
// - concurrent SSA code generation of multiple packages.
// - consider function-local NamedTypes.
// They can have nonempty method-sets due to promotion. Test.
-// - polish.
-// - tests.
import (
"fmt"
@@ -58,6 +53,8 @@ var (
tByte = types.Typ[types.Byte]
tFloat32 = types.Typ[types.Float32]
tFloat64 = types.Typ[types.Float64]
+ tComplex64 = types.Typ[types.Complex64]
+ tComplex128 = types.Typ[types.Complex128]
tInt = types.Typ[types.Int]
tInvalid = types.Typ[types.Invalid]
tUntypedNil = types.Typ[types.UntypedNil]
@@ -1128,17 +1125,21 @@ func (b *Builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {
var bptypes []types.Type // formal parameter types of builtins
switch builtin := e.Fun.(*ast.Ident).Name; builtin {
case "append":
- // append([]T, ...T) []T
- // append([]byte, string...) []byte // TODO(adonovan): fix: support.
// Infer arg types from result type:
rt := b.exprType(e)
- vt = underlyingType(rt).(*types.Slice).Elt // variadic
- if !c.HasEllipsis {
+ bptypes = append(bptypes, rt)
+ if c.HasEllipsis {
+ // 2-arg '...' call form. No conversions.
+ // append([]T, []T) []T
+ // append([]byte, string) []byte
+ } else {
+ // variadic call form.
+ // append([]T, ...T) []T
args, varargs = args[:1], args[1:]
+ vt = underlyingType(rt).(*types.Slice).Elt
}
- bptypes = append(bptypes, rt)
case "close":
- bptypes = append(bptypes, nil) // no conv
+ // no conv
case "copy":
// copy([]T, []T) int
// Infer arg types from each other. Sleazy.
@@ -1151,22 +1152,33 @@ func (b *Builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {
}
case "delete":
// delete(map[K]V, K)
- // TODO(adonovan): fix: this is incorrect.
- bptypes = append(bptypes, nil) // map
- bptypes = append(bptypes, nil) // key
+ tkey := underlyingType(b.exprType(args[0])).(*types.Map).Key
+ bptypes = append(bptypes, nil) // map: no conv
+ bptypes = append(bptypes, tkey) // key
case "print", "println": // print{,ln}(any, ...any)
vt = tEface // variadic
if !c.HasEllipsis {
args, varargs = args[:1], args[1:]
}
case "len":
- bptypes = append(bptypes, nil) // no conv
+ // no conv
case "cap":
- bptypes = append(bptypes, nil) // no conv
+ // no conv
case "real", "imag":
- // TODO(adonovan): fix: apply reverse conversion
- // to "complex" case below.
- bptypes = append(bptypes, nil)
+ // Reverse conversion to "complex" case below.
+ // Typechecker, help us out. :(
+ var argType types.Type
+ switch b.exprType(e).(*types.Basic).Kind {
+ case types.UntypedFloat:
+ argType = types.Typ[types.UntypedComplex]
+ case types.Float64:
+ argType = tComplex128
+ case types.Float32:
+ argType = tComplex64
+ default:
+ unreachable()
+ }
+ bptypes = append(bptypes, argType, argType)
case "complex":
// Typechecker, help us out. :(
var argType types.Type
diff --git a/src/pkg/exp/ssa/emit.go b/src/pkg/exp/ssa/emit.go
index d361463d98..7070c18b42 100644
--- a/src/pkg/exp/ssa/emit.go
+++ b/src/pkg/exp/ssa/emit.go
@@ -34,7 +34,6 @@ func emitLoad(f *Function, addr Value) Value {
func emitArith(f *Function, op token.Token, x, y Value, t types.Type) Value {
switch op {
case token.SHL, token.SHR:
- // TODO(adonovan): fix: is this correct?
x = emitConv(f, x, t)
y = emitConv(f, y, types.Typ[types.Uint64])
@@ -59,7 +58,6 @@ func emitArith(f *Function, op token.Token, x, y Value, t types.Type) Value {
// comparison comparison 'x op y'.
//
func emitCompare(f *Function, op token.Token, x, y Value) Value {
- // TODO(adonovan): fix: this is incomplete.
xt := underlyingType(x.Type())
yt := underlyingType(y.Type())
diff --git a/src/pkg/exp/ssa/interp/interp.go b/src/pkg/exp/ssa/interp/interp.go
index 0fa4316bf0..c20ddb9622 100644
--- a/src/pkg/exp/ssa/interp/interp.go
+++ b/src/pkg/exp/ssa/interp/interp.go
@@ -35,6 +35,10 @@
// program are assumed to be the same as those of the interpreter
// itself.
//
+// * all values occupy space, even those of types defined by the spec
+// to have zero size, e.g. struct{}. This can cause asymptotic
+// performance degradation.
+//
// * os.Exit is implemented using panic, causing deferred functions to
// run.
package interp
diff --git a/src/pkg/exp/ssa/interp/testdata/coverage.go b/src/pkg/exp/ssa/interp/testdata/coverage.go
index 7573e0f69e..1ef82e9cf8 100644
--- a/src/pkg/exp/ssa/interp/testdata/coverage.go
+++ b/src/pkg/exp/ssa/interp/testdata/coverage.go
@@ -292,3 +292,31 @@ func init() {
panic(c)
}
}
+
+// Shifts.
+func init() {
+ var i int64 = 1
+ var u uint64 = 1 << 32
+ if x := i << uint32(u); x != 1 {
+ panic(x)
+ }
+ if x := i << uint64(u); x != 0 {
+ panic(x)
+ }
+}
+
+// Implicit conversion of delete() key operand.
+func init() {
+ type I interface{}
+ m := make(map[I]bool)
+ m[1] = true
+ m[I(2)] = true
+ if len(m) != 2 {
+ panic(m)
+ }
+ delete(m, I(1))
+ delete(m, 2)
+ if len(m) != 0 {
+ panic(m)
+ }
+}