summaryrefslogtreecommitdiff
path: root/src/cmd/gc
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-05-23 09:45:29 +0200
committerOndřej Surý <ondrej@sury.org>2011-05-23 09:45:29 +0200
commit63d29fefab5290dc96e0a03ff70603aefa995887 (patch)
tree95da0105686f9aba568a72e7a8ebd580a4fda20e /src/cmd/gc
parentad811fbb8897a9a3063274e927133915941f1dca (diff)
downloadgolang-63d29fefab5290dc96e0a03ff70603aefa995887.tar.gz
Imported Upstream version 2011.05.22upstream-weekly/2011.05.22
Diffstat (limited to 'src/cmd/gc')
-rw-r--r--src/cmd/gc/builtin.c.boot4
-rw-r--r--src/cmd/gc/go.h1
-rw-r--r--src/cmd/gc/runtime.go1
-rw-r--r--src/cmd/gc/subr.c14
-rw-r--r--src/cmd/gc/swt.c5
-rw-r--r--src/cmd/gc/typecheck.c21
-rw-r--r--src/cmd/gc/unsafe.c1
-rw-r--r--src/cmd/gc/walk.c146
8 files changed, 131 insertions, 62 deletions
diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot
index bdbca7f78..c9bf501d1 100644
--- a/src/cmd/gc/builtin.c.boot
+++ b/src/cmd/gc/builtin.c.boot
@@ -1,5 +1,6 @@
char *runtimeimport =
"package runtime\n"
+ "import runtime \"runtime\"\n"
"func \"\".new (? int32) *any\n"
"func \"\".panicindex ()\n"
"func \"\".panicslice ()\n"
@@ -21,7 +22,6 @@ char *runtimeimport =
"func \"\".printsp ()\n"
"func \"\".goprintf ()\n"
"func \"\".concatstring ()\n"
- "func \"\".append ()\n"
"func \"\".appendslice (typ *uint8, x any, y []any) any\n"
"func \"\".cmpstring (? string, ? string) int\n"
"func \"\".slicestring (? string, ? int, ? int) string\n"
@@ -81,6 +81,7 @@ char *runtimeimport =
"func \"\".selectgo (sel *uint8)\n"
"func \"\".block ()\n"
"func \"\".makeslice (typ *uint8, nel int64, cap int64) []any\n"
+ "func \"\".growslice (typ *uint8, old []any, cap int64) []any\n"
"func \"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n"
"func \"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n"
"func \"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n"
@@ -98,6 +99,7 @@ char *runtimeimport =
"$$\n";
char *unsafeimport =
"package unsafe\n"
+ "import runtime \"runtime\"\n"
"type \"\".Pointer uintptr\n"
"func \"\".Offsetof (? any) int\n"
"func \"\".Sizeof (? any) int\n"
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index f58b76789..359881e11 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -225,6 +225,7 @@ struct Node
Type* realtype; // as determined by typecheck
NodeList* list;
NodeList* rlist;
+ Node* orig; // original form, for printing
// for-body
NodeList* ninit;
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index 35d11eca9..00fc720b8 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -110,6 +110,7 @@ func selectgo(sel *byte)
func block()
func makeslice(typ *byte, nel int64, cap int64) (ary []any)
+func growslice(typ *byte, old []any, n int64) (ary []any)
func sliceslice1(old []any, lb uint64, width uint64) (ary []any)
func sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
func slicearray(old *any, nel uint64, lb uint64, hb uint64, width uint64) (ary []any)
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index bb2505694..326a5ba74 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -1073,6 +1073,9 @@ Jconv(Fmt *fp)
if(n->implicit != 0)
fmtprint(fp, " implicit(%d)", n->implicit);
+ if(n->pun != 0)
+ fmtprint(fp, " pun(%d)", n->pun);
+
return 0;
}
@@ -1141,7 +1144,7 @@ Tpretty(Fmt *fp, Type *t)
Type *t1;
Sym *s;
- if(debug['r']) {
+ if(0 && debug['r']) {
debug['r'] = 0;
fmtprint(fp, "%T (orig=%T)", t, t->orig);
debug['r'] = 1;
@@ -1454,6 +1457,8 @@ Nconv(Fmt *fp)
}
if(fp->flags & FmtSharp) {
+ if(n->orig != N)
+ n = n->orig;
exprfmt(fp, n, 0);
goto out;
}
@@ -3107,7 +3112,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
Type *tpad;
int isddd;
- if(debug['r'])
+ if(0 && debug['r'])
print("genwrapper rcvrtype=%T method=%T newnam=%S\n",
rcvr, method, newnam);
@@ -3161,7 +3166,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
fn->nbody = list1(n);
}
- if(debug['r'])
+ if(0 && debug['r'])
dumplist("genwrapper body", fn->nbody);
funcbody(fn);
@@ -3256,8 +3261,9 @@ implements(Type *t, Type *iface, Type **m, Type **samename, int *ptr)
// the method does not exist for value types.
rcvr = getthisx(tm->type)->type->type;
if(isptr[rcvr->etype] && !isptr[t0->etype] && !followptr && !isifacemethod(tm->type)) {
- if(debug['r'])
+ if(0 && debug['r'])
yyerror("interface pointer mismatch");
+
*m = im;
*samename = nil;
*ptr = 1;
diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c
index 6e8436c3c..c2968c44b 100644
--- a/src/cmd/gc/swt.c
+++ b/src/cmd/gc/swt.c
@@ -867,8 +867,11 @@ typecheckswitch(Node *n)
case Etype: // type switch
if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL))
;
- else if(ll->n->op != OTYPE && ll->n->type != T)
+ else if(ll->n->op != OTYPE && ll->n->type != T) {
yyerror("%#N is not a type", ll->n);
+ // reset to original type
+ ll->n = n->ntest->right;
+ }
break;
}
}
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index c48bf7a29..9aaf3e6ef 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -894,12 +894,20 @@ reswitch:
// might be constant
switch(t->etype) {
case TSTRING:
- if(isconst(l, CTSTR))
- nodconst(n, types[TINT], l->val.u.sval->len);
+ if(isconst(l, CTSTR)) {
+ r = nod(OXXX, N, N);
+ nodconst(r, types[TINT], l->val.u.sval->len);
+ r->orig = n;
+ n = r;
+ }
break;
case TARRAY:
- if(t->bound >= 0 && l->op == ONAME)
- nodconst(n, types[TINT], t->bound);
+ if(t->bound >= 0 && l->op == ONAME) {
+ r = nod(OXXX, N, N);
+ nodconst(r, types[TINT], t->bound);
+ r->orig = n;
+ n = r;
+ }
break;
}
n->type = types[TINT];
@@ -1357,7 +1365,10 @@ ret:
goto error;
}
if((top & Etop) && !(top & (Ecall|Erv|Etype)) && !(ok & Etop)) {
- yyerror("%#N not used", n);
+ if(n->diag == 0) {
+ yyerror("%#N not used", n);
+ n->diag = 1;
+ }
goto error;
}
diff --git a/src/cmd/gc/unsafe.c b/src/cmd/gc/unsafe.c
index 33f375631..540994ddd 100644
--- a/src/cmd/gc/unsafe.c
+++ b/src/cmd/gc/unsafe.c
@@ -41,6 +41,7 @@ unsafenmagic(Node *nn)
tr = r->type;
if(tr == T)
goto bad;
+ dowidth(tr);
v = tr->width;
goto yes;
}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 278eef414..b3b400556 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -18,12 +18,13 @@ static NodeList* paramstoheap(Type **argin, int out);
static NodeList* reorder1(NodeList*);
static NodeList* reorder3(NodeList*);
static Node* addstr(Node*, NodeList**);
+static Node* appendslice(Node*, NodeList**);
static Node* append(Node*, NodeList**);
static NodeList* walkdefstack;
// can this code branch reach the end
-// without an undcontitional RETURN
+// without an unconditional RETURN
// this is hard, so it is conservative
static int
walkret(NodeList *l)
@@ -805,18 +806,17 @@ walkexpr(Node **np, NodeList **init)
n->ninit = nil;
walkexpr(&n->left, init);
n->left = safeexpr(n->left, init);
+
if(oaslit(n, init))
goto ret;
+
walkexpr(&n->right, init);
- l = n->left;
- r = n->right;
- if(l == N || r == N)
- goto ret;
- r = ascompatee1(n->op, l, r, init);
- if(r != N) {
+ if(n->left != N && n->right != N) {
+ r = convas(nod(OAS, n->left, n->right), init);
r->dodata = n->dodata;
n = r;
}
+
goto ret;
case OAS2:
@@ -1134,6 +1134,7 @@ walkexpr(Node **np, NodeList **init)
case OINDEXMAP:
if(n->etype == 1)
goto ret;
+
t = n->left->type;
n = mkcall1(mapfn("mapaccess1", t), t->type, init, n->left, n->right);
goto ret;
@@ -1188,6 +1189,7 @@ walkexpr(Node **np, NodeList **init)
// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
// sliceslice1(old []any, lb uint64, width uint64) (ary []any)
t = n->type;
+ et = n->etype;
if(n->right->left == N)
l = nodintconst(0);
else
@@ -1210,6 +1212,7 @@ walkexpr(Node **np, NodeList **init)
l,
nodintconst(t->type->width));
}
+ n->etype = et; // preserve no-typecheck flag from OSLICE to the slice* call.
goto ret;
slicearray:
@@ -1332,7 +1335,10 @@ walkexpr(Node **np, NodeList **init)
goto ret;
case OAPPEND:
- n = append(n, init);
+ if(n->isddd)
+ n = appendslice(n, init);
+ else
+ n = append(n, init);
goto ret;
case OCOPY:
@@ -1953,23 +1959,18 @@ callnew(Type *t)
static Node*
convas(Node *n, NodeList **init)
{
- Node *l, *r;
Type *lt, *rt;
if(n->op != OAS)
fatal("convas: not OAS %O", n->op);
- n->typecheck = 1;
- lt = T;
- rt = T;
+ n->typecheck = 1;
- l = n->left;
- r = n->right;
- if(l == N || r == N)
+ if(n->left == N || n->right == N)
goto out;
- lt = l->type;
- rt = r->type;
+ lt = n->left->type;
+ rt = n->right->type;
if(lt == T || rt == T)
goto out;
@@ -1987,7 +1988,7 @@ convas(Node *n, NodeList **init)
if(eqtype(lt, rt))
goto out;
- n->right = assignconv(r, lt, "assignment");
+ n->right = assignconv(n->right, lt, "assignment");
walkexpr(&n->right, init);
out:
@@ -2365,42 +2366,85 @@ addstr(Node *n, NodeList **init)
}
static Node*
-append(Node *n, NodeList **init)
+appendslice(Node *n, NodeList **init)
{
- int i, j;
- Node *f, *r;
- NodeList *in, *args;
+ Node *f;
- if(n->isddd) {
- f = syslook("appendslice", 1);
- argtype(f, n->type);
- argtype(f, n->type->type);
- argtype(f, n->type);
- r = mkcall1(f, n->type, init, typename(n->type), n->list->n, n->list->next->n);
- return r;
+ f = syslook("appendslice", 1);
+ argtype(f, n->type);
+ argtype(f, n->type->type);
+ argtype(f, n->type);
+ return mkcall1(f, n->type, init, typename(n->type), n->list->n, n->list->next->n);
+}
+
+// expand append(src, a [, b]* ) to
+//
+// init {
+// s := src
+// const argc = len(args) - 1
+// if cap(s) - len(s) < argc {
+// s = growslice(s, argc)
+// }
+// n := len(s)
+// s = s[:n+argc]
+// s[n] = a
+// s[n+1] = b
+// ...
+// }
+// s
+static Node*
+append(Node *n, NodeList **init)
+{
+ NodeList *l, *a;
+ Node *nsrc, *ns, *nn, *na, *nx, *fn;
+ int argc;
+
+ walkexprlistsafe(n->list, init);
+
+ nsrc = n->list->n;
+ argc = count(n->list) - 1;
+ if (argc < 1) {
+ return nsrc;
}
- j = count(n->list) - 1;
- f = syslook("append", 1);
- f->type = T;
- f->ntype = nod(OTFUNC, N, N);
- in = list1(nod(ODCLFIELD, N, typenod(ptrto(types[TUINT8])))); // type
- in = list(in, nod(ODCLFIELD, N, typenod(types[TINT]))); // count
- in = list(in, nod(ODCLFIELD, N, typenod(n->type))); // slice
- for(i=0; i<j; i++)
- in = list(in, nod(ODCLFIELD, N, typenod(n->type->type)));
- f->ntype->list = in;
- f->ntype->rlist = list1(nod(ODCLFIELD, N, typenod(n->type)));
-
- args = list1(typename(n->type));
- args = list(args, nodintconst(j));
- args = concat(args, n->list);
-
- r = nod(OCALL, f, N);
- r->list = args;
- typecheck(&r, Erv);
- walkexpr(&r, init);
- r->type = n->type;
+ l = nil;
- return r;
+ ns = nod(OXXX, N, N); // var s
+ tempname(ns, nsrc->type);
+ l = list(l, nod(OAS, ns, nsrc)); // s = src
+
+ na = nodintconst(argc); // const argc
+ nx = nod(OIF, N, N); // if cap(s) - len(s) < argc
+ nx->ntest = nod(OLT, nod(OSUB, nod(OCAP, ns, N), nod(OLEN, ns, N)), na);
+
+ fn = syslook("growslice", 1); // growslice(<type>, old []T, n int64) (ret []T)
+ argtype(fn, ns->type->type); // 1 old []any
+ argtype(fn, ns->type->type); // 2 ret []any
+
+ nx->nbody = list1(nod(OAS, ns, mkcall1(fn, ns->type, &nx->ninit,
+ typename(ns->type),
+ ns,
+ conv(na, types[TINT64]))));
+ l = list(l, nx);
+
+ nn = nod(OXXX, N, N); // var n
+ tempname(nn, types[TINT]);
+ l = list(l, nod(OAS, nn, nod(OLEN, ns, N))); // n = len(s)
+
+ nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na))); // ...s[:n+argc]
+ nx->etype = 1; // disable bounds check
+ l = list(l, nod(OAS, ns, nx)); // s = s[:n+argc]
+
+ for (a = n->list->next; a != nil; a = a->next) {
+ nx = nod(OINDEX, ns, nn); // s[n] ...
+ nx->etype = 1; // disable bounds check
+ l = list(l, nod(OAS, nx, a->n)); // s[n] = arg
+ if (a->next != nil)
+ l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1)))); // n = n + 1
+ }
+
+ typechecklist(l, Etop);
+ walkstmtlist(l);
+ *init = concat(*init, l);
+ return ns;
}