home *** CD-ROM | disk | FTP | other *** search
/ Total Destruction / Total_Destruction.iso / addons / Lccwin32.exe / Lccwin32 / lccpub / src / Gen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-11  |  31.2 KB  |  1,249 lines

  1. #include "c.h"
  2. extern Symbol intreg[];
  3. //#define DODEBUG
  4. #define NORMAL_REG_ORDER
  5. #define readsreg(p) \
  6.     (generic((p)->op)==INDIR && (p)->kids[0]->op==VREG+P)
  7. #define setsrc(d) ((d) && (d)->x.regnode && \
  8.     (d)->x.regnode->set == src->x.regnode->set && \
  9.     (d)->x.regnode->mask&src->x.regnode->mask)
  10.  
  11. #define relink(a, b) ((b)->x.prev = (a), (a)->x.next = (b))
  12.  
  13. static Symbol   askfixedreg     ARGS((Symbol));
  14. static Symbol   askreg          ARGS((Symbol, unsigned*));
  15. static void     blkunroll       ARGS((int, int, int, int, int, int, int[]));
  16. static void     docall          ARGS((Node));
  17. static void     dumpcover       ARGS((Node, int, int));
  18. static void     dumpregs        ARGS((char *, char *, char *,char *));
  19. static void     dumprule        ARGS((int));
  20. void     dumptree        ARGS((Node,int));
  21. unsigned    emitasm        ARGS((Node, int));
  22. static void     genreload       ARGS((Node, Symbol, int));
  23. static void     genspill        ARGS((Symbol, Node, Symbol));
  24. static Symbol   getreg          ARGS((Symbol, unsigned*, Node,int));
  25. static int      getrule         ARGS((Node, int));
  26. void     linearize       ARGS((Node, Node));
  27. int      moveself        ARGS((Node));
  28. static void     prelabel        ARGS((Node));
  29. static Node*    prune           ARGS((Node, Node*));
  30. static void     putreg          ARGS((Symbol));
  31. static void     ralloc          ARGS((Node));
  32. static void     reduce          ARGS((Node, int));
  33. static int      reprune         ARGS((Node*, int, int, Node));
  34. int      requate         ARGS((Node));
  35. static Node     reuse           ARGS((Node, int));
  36. static void     rewrite         ARGS((Node));
  37. static Symbol   spillee         ARGS((Symbol, Node));
  38. static void     spillr          ARGS((Symbol, Node));
  39. static int      trashes         ARGS((Node, Node));
  40. static int      uses            ARGS((Node, unsigned));
  41.  
  42. int offset;
  43.  
  44. int maxoffset;
  45.  
  46. int framesize;
  47. int argoffset;
  48.  
  49. int maxargoffset;
  50.  
  51. int dalign, salign;
  52. int bflag = 0;  /* omit */
  53. int dflag = 0;
  54.  
  55. int swap;
  56.  
  57. static int unsafe=1;
  58.  
  59. unsigned (*emitter) ARGS((Node, int)) = emitasm;
  60. static char NeedsReg[] = {
  61.     0,                      /* unused */
  62.     1,                      /* CNST */
  63.     0, 0,                   /* ARG ASGN */
  64.     1,                      /* INDIR  */
  65.     1, 1, 1, 1,             /* CVC CVD CVF CVI */
  66.     1, 1, 1, 1,             /* CVP CVS CVU NEG */
  67.     1,                      /* CALL */
  68.     1,                      /* LOAD */
  69.     0,                      /* RET */
  70.     1, 1, 1,                /* ADDRG ADDRF ADDRL */
  71.     1, 1, 1, 1, 1,          /* ADD SUB LSH MOD RSH */
  72.     1, 1, 1, 1,             /* BAND BCOM BOR BXOR */
  73.     1, 1,                   /* DIV MUL */
  74.     0, 0, 0, 0, 0, 0,       /* EQ GE GT LE LT NE */
  75.     0, 0,                   /* JUMP LABEL   */
  76.     1
  77. };
  78. Symbol rmap[16];
  79. Node head;
  80.  
  81. unsigned freemask[2];
  82. unsigned usedmask[2];
  83. unsigned tmask[2];
  84. unsigned vmask[2];
  85. Symbol mkreg(char *fmt,int n,int mask,int set)
  86. {
  87.     Symbol p;
  88.  
  89.     NEW0(p, PERM);
  90.     p->name = fmt+1;
  91.     p->x.name = stringf(fmt, n);
  92.     NEW0(p->x.regnode, PERM);
  93.     p->x.regnode->number = (short)n;
  94.     p->x.regnode->mask = mask<<n;
  95.     p->x.regnode->set = (short)set;
  96.     return p;
  97. }
  98. Symbol mkwildcard(Symbol *syms)
  99. {
  100.     Symbol p;
  101.  
  102.     NEW0(p, PERM);
  103.     p->x.name = "wildcard";
  104.     p->x.wildcard = syms;
  105.     return p;
  106. }
  107. void mkauto(Symbol p)
  108. {
  109.     assert(p->sclass == AUTO);
  110.     offset = roundup(offset + p->type->size, p->type->align);
  111.     p->x.offset = -offset;
  112.     if (hasExceptions)
  113.         p->x.offset -= 24;
  114.     p->x.name = stringd(p->x.offset);
  115. }
  116. void blockbeg(Env *e)
  117. {
  118.     e->offset = offset;
  119.     e->freemask[IREG] = freemask[IREG];
  120.     e->freemask[FREG] = freemask[FREG];
  121. }
  122. void blockend(Env *e)
  123. {
  124.     if (offset > maxoffset)
  125.         maxoffset = offset;
  126.     offset = e->offset;
  127.     freemask[IREG] = e->freemask[IREG];
  128.     freemask[FREG] = e->freemask[FREG];
  129. }
  130. int mkactual(int align,int size)
  131. {
  132.     int n = roundup(argoffset, align);
  133.  
  134.     argoffset = n + size;
  135.     return n;
  136. }
  137. static void docall(Node p)
  138. {
  139.     FunctionHasCalls = 1;
  140.     p->syms[0] = intconst(argoffset);
  141.     if (argoffset > maxargoffset)
  142.         maxargoffset = argoffset;
  143.     argoffset = 0;
  144. }
  145. void blkcopy(int dreg,int doff,int sreg,int soff,int size,int tmp[])
  146. {
  147.     assert(size >= 0);
  148.     if (size == 0)
  149.         return;
  150.     else if (size <= 2)
  151.         blkunroll(size, dreg, doff, sreg, soff, size, tmp);
  152.     else if (size == 3) {
  153.         blkunroll(2, dreg, doff,   sreg, soff,   2, tmp);
  154.         blkunroll(1, dreg, doff+2, sreg, soff+2, 1, tmp);
  155.     }
  156.     else if (size <= 16) {
  157.         blkunroll(4, dreg, doff, sreg, soff, size&~3, tmp);
  158.         blkcopy(dreg, doff+(size&~3),
  159.                     sreg, soff+(size&~3), size&3, tmp);
  160.     }
  161.     else
  162.         (*IR->x.blkloop)(dreg, doff, sreg, soff, size, tmp);
  163. }
  164. static void blkunroll(int k,int dreg,int doff,int sreg,int soff,int size,int tmp[])
  165. {
  166.     int i;
  167.  
  168.     assert(IR->x.max_unaligned_load);
  169.     if (k > IR->x.max_unaligned_load
  170.     && (k > salign || k > dalign))
  171.         k = IR->x.max_unaligned_load;
  172.     for (i = 0; i+k < size; i += 2*k) {
  173.         (*IR->x.blkfetch)(k, soff+i,   sreg, tmp[0]);
  174.         (*IR->x.blkfetch)(k, soff+i+k, sreg, tmp[1]);
  175.         (*IR->x.blkstore)(k, doff+i,   dreg, tmp[0]);
  176.         (*IR->x.blkstore)(k, doff+i+k, dreg, tmp[1]);
  177.     }
  178.     if (i < size) {
  179.         (*IR->x.blkfetch)(k, i+soff, sreg, tmp[0]);
  180.         (*IR->x.blkstore)(k, i+doff, dreg, tmp[0]);
  181.     }
  182. }
  183. void parseflags(int argc,char *argv[])
  184. {
  185.     int i;
  186.  
  187.     for (i = 0; i < argc; i++)
  188.         if (strcmp(argv[i], "-d") == 0)
  189.             dflag = 1;
  190.         else if (strcmp(argv[i], "-b") == 0)    /* omit */
  191.             bflag = 1;            /* omit */
  192. }
  193. /*------------------------------------------------------------------------
  194.  Procedure:     getrule ID:1
  195.  Purpose:       This function just encapsulates the call to the
  196.                 interface rule function. 14.3.382
  197.  Input:
  198.  Output:
  199.  Errors:
  200. ------------------------------------------------------------------------*/
  201. static int getrule(Node p,int nt)
  202. {
  203.     int rulenum;
  204.  
  205.     assert(p);
  206.     rulenum = (*IR->x._rule)(p->x.state, nt);
  207.     if (rulenum == 0) {
  208.         assert(0);
  209.     }
  210.     return rulenum;
  211. }
  212. static void reduce(Node p,int nt)
  213. {
  214.     int rulenum, i;
  215.     short *nts;
  216.     Node kids[10];
  217.  
  218.     p = reuse(p, nt);
  219. #ifdef PURIFY
  220.     rulenum = getrule(p, nt);
  221. #else
  222.     rulenum = (*IR->x._rule)(p->x.state, nt);
  223. #endif
  224.     nts = IR->x._nts[rulenum];
  225.     p->x.rulenum = rulenum;
  226.     (*IR->x._kids)(p, rulenum, kids);
  227.     for (i = 0; nts[i]; i++)
  228.         reduce(kids[i], nts[i]);
  229.     if (IR->x._isinstruction[rulenum]) {
  230.         assert(p->x.inst == 0 || p->x.inst == nt);
  231.         p->x.inst = (short)nt;
  232.         if (p->syms[RX] && p->syms[RX]->temporary) {
  233. #ifdef DODEBUG
  234.             fprint(2, "(using %s)\n", p->syms[RX]->name);
  235. #endif
  236.             p->syms[RX]->x.usecount++;
  237.         }
  238.     }
  239. }
  240. /*------------------------------------------------------------------------
  241.  Procedure:     reuse ID:1
  242.  Purpose:       The call to reuse sees if the reduction of node p using
  243.                 nonterminal nt uses a 'bonus match'. If so, it returns
  244.                 the common subexpression instead of p. The objective is
  245.                 to reprocess the common subexpression and ignore the
  246.                 temporary. It collaborates with reduce to recalculate
  247.                 expressions that are cheaper to recalculate than to
  248.                 store into a register.14.3.383
  249.  Input:
  250.  Output:
  251.  Errors:
  252. ------------------------------------------------------------------------*/
  253. static Node reuse(Node p,int nt)
  254. {
  255.     struct _state {
  256.         short cost[1];
  257.     };
  258.     Symbol r = p->syms[RX];
  259.  
  260.     if (generic(p->op) == INDIR && p->kids[0]->op == VREG+P
  261.     && r->u.t.cse && p->x.mayrecalc
  262.     && ((struct _state*)r->u.t.cse->x.state)->cost[nt] == 0)
  263.         return r->u.t.cse;
  264.     else
  265.         return p;
  266. }
  267.  
  268. int mayrecalc(Node p)
  269. {
  270.     Node q;
  271.  
  272.     assert(p && p->syms[RX]);
  273.     if (!p->syms[RX]->u.t.cse)
  274.         return 0;
  275.     for (q = head; q && q->x.listed; q = q->link)
  276.         if (generic(q->op) == ASGN
  277.         && trashes(q->kids[0], p->syms[RX]->u.t.cse))
  278.             return 0;
  279.     p->x.mayrecalc = 1;
  280.     return 1;
  281. }
  282. static int trashes(Node p,Node q)
  283. {
  284.     assert(p);
  285.     if (!q)
  286.         return 0;
  287.     /*
  288.     This read before syms[0]. It should be syms[RX] in my opinion. I leave both
  289.     */
  290.     else if (p->op == q->op && 
  291.         (p->syms[RX] == q->syms[RX] || p->syms[0] == q->syms[0]))
  292.         return 1;
  293.     else
  294.         return trashes(p, q->kids[0])
  295.             || trashes(p, q->kids[1]);
  296. }
  297. static Node *prune(Node p,Node pp[])
  298. {
  299.     if (p == NULL)
  300.         return pp;
  301. #if 0 /* here I have a problem. The origianl sources didn't make this assertion. Where does this come from? */
  302.     if(p->x.kids[2] != NULL) {
  303.         assert(0);
  304.     }
  305. #endif
  306.     p->x.kids[0] = p->x.kids[1] = p->x.kids[2] = NULL;
  307.     if (p->x.inst == 0)
  308.         return prune(p->kids[1], prune(p->kids[0], pp));
  309.     else if (p->syms[RX] && p->syms[RX]->temporary
  310.     && p->syms[RX]->x.usecount < 2) {
  311.         p->x.inst = 0;
  312. #ifdef DODEBUG
  313.         fprint(2, "(clobbering %s)\n", p->syms[RX]->name);
  314. #endif
  315.         return prune(p->kids[1], prune(p->kids[0], pp));
  316.     }
  317.     else {
  318.         prune(p->kids[1], prune(p->kids[0], &p->x.kids[0]));
  319.         *pp = p;
  320.         return pp + 1;
  321.     }
  322. }
  323.  
  324. #define ck(i) return (i) ? 0 : LBURG_MAX
  325.  
  326. int range(Node p,int lo,int hi)
  327. {
  328.     Symbol s = p->syms[0];
  329.  
  330.     switch (p->op) {
  331.     case ADDRFP: ck(s->x.offset >= lo && s->x.offset <= hi);
  332.     case ADDRLP: ck(s->x.offset >= lo && s->x.offset <= hi);
  333.     case CNSTC:  ck(s->u.c.v.sc >= lo && s->u.c.v.sc <= hi);
  334.     case CNSTI:  ck(s->u.c.v.i  >= lo && s->u.c.v.i  <= hi);
  335.     case CNSTS:  ck(s->u.c.v.ss >= lo && s->u.c.v.ss <= hi);
  336.     case CNSTU:  ck(s->u.c.v.u  >= (unsigned)lo && s->u.c.v.u  <= (unsigned)hi);
  337.     case CNSTP:  ck(s->u.c.v.p  == 0  && lo <= 0 && hi >= 0);
  338.     }
  339.     return LBURG_MAX;
  340. }
  341. void dumptree(Node p,int level)
  342. {
  343.     fprint(2, "%s(", IR->x._opname[p->op]);
  344.     if (IR->x._arity[p->op] == 0 && p->syms[0])
  345.         fprint(2, "%s", p->syms[0]->name);
  346.     else if (IR->x._arity[p->op] == 1)
  347.         dumptree(p->kids[0],level+1);
  348.     else if (IR->x._arity[p->op] == 2) {
  349.         dumptree(p->kids[0],level+1);
  350.         fprint(2, ", ");
  351.         dumptree(p->kids[1],level+1);
  352.     }
  353.     fprint(2, ")");
  354. }
  355. void ildumptree(Node p,int level)
  356. {
  357.     fprintf(ilFile, "%s(", IR->x._opname[p->op]);
  358.     if (IR->x._arity[p->op] == 0 && p->syms[0]) {
  359.         if (p->syms[0]->name == NULL)
  360.             fprintf(ilFile,"%s",p->syms[0]->x.name);
  361.         else
  362.             fprintf(ilFile, "%s", p->syms[0]->name);
  363.     }
  364.     else if (IR->x._arity[p->op] == 1)
  365.         ildumptree(p->kids[0],level+1);
  366.     else if (IR->x._arity[p->op] == 2) {
  367.         ildumptree(p->kids[0],level+1);
  368.         fprintf(ilFile, ", ");
  369.         ildumptree(p->kids[1],level+1);
  370.     }
  371.     fprintf(ilFile, ")");
  372. }
  373. static void ildumprule(int rulenum)
  374. {
  375.     assert(rulenum);
  376.     fprintf(ilFile, "%s / %s", IR->x._string[rulenum],
  377.         IR->x._templates[rulenum]);
  378.     if (!IR->x._isinstruction[rulenum])
  379.         fprintf(ilFile, "\n");
  380. }
  381. void ildumpcover(Node p,int nt,int in)
  382. {
  383.     int rulenum, i;
  384.     short *nts;
  385.     Node kids[10];
  386.  
  387.     p = reuse(p, nt);
  388.     rulenum = (*IR->x._rule)(p->x.state, nt);
  389.     nts = IR->x._nts[rulenum];
  390.     for (i = 0; i < in; i++)
  391.         fprintf(ilFile, " ");
  392.     ildumprule(rulenum);
  393.     (*IR->x._kids)(p, rulenum, kids);
  394.     for (i = 0; nts[i]; i++)
  395.         ildumpcover(kids[i], nts[i], in+1);
  396. }
  397. #ifdef DODEBUG
  398.  
  399. static void dumpcover(Node p,int nt,int in)
  400. {
  401.     int rulenum, i;
  402.     short *nts;
  403.     Node kids[10];
  404.  
  405.     p = reuse(p, nt);
  406. #ifdef PURIFY
  407.     rulenum = getrule(p, nt);
  408. #else
  409.     rulenum = (*IR->x._rule)(p->x.state, nt);
  410. #endif
  411.     nts = IR->x._nts[rulenum];
  412.     fprint(2, "dumpcover(%x) = ", p);
  413.     for (i = 0; i < in; i++)
  414.         fprint(2, " ");
  415.     dumprule(rulenum);
  416.     (*IR->x._kids)(p, rulenum, kids);
  417.     for (i = 0; nts[i]; i++)
  418.         dumpcover(kids[i], nts[i], in+1);
  419. }
  420.  
  421. static void dumprule(int rulenum)
  422. {
  423.     assert(rulenum);
  424.     fprint(2, "%s / %s", IR->x._string[rulenum],
  425.         IR->x._templates[rulenum]);
  426.     if (!IR->x._isinstruction[rulenum])
  427.         fprint(2, "\n");
  428. }
  429. #endif /* DODEBUG */
  430. /*------------------------------------------------------------------------
  431.  Procedure:     emitasm ID:1
  432.  Purpose:       Processes a partially linearized tree. List elements are
  433.                 the roots of subtrees for instructions. It traces the
  434.                 sub-instructions which correspond to  addressing modes
  435.                 and other calculations inside a logical instruction. The
  436.                 driver of emitasm, 'emit' ensures that this instructions
  437.                 are seen in the right order.
  438.                 It sets the x.emitted flag as it emits them. 14.6.392
  439.  Input:
  440.  Output:
  441.  Errors:
  442. ------------------------------------------------------------------------*/
  443. extern int hasAllocA;
  444. unsigned emitasm(Node p,int nt)
  445. {
  446.     int rulenum;
  447.     short *nts; /* Used only in a recursive call
  448.                    Contains the nonterminals for the rule's pattern */
  449.     register char *fmt;
  450.     Node kids[10];
  451.     int isinstruction;
  452.     char *oldbp;
  453.     extern int cseg;
  454.  
  455.     p = reuse(p, nt);
  456. #ifdef PURIFY
  457.     rulenum = getrule(p, nt);
  458. #else
  459.     rulenum = (*IR->x._rule)(p->x.state, nt);
  460. #endif
  461.     nts = IR->x._nts[rulenum];
  462.     fmt = IR->x._templates[rulenum];
  463.     assert(fmt);
  464.     oldbp = bp;
  465.     isinstruction = IR->x._isinstruction[rulenum];
  466.     if (p->x.intrinsic) {
  467.         if (p->x.emitted) {
  468.             outs(p->syms[RX]->x.name);
  469.             return 0;
  470.         }
  471.         p->x.emitted = 1;
  472.         Intrinsic(p);
  473.         return 0;
  474.     }
  475.     if (isinstruction && p->x.emitted) {
  476.         /* When an instruction has already been emitted, only the name of the
  477.            register where the instruction left its result will be output
  478.         */
  479.         outs(p->syms[RX]->x.name);
  480.     }
  481.     else if (*fmt == '#')
  482.         /* This is an escape hatch to generate machine specific code like
  483.            structure arguments
  484.         */
  485.         (*IR->x.emit2)(p);
  486.     else {
  487.         if (*fmt == '?') {
  488.             /* Omit redundant expressions */
  489.             fmt++;
  490.             assert(p->x.kids[0]);
  491.             /* This was updated after my complaints about redundant expressions */
  492.             if (p->syms[RX] == p->x.kids[0]->syms[RX])
  493.                 while (*fmt++ != '\n')
  494.                     ;
  495.         }
  496.         if (p->x.Flags && (rulenum == 207 || rulenum == 209)) {
  497.             while (*fmt++ != '\n')
  498.                 ;
  499.         }
  500.         for ((*IR->x._kids)(p, rulenum, kids); *fmt; fmt++)
  501.             if (*fmt != '%')
  502.                 *bp++ = *fmt;
  503.             else if (*++fmt == 'F')
  504.                 /* Emit the framesize, for accessing local variables */
  505.                 print("%d", framesize);
  506.             else if (*fmt >= '0' && *fmt <= '9') {
  507.                 int n = *fmt - '0';
  508.                 /* Emit recursively the subtree corresponding to the 'digit'-th
  509.                    nonterminal for the pattern, counting from zero, left to
  510.                    right.
  511.                  */
  512.                 emitasm(kids[n], nts[n]);
  513. #if 0
  514.                 {
  515.                     if (p->x.intrinsicArg) {
  516.                         IntrinsicArg(kids[n],nts[n]);
  517.                     }
  518.                 }
  519. #endif
  520.                 if (rulenum > 230 /*&& nt == 2*/) { /* call instruction */
  521.                         if (kids[n]->syms && kids[n]->syms[0] &&
  522.                              kids[n]->syms[0]->Flags) {
  523.                         *bp++ = '\n';
  524.                         return(0);
  525.                     }
  526.                     else if (oldbp[7] == 'a' && !strncmp(oldbp+6,"_alloca",7)) {
  527.                         int c = oldbp[13];
  528.                         if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'z') ||
  529.                                 (c >= '0' && c <= '9'))) {
  530.                             hasAllocA = 1;
  531.                             *bp++ = '\n';
  532.                             return 0;
  533.                         }
  534.                     }
  535.                 }
  536.             }
  537.             else if (*fmt >= 'a' && *fmt < 'a' + NELEMS(p->syms))
  538.                 /* This evaluates to a register name */
  539.                 outs(p->syms[*fmt - 'a']->x.name);
  540.             else
  541.                 *bp++ = *fmt;
  542.     }
  543.     if (OptimizeFlag && hasExceptions == 0 && isinstruction && !p->x.emitted) {
  544.         if (rulenum == 193 && cseg == 1 /*&& p->syms[0]->ref != 0.0*/) { /* LABELV */
  545.             SendToOptimizer();
  546.         }
  547.     }
  548.     return 0;
  549. }
  550.  
  551.  
  552. void emit(Node p)
  553. {
  554.     for (; p; p = p->x.next) {
  555.         assert(p->x.registered);
  556.         if (p->x.equatable && requate(p) || moveself(p)) {
  557.             ;
  558.         }
  559.         else {
  560.             char *oldbp = bp;
  561.             (*emitter)(p, p->x.inst);
  562. //            p->x.Asm = oldbp;
  563.             if (IntermediateLanguageFile) {
  564.                 int rulenum;
  565.  
  566.                 ildumptree(p,0);
  567.                 fprintf(ilFile,"\n");
  568.                 rulenum = getrule(p, p->x.inst);
  569.                 ildumprule(rulenum);
  570.                 fprintf(ilFile,"%s",oldbp);
  571.             }
  572.             oldbp = bp;
  573.         }
  574.         
  575.         p->x.emitted = 1;
  576.     }
  577. }
  578. int moveself(Node p)
  579. {
  580.     if (p->x.kids[0] == NULL) return 0;
  581.     return p->x.copy
  582.     && p->syms[RX]->x.name == p->x.kids[0]->syms[RX]->x.name;
  583. }
  584. int move(Node p)
  585. {
  586.     p->x.copy = 1;
  587.     return 1;
  588. }
  589. int requate(Node q)
  590. {
  591.     Symbol src = q->x.kids[0]->syms[RX];
  592.     Symbol tmp = q->syms[RX];
  593.     Node p;
  594.     int n = 0;
  595.  
  596. #ifdef DODEBUG
  597.     fprint(2, "(requate(%x): tmp=%s src=%s)\n", q, tmp->x.name, src->x.name);
  598. #endif
  599.     for (p = q->x.next; p; p = p->x.next)
  600.         if (p->x.copy && p->syms[RX] == src
  601.         &&  p->x.kids[0]->syms[RX] == tmp)
  602. #ifdef DODEBUG
  603.             fprint(2, "(requate arm 0 at %x)\n", p),
  604. #endif
  605.             p->syms[RX] = tmp;
  606.         else if (setsrc(p->syms[RX]) && !moveself(p) && !readsreg(p))
  607.             return 0;
  608. #if OLD
  609.         else if (generic(p->op) == ASGN && p->kids[0]->op == ADDRLP
  610.         && p->kids[0]->syms[0]->temporary
  611.         && p->kids[1]->syms[RX]->x.name == tmp->x.name)
  612.             return 0;
  613. #else
  614.         else if (p->x.spills)
  615.             return 0;
  616.         
  617. #endif
  618.         else if (generic(p->op) == CALL && p->x.next)
  619.             return 0;
  620.         else if (p->op == LABEL+V && p->x.next)
  621.             return 0;
  622.         else if (p->syms[RX] == tmp && readsreg(p))
  623. #ifdef DODEBUG
  624.             fprint(2, "(requate arm 5 at %x)\n", p),
  625. #endif
  626.             n++;
  627.         else if (p->syms[RX] == tmp)
  628.             break;
  629. #ifdef DODEBUG
  630.     fprint(2, "(requate arm 7 at %x)\n", p);
  631. #endif
  632.     assert(n > 0);
  633.     for (p = q->x.next; p; p = p->x.next)
  634.         if (p->syms[RX] == tmp && readsreg(p)) {
  635.             p->syms[RX] = src;
  636.             if (--n <= 0)
  637.                 break;
  638.         }
  639.     return 1;
  640. }
  641.  
  642.  
  643. static void prelabel(Node p)
  644. {
  645.     if (p == NULL)
  646.         return;
  647.     prelabel(p->kids[0]);
  648.     prelabel(p->kids[1]);
  649.     if (NeedsReg[opindex(p->op)])
  650.         setreg(p, rmap[optype(p->op)]);
  651.     switch (generic(p->op)) {
  652.     case ADDRF: case ADDRL:
  653.         if (p->syms[0]->sclass == REGISTER)
  654.             p->op = VREG+P;
  655.         break;
  656.     case INDIR:
  657.         if (p->kids[0]->op == VREG+P)
  658.             setreg(p, p->kids[0]->syms[0]);
  659.         break;
  660.     case ASGN:
  661.         if (p->kids[0]->op == VREG+P) {
  662. #ifdef DODEBUG
  663.             fprint(2, "(cse=%x)\n", p->kids[0]->syms[0]->u.t.cse);
  664. #endif
  665.             rtarget(p, 1, p->kids[0]->syms[0]);
  666.         }
  667.         break;
  668.     }
  669.     (IR->x.target)(p);
  670. }
  671. void setreg(Node p,Symbol r)
  672. {
  673.     p->syms[RX] = r;
  674. }
  675. void rtarget(Node p,int n,Symbol r)
  676. {
  677.     Node q = p->kids[n];
  678.  
  679.     assert(q);
  680.     assert(r->sclass == REGISTER || !r->x.wildcard);
  681.     assert(q->syms[RX]);
  682.     if (r != q->syms[RX] && !q->syms[RX]->x.wildcard) {
  683. lab1:
  684.         q = newnode(LOAD + optype(q->op),
  685.             q, NULL, q->syms[0]);
  686.         if (r->u.t.cse == p->kids[n])
  687.             r->u.t.cse = q;
  688.         p->kids[n] = p->x.kids[n] = q;
  689.         q->x.kids[0] = q->kids[0];
  690.         setreg(q,r);
  691.     }
  692.     else if (q->kids[1] == NULL ||
  693.         p->kids[0]->syms[0] == NULL ||
  694.         p->kids[0]->syms[0]->u.t.cse ||
  695.         !(/*q->kids[0]->syms[RX]->x.name[0] == '?' &&*/
  696.         p->kids[0]->syms[0] == q->kids[1]->syms[RX]))
  697.         setreg(q, r);
  698.     else {
  699. //        printf("not taken line %d\n",src.y);
  700.         goto lab1;
  701.     }
  702. //    q->x.unsafe = 1;
  703. #ifdef DODEBUG
  704.     fprint(2, "(targeting %x->x.kids[%d]=%x to %s)\n", p, n, p->kids[n], r->x.name);
  705. #endif
  706. }
  707. static void rewrite(Node p)
  708. {
  709.     assert(p->x.inst == 0);
  710.     prelabel(p);
  711. #ifdef DODEBUG
  712.     dumptree(p,0);
  713.     fprint(2, "\n");
  714. #endif
  715.     (*IR->x._label)(p);
  716. #ifdef DODEBUG
  717.     dumpcover(p, 1, 0);
  718. #endif
  719.     reduce(p, 1);
  720. }
  721. /*
  722. The interface function gen receives a forest from the front end and makes
  723. several passes over the trees.
  724. */
  725. Node gen(Node forest)
  726. {
  727.     int i;
  728.     struct node sentinel;
  729.     Node dummy, p;
  730.  
  731.     head = forest;
  732.     if (OptimizeFlag)
  733.         unsafe = head->x.unsafe;
  734.     else
  735.         unsafe = 1;
  736.     /*
  737.     The first pass calls rewrite to select instructions, and the second
  738.     prunes the subinstructions out of the tree.
  739.     */
  740.     for (p = forest; p; p = p->link) {
  741.         assert(p->count == 0);
  742.         if (generic(p->op) == CALL)
  743.             docall(p);
  744.         else /* If the call returns no value, or if the returned
  745.                 value is ignored, then the call itself appears in the forst.
  746.                 This statement recognizes this pattern */
  747.         if (generic(p->op) == ASGN
  748.         && generic(p->kids[1]->op) == CALL)
  749.             docall(p->kids[1]);
  750.         else if (generic(p->op) == ARG)
  751.             (*IR->x.doarg)(p);
  752.         rewrite(p);
  753.         p->x.listed = 1;
  754.     }
  755.     for (p = forest; p; p = p->link)
  756.         prune(p, &dummy);
  757.     relink(&sentinel, &sentinel);
  758.     for (p = forest; p; p = p->link)
  759.         linearize(p, &sentinel);
  760.     forest = sentinel.x.next;
  761.     assert(forest);
  762.     sentinel.x.next->x.prev = NULL;
  763.     sentinel.x.prev->x.next = NULL;
  764.     for (p = forest; p; p = p->x.next)
  765.         for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
  766.             assert(p->x.kids[i]->syms[RX]);
  767.             if (p->x.kids[i]->syms[RX]->temporary) {
  768.                 p->x.kids[i]->x.prevuse =
  769.                     p->x.kids[i]->syms[RX]->x.lastuse;
  770.                 p->x.kids[i]->syms[RX]->x.lastuse = p->x.kids[i];
  771.             }
  772.         }
  773. #if 0 // This is the patch proposed by Chris Fraser end of April 97.
  774.     for (p = forest; p; p = p->x.next)
  775.         if (p->x.copy && p->x.kids[0] && p->x.kids[0]->syms[RX]->u.t.cse) {
  776.             Symbol dst = p->syms[RX];
  777.             Symbol temp = p->x.kids[0]->syms[RX];
  778.             Node q;
  779.  
  780.             assert(temp->x.lastuse);
  781.             for (q = temp->u.t.cse; q; q = q->x.next)
  782.                 if (p != q && dst == q->syms[RX]
  783.                 || (q->op == LABELV || q->op == JUMPV || generic(q->op)==RET ||
  784.                     generic(q->op)==EQ || generic(q->op)==NE ||
  785.                     generic(q->op)==LE || generic(q->op)==LT ||
  786.                     generic(q->op)==GE || generic(q->op)==GT ||
  787.                     q->op == ASGNB || /* This costed me a week */
  788.                     (generic(q->op) == CALL && dst->sclass != REGISTER)))
  789.                     break;
  790.             if (!q)
  791.                 for (q = temp->x.lastuse; q; q = q->x.prevuse)
  792.                     q->syms[RX] = dst;
  793.         }
  794. #endif
  795.     for (p = forest; p; p = p->x.next) {
  796.         if (p->x.unsafe || (p->x.next && p->x.next->x.unsafe))
  797.             unsafe = 1;
  798.         ralloc(p);
  799.         if (p->x.listed && NeedsReg[opindex(p->op)]
  800.         && rmap[optype(p->op)]) {
  801.             assert(generic(p->op) == CALL || generic(p->op) == LOAD);
  802.             putreg(p->syms[RX]);
  803.         }
  804.     }
  805.     unsafe = 1;
  806.     return forest;
  807. }
  808. int notarget(Node p)
  809. {
  810.     return p->syms[RX]->x.wildcard ? 0 : LBURG_MAX;
  811. }
  812. static void putreg(Symbol r)
  813. {
  814.     assert(r && r->x.regnode);
  815.     freemask[r->x.regnode->set] |= r->x.regnode->mask;
  816. #ifdef DODEBUG
  817.     dumpregs("(freeing %s)\n", r->x.name, NULL,NULL);
  818. #endif
  819. }
  820. static Symbol askfixedreg(Symbol s)
  821. {
  822.     Regnode r = s->x.regnode;
  823.     int n = r->set;
  824.  
  825.     if (r->mask&~freemask[n])
  826.         return NULL;
  827.     else {
  828.         freemask[n] &= ~r->mask;
  829.         usedmask[n] |=  r->mask;
  830.         return s;
  831.     }
  832. }
  833. extern int clobbering;
  834.  
  835. static Symbol askreg(Symbol rs,unsigned rmask[])
  836. {
  837.     int i;
  838.     Symbol r;
  839.  
  840.     if (rs->x.wildcard == NULL)
  841.         return askfixedreg(rs);
  842.     if (unsafe)
  843.     for (i = 31; i >= 0; i--) {
  844.         r = rs->x.wildcard[i];
  845.         if (r != NULL
  846.         && !(r->x.regnode->mask&~rmask[r->x.regnode->set])
  847.         && askfixedreg(r)) {
  848.             return r;
  849.         }
  850.     }
  851.     else {
  852.         r = rs->x.wildcard[2]; // EDX
  853.         if (r != NULL
  854.             && !(r->x.regnode->mask&~rmask[r->x.regnode->set])
  855.             && askfixedreg(r))
  856.                 return r;
  857.         r = rs->x.wildcard[1]; // ECX
  858.         if (r != NULL
  859.             && !(r->x.regnode->mask&~rmask[r->x.regnode->set])
  860.             && askfixedreg(r))
  861.             return r;
  862.         r = rs->x.wildcard[0]; // EAX
  863.         if (r != NULL
  864.             && !(r->x.regnode->mask&~rmask[r->x.regnode->set])
  865.             && askfixedreg(r))
  866.             return r;
  867.     /* It is better to start with the eax, ebx ecx, etc registers.
  868.        This limits the number of unnecessary moves and makes esi edi
  869.        available for further optimizations.
  870.     */
  871.         for (i = 0; i < 32; i++) {
  872.             Symbol r = rs->x.wildcard[i];
  873.             if (r != NULL
  874.             && !(r->x.regnode->mask&~rmask[r->x.regnode->set])
  875.             && askfixedreg(r))
  876.                 return r;
  877.         }
  878.     }
  879.     return NULL;
  880. }
  881.  
  882. static Symbol getreg(Symbol s,unsigned mask[],Node p,int tmpflag)
  883. {
  884.     Symbol r;
  885.  
  886.     if (p->x.dangerousChildren)
  887.         mask[0] &= ~1;
  888.     r = askreg(s, mask);
  889.  
  890.     if (r == NULL) {
  891.         r = spillee(s, p);
  892.         assert(r);
  893.         spill(r->x.regnode->mask, r->x.regnode->set, p);
  894.         putreg(r);
  895.         r = askreg(s, mask);
  896.         if (r == NULL) {
  897.             r = askreg(s,mask);
  898.             assert(r);
  899.         }
  900.     }
  901.     assert(r->x.regnode);
  902.     r->x.regnode->vbl = NULL;
  903.     return r;
  904. }
  905. int askregvar(Symbol p,Symbol regs)
  906. {
  907.     Symbol r;
  908.  
  909.     assert(p);
  910.     if (p->sclass != REGISTER)
  911.         return 0;
  912.     else if (!isscalar(p->type)) {
  913.         p->sclass = AUTO;
  914.         return 0;
  915.     }
  916.     else if (p->temporary && p->u.t.cse) {
  917.         p->x.name = "?";
  918.         return 1;
  919.     }
  920.     /*
  921.     test if SetupRegisterVariables has assigned this already...
  922.     */
  923.     else if (p->x.regnode && OptimizeFlag)
  924.         return 1;
  925.     else if (p->x.switchSymbol &&
  926.             p->generated) {
  927.             Symbol r = intreg[0];
  928.             p->sclass = REGISTER;
  929.             p->x.regnode = r->x.regnode;
  930.             p->x.regnode->vbl = p;
  931.             p->x.name = r->x.name;
  932.             return 1;
  933.     }
  934.  
  935.     else if ((r = askreg(regs, vmask)) != NULL) {
  936.         p->x.regnode = r->x.regnode;
  937.         p->x.regnode->vbl = p;
  938.         p->x.name = r->x.name;
  939. #ifdef DODEBUG
  940.         dumpregs("(allocating %s to symbol %s)\n", p->x.name, p->name,NULL);
  941. #endif
  942.         return 1;
  943.     }
  944.     else {
  945.         p->sclass = AUTO;
  946.         return 0;
  947.     }
  948. }
  949. void linearize(Node p,Node next)
  950. {
  951.     int i;
  952.  
  953.     for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
  954.         linearize(p->x.kids[i], next);
  955.     relink(next->x.prev, p);
  956.     relink(p, next);
  957. #ifdef DODEBUG
  958.     fprint(2, "(listing %x)\n", p);
  959. #endif
  960. }
  961. static void ralloc(Node p)
  962. {
  963.     int i,tmpflag=0;
  964.     unsigned mask[2];
  965.  
  966.     mask[0] = tmask[0];
  967.     mask[1] = tmask[1];
  968.     assert(p);
  969. #ifdef DODEBUG
  970.     fprint(2, "(rallocing %x: %s)\n", p,IR->x._opname[p->op]);
  971. #endif
  972.     for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
  973.         Node kid = p->x.kids[i];
  974.         Symbol r = kid->syms[RX];
  975.         assert(r && kid->x.registered);
  976.         if (r->sclass != REGISTER && r->x.lastuse == kid)
  977.             putreg(r);
  978.     }
  979.     if (!p->x.registered && NeedsReg[opindex(p->op)]
  980.     && rmap[optype(p->op)]) {
  981.         Symbol sym = p->syms[RX], set = sym;
  982.         assert(sym);
  983.         if (sym->temporary && sym->u.t.cse) {
  984.             tmpflag = 1;
  985.             set = rmap[optype(p->op)];
  986.         }
  987.         assert(set);
  988.         if (set->sclass != REGISTER) {
  989.             Symbol r;
  990.             char *prule = IR->x._templates[getrule(p, p->x.inst)];
  991.             if (*prule == '?')
  992.                 for (i = 1; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
  993.                     Symbol r = p->x.kids[i]->syms[RX];
  994.                     assert(p->x.kids[i]->x.registered);
  995.                     assert(r && r->x.regnode);
  996. //                    assert(sym->x.wildcard || sym != r);
  997.                     if (!(sym->x.wildcard || sym != r )) {
  998.                         if (strcmp(r->x.name,sym->x.name)) {
  999. #ifndef NDEBUG
  1000.                         dumpregs("error in %s %x %s\n",r->x.name,(char *)p,opname(p->op));
  1001.                         dumptree(p,0);
  1002.                         dumptree(p->x.kids[i],0);
  1003. #endif
  1004.                         assert(0);
  1005.                         }
  1006.                     }
  1007.  
  1008.                     mask[r->x.regnode->set] &= ~r->x.regnode->mask;
  1009.                 }
  1010.             /* Avoid ESI and EDI when converting int to char, because
  1011.             those registers have no byte registers
  1012.             */
  1013.             if ((p->x.next && ((optype(p->x.next->op) == C) )
  1014.                     || optype(p->op) == C)) {
  1015.                 mask[0] &= ~((1 << 6)|(1<< 7));
  1016.             }
  1017.             if (p->x.intrinsicArg) {
  1018.                 r = AssignIntrinsicArg(p);
  1019.                 if (r == NULL)
  1020.                     r = getreg(set, mask, p, tmpflag);
  1021.             }
  1022.             else 
  1023.                 r = getreg(set, mask, p,tmpflag);
  1024.             if (sym->temporary && sym->u.t.cse) {
  1025.                 Node q;
  1026.                 r->x.lastuse = sym->x.lastuse;
  1027.                 for (q = sym->x.lastuse; q; q = q->x.prevuse) {
  1028.                     q->syms[RX] = r;
  1029.                     q->x.registered = 1;
  1030.                     if (q->x.copy)
  1031.                         q->x.equatable = 1;
  1032.                 }
  1033.             } else {
  1034.                 p->syms[RX] = r;
  1035.                 r->x.lastuse = p;
  1036.             }
  1037. #ifdef DODEBUG
  1038.             dumpregs("(allocating %s to node %x %s)\n", r->x.name, (char *) p,opname(p->op));
  1039.             dumptree(p,0);
  1040. #endif
  1041.         }
  1042.     }
  1043.     p->x.registered = 1;
  1044.     (*IR->x.clobber)(p);
  1045. }
  1046. static Symbol spillee(Symbol set,Node here)
  1047. {
  1048.     Symbol bestreg = NULL;
  1049.     int bestdist = -1, i;
  1050.  
  1051.     assert(set);
  1052.     if (!set->x.wildcard)
  1053.         return set;
  1054.     if (FunctionInfo.leafFunction == 0)
  1055.     for (i = 31; i >= 0; i--) {
  1056.         Symbol ri = set->x.wildcard[i];
  1057.         if (ri != NULL && ri->x.lastuse
  1058.         && ri->x.regnode->mask&tmask[ri->x.regnode->set] ) {
  1059.             Regnode rn = ri->x.regnode;
  1060.             Node q = here;
  1061.             int dist = 0;
  1062.             for (; q && !uses(q, rn->mask); q = q->x.next)
  1063.                 dist++;
  1064.             if (q && dist > bestdist) {
  1065.                 bestdist = dist;
  1066.                 bestreg = ri;
  1067.             }
  1068.         }
  1069.     }
  1070.     else {
  1071.         for (i = 0; i < 32; i++) {
  1072.             Symbol ri = set->x.wildcard[i];
  1073.             if (ri != NULL && ri->x.lastuse
  1074.             && ri->x.regnode->mask&tmask[ri->x.regnode->set]) {
  1075.                 Regnode rn = ri->x.regnode;
  1076.                 Node q = here;
  1077.                 int dist = 0;
  1078.                 for (; q && !uses(q, rn->mask); q = q->x.next)
  1079.                     dist++;
  1080.                 if (q && dist > bestdist) {
  1081.                     bestdist = dist;
  1082.                     bestreg = ri;
  1083.                 }
  1084.             }
  1085.         }
  1086.     }
  1087.     return bestreg;
  1088. }
  1089. static int uses(Node p,unsigned mask)
  1090. {
  1091.     int i;
  1092.     Node q;
  1093.  
  1094.     for (i = 0; i < NELEMS(p->x.kids)
  1095.         && (q = p->x.kids[i]) != NULL; i++)
  1096.         if (q->x.registered
  1097.         && mask&q->syms[RX]->x.regnode->mask)
  1098.             return 1;
  1099.     return 0;
  1100. }
  1101. static void spillr(Symbol r,Node here)
  1102. {
  1103.     int i;
  1104.     Node p = r->x.lastuse;
  1105.     Symbol tmp;
  1106.  
  1107.     if (p == NULL) {
  1108.         putreg(r);
  1109.         return;
  1110.     }
  1111.     assert(p);
  1112.     while (p->x.prevuse) {
  1113.         assert(r == p->syms[RX]);
  1114.         p = p->x.prevuse;
  1115.     }
  1116.     assert(p->x.registered && !readsreg(p));
  1117.     tmp = newtemp(AUTO, optype(p->op));
  1118.     genspill(r, p, tmp);
  1119.     for (p = here->x.next; p; p = p->x.next)
  1120.         for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
  1121.             Node k = p->x.kids[i];
  1122.  
  1123.             if (k->x.registered && k->syms[RX] == r)
  1124.                 genreload(p, tmp, i);
  1125.         }
  1126.     putreg(r);
  1127. }
  1128. int NrOfSpills;
  1129. static void genspill(Symbol r,Node last,Symbol tmp)
  1130. {
  1131.     Node p, q;
  1132.     Symbol s;
  1133.     unsigned ty;
  1134. #ifdef DODEBUG
  1135.     fprint(2, "(spilling %s to local %s)\n", r->x.name, tmp->x.name);
  1136.     fprint(2, "(genspill: ");
  1137.     dumptree(last,0);
  1138.     fprint(2, ")\n");
  1139. #endif
  1140.     NrOfSpills++;
  1141.     ty = optype(last->op);
  1142.     if (ty == U)
  1143.         ty = I;
  1144.     NEW0(s, FUNC);
  1145.     s->sclass = REGISTER;
  1146.     s->x.name = r->x.name;
  1147.     s->x.regnode = r->x.regnode;
  1148.     s->x.regnode->vbl = s;
  1149.     q = newnode(ADDRLP, NULL, NULL, s);
  1150.     q = newnode(INDIR + ty, q, NULL, NULL);
  1151.     p = newnode(ADDRLP, NULL, NULL, tmp);
  1152.     p = newnode(ASGN + ty, p, q, NULL);
  1153.     p->x.spills = 1;
  1154.     rewrite(p);
  1155.     prune(p, &q);
  1156.     q = last->x.next;
  1157.     linearize(p, q);
  1158.     for (p = last->x.next; p != q; p = p->x.next) {
  1159.         ralloc(p);
  1160.         assert(!p->x.listed || !NeedsReg[opindex(p->op)] || !rmap[optype(p->op)]);
  1161.     }
  1162. }
  1163.  
  1164. static void genreload(Node p,Symbol tmp,int i)
  1165. {
  1166.     Node q;
  1167.     int ty;
  1168. #ifdef DODEBUG
  1169.     fprint(2, "(replacing %x with a reload from %s)\n", p->x.kids[i], tmp->x.name);
  1170.     fprint(2, "(genreload: ");
  1171.     dumptree(p->x.kids[i],0);
  1172.     fprint(2, ")\n");
  1173. #endif
  1174.     ty = optype(p->x.kids[i]->op);
  1175.     if (ty == U)
  1176.         ty = I;
  1177.     q = newnode(ADDRLP, NULL, NULL, tmp);
  1178.     p->x.kids[i] = newnode(INDIR + ty, q, NULL, NULL);
  1179.     rewrite(p->x.kids[i]);
  1180.     prune(p->x.kids[i], &q);
  1181.     reprune(&p->kids[1], reprune(&p->kids[0], 0, i, p), i, p);
  1182.     prune(p, &q);
  1183.     linearize(p->x.kids[i], p);
  1184. }
  1185. static int reprune(Node *pp,int k,int n,Node p)
  1186. {
  1187.     struct node x, *q = *pp;
  1188.  
  1189.     if (q == NULL || k > n)
  1190.         return k;
  1191.     else if (q->x.inst == 0)
  1192.         return reprune(&q->kids[1],
  1193.             reprune(&q->kids[0], k, n, p), n, p);
  1194.     else if (k == n) {
  1195. #ifdef DODEBUG
  1196.         fprint(2, "(reprune changes %x from %x to %x)\n", pp, *pp, p->x.kids[n]);
  1197. #endif
  1198.         *pp = p->x.kids[n];
  1199.         x = *p;        /* explain this */
  1200.         (IR->x.target)(&x);
  1201.     }
  1202.     return k + 1;
  1203. }
  1204. void spill(unsigned mask,int n,Node here)
  1205. {
  1206.     int i;
  1207.     Node p;
  1208.  
  1209.     here->x.spills = 1;
  1210.     usedmask[n] |= mask;
  1211.     if (mask&~freemask[n])
  1212.         for (p = here; p; p = p->x.next)
  1213.             for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
  1214.                 Symbol r = p->x.kids[i]->syms[RX];
  1215.                 assert(r);
  1216.                 if (p->x.kids[i]->x.registered && r->x.regnode->set == n
  1217.                 && r->x.regnode->mask&mask)
  1218.                     spillr(r, here);
  1219.             }
  1220. }
  1221. #ifndef NDEBUG
  1222.  
  1223. static void dumpregs(char *msg,char *a,char *b,char *c) 
  1224. {
  1225.     fprint(2, msg, a, b, c);
  1226.     fprint(2, "(free[0]=%x)", freemask[0]);
  1227.     if (freemask[0] & 1) fprint(2," eax");
  1228.     if (freemask[0] & (1 << 1)) fprint(2," ecx");
  1229.     if (freemask[0] & (1 << 2)) fprint(2," edx");
  1230.     if (freemask[0] & (1 << 3)) fprint(2," ebx");
  1231.     if (freemask[0] & (1 << 6)) fprint(2," esi");
  1232.     if (freemask[0] & (1 << 7)) fprint(2," edi");
  1233.     fprint(2,"\n");
  1234. }
  1235. #endif
  1236. int getregnum(Node p)
  1237. {
  1238.     assert(p && p->syms[RX] && p->syms[RX]->x.regnode);
  1239.     return p->syms[RX]->x.regnode->number;
  1240. }
  1241.  
  1242.  
  1243. unsigned regloc(Symbol p)
  1244. {
  1245.     assert(p && p->sclass == REGISTER && p->sclass == REGISTER && p->x.regnode);
  1246.     return p->x.regnode->set<<8 | p->x.regnode->number;
  1247. }
  1248.  
  1249.