shithub: mc

Download patch

ref: cb0c1ccdd7525db9d777c86010dc08e7edb4820c
parent: 0e624db312994ed6e74a63187ecf8f3ac6babeb5
author: Ori Bernstein <[email protected]>
date: Mon Jul 16 07:50:01 EDT 2012

Make nested functions work.

--- a/8/asm.h
+++ b/8/asm.h
@@ -31,7 +31,8 @@
     Locreg,  /* register */
     Locmem,  /* reg offset mem */
     Locmeml, /* label offset mem */
-    Loclit,
+    Loclit,  /* literal value */
+    // FIXME: later. Loclitl  /* label address */
 } LocType;
 
 typedef enum {
@@ -178,6 +179,7 @@
 Loc *locmems(long disp, Loc *base, Loc *idx, int scale, Mode mode);
 Loc *locmemls(char *disp, Loc *base, Loc *idx, int scale, Mode mode);
 Loc *loclit(long val);
+/*Loc *loclitl(char *lbl); FIXME: later */
 
 void locprint(FILE *fd, Loc *l, char spec);
 void iprintf(FILE *fd, Insn *insn);
--- a/8/insns.def
+++ b/8/insns.def
@@ -54,6 +54,7 @@
 
 /* branch instructions */
 Insn(Icall,     "\tcall %v\n",                  Use(.l={1}), Def())
+Insn(Icallind,  "\tcall *%v\n",                 Use(.l={1}), Def())
 Insn(Ijmp,      "\tjmp %v\n",                   Use(.l={1}), Def())
 Insn(Ijz,       "\tjz %v\n",                    Use(.l={1}), Def())
 Insn(Ijnz,      "\tjnz %v\n",                   Use(.l={1}), Def())
--- a/8/isel.c
+++ b/8/isel.c
@@ -396,7 +396,10 @@
         argoff += size(n->expr.args[i]);
     }
     fn = selexpr(s, n->expr.args[0]);
-    g(s, Icall, fn, NULL);
+    if (fn->type == Loclbl)
+        g(s, Icall, fn, NULL);
+    else
+        g(s, Icallind, inr(s, fn), NULL);
     if (argsz)
         g(s, Iadd, stkbump, esp, NULL);
     return eax;
@@ -405,7 +408,7 @@
 Loc *selexpr(Isel *s, Node *n)
 {
     Loc *a, *b, *c, *d, *r;
-    Loc *eax, *edx, *cl; /* x86 wanst some hard-coded regs */
+    Loc *eax, *edx, *cl; /* x86 wants some hard-coded regs */
     Node **args;
 
     args = n->expr.args;
--- a/8/simp.c
+++ b/8/simp.c
@@ -490,19 +490,25 @@
     }
 }
 
-static Node *bloblit(Simp *s, Node *lit)
+static Node *lowerlit(Simp *s, Node *lit, Node ***l, size_t *nl)
 {
-    Node *n, *t, *r;
+    Node *n, *d, *r;
     char lbl[128];
 
     n = mkname(lit->line, genlblstr(lbl, 128));
-    t = mkdecl(lit->line, n, lit->expr.type);
+    d = mkdecl(lit->line, n, lit->expr.type);
     r = mkexpr(lit->line, Ovar, n, NULL);
+
+    d->decl.init = lit;
+    d->decl.type = lit->expr.type;
+    d->decl.isconst = 1;
+    r->expr.did = d->decl.did;
     r->expr.type = lit->expr.type;
-    r->expr.did = t->decl.did;
-    t->decl.init = lit;
-    htput(s->globls, t, strdup(lbl));
-    lappend(&s->blobs, &s->nblobs, t);
+    if (tybase(r->expr.type)->type == Tyfunc)
+        r = addr(r, tybase(r->expr.type));
+
+    htput(s->globls, d, strdup(lbl));
+    lappend(l, nl, d);
     return r;
 }
 
@@ -935,10 +941,10 @@
                     r = n;
                     break;
                 case Lstr: case Lseq: case Lflt:
-                    r = bloblit(s, n);
+                    r = lowerlit(s, n, &s->blobs, &s->nblobs);
                     break;
                 case Lfunc:
-                    die("Func lits not handled yet");
+                    r = lowerlit(s, n, &file->file.stmts, &file->file.nstmts);
                     break;
             }
             break;
@@ -1177,9 +1183,9 @@
 void gen(Node *file, char *out)
 {
     Htab *globls;
-    Node **n, **blob;
+    Node *n, **blob;
     Func **fn;
-    size_t nn, nfn, nblob;
+    size_t nfn, nblob;
     size_t i;
     FILE *fd;
 
@@ -1195,22 +1201,21 @@
     nfn = 0;
     blob = NULL;
     nblob = 0;
-    n = file->file.stmts;
-    nn = file->file.nstmts;
     globls = mkht(dclhash, dcleq);
 
     /* We need to define all global variables before use */
     fillglobls(file->file.globls, globls);
 
-    for (i = 0; i < nn; i++) {
-        switch (n[i]->type) {
+    for (i = 0; i < file->file.nstmts; i++) {
+        n = file->file.stmts[i];
+        switch (n->type) {
             case Nuse: /* nothing to do */ 
                 break;
             case Ndecl:
-                lowerdcl(n[i], globls, &fn, &nfn, &blob, &nblob);
+                lowerdcl(n, globls, &fn, &nfn, &blob, &nblob);
                 break;
             default:
-                die("Bad node %s in toplevel", nodestr(n[i]->type));
+                die("Bad node %s in toplevel", nodestr(n->type));
                 break;
         }
     }