shithub: mc

Download patch

ref: 8c2fb645b95fa69e53e910102c601f3a80007251
parent: bc18d36c3cf2e2ceea1e78a21242423d6878ed12
author: Ori Bernstein <[email protected]>
date: Tue Jun 18 08:59:26 EDT 2013

Move away from literal types that aren't actual compile time constants.

--- a/6/isel.c
+++ b/6/isel.c
@@ -34,7 +34,9 @@
 
 /* forward decls */
 Loc *selexpr(Isel *s, Node *n);
+static void writeblob(FILE *fd, Node *blob);
 
+
 /* used to decide which operator is appropriate
  * for implementing various conditional operators */
 struct {
@@ -84,16 +86,16 @@
 
     switch (exprop(n)) {
         case Ovar:
-            if (hthas(s->stkoff, n)) {
-                stkoff = (ssize_t)htget(s->stkoff, n);
-                l = locmem(-stkoff, locphysreg(Rrbp), NULL, mode(n));
-            } else if (hthas(s->globls, n)) {
+            if (hthas(s->globls, n)) {
                 if (tybase(exprtype(n))->type == Tyfunc)
                     rip = NULL;
                 else
                     rip = locphysreg(Rrip);
                 l = locmeml(htget(s->globls, n), rip, NULL, mode(n));
-            } else {
+            } else if (hthas(s->stkoff, n)) {
+                stkoff = (ssize_t)htget(s->stkoff, n);
+                l = locmem(-stkoff, locphysreg(Rrbp), NULL, mode(n));
+            }  else {
                 if (!hthas(s->reglocs, n))
                     htput(s->reglocs, n, locreg(mode(n)));
                 return htget(s->reglocs, n);
@@ -614,7 +616,7 @@
         case Osubeq: case Omuleq: case Odiveq: case Omodeq: case Oboreq:
         case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb:
         case Oslice: case Oidx: case Osize: case Numops:
-        case Oucon: case Ouget: case Otup: case Oarr:
+        case Oucon: case Ouget: case Otup: case Oarr: case Ostruct:
         case Oslbase: case Osllen: case Ocast:
             dump(n, stdout);
             die("Should not see %s in isel", opstr(exprop(n)));
@@ -854,7 +856,7 @@
     return as;
 }
 
-static void writeblob(FILE *fd, char *p, size_t sz)
+static void writebytes(FILE *fd, char *p, size_t sz)
 {
     size_t i;
 
@@ -861,8 +863,8 @@
     for (i = 0; i < sz; i++) {
         if (i % 60 == 0)
             fprintf(fd, "\t.ascii \"");
-	if (p[i] == '"')
-	    fprintf(fd, "\\");
+        if (p[i] == '"')
+            fprintf(fd, "\\");
         if (isprint(p[i]))
             fprintf(fd, "%c", p[i]);
         else
@@ -876,8 +878,6 @@
 static void writelit(FILE *fd, Node *v, size_t sz)
 {
     char lbl[128];
-    size_t i;
-    Node *val;
     char *intsz[] = {
         [1] = ".byte",
         [2] = ".short",
@@ -887,27 +887,15 @@
 
     assert(v->type == Nlit);
     switch (v->lit.littype) {
+        case Lint:      fprintf(fd, "\t%s %lld\n", intsz[sz], v->lit.intval);    break;
         case Lbool:     fprintf(fd, "\t.byte %d\n", v->lit.boolval);     break;
         case Lchr:      fprintf(fd, "\t.long %d\n",  v->lit.chrval);     break;
-        case Lint:      fprintf(fd, "\t%s %lld\n", intsz[sz], v->lit.intval);    break;
         case Lflt:      fprintf(fd, "\t.double %f\n", v->lit.fltval);    break;
         case Lstr:      fprintf(fd, "\t.quad %s\n", genlblstr(lbl, 128));
                         fprintf(fd, "\t.quad %zd\n", strlen(v->lit.strval));
                         fprintf(fd, "%s:\n", lbl);
-                        writeblob(fd, v->lit.strval, strlen(v->lit.strval));
+                        writebytes(fd, v->lit.strval, strlen(v->lit.strval));
                         break;
-        case Larray:
-            for (i = 0; i < v->lit.nelt; i++) {
-                val = v->lit.seqval[i]->idxinit.init;
-                writelit(fd, val->expr.args[0], size(val));
-            }
-            break;
-        case Lstruct:
-            for (i = 0; i < v->lit.nelt; i++) {
-                val = v->lit.seqval[i]->idxinit.init;
-                writelit(fd, val->expr.args[0], size(val));
-            }
-            break;
         case Lfunc:
             die("Generating this shit ain't ready yet ");
             break;
@@ -917,9 +905,56 @@
     }
 }
 
-void genblob(FILE *fd, Node *blob, Htab *globls)
+static void writepad(FILE *fd, size_t sz)
 {
     size_t i;
+
+    for (i = 0; i < sz; i++)
+        fprintf(fd, "\t.byte 0\n");
+}
+
+static void writetup(FILE *fd, Node *n)
+{
+    size_t i;
+
+    for (i = 0; i < n->expr.nargs; i++) {
+        writeblob(fd, n->expr.args[i]);
+    }
+}
+
+static void writearr(FILE *fd, Node *n)
+{
+    size_t i;
+
+    for (i = 0; i < n->expr.nargs; i++) {
+        writeblob(fd, n->expr.args[i]);
+    }
+}
+
+static void writestruct(FILE *fd, Node *n)
+{
+    size_t i;
+
+    for (i = 0; i < n->expr.nargs; i++) {
+        writeblob(fd, n->expr.args[i]);
+    }
+}
+
+static void writeblob(FILE *fd, Node *n)
+{
+    switch(exprop(n)) {
+        case Otup:  writetup(fd, n);  break;
+        case Oarr:  writearr(fd, n);  break;
+        case Ostruct: writestruct(fd, n); break;
+        case Olit:  writelit(fd, n->expr.args[0], size(n)); break;
+        default:
+                    die("Nonliteral initializer for global");
+                    break;
+    }
+}
+
+void genblob(FILE *fd, Node *blob, Htab *globls)
+{
     char *lbl;
 
     /* lits and such also get wrapped in decls */
@@ -929,14 +964,10 @@
     if (blob->decl.isexport)
         fprintf(fd, ".globl %s\n", lbl);
     fprintf(fd, "%s:\n", lbl);
-    if (blob->decl.init) {
-        if (exprop(blob->decl.init) != Olit)
-            die("Nonliteral initializer for global");
-        writelit(fd, blob->decl.init->expr.args[0], size(blob));
-    } else {
-        for (i = 0; i < size(blob); i++)
-            fprintf(fd, "\t.byte 0\n");
-    }
+    if (blob->decl.init)
+        writeblob(fd, blob->decl.init);
+    else
+        writepad(fd, size(blob));
 }
 
 /* genasm requires all nodes in 'nl' to map cleanly to operations that are
--- a/6/simp.c
+++ b/6/simp.c
@@ -54,6 +54,7 @@
 static Node *assign(Simp *s, Node *lhs, Node *rhs);
 static void declarelocal(Simp *s, Node *n);
 static void simpcond(Simp *s, Node *n, Node *ltrue, Node *lfalse);
+static void simpconstinit(Simp *s, Node *dcl);
 
 /* useful constants */
 static Type *tyintptr;
@@ -932,6 +933,7 @@
 
     off = 0;
     for (i = 0; i < n->expr.nargs; i++) {
+        off = align(off, size(args[i]));
         val = rval(s, args[i], NULL);
         pdst = add(r, disp(n->line, off));
 
@@ -1157,7 +1159,7 @@
                 case Lchr: case Lbool: case Lint: case Llbl:
                     r = n;
                     break;
-                case Lstr: case Lstruct: case Larray: case Lflt:
+                case Lstr: case Lflt:
                     r = simplit(s, n, &s->blobs, &s->nblobs);
                     break;
                 case Lfunc:
@@ -1203,6 +1205,20 @@
             else
                 r = t->expr.args[0];
             break;
+        case Oarr:
+            if (dst)
+                r = dst;
+            else
+                r = temp(s, n);
+            die("No initialization done yet");
+            break;
+        case Ostruct:
+            if (dst)
+                r = dst;
+            else
+                r = temp(s, n);
+            die("No initialization done yet");
+            break;
         default:
             r = visit(s, n);
     }
@@ -1270,14 +1286,14 @@
 
         case Ndecl:
             declarelocal(s, n);
-            if (n->decl.init) {
-                t = mkexpr(n->line, Ovar, n->decl.name, NULL);
-                u = mkexpr(n->line, Oasn, t, n->decl.init, NULL);
-                u->expr.type = n->decl.type;
-                t->expr.type = n->decl.type;
-                t->expr.did = n->decl.did;
-                simp(s, u);
-            }
+            if (!n->decl.init)
+                break;
+            t = mkexpr(n->line, Ovar, n->decl.name, NULL);
+            u = mkexpr(n->line, Oasn, t, n->decl.init, NULL);
+            u->expr.type = n->decl.type;
+            t->expr.type = n->decl.type;
+            t->expr.did = n->decl.did;
+            simp(s, u);
             break;
         default:
             die("Bad node passsed to simp()");
@@ -1331,8 +1347,6 @@
     if(debugopt['i'])
         printf("\n\nfunction %s\n", name);
 
-    if (!n->decl.init)
-        return NULL;
     /* set up the simp context */
     /* unwrap to the function body */
     n = n->expr.args[0];
@@ -1395,8 +1409,31 @@
     free(k);
 }
 
-static void simpdcl(Node *dcl, Htab *globls, Func ***fn, size_t *nfn, Node ***blob, size_t *nblob)
+static void simpconstinit(Simp *s, Node *dcl)
 {
+    Node *e;
+
+    dcl->decl.init = fold(dcl->decl.init);;
+    e = dcl->decl.init;
+    if (e && exprop(e) == Olit) {
+        if (e->expr.args[0]->lit.littype == Lfunc)
+            simplit(s, e->expr.args[0], &file->file.stmts, &file->file.nstmts);
+        else
+            lappend(&s->blobs, &s->nblobs, dcl);
+    } else if (dcl->decl.isconst && exprop(e) == Oarr) {
+        lappend(&s->blobs, &s->nblobs, dcl);
+    } else if (dcl->decl.isconst && exprop(e) == Ostruct) {
+        lappend(&s->blobs, &s->nblobs, dcl);
+    /* uninitialized global vars get zero-initialized decls */
+    } else if (!dcl->decl.isconst && !e) {
+        lappend(&s->blobs, &s->nblobs, dcl);
+    } else {
+        fatal(dcl->line, "Declaration %s initialized with nonconstant value", declname(dcl));
+    }
+}
+
+static void simpglobl(Node *dcl, Htab *globls, Func ***fn, size_t *nfn, Node ***blob, size_t *nblob)
+{
     Simp s = {0,};
     char *name;
     Func *f;
@@ -1413,14 +1450,7 @@
             lappend(fn, nfn, f);
         }
     } else {
-        dcl->decl.init = fold(dcl->decl.init);
-        if (dcl->decl.init && exprop(dcl->decl.init) == Olit)
-            lappend(&s.blobs, &s.nblobs, dcl);
-        /* uninitialized global vars get zero-initialized decls */
-        else if (!dcl->decl.isconst && !dcl->decl.init)
-            lappend(&s.blobs, &s.nblobs, dcl);
-        else
-            die("We don't simp globls with nonlit inits yet...");
+        simpconstinit(&s, dcl);
     }
     *blob = s.blobs;
     *nblob = s.nblobs;
@@ -1457,7 +1487,7 @@
             case Nuse: /* nothing to do */ 
                 break;
             case Ndecl:
-                simpdcl(n, globls, &fn, &nfn, &blob, &nblob);
+                simpglobl(n, globls, &fn, &nfn, &blob, &nblob);
                 break;
             default:
                 die("Bad node %s in toplevel", nodestr(n->type));
--- a/libstd/fmt.myr
+++ b/libstd/fmt.myr
@@ -154,7 +154,7 @@
 }
 
 const intfmt = {buf, val, base
-	var digits = [
+	const digits = [
 		'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
 	]
 	var isneg
--- a/parse/dump.c
+++ b/parse/dump.c
@@ -61,6 +61,7 @@
     size_t i, n;
     void **k;
     char *ty;
+    Type *t;
 
     indent(fd, depth);
     fprintf(fd, "Stab %p (super = %p, name=\"%s\")\n", st, st->super, namestr(st->name));
@@ -74,8 +75,9 @@
         fprintf(fd, "T ");
         /* already indented */
         outname(k[i], fd); 
-        ty = tystr(gettype(st, k[i]));
-        fprintf(fd, " = %s\n", ty);
+        t = gettype(st, k[i]);
+        ty = tystr(t);
+        fprintf(fd, " = %s [tid=%d]\n", ty, t->tid);
         free(ty);
     }
     free(k);
@@ -172,9 +174,10 @@
             break;
         case Nexpr:
             ty = tystr(n->expr.type);
-            fprintf(fd, " (type = %s, op = %s, isconst = %d, did=%zd)\n",
-                    ty, opstr(n->expr.op), n->expr.isconst, n->expr.did);
+            fprintf(fd, " (type = %s [tid %d], op = %s, isconst = %d, did=%zd)\n",
+                    ty, n->expr.type->tid, opstr(n->expr.op), n->expr.isconst, n->expr.did);
             free(ty);
+            outnode(n->expr.idx, fd, depth + 1);
             for (i = 0; i < n->expr.nargs; i++)
                 outnode(n->expr.args[i], fd, depth+1);
             break;
@@ -190,16 +193,6 @@
                     fprintf(fd, " Lfunc\n");
                     outnode(n->lit.fnval, fd, depth+1);
                     break;
-                case Larray:
-                    fprintf(fd, " Larray\n");
-                    for (i = 0; i < n->lit.nelt; i++)
-                        outnode(n->lit.seqval[i], fd, depth+1);
-                    break;
-                case Lstruct:
-                    fprintf(fd, " Lstruct\n");
-                    for (i = 0; i < n->lit.nelt; i++)
-                        outnode(n->lit.seqval[i], fd, depth+1);
-                    break;
             }
             break;
         case Nfunc:
@@ -221,11 +214,6 @@
         case Nnone:
             fprintf(stderr, "Nnone not a real node type!");
             fprintf(fd, "Nnone\n");
-            break;
-        case Nidxinit:
-            fprintf(fd, "\n");
-            outnode(n->idxinit.idx, fd, depth + 1);
-            outnode(n->idxinit.init, fd, depth + 1);
             break;
     }
 }
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -561,7 +561,7 @@
 atomicexpr
         : Tident
             {$$ = mkexpr($1->line, Ovar, mkname($1->line, $1->str), NULL);}
-        | literal {$$ = mkexpr($1->line, Olit, $1, NULL);}
+        | literal
         | Toparen expr Tcparen
             {$$ = $2;}
         | Toparen tupbody Tcparen
@@ -586,9 +586,9 @@
             {lappend(&$$.nl, &$$.nn, $3);}
         ;
 
-literal : funclit       {$$ = $1;}
+literal : funclit       {$$ = mkexpr($1->line, Olit, $1, NULL);}
+        | littok        {$$ = mkexpr($1->line, Olit, $1, NULL);}
         | seqlit        {$$ = $1;}
-        | littok        {$$ = $1;}
         ;
 
 littok  : Tstrlit       {$$ = mkstr($1->line, $1->str);}
@@ -613,9 +613,9 @@
         ;
 
 seqlit  : Tosqbrac arrayelts Tcsqbrac
-            {$$ = mkarray($1->line, $2.nl, $2.nn);}
+            {$$ = mkexprl($1->line, Oarr, $2.nl, $2.nn);}
         | Tosqbrac structelts Tcsqbrac
-            {$$ = mkstruct($1->line, $2.nl, $2.nn);}
+            {$$ = mkexprl($1->line, Ostruct, $2.nl, $2.nn);}
         ;
 
 arrayelts
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -58,8 +58,10 @@
     char *s;
     char *t;
     char *u;
+    char *idx;
     char buf[512];
 
+    idx = NULL;
     switch (n->type) {
         default:
             s = nodestr(n->type);
@@ -75,6 +77,8 @@
             s = namestr(n);
             break;
         case Nexpr:
+            if (n->expr.idx)
+                idx = ctxstr(st, n->expr.idx);
             if (exprop(n) == Ovar)
                 u = namestr(n->expr.args[0]);
             else
@@ -83,17 +87,13 @@
                 t = tystr(tf(st, exprtype(n)));
             else
                 t = strdup("unknown");
-            snprintf(buf, sizeof buf, "%s:%s", u, t);
-            s = strdup(buf);
+            if (idx)
+                snprintf(buf, sizeof buf, ".%s=%s:%s", idx, u, t);
+            else
+                snprintf(buf, sizeof buf, "%s:%s", u, t);
+            free(idx);
             free(t);
-            break;
-        case Nidxinit:
-            t = ctxstr(st, n->idxinit.idx);
-            u = ctxstr(st, n->idxinit.init);
-            snprintf(buf, sizeof buf, "%s=%s", t, u);
             s = strdup(buf);
-            free(t);
-            free(u);
             break;
     }
     return s;
@@ -313,8 +313,6 @@
         case Lstr:      return mktyslice(n->line, mktype(n->line, Tybyte));     break;
         case Llbl:      return mktyptr(n->line, mktype(n->line, Tyvoid));       break;
         case Lfunc:     return n->lit.fnval->func.type;                         break;
-        case Lstruct:   return NULL; break;
-        case Larray:    return NULL; break;
     };
     die("Bad lit type %d", n->lit.littype);
     return NULL;
@@ -339,7 +337,6 @@
       case Nexpr:       t = n->expr.type;       break;
       case Ndecl:       t = decltype(n);        break;
       case Nfunc:       t = n->func.type;       break;
-      case Nidxinit:    t = type(st, n->idxinit.init); break;
       default:
         t = NULL;
         die("untypeable node %s", nodestr(n->type));
@@ -747,9 +744,9 @@
     size_t i;
 
     *isconst = 1;
-    for (i = 0; i < n->lit.nelt; i++) {
-        infernode(st, n->lit.seqval[i], NULL, NULL);
-        if (!n->lit.seqval[i]->idxinit.init->expr.isconst)
+    for (i = 0; i < n->expr.nargs; i++) {
+        infernode(st, n->expr.args[i], NULL, NULL);
+        if (!n->expr.args[i]->expr.isconst)
             *isconst = 0;
     }
     settype(st, n, mktyvar(n->line));
@@ -764,16 +761,28 @@
 
     len = mkintlit(n->line, n->lit.nelt);
     t = mktyarray(n->line, mktyvar(n->line), len);
-    *isconst = 1;
-    for (i = 0; i < n->lit.nelt; i++) {
-        infernode(st, n->lit.seqval[i], NULL, NULL);
-        unify(st, n, t->sub[0], type(st, n->lit.seqval[i]));
-        if (!n->lit.seqval[i]->idxinit.init->expr.isconst)
+    for (i = 0; i < n->expr.nargs; i++) {
+        infernode(st, n->expr.args[i], NULL, NULL);
+        unify(st, n, t->sub[0], type(st, n->expr.args[i]));
+        if (!n->expr.args[i]->expr.isconst)
             *isconst = 0;
     }
     settype(st, n, t);
 }
 
+static void infertuple(Inferstate *st, Node *n, int *isconst)
+{
+    Type **types;
+    size_t i;
+
+    types = xalloc(sizeof(Type *)*n->expr.nargs);
+    for (i = 0; i < n->expr.nargs; i++) {
+        n->expr.isconst = n->expr.isconst && n->expr.args[i]->expr.isconst;
+        types[i] = type(st, n->expr.args[i]);
+    }
+    settype(st, n, mktytuple(n->line, types, n->expr.nargs));
+}
+
 static void inferpat(Inferstate *st, Node *n, Node *val, Node ***bind, size_t *nbind)
 {
     size_t i;
@@ -839,7 +848,6 @@
 static void inferexpr(Inferstate *st, Node *n, Type *ret, int *sawret)
 {
     Node **args;
-    Type **types;
     size_t i, nargs;
     Ucon *uc;
     Node *s;
@@ -858,6 +866,7 @@
             inferexpr(st, args[i], ret, sawret);
         }
     }
+    infernode(st, n->expr.idx, NULL, NULL);
     switch (exprop(n)) {
         /* all operands are same type */
         case Oadd:      /* @a + @a -> @a */
@@ -988,15 +997,13 @@
             settype(st, n, delayed(st, uc->utype));
             break;
         case Otup:
-            types = xalloc(sizeof(Type *)*n->expr.nargs);
-            for (i = 0; i < n->expr.nargs; i++)
-                types[i] = type(st, n->expr.args[i]);
-            settype(st, n, mktytuple(n->line, types, n->expr.nargs));
+            infertuple(st, n, &n->expr.isconst);
             break;
+        case Ostruct:
+            inferstruct(st, n, &n->expr.isconst);
+            break;
         case Oarr:
-            for (i = 0; i < n->expr.nargs; i++)
-                unify(st, n, type(st, n->expr.args[0]), type(st, n->expr.args[i]));
-            settype(st, n, mktyarray(n->line, type(st, n->expr.args[0]), mkintlit(n->line, n->expr.nargs)));
+            inferarray(st, n, &n->expr.isconst);
             break;
         case Olit:      /* <lit>:@a::tyclass -> @a */
             switch (args[0]->lit.littype) {
@@ -1004,12 +1011,6 @@
                     infernode(st, args[0]->lit.fnval, NULL, NULL); break;
                     /* FIXME: env capture means this is non-const */
                     n->expr.isconst = 1;
-                case Larray:
-                    inferarray(st, args[0], &n->expr.isconst);
-                    break;
-                case Lstruct:
-                    inferstruct(st, args[0], &n->expr.isconst);
-                    break;
                 default:
                     n->expr.isconst = 1;
                     break;
@@ -1163,10 +1164,6 @@
             inferfunc(st, n);
             popstab();
             break;
-        case Nidxinit:
-            infernode(st, n->idxinit.idx, NULL, NULL);
-            infernode(st, n->idxinit.init, NULL, NULL);
-            break;
         case Nname:
         case Nlit:
         case Nuse:
@@ -1276,7 +1273,7 @@
 static void checkstruct(Inferstate *st, Node *n)
 {
     Type *t, *et;
-    Node *elt, *name, *val;
+    Node *val, *name;
     size_t i, j;
 
     t = tybase(tf(st, n->lit.type));
@@ -1283,10 +1280,9 @@
     if (t->type != Tystruct)
         fatal(n->line, "Type %s for struct literal is not struct near %s", tystr(t), ctxstr(st, n));
 
-    for (i = 0; i < n->lit.nelt; i++) {
-        elt = n->lit.seqval[i];
-        name = elt->idxinit.idx;
-        val = elt->idxinit.init;
+    for (i = 0; i < n->expr.nargs; i++) {
+        val = n->expr.args[i];
+        name = val->expr.idx;
 
         et = NULL;
         for (j = 0; j < t->nmemb; j++) {
@@ -1300,7 +1296,7 @@
             fatal(n->line, "Could not find member %s in struct %s, near %s",
                   namestr(name), tystr(t), ctxstr(st, n));
 
-        unify(st, elt, et, type(st, val));
+        unify(st, val, et, type(st, val));
     }
 }
 
@@ -1315,7 +1311,7 @@
             infercompn(st, n);
         else if (n->type == Nexpr && exprop(n) == Ocast)
             checkcast(st, n);
-        else if (n->type == Nlit && n->lit.littype == Lstruct)
+        else if (n->type == Nexpr && exprop(n) == Ostruct)
             checkstruct(st, n);
         else
             die("Thing we shouldn't be checking in postcheck\n");
@@ -1398,6 +1394,7 @@
             break;
         case Nexpr:
             settype(st, n, tyfix(st, n, type(st, n)));
+            typesub(st, n->expr.idx);
             for (i = 0; i < n->expr.nargs; i++)
                 typesub(st, n->expr.args[i]);
             break;
@@ -1414,20 +1411,8 @@
             switch (n->lit.littype) {
                 case Lfunc:
                     typesub(st, n->lit.fnval); break;
-                case Larray:
-                    for (i = 0; i < n->lit.nelt; i++)
-                        typesub(st, n->lit.seqval[i]);
-                    break;
-                case Lstruct:
-                    for (i = 0; i < n->lit.nelt; i++)
-                        typesub(st, n->lit.seqval[i]);
-                    break;
                 default:        break;
             }
-            break;
-        case Nidxinit:
-            typesub(st, n->idxinit.idx);
-            typesub(st, n->idxinit.init);
             break;
         case Nname:
         case Nuse:
--- a/parse/lits.def
+++ b/parse/lits.def
@@ -4,6 +4,4 @@
 L(Lflt)
 L(Lstr)
 L(Lfunc)
-L(Lstruct)
-L(Larray)
 L(Llbl)
--- a/parse/node.c
+++ b/parse/node.c
@@ -232,39 +232,10 @@
     return n;
 }
 
-Node *mkarray(int line, Node **vals, size_t nvals)
-{
-    Node *n;
-
-    n = mknode(line, Nlit);
-    n->lit.littype = Larray;
-    n->lit.nelt = nvals;
-    n->lit.seqval = vals;
-
-    return n;
-}
-
-Node *mkstruct(int line, Node **vals, size_t nvals)
-{
-    Node *n;
-
-    n = mknode(line, Nlit);
-    n->lit.littype = Lstruct;
-    n->lit.nelt = nvals;
-    n->lit.seqval = vals;
-
-    return n;
-}
-
 Node *mkidxinit(int line, Node *idx, Node *init)
 {
-    Node *n;
-
-    n = mknode(line, Nidxinit);
-    n->idxinit.idx = idx;
-    n->idxinit.init = init;
-
-    return n;
+    init->expr.idx = idx;
+    return init;
 }
 
 Node *mkname(int line, char *name)
--- a/parse/nodes.def
+++ b/parse/nodes.def
@@ -11,4 +11,3 @@
 N(Nname)
 N(Ndecl)
 N(Nfunc)
-N(Nidxinit)
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -52,6 +52,7 @@
 O(Oucon, 1)
 O(Ouget, 1)
 O(Otup, 1)
+O(Ostruct, 1)
 O(Oarr, 1)
 /* backend-only */
 O(Ocjmp, 1)        /* conditional jump */
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -168,6 +168,7 @@
             int isconst;
             size_t did; /* for Ovar, we want a mapping to the decl id */
             size_t nargs;
+            Node *idx; /* used when this is in an indexed initializer */
             Node **args;
         } expr;
 
@@ -222,11 +223,6 @@
         } match;
 
         struct {
-            Node *idx;
-            Node *init;
-        } idxinit;
-
-        struct {
             Stab *scope;
             size_t nstmts;
             Node **stmts;
@@ -400,9 +396,6 @@
 Node *mkstr(int line, char *s);
 Node *mkfloat(int line, double flt);
 Node *mkfunc(int line, Node **args, size_t nargs, Type *ret, Node *body);
-Node *mkstruct(int line, Node **vals, size_t nvals);
-Node *mkarray(int line, Node **vals, size_t nvals);
-Node *mktuple(int line, Node **vals, size_t nvals);
 Node *mkname(int line, char *name);
 Node *mknsname(int line, char *ns, char *name);
 Node *mkdecl(int line, Node *name, Type *ty);
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -131,6 +131,7 @@
             die("Node %s not allowed here\n", nodestr(n->type));
             break;
         case Nexpr:
+            fixup(n->expr.idx);
             for (i = 0; i < n->expr.nargs; i++)
                 fixup(n->expr.args[i]);
             if (n->expr.op == Ovar) {
@@ -145,14 +146,6 @@
         case Nlit:
             switch (n->lit.littype) {
                 case Lfunc:     fixup(n->lit.fnval);          break;
-                case Larray:
-                    for (i = 0; i < n->lit.nelt; i++)
-                        fixup(n->lit.seqval[i]);
-                    break;
-                case Lstruct:
-                    for (i = 0; i < n->lit.nelt; i++)
-                        fixup(n->lit.seqval[i]);
-                    break;
                 case Lchr: case Lint: case Lflt:
                 case Lstr: case Llbl: case Lbool:
                     break;
@@ -192,9 +185,6 @@
             fixup(n->func.body);
             popstab();
             break;
-        case Nidxinit:
-            fixup(n->idxinit.idx);
-            fixup(n->idxinit.init);
         case Nnone: case Nname:
             break;
     }
@@ -224,6 +214,7 @@
             r->expr.type = tysubst(n->expr.type, tsmap);
             r->expr.isconst = n->expr.isconst;
             r->expr.nargs = n->expr.nargs;
+            r->expr.idx = specializenode(n->expr.idx, tsmap);
             r->expr.args = xalloc(n->expr.nargs * sizeof(Node*));
             for (i = 0; i < n->expr.nargs; i++)
                 r->expr.args[i] = specializenode(n->expr.args[i], tsmap);
@@ -244,16 +235,6 @@
                 case Llbl:      r->lit.lblval = n->lit.lblval;       break;
                 case Lbool:     r->lit.boolval = n->lit.boolval;     break;
                 case Lfunc:     r->lit.fnval = specializenode(n->lit.fnval, tsmap);       break;
-                case Larray:
-                    r->lit.seqval = xalloc(n->lit.nelt * sizeof(Node*));
-                    for (i = 0; i < n->lit.nelt; i++)
-                        r->lit.seqval[i] = specializenode(n->lit.seqval[i], tsmap);
-                    break;
-                case Lstruct:
-                    r->lit.seqval = xalloc(n->lit.nelt * sizeof(Node*));
-                    for (i = 0; i < n->lit.nelt; i++)
-                        r->lit.seqval[i] = specializenode(n->lit.seqval[i], tsmap);
-                    break;
             }
             break;
         case Nifstmt:
@@ -314,10 +295,6 @@
                 r->func.args[i] = specializenode(n->func.args[i], tsmap);
             r->func.body = specializenode(n->func.body, tsmap);
             popstab();
-            break;
-        case Nidxinit:
-            r->idxinit.idx = specializenode(n->idxinit.idx, tsmap);
-            r->idxinit.init = specializenode(n->idxinit.init, tsmap);
             break;
         case Nnone:
             die("Nnone should not be seen as node type!");
--- a/parse/use.c
+++ b/parse/use.c
@@ -328,6 +328,7 @@
             wrbyte(fd, n->expr.op);
             wrtype(fd, n->expr.type);
             wrbool(fd, n->expr.isconst);
+            pickle(n->expr.idx, fd);
             wrint(fd, n->expr.nargs);
             for (i = 0; i < n->expr.nargs; i++)
                 pickle(n->expr.args[i], fd);
@@ -355,14 +356,6 @@
                 case Llbl:      wrstr(fd, n->lit.lblval);       break;
                 case Lbool:     wrbool(fd, n->lit.boolval);     break;
                 case Lfunc:     pickle(n->lit.fnval, fd);       break;
-                case Larray:
-                    for (i = 0; i < n->lit.nelt; i++)
-                        pickle(n->lit.seqval[i], fd);
-                    break;
-                case Lstruct:
-                    for (i = 0; i < n->lit.nelt; i++)
-                        pickle(n->lit.seqval[i], fd);
-                    break;
             }
             break;
         case Nloopstmt:
@@ -413,10 +406,6 @@
                 pickle(n->func.args[i], fd);
             pickle(n->func.body, fd);
             break;
-        case Nidxinit:
-            pickle(n->idxinit.idx, fd);
-            pickle(n->idxinit.init, fd);
-            break;
         case Nnone:
             die("Nnone should not be seen as node type!");
             break;
@@ -456,6 +445,7 @@
             n->expr.op = rdbyte(fd);
             rdtype(fd, &n->expr.type);
             n->expr.isconst = rdbool(fd);
+            n->expr.idx = unpickle(fd);
             n->expr.nargs = rdint(fd);
             n->expr.args = xalloc(sizeof(Node *)*n->expr.nargs);
             for (i = 0; i < n->expr.nargs; i++)
@@ -482,14 +472,6 @@
                 case Llbl:      n->lit.lblval = rdstr(fd);       break;
                 case Lbool:     n->lit.boolval = rdbool(fd);     break;
                 case Lfunc:     n->lit.fnval = unpickle(fd);       break;
-                case Larray:
-                    for (i = 0; i < n->lit.nelt; i++)
-                        n->lit.seqval[i] = unpickle(fd);
-                    break;
-                case Lstruct:
-                    for (i = 0; i < n->lit.nelt; i++)
-                        n->lit.seqval[i] = unpickle(fd);
-                    break;
             }
             break;
         case Nloopstmt:
@@ -550,10 +532,6 @@
             n->func.body = unpickle(fd);
             popstab();
             break;
-        case Nidxinit:
-            n->idxinit.idx = unpickle(fd);
-            n->idxinit.init = unpickle(fd);
-            break;
         case Nnone:
             die("Nnone should not be seen as node type!");
             break;
@@ -745,6 +723,7 @@
             nodetag(n->match.block);
             break;
         case Nexpr:
+            nodetag(n->expr.idx);
             taghidden(n->expr.type);
             for (i = 0; i < n->expr.nargs; i++)
                 nodetag(n->expr.args[i]);
@@ -751,19 +730,8 @@
             break;
         case Nlit:
             taghidden(n->lit.type);
-            switch (n->lit.littype) {
-                case Lfunc: nodetag(n->lit.fnval); break;
-                case Larray:
-                    for (i = 0; i < n->lit.nelt; i++)
-                        nodetag(n->lit.seqval[i]);
-                    break;
-                case Lstruct:
-                    for (i = 0; i < n->lit.nelt; i++)
-                        nodetag(n->lit.seqval[i]);
-                    break;
-                default:
-                    break;
-            }
+            if (n->lit.littype == Lfunc)
+                nodetag(n->lit.fnval);
             break;
         case Ndecl:
             taghidden(n->decl.type);
@@ -776,10 +744,6 @@
             for (i = 0; i < n->func.nargs; i++)
                 nodetag(n->func.args[i]);
             nodetag(n->func.body);
-            break;
-        case Nidxinit:
-            nodetag(n->idxinit.idx);
-            nodetag(n->idxinit.init);
             break;
 
         case Nuse: case Nname:
--- a/test/tests
+++ b/test/tests
@@ -71,6 +71,7 @@
 B matchunion_sl	P	foo
 B matchbind	E	8
 B arraylit-ni	E	2
+B livearraylit	E	21
 # B arraylit	E	3       ## BUGGERED
 B structlit	E	42
 B livestructlit	E	21