Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

gen.c

Go to the documentation of this file.
00001 #include "c.h"
00002 
00003 
00004 #define readsreg(p) \
00005     (generic((p)->op)==INDIR && (p)->kids[0]->op==VREG+P)
00006 #define setsrc(d) ((d) && (d)->x.regnode && \
00007     (d)->x.regnode->set == src->x.regnode->set && \
00008     (d)->x.regnode->mask&src->x.regnode->mask)
00009 
00010 #define relink(a, b) ((b)->x.prev = (a), (a)->x.next = (b))
00011 
00012 static Symbol   askfixedreg(Symbol);
00013 static Symbol   askreg(Symbol, unsigned*);
00014 static void     blkunroll(int, int, int, int, int, int, int[]);
00015 static void     docall(Node);
00016 static void     dumpcover(Node, int, int);
00017 static void     dumpregs(char *, char *, char *);
00018 static void     dumprule(int);
00019 static void     dumptree(Node);
00020 static unsigned emitasm(Node, int);
00021 static void     genreload(Node, Symbol, int);
00022 static void     genspill(Symbol, Node, Symbol);
00023 static Symbol   getreg(Symbol, unsigned*, Node);
00024 static int      getrule(Node, int);
00025 static void     linearize(Node, Node);
00026 static int      moveself(Node);
00027 static void     prelabel(Node);
00028 static Node*    prune(Node, Node*);
00029 static void     putreg(Symbol);
00030 static void     ralloc(Node);
00031 static void     reduce(Node, int);
00032 static int      reprune(Node*, int, int, Node);
00033 static int      requate(Node);
00034 static Node     reuse(Node, int);
00035 static void     rewrite(Node);
00036 static Symbol   spillee(Symbol, unsigned mask[], Node);
00037 static void     spillr(Symbol, Node);
00038 static int      uses(Node, Regnode);
00039 
00040 int offset;
00041 
00042 int maxoffset;
00043 
00044 int framesize;
00045 int argoffset;
00046 
00047 int maxargoffset;
00048 
00049 int dalign, salign;
00050 int bflag = 0;  /* omit */
00051 int dflag = 0;
00052 
00053 int swap;
00054 
00055 unsigned (*emitter)(Node, int) = emitasm;
00056 static char NeedsReg[] = {
00057     0,                      /* unused */
00058     1,                      /* CNST */
00059     0, 0,                   /* ARG ASGN */
00060     1,                      /* INDIR  */
00061     0, 0, 1, 1,             /*  -  - CVF CVI */
00062     1, 0, 1, 1,             /* CVP - CVU NEG */
00063     1,                      /* CALL */
00064     1,                      /* LOAD */
00065     0,                      /* RET */
00066     1, 1, 1,                /* ADDRG ADDRF ADDRL */
00067     1, 1, 1, 1, 1,          /* ADD SUB LSH MOD RSH */
00068     1, 1, 1, 1,             /* BAND BCOM BOR BXOR */
00069     1, 1,                   /* DIV MUL */
00070     0, 0, 0, 0, 0, 0,       /* EQ GE GT LE LT NE */
00071     0, 0                   /* JUMP LABEL   */
00072 };
00073 Node head;
00074 
00075 unsigned freemask[2];
00076 unsigned usedmask[2];
00077 unsigned tmask[2];
00078 unsigned vmask[2];
00079 Symbol mkreg(char *fmt, int n, int mask, int set) {
00080     Symbol p;
00081 
00082     NEW0(p, PERM);
00083     p->name = p->x.name = stringf(fmt, n);
00084     NEW0(p->x.regnode, PERM);
00085     p->x.regnode->number = n;
00086     p->x.regnode->mask = mask<<n;
00087     p->x.regnode->set = set;
00088     return p;
00089 }
00090 Symbol mkwildcard(Symbol *syms) {
00091     Symbol p;
00092 
00093     NEW0(p, PERM);
00094     p->name = p->x.name = "wildcard";
00095     p->x.wildcard = syms;
00096     return p;
00097 }
00098 void mkauto(Symbol p) {
00099     assert(p->sclass == AUTO);
00100     offset = roundup(offset + p->type->size, p->type->align);
00101     p->x.offset = -offset;
00102     p->x.name = stringd(-offset);
00103 }
00104 void blockbeg(Env *e) {
00105     e->offset = offset;
00106     e->freemask[IREG] = freemask[IREG];
00107     e->freemask[FREG] = freemask[FREG];
00108 }
00109 void blockend(Env *e) {
00110     if (offset > maxoffset)
00111         maxoffset = offset;
00112     offset = e->offset;
00113     freemask[IREG] = e->freemask[IREG];
00114     freemask[FREG] = e->freemask[FREG];
00115 }
00116 int mkactual(int align, int size) {
00117     int n = roundup(argoffset, align);
00118 
00119     argoffset = n + size;
00120     return n;
00121 }
00122 static void docall(Node p) {
00123     p->syms[1] = p->syms[0];
00124     p->syms[0] = intconst(argoffset);
00125     if (argoffset > maxargoffset)
00126         maxargoffset = argoffset;
00127     argoffset = 0;
00128 }
00129 void blkcopy(int dreg, int doff, int sreg, int soff, int size, int tmp[]) {
00130     assert(size >= 0);
00131     if (size == 0)
00132         return;
00133     else if (size <= 2)
00134         blkunroll(size, dreg, doff, sreg, soff, size, tmp);
00135     else if (size == 3) {
00136         blkunroll(2, dreg, doff,   sreg, soff,   2, tmp);
00137         blkunroll(1, dreg, doff+2, sreg, soff+2, 1, tmp);
00138     }
00139     else if (size <= 16) {
00140         blkunroll(4, dreg, doff, sreg, soff, size&~3, tmp);
00141         blkcopy(dreg, doff+(size&~3),
00142                     sreg, soff+(size&~3), size&3, tmp);
00143     }
00144     else
00145         (*IR->x.blkloop)(dreg, doff, sreg, soff, size, tmp);
00146 }
00147 static void blkunroll(int k, int dreg, int doff, int sreg, int soff, int size, int tmp[]) {
00148     int i;
00149 
00150     assert(IR->x.max_unaligned_load);
00151     if (k > IR->x.max_unaligned_load
00152     && (k > salign || k > dalign))
00153         k = IR->x.max_unaligned_load;
00154     for (i = 0; i+k < size; i += 2*k) {
00155         (*IR->x.blkfetch)(k, soff+i,   sreg, tmp[0]);
00156         (*IR->x.blkfetch)(k, soff+i+k, sreg, tmp[1]);
00157         (*IR->x.blkstore)(k, doff+i,   dreg, tmp[0]);
00158         (*IR->x.blkstore)(k, doff+i+k, dreg, tmp[1]);
00159     }
00160     if (i < size) {
00161         (*IR->x.blkfetch)(k, i+soff, sreg, tmp[0]);
00162         (*IR->x.blkstore)(k, i+doff, dreg, tmp[0]);
00163     }
00164 }
00165 void parseflags(int argc, char *argv[]) {
00166     int i;
00167 
00168     for (i = 0; i < argc; i++)
00169         if (strcmp(argv[i], "-d") == 0)
00170             dflag = 1;
00171         else if (strcmp(argv[i], "-b") == 0)    /* omit */
00172             bflag = 1;          /* omit */
00173 }
00174 static int getrule(Node p, int nt) {
00175     int rulenum;
00176 
00177     assert(p);
00178     rulenum = (*IR->x._rule)(p->x.state, nt);
00179     if (!rulenum) {
00180         fprint(stderr, "(%x->op=%s at %w is corrupt.)\n", p, opname(p->op), &src);
00181         assert(0);
00182     }
00183     return rulenum;
00184 }
00185 static void reduce(Node p, int nt) {
00186     int rulenum, i;
00187     short *nts;
00188     Node kids[10];
00189 
00190     p = reuse(p, nt);
00191     rulenum = getrule(p, nt);
00192     nts = IR->x._nts[rulenum];
00193     (*IR->x._kids)(p, rulenum, kids);
00194     for (i = 0; nts[i]; i++)
00195         reduce(kids[i], nts[i]);
00196     if (IR->x._isinstruction[rulenum]) {
00197         assert(p->x.inst == 0 || p->x.inst == nt);
00198         p->x.inst = nt;
00199         if (p->syms[RX] && p->syms[RX]->temporary) {
00200             debug(fprint(stderr, "(using %s)\n", p->syms[RX]->name));
00201             p->syms[RX]->x.usecount++;
00202         }
00203     }
00204 }
00205 static Node reuse(Node p, int nt) {
00206     struct _state {
00207         short cost[1];
00208     };
00209     Symbol r = p->syms[RX];
00210 
00211     if (generic(p->op) == INDIR && p->kids[0]->op == VREG+P
00212     && r->u.t.cse && p->x.mayrecalc
00213     && ((struct _state*)r->u.t.cse->x.state)->cost[nt] == 0)
00214         return r->u.t.cse;
00215     else
00216         return p;
00217 }
00218 
00219 int mayrecalc(Node p) {
00220     int op;
00221 
00222     assert(p && p->syms[RX]);
00223     if (p->syms[RX]->u.t.cse == NULL)
00224         return 0;
00225     op = generic(p->syms[RX]->u.t.cse->op);
00226     if (op == CNST || op == ADDRF || op == ADDRG || op == ADDRL) {
00227         p->x.mayrecalc = 1;
00228         return 1;
00229     } else
00230         return 0;
00231 }
00232 static Node *prune(Node p, Node pp[]) {
00233     if (p == NULL)
00234         return pp;
00235     p->x.kids[0] = p->x.kids[1] = p->x.kids[2] = NULL;
00236     if (p->x.inst == 0)
00237         return prune(p->kids[1], prune(p->kids[0], pp));
00238     else if (p->syms[RX] && p->syms[RX]->temporary
00239     && p->syms[RX]->x.usecount < 2) {
00240         p->x.inst = 0;
00241         debug(fprint(stderr, "(clobbering %s)\n", p->syms[RX]->name));
00242         return prune(p->kids[1], prune(p->kids[0], pp));
00243     }
00244     else {
00245         prune(p->kids[1], prune(p->kids[0], &p->x.kids[0]));
00246         *pp = p;
00247         return pp + 1;
00248     }
00249 }
00250 
00251 #define ck(i) return (i) ? 0 : LBURG_MAX
00252 
00253 int range(Node p, int lo, int hi) {
00254     Symbol s = p->syms[0];
00255 
00256     switch (specific(p->op)) {
00257     case ADDRF+P:
00258     case ADDRL+P: ck(s->x.offset >= lo && s->x.offset <= hi);
00259     case CNST+I:  ck(s->u.c.v.i  >= lo && s->u.c.v.i  <= hi);
00260     case CNST+U:  ck(s->u.c.v.u  >= lo && s->u.c.v.u  <= hi);
00261     case CNST+P:  ck(s->u.c.v.p  == 0  && lo <= 0 && hi >= 0);
00262     }
00263     return LBURG_MAX;
00264 }
00265 static void dumptree(Node p) {
00266     if (p->op == VREG+P && p->syms[0]) {
00267         fprint(stderr, "VREGP(%s)", p->syms[0]->name);
00268         return;
00269     } else if (generic(p->op) == LOAD) {
00270         fprint(stderr, "LOAD(");
00271         dumptree(p->kids[0]);
00272         fprint(stderr, ")");
00273         return;
00274     }
00275     fprint(stderr, "%s(", opname(p->op));
00276     switch (generic(p->op)) {
00277     case CNST: case LABEL:
00278     case ADDRG: case ADDRF: case ADDRL:
00279         if (p->syms[0])
00280             fprint(stderr, "%s", p->syms[0]->name);
00281         break;
00282     case RET:
00283         if (p->kids[0])
00284             dumptree(p->kids[0]);
00285         break;
00286     case CVF: case CVI: case CVP: case CVU: case JUMP: 
00287     case ARG: case BCOM: case NEG: case INDIR:
00288         dumptree(p->kids[0]);
00289         break;
00290     case CALL:
00291         if (optype(p->op) != B) {
00292             dumptree(p->kids[0]);
00293             break;
00294         }
00295         /* else fall thru */
00296     case EQ: case NE: case GT: case GE: case LE: case LT:
00297     case ASGN: case BOR: case BAND: case BXOR: case RSH: case LSH:
00298     case ADD: case SUB:  case DIV: case MUL: case MOD:
00299         dumptree(p->kids[0]);
00300         fprint(stderr, ", ");
00301         dumptree(p->kids[1]);
00302         break;
00303     default: assert(0);
00304     }
00305     fprint(stderr, ")");
00306 }
00307 static void dumpcover(Node p, int nt, int in) {
00308     int rulenum, i;
00309     short *nts;
00310     Node kids[10];
00311 
00312     p = reuse(p, nt);
00313     rulenum = getrule(p, nt);
00314     nts = IR->x._nts[rulenum];
00315     fprint(stderr, "dumpcover(%x) = ", p);
00316     for (i = 0; i < in; i++)
00317         fprint(stderr, " ");
00318     dumprule(rulenum);
00319     (*IR->x._kids)(p, rulenum, kids);
00320     for (i = 0; nts[i]; i++)
00321         dumpcover(kids[i], nts[i], in+1);
00322 }
00323 
00324 static void dumprule(int rulenum) {
00325     assert(rulenum);
00326     fprint(stderr, "%s / %s", IR->x._string[rulenum],
00327         IR->x._templates[rulenum]);
00328     if (!IR->x._isinstruction[rulenum])
00329         fprint(stderr, "\n");
00330 }
00331 static unsigned emitasm(Node p, int nt) {
00332     int rulenum;
00333     short *nts;
00334     char *fmt;
00335     Node kids[10];
00336 
00337     p = reuse(p, nt);
00338     rulenum = getrule(p, nt);
00339     nts = IR->x._nts[rulenum];
00340     fmt = IR->x._templates[rulenum];
00341     assert(fmt);
00342     if (IR->x._isinstruction[rulenum] && p->x.emitted)
00343         print("%s", p->syms[RX]->x.name);
00344     else if (*fmt == '#')
00345         (*IR->x.emit2)(p);
00346     else {
00347         if (*fmt == '?') {
00348             fmt++;
00349             assert(p->kids[0]);
00350             if (p->syms[RX] == p->x.kids[0]->syms[RX])
00351                 while (*fmt++ != '\n')
00352                     ;
00353         }
00354         for ((*IR->x._kids)(p, rulenum, kids); *fmt; fmt++)
00355             if (*fmt != '%')
00356                 (void)putchar(*fmt);
00357             else if (*++fmt == 'F')
00358                 print("%d", framesize);
00359             else if (*fmt >= '0' && *fmt <= '9')
00360                 emitasm(kids[*fmt - '0'], nts[*fmt - '0']);
00361             else if (*fmt >= 'a' && *fmt < 'a' + NELEMS(p->syms))
00362                 fputs(p->syms[*fmt - 'a']->x.name, stdout);
00363             else
00364                 (void)putchar(*fmt);
00365     }
00366     return 0;
00367 }
00368 void emit(Node p) {
00369     for (; p; p = p->x.next) {
00370         assert(p->x.registered);
00371         if (p->x.equatable && requate(p) || moveself(p))
00372             ;
00373         else
00374             (*emitter)(p, p->x.inst);
00375         p->x.emitted = 1;
00376     }
00377 }
00378 static int moveself(Node p) {
00379     return p->x.copy
00380     && p->syms[RX]->x.name == p->x.kids[0]->syms[RX]->x.name;
00381 }
00382 int move(Node p) {
00383     p->x.copy = 1;
00384     return 1;
00385 }
00386 static int requate(Node q) {
00387     Symbol src = q->x.kids[0]->syms[RX];
00388     Symbol tmp = q->syms[RX];
00389     Node p;
00390     int n = 0;
00391 
00392     debug(fprint(stderr, "(requate(%x): tmp=%s src=%s)\n", q, tmp->x.name, src->x.name));
00393     for (p = q->x.next; p; p = p->x.next)
00394         if (p->x.copy && p->syms[RX] == src
00395         &&  p->x.kids[0]->syms[RX] == tmp)
00396             debug(fprint(stderr, "(requate arm 0 at %x)\n", p)),
00397             p->syms[RX] = tmp;
00398         else if (setsrc(p->syms[RX]) && !moveself(p) && !readsreg(p))
00399             return 0;
00400         else if (p->x.spills)
00401             return 0;
00402         else if (generic(p->op) == CALL && p->x.next)
00403             return 0;
00404         else if (p->op == LABEL+V && p->x.next)
00405             return 0;
00406         else if (p->syms[RX] == tmp && readsreg(p))
00407             debug(fprint(stderr, "(requate arm 5 at %x)\n", p)),
00408             n++;
00409         else if (p->syms[RX] == tmp)
00410             break;
00411     debug(fprint(stderr, "(requate arm 7 at %x)\n", p));
00412     assert(n > 0);
00413     for (p = q->x.next; p; p = p->x.next)
00414         if (p->syms[RX] == tmp && readsreg(p)) {
00415             p->syms[RX] = src;
00416             if (--n <= 0)
00417                 break;
00418         }
00419     return 1;
00420 }
00421 static void prelabel(Node p) {
00422     if (p == NULL)
00423         return;
00424     prelabel(p->kids[0]);
00425     prelabel(p->kids[1]);
00426     if (NeedsReg[opindex(p->op)])
00427         setreg(p, (*IR->x.rmap)(opkind(p->op)));
00428     switch (generic(p->op)) {
00429     case ADDRF: case ADDRL:
00430         if (p->syms[0]->sclass == REGISTER)
00431             p->op = VREG+P;
00432         break;
00433     case INDIR:
00434         if (p->kids[0]->op == VREG+P)
00435             setreg(p, p->kids[0]->syms[0]);
00436         break;
00437     case ASGN:
00438         if (p->kids[0]->op == VREG+P)
00439             rtarget(p, 1, p->kids[0]->syms[0]);
00440         break;
00441     case CVI: case CVU: case CVP:
00442         if (optype(p->op) != F
00443         &&  opsize(p->op) <= p->syms[0]->u.c.v.i)
00444             p->op = LOAD + opkind(p->op);
00445         break;
00446     }
00447     (IR->x.target)(p);
00448 }
00449 void setreg(Node p, Symbol r) {
00450     p->syms[RX] = r;
00451 }
00452 void rtarget(Node p, int n, Symbol r) {
00453     Node q = p->kids[n];
00454 
00455     assert(q);
00456     assert(r);
00457     assert(r->sclass == REGISTER || !r->x.wildcard);
00458     assert(q->syms[RX]);
00459     if (r != q->syms[RX] && !q->syms[RX]->x.wildcard) {
00460         q = newnode(LOAD + opkind(q->op),
00461             q, NULL, q->syms[0]);
00462         if (r->u.t.cse == p->kids[n])
00463             r->u.t.cse = q;
00464         p->kids[n] = p->x.kids[n] = q;
00465         q->x.kids[0] = q->kids[0];
00466     }
00467     setreg(q, r);
00468     debug(fprint(stderr, "(targeting %x->x.kids[%d]=%x to %s)\n", p, n, p->kids[n], r->x.name));
00469 }
00470 static void rewrite(Node p) {
00471     assert(p->x.inst == 0);
00472     prelabel(p);
00473     debug(dumptree(p));
00474     debug(fprint(stderr, "\n"));
00475     (*IR->x._label)(p);
00476     debug(dumpcover(p, 1, 0));
00477     reduce(p, 1);
00478 }
00479 Node gen(Node forest) {
00480     int i;
00481     struct node sentinel;
00482     Node dummy, p;
00483 
00484     head = forest;
00485     for (p = forest; p; p = p->link) {
00486         assert(p->count == 0);
00487         if (generic(p->op) == CALL)
00488             docall(p);
00489         else if (   generic(p->op) == ASGN
00490         && generic(p->kids[1]->op) == CALL)
00491             docall(p->kids[1]);
00492         else if (generic(p->op) == ARG)
00493             (*IR->x.doarg)(p);
00494         rewrite(p);
00495         p->x.listed = 1;
00496     }
00497     for (p = forest; p; p = p->link)
00498         prune(p, &dummy);
00499     relink(&sentinel, &sentinel);
00500     for (p = forest; p; p = p->link)
00501         linearize(p, &sentinel);
00502     forest = sentinel.x.next;
00503     assert(forest);
00504     sentinel.x.next->x.prev = NULL;
00505     sentinel.x.prev->x.next = NULL;
00506     for (p = forest; p; p = p->x.next)
00507         for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
00508             assert(p->x.kids[i]->syms[RX]);
00509             if (p->x.kids[i]->syms[RX]->temporary) {
00510                 p->x.kids[i]->x.prevuse =
00511                     p->x.kids[i]->syms[RX]->x.lastuse;
00512                 p->x.kids[i]->syms[RX]->x.lastuse = p->x.kids[i];
00513             }
00514         }
00515     for (p = forest; p; p = p->x.next) {
00516         ralloc(p);
00517         if (p->x.listed && NeedsReg[opindex(p->op)]
00518         && (*IR->x.rmap)(opkind(p->op))) {
00519             assert(generic(p->op) == CALL || generic(p->op) == LOAD);
00520             putreg(p->syms[RX]);
00521         }
00522     }
00523     return forest;
00524 }
00525 int notarget(Node p) {
00526     return p->syms[RX]->x.wildcard ? 0 : LBURG_MAX;
00527 }
00528 static void putreg(Symbol r) {
00529     assert(r && r->x.regnode);
00530     freemask[r->x.regnode->set] |= r->x.regnode->mask;
00531     debug(dumpregs("(freeing %s)\n", r->x.name, NULL));
00532 }
00533 static Symbol askfixedreg(Symbol s) {
00534     Regnode r = s->x.regnode;
00535     int n = r->set;
00536 
00537     if (r->mask&~freemask[n])
00538         return NULL;
00539     else {
00540         freemask[n] &= ~r->mask;
00541         usedmask[n] |=  r->mask;
00542         return s;
00543     }
00544 }
00545 static Symbol askreg(Symbol rs, unsigned rmask[]) {
00546     int i;
00547 
00548     if (rs->x.wildcard == NULL)
00549         return askfixedreg(rs);
00550     for (i = 31; i >= 0; i--) {
00551         Symbol r = rs->x.wildcard[i];
00552         if (r != NULL
00553         && !(r->x.regnode->mask&~rmask[r->x.regnode->set])
00554         && askfixedreg(r))
00555             return r;
00556     }
00557     return NULL;
00558 }
00559 
00560 static Symbol getreg(Symbol s, unsigned mask[], Node p) {
00561     Symbol r = askreg(s, mask);
00562     if (r == NULL) {
00563         r = spillee(s, mask, p);
00564         assert(r && r->x.regnode);
00565         spill(r->x.regnode->mask, r->x.regnode->set, p);
00566         r = askreg(s, mask);
00567     }
00568     assert(r && r->x.regnode);
00569     r->x.regnode->vbl = NULL;
00570     return r;
00571 }
00572 int askregvar(Symbol p, Symbol regs) {
00573     Symbol r;
00574 
00575     assert(p);
00576     if (p->sclass != REGISTER)
00577         return 0;
00578     else if (!isscalar(p->type)) {
00579         p->sclass = AUTO;
00580         return 0;
00581     }
00582     else if (p->temporary) {
00583         p->x.name = "?";
00584         return 1;
00585     }
00586     else if ((r = askreg(regs, vmask)) != NULL) {
00587         p->x.regnode = r->x.regnode;
00588         p->x.regnode->vbl = p;
00589         p->x.name = r->x.name;
00590         debug(dumpregs("(allocating %s to symbol %s)\n", p->x.name, p->name));
00591         return 1;
00592     }
00593     else {
00594         p->sclass = AUTO;
00595         return 0;
00596     }
00597 }
00598 static void linearize(Node p, Node next) {
00599     int i;
00600 
00601     for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
00602         linearize(p->x.kids[i], next);
00603     relink(next->x.prev, p);
00604     relink(p, next);
00605     debug(fprint(stderr, "(listing %x)\n", p));
00606 }
00607 static void ralloc(Node p) {
00608     int i;
00609     unsigned mask[2];
00610 
00611     mask[0] = tmask[0];
00612     mask[1] = tmask[1];
00613     assert(p);
00614     debug(fprint(stderr, "(rallocing %x)\n", p));
00615     for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
00616         Node kid = p->x.kids[i];
00617         Symbol r = kid->syms[RX];
00618         assert(r && kid->x.registered);
00619         if (r->sclass != REGISTER && r->x.lastuse == kid)
00620             putreg(r);
00621     }
00622     if (!p->x.registered && NeedsReg[opindex(p->op)]
00623     && (*IR->x.rmap)(opkind(p->op))) {
00624         Symbol sym = p->syms[RX], set = sym;
00625         assert(sym);
00626         if (sym->temporary)
00627             set = (*IR->x.rmap)(opkind(p->op));
00628         assert(set);
00629         if (set->sclass != REGISTER) {
00630             Symbol r;
00631             if (*IR->x._templates[getrule(p, p->x.inst)] == '?')
00632                 for (i = 1; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
00633                     Symbol r = p->x.kids[i]->syms[RX];
00634                     assert(p->x.kids[i]->x.registered);
00635                     assert(r && r->x.regnode);
00636                     assert(sym->x.wildcard || sym != r);
00637                     mask[r->x.regnode->set] &= ~r->x.regnode->mask;
00638                 }
00639             r = getreg(set, mask, p);
00640             if (sym->temporary) {
00641                 Node q;
00642                 r->x.lastuse = sym->x.lastuse;
00643                 for (q = sym->x.lastuse; q; q = q->x.prevuse) {
00644                     q->syms[RX] = r;
00645                     q->x.registered = 1;
00646                     if (sym->u.t.cse && q->x.copy)
00647                         q->x.equatable = 1;
00648                 }
00649             } else {
00650                 p->syms[RX] = r;
00651                 r->x.lastuse = p;
00652             }
00653             debug(dumpregs("(allocating %s to node %x)\n", r->x.name, (char *) p));
00654         }
00655     }
00656     p->x.registered = 1;
00657     (*IR->x.clobber)(p);
00658 }
00659 static Symbol spillee(Symbol set, unsigned mask[], Node here) {
00660     Symbol bestreg = NULL;
00661     int bestdist = -1, i;
00662 
00663     assert(set);
00664     if (!set->x.wildcard)
00665         bestreg = set;
00666     else {
00667         for (i = 31; i >= 0; i--) {
00668             Symbol ri = set->x.wildcard[i];
00669             if (
00670                 ri != NULL &&
00671                 ri->x.lastuse &&
00672                 (ri->x.regnode->mask&tmask[ri->x.regnode->set]&mask[ri->x.regnode->set])
00673             ) {
00674                 Regnode rn = ri->x.regnode;
00675                 Node q = here;
00676                 int dist = 0;
00677                 for (; q && !uses(q, rn); q = q->x.next)
00678                     dist++;
00679                 if (q && dist > bestdist) {
00680                     bestdist = dist;
00681                     bestreg = ri;
00682                 }
00683             }
00684         }
00685     }
00686     assert(bestreg); /* Must be able to spill something. Reconfigure the register allocator
00687         to ensure that we can allocate a register for all nodes without spilling
00688         the node's necessary input regs. */ 
00689     assert(bestreg->x.regnode->vbl == NULL); /* Can't spill register variables because
00690         the reload site might be in other blocks. Reconfigure the register allocator
00691         to ensure that this register is never allocated to a variable. */
00692     return bestreg;
00693 }
00694 static int uses(Node p, Regnode rn) {
00695     int i;
00696 
00697     for (i = 0; i < NELEMS(p->x.kids); i++)
00698         if (
00699             p->x.kids[i] &&
00700             p->x.kids[i]->x.registered &&
00701             rn->set == p->x.kids[i]->syms[RX]->x.regnode->set &&
00702             (rn->mask&p->x.kids[i]->syms[RX]->x.regnode->mask)
00703         )
00704             return 1;
00705     return 0;
00706 }
00707 static void spillr(Symbol r, Node here) {
00708     int i;
00709     Symbol tmp;
00710     Node p = r->x.lastuse;
00711     assert(p);
00712     while (p->x.prevuse)
00713         assert(r == p->syms[RX]),
00714         p = p->x.prevuse;
00715     assert(p->x.registered && !readsreg(p));
00716     tmp = newtemp(AUTO, optype(p->op), opsize(p->op));
00717     genspill(r, p, tmp);
00718     for (p = here->x.next; p; p = p->x.next)
00719         for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
00720             Node k = p->x.kids[i];
00721             if (k->x.registered && k->syms[RX] == r)
00722                 genreload(p, tmp, i);
00723         }
00724     putreg(r);
00725 }
00726 static void genspill(Symbol r, Node last, Symbol tmp) {
00727     Node p, q;
00728     Symbol s;
00729     unsigned ty;
00730 
00731     debug(fprint(stderr, "(spilling %s to local %s)\n", r->x.name, tmp->x.name));
00732     debug(fprint(stderr, "(genspill: "));
00733     debug(dumptree(last));
00734     debug(fprint(stderr, ")\n"));
00735     ty = opkind(last->op);
00736     NEW0(s, FUNC);
00737     s->sclass = REGISTER;
00738     s->name = s->x.name = r->x.name;
00739     s->x.regnode = r->x.regnode;
00740     q = newnode(ADDRL+