]> Cypherpunks repositories - gostls13.git/commitdiff
first version of closures. test/closure doesn't yet pass.
authorKai Backman <kaib@golang.org>
Tue, 20 Oct 2009 02:59:39 +0000 (19:59 -0700)
committerKai Backman <kaib@golang.org>
Tue, 20 Oct 2009 02:59:39 +0000 (19:59 -0700)
go/test: passes 87% (300/343)

R=rsc
APPROVED=rsc
DELTA=125  (125 added, 0 deleted, 0 changed)
OCL=35893
CL=35900

src/pkg/runtime/arm/closure.c
test/arm-pass.txt

index bfa9df67f0530880c837dc5f1d0ab2514ca9c418..b0aa2ad8b08d82ad07b3a025ded8525ba60fb97f 100644 (file)
@@ -1,3 +1,125 @@
 // Copyright 2009 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.
+
+#include "runtime.h"
+
+/*
+       There are two bits of magic:
+       - The signature of the compiler generated function uses two stack frames
+       as arguments (callerpc separates these frames)
+       - size determines how many arguments runtime.closure actually has
+       starting at arg0.
+
+       Example closure with 3 captured variables:
+       func closure(siz int32,
+       fn func(arg0, arg1, arg2 *ptr, callerpc uintptr, xxx) yyy,
+               arg0, arg1, arg2 *ptr) (func(xxx) yyy)
+
+       Code generated:
+       src R0
+       dst R1
+       end R3
+       tmp R4
+       frame = siz+4
+
+//skip loop for 0 size closures
+               MOVW.W  R14,-frame(R13)
+
+               MOVW    $vars(PC), R0
+               MOVW    $4(SP), R1
+               MOVW    $siz(R0), R3
+loop:          MOVW.P  4(R0), R4
+               MOVW.P  R4, 4(R1)
+               CMP             R0, R3
+               BNE             loop
+
+               MOVW    8(PC), R0
+               BL              (R0)                    // 2 words
+               MOVW.P  frame(R13),R15
+fptr:          WORD    *fn
+vars:          WORD    arg0
+               WORD    arg1
+               WORD    arg2
+*/
+
+#pragma textflag 7
+void
+runtime·closure(int32 siz, byte *fn, byte *arg0)
+{
+       byte *p, *q, **ret;
+       uint32 *pc;
+       int32 n;
+
+       if(siz < 0 || siz%4 != 0)
+               throw("bad closure size");
+
+       ret = (byte**)((byte*)&arg0 + siz);
+
+       if(siz > 100) {
+               // TODO(kaib): implement stack growth preamble?
+               throw("closure too big");
+       }
+
+       // size of new fn.
+       // must match code laid out below.
+       if (siz > 0)
+               n = 6 * 4 + 7 * 4;
+       else
+               n = 6 * 4;
+
+       // store args aligned after code, so gc can find them.
+       n += siz;
+
+       p = mal(n);
+       *ret = p;
+       q = p + n - siz;
+
+       pc = (uint32*)p;
+
+       //      MOVW.W  R14,-frame(R13)
+       *pc++ = 0xe52de000 | (siz + 4);
+
+       if(siz > 0) {
+               mcpy(q, (byte*)&arg0, siz);
+
+               //      MOVW    $vars(PC), R0
+               *pc = 0xe28f0000 | (int32)(q - (byte*)pc - 8);
+               pc++;
+
+               //      MOVW    $4(SP), R1
+               *pc++ = 0xe28d1004;
+
+               //      MOVW    $siz(R0), R3
+               *pc++ = 0xe2803000 | siz;
+
+               //      MOVW.P  4(R0), R4
+               *pc++ = 0xe4904004;
+               //      MOVW.P  R4, 4(R1)
+               *pc++ = 0xe4814004;
+               //      CMP             R0, R3
+               *pc++ = 0xe1530000;
+               //      BNE             loop
+               *pc++ = 0x1afffffb;
+       }
+
+       //      MOVW    fptr(PC), R0
+       *pc = 0xe59f0008 | (int32)((q - 4) -(byte*) pc - 8);
+       pc++;
+
+       //      BL              (R0)
+       *pc++ = 0xe28fe000;
+       *pc++ = 0xe280f000;
+
+       //      MOVW.P  frame(R13),R15
+       *pc++ = 0xe49df000 | (siz + 4);
+
+       //      WORD    *fn
+       *pc++ = (uint32)fn;
+
+       p = (byte*)pc;
+
+       if(p > q)
+               throw("bad math in sys.closure");
+}
+
index 626051019a812074178c98326180149164d1795d..6930db1a9c07b1ff50d487d2b9e88cf492c956e0 100644 (file)
@@ -27,6 +27,7 @@ convlit1.go
 decl.go
 declbad.go
 empty.go
+env.go
 escape1.go
 fixedbugs/bug000.go
 fixedbugs/bug001.go
@@ -83,6 +84,7 @@ fixedbugs/bug063.go
 fixedbugs/bug064.go
 fixedbugs/bug065.go
 fixedbugs/bug066.go
+fixedbugs/bug067.go
 fixedbugs/bug068.go
 fixedbugs/bug069.go
 fixedbugs/bug070.go
@@ -253,6 +255,7 @@ ken/interbasic.go
 ken/interfun.go
 ken/intervar.go
 ken/label.go
+ken/litfun.go
 ken/mfunc.go
 ken/ptrfun.go
 ken/ptrvar.go