Quick Search:

Mode

Context

Displaying the whole file. None | Less | More | Full

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.284
 
1.285
 
MAIN:ragge:20121213160341
 
reader.c
_>11 /*      $Id$    */
 22 /*
 33  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
 44  * All rights reserved.
 55  *
 66  * Redistribution and use in source and binary forms, with or without
 77  * modification, are permitted provided that the following conditions
 88  * are met:
 99  * 1. Redistributions of source code must retain the above copyright
 1010  *    notice, this list of conditions and the following disclaimer.
 1111  * 2. Redistributions in binary form must reproduce the above copyright
 1212  *    notice, this list of conditions and the following disclaimer in the
 1313  *    documentation and/or other materials provided with the distribution.
 1414  *
 1515  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 1616  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 1717  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 1818  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 1919  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 2020  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 2121  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 2222  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 2323  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 2424  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 2525  */
 2626 
 2727 /*
 2828  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
 2929  *
 3030  * Redistribution and use in source and binary forms, with or without
 3131  * modification, are permitted provided that the following conditions
 3232  * are met:
 3333  *
 3434  * Redistributions of source code and documentation must retain the above
 3535  * copyright notice, this list of conditions and the following disclaimer.
 3636  * Redistributions in binary form must reproduce the above copyright
 3737  * notice, this list of conditionsand the following disclaimer in the
 3838  * documentation and/or other materials provided with the distribution.
 3939  * All advertising materials mentioning features or use of this software
 4040  * must display the following acknowledgement:
 4141  *      This product includes software developed or owned by Caldera
 4242  *      International, Inc.
 4343  * Neither the name of Caldera International, Inc. nor the names of other
 4444  * contributors may be used to endorse or promote products derived from
 4545  * this software without specific prior written permission.
 4646  *
 4747  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
 4848  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
 4949  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 5050  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 5151  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
 5252  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 5353  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 5454  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 5555  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
 5656  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 5757  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 5858  * POSSIBILITY OF SUCH DAMAGE.
 5959  */
 6060 
 6161 /*
 6262  * Everything is entered via pass2_compile().  No functions are
 6363  * allowed to recurse back into pass2_compile().
 6464  */
 6565 
 6666 # include "pass2.h"
 6767 
 6868 #include <string.h>
 6969 #include <stdarg.h>
 7070 #include <stdlib.h>
 7171 
 7272 /*      some storage declarations */
 7373 int nrecur;
 7474 int thisline;
 7575 int fregs;
 7676 int p2autooff, p2maxautooff;
 7777 
 7878 NODE *nodepole;
 7979 struct interpass prepole;
 8080 
 8181 void saveip(struct interpass *ip);
 8282 void deltemp(NODE *p, void *);
 8383 static void cvtemps(struct interpass *ipole, int op, int off);
 8484 NODE *store(NODE *);
 8585 static void fixxasm(struct p2env *);
 8686 
 8787 static void gencode(NODE *p, int cookie);
 8888 static void genxasm(NODE *p);
 8989 static void afree(void);
 9090 
 9191 struct p2env p2env;
 9292 
 9393 int
 9494 getlab2(void)
 9595 {
 9696         extern int getlab(void);
 9797         int rv = getlab();
 9898 #ifdef PCC_DEBUG
 9999         if (p2env.epp->ip_lblnum != rv)
 100100                 comperr("getlab2 error: %d != %d", p2env.epp->ip_lblnum, rv);
 101101 #endif
 102102         p2env.epp->ip_lblnum++;
 103103         return rv;
 104104 }
 105105 
 106106 #ifdef PCC_DEBUG
 107107 static int *lbldef, *lbluse;
 108108 static void
 109109 cktree(NODE *p, void *arg)
 110110 {
 111111         int i;
 112112 
 113113         if (p->n_op > MAXOP)
 114114                 cerror("%p) op %d slipped through", p, p->n_op);
 115115 #ifndef FIELDOPS
 116116         if (p->n_op == FLD)
 117117                 cerror("%p) FLD slipped through", p);
 118118 #endif
 119119         if (BTYPE(p->n_type) > MAXTYPES)
 120120                 cerror("%p) type %x slipped through", p, p->n_type);
 121121         if (p->n_op == CBRANCH) {
 122122                  if (!logop(p->n_left->n_op))
 123123                         cerror("%p) not logop branch", p);
 124124                 i = (int)p->n_right->n_lval;
 125125                 if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum)
 126126                         cerror("%p) label %d outside boundaries %d-%d",
 127127                             p, i, p2env.ipp->ip_lblnum, p2env.epp->ip_lblnum);
 128128                 lbluse[i-p2env.ipp->ip_lblnum] = 1;
 129129         }
 130130         if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN)
 131131                 cerror("%p) asgop %d slipped through", p, p->n_op);
 132132         if (p->n_op == TEMP &&
 133133             (regno(p) < p2env.ipp->ip_tmpnum || regno(p) >= p2env.epp->ip_tmpnum))
 134134                 cerror("%p) temporary %d outside boundaries %d-%d",
 135135                     p, regno(p), p2env.ipp->ip_tmpnum, p2env.epp->ip_tmpnum);
 136136         if (p->n_op == GOTO && p->n_left->n_op == ICON) {
 137137                 i = (int)p->n_left->n_lval;
 138138                 if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum)
 139139                         cerror("%p) label %d outside boundaries %d-%d",
 140140                             p, i, p2env.ipp->ip_lblnum, p2env.epp->ip_lblnum);
 141141                 lbluse[i-p2env.ipp->ip_lblnum] = 1;
 142142         }
 143143 }
 144144 
 145145 /*
 146146  * Check that the trees are in a suitable state for pass2.
 147147  */
 148148 static void
 149149 sanitychecks(struct p2env *p2e)
 150150 {
 151151         struct interpass *ip;
 152152         int i;
 153153 #ifdef notyet
 154154         TMPMARK();
 155155 #endif
 156156         lbldef = tmpcalloc(sizeof(int) * (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum));
 157157         lbluse = tmpcalloc(sizeof(int) * (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum));
 158158 
 159159         DLIST_FOREACH(ip, &p2env.ipole, qelem) {
 160160                 if (ip->type == IP_DEFLAB) {
 161161                         i = ip->ip_lbl;
 162162                         if (i < p2e->ipp->ip_lblnum || i >= p2e->epp->ip_lblnum)
 163163                                 cerror("label %d outside boundaries %d-%d",
 164164                                     i, p2e->ipp->ip_lblnum, p2e->epp->ip_lblnum);
 165165                         lbldef[i-p2e->ipp->ip_lblnum] = 1;
 166166                 }
 167167                 if (ip->type == IP_NODE)
 168168                         walkf(ip->ip_node, cktree, 0);
 169169         }
 170170         for (i = 0; i < (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum); i++)
 171171                 if (lbluse[i] != 0 && lbldef[i] == 0)
 172172                         cerror("internal label %d not defined",
 173173                             i + p2e->ipp->ip_lblnum);
 174174 
 175175 #ifdef notyet
 176176         TMPFREE();
 177177 #endif
 178178 }
 179179 #endif
 180180 
 181181 /*
 182182  * Look if a temporary comes from a on-stack argument, in that case
 183183  * use the already existing stack position instead of moving it to
 184184  * a new place, and remove the move-to-temp statement.
 185185  */
 186186 static int
 187187 stkarg(int tnr, int (*soff)[2])
 188188 {
 189189         struct p2env *p2e = &p2env;
 190190         struct interpass *ip;
 191191         NODE *p;
 192192 
 193193         ip = DLIST_NEXT((struct interpass *)p2e->ipp, qelem);
 194194         while (ip->type != IP_DEFLAB) /* search for first DEFLAB */
 195195                 ip = DLIST_NEXT(ip, qelem);
 196196 
 197197         ip = DLIST_NEXT(ip, qelem); /* first NODE */
 198198 
 199199         for (; ip->type != IP_DEFLAB; ip = DLIST_NEXT(ip, qelem)) {
 200200                 if (ip->type != IP_NODE)
 201201                         continue;
 202202 
 203203                 p = ip->ip_node;
 204204                 if (p->n_op == XASM)
 205205                         continue; /* XXX - hack for x86 PIC */
 206206 #ifdef notdef
 207207                 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
 208208                         comperr("temparg");
 209209 #endif
 210210                 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
 211211                         continue; /* unknown tree */
 212212 
 213213                 if (p->n_right->n_op != OREG && p->n_right->n_op != UMUL)
 214214                         continue; /* arg in register */
 215215                 if (tnr != regno(p->n_left))
 216216                         continue; /* wrong assign */
 217217                 p = p->n_right;
 218218                 if (p->n_op == UMUL &&
 219219                     p->n_left->n_op == PLUS &&
 220220                     p->n_left->n_left->n_op == REG &&
 221221                     p->n_left->n_right->n_op == ICON) {
 222222                         soff[0][0] = regno(p->n_left->n_left);
 223223                         soff[0][1] = (int)p->n_left->n_right->n_lval;
 224224                 } else if (p->n_op == OREG) {
 225225                         soff[0][0] = regno(p);
 226226                         soff[0][1] = (int)p->n_lval;
 227227                 } else
 228228                         comperr("stkarg: bad arg");
 229229                 tfree(ip->ip_node);
 230230                 DLIST_REMOVE(ip, qelem);
 231231                 return 1;
 232232         }
 233233         return 0;
 234234 }
 235235 
 236236 /*
 237237  * See if an ADDROF is somewhere inside the expression tree.
 238238  * If so, fill in the offset table.
 239239  */
 240240 static void
 241241 findaof(NODE *p, void *arg)
 242242 {
 243243         int (*aof)[2] = arg;
 244244         int tnr;
 245245 
 246246         if (p->n_op != ADDROF || p->n_left->n_op != TEMP)
 247247                 return;
 248248         tnr = regno(p->n_left);
 249249         if (aof[tnr][0])
 250250                 return; /* already gotten stack address */
 251251         if (stkarg(tnr, &aof[tnr]))
 252252                 return/* argument was on stack */
 253253         aof[tnr][0] = FPREG;
 254254         aof[tnr][1] = BITOOR(freetemp(szty(p->n_left->n_type)));
 255255 }
 256256 
 257257 /*
 258258  * Check if a node has side effects.
 259259  */
 260260 static int
 261261 isuseless(NODE *n)
 262262 {
 263263         switch (n->n_op) {
 264264         case XASM:
 265265         case FUNARG:
 266266         case UCALL:
 267267         case UFORTCALL:
 268268         case FORCE:
 269269         case ASSIGN:
 270270         case CALL:
 271271         case FORTCALL:
 272272         case CBRANCH:
 273273         case RETURN:
 274274         case GOTO:
 275275         case STCALL:
 276276         case USTCALL:
 277277         case STASG:
 278278         case STARG:
 279279                 return 0;
 280280         default:
 281281                 return 1;
 282282         }
 283283 }
 284284 
 285285 /*
 286286  * Delete statements with no meaning (like a+b; or 513.4;)
 287287  */
 288288 NODE *
 289289 deluseless(NODE *p)
 290290 {
 291291         struct interpass *ip;
 292292         NODE *l, *r;
 293293 
 294294         if (optype(p->n_op) == LTYPE) {
 295295                 nfree(p);
 296296                 return NULL;
 297297         }
 298298         if (isuseless(p) == 0)
 299299                 return p;
 300300 
 301301         if (optype(p->n_op) == UTYPE) {
 302302                 l = p->n_left;
 303303                 nfree(p);
 304304                 return deluseless(l);
 305305         }
 306306 
 307307         /* Be sure that both leaves may be valid */
 308308         l = deluseless(p->n_left);
 309309         r = deluseless(p->n_right);
 310310         nfree(p);
 311311         if (l && r) {
 312312                 ip = ipnode(l);
 313313                 DLIST_INSERT_AFTER(&prepole, ip, qelem);
 314314                 return r;
 315315         } else if (l)
 316316                 return l;
 317317         else if (r)
 318318                 return r;
 319319         return NULL;
 320320 }
 321321 
 322322 /*
 323323  * Receives interpass structs from pass1.
 324324  */
 325325 void
 326326 pass2_compile(struct interpass *ip)
 327327 {
 328328         void deljumps(struct p2env *);
 329329         struct p2env *p2e = &p2env;
 330330         int (*addrp)[2];
 331331         MARK mark;
 332332 
 333333         if (ip->type == IP_PROLOG) {
 334334                 memset(p2e, 0, sizeof(struct p2env));
 335335                 p2e->ipp = (struct interpass_prolog *)ip;
 336336                 DLIST_INIT(&p2e->ipole, qelem);
 337337         }
 338338         DLIST_INSERT_BEFORE(&p2e->ipole, ip, qelem);
 339339         if (ip->type != IP_EPILOG)
 340340                 return;
 341341 
 342342 #ifdef PCC_DEBUG
 343343         if (e2debug) {
 344344                 printf("Entering pass2\n");
 345345                 printip(&p2e->ipole);
 346346         }
 347347 #endif
 348348 
 349349         afree();
 350350         p2e->epp = (struct interpass_prolog *)DLIST_PREV(&p2e->ipole, qelem);
 351351         p2maxautooff = p2autooff = p2e->epp->ipp_autos;
 352352 
 353353 #ifdef PCC_DEBUG
 354354         sanitychecks(p2e);
 355355 #endif
 356356         myreader(&p2e->ipole); /* local massage of input */
 357357 
 358358         /*
 359359          * Do initial modification of the trees.  Two loops;
 360360          * - first, search for ADDROF of TEMPs, these must be
 361361          *   converterd to OREGs on stack.
 362362          * - second, do the actual conversions, in case of not xtemps
 363363          *   convert all temporaries to stack references.
 364364          */
 365365         markset(&mark);
 366366         if (p2e->epp->ip_tmpnum != p2e->ipp->ip_tmpnum) {
 367367                 addrp = tmpcalloc(sizeof(*addrp) *
 368368                     (p2e->epp->ip_tmpnum - p2e->ipp->ip_tmpnum));
 369369                 addrp -= p2e->ipp->ip_tmpnum;
 370370         } else
 371371                 addrp = NULL;
 372372         if (xtemps) {
 373373                 DLIST_FOREACH(ip, &p2e->ipole, qelem) {
 374374                         if (ip->type == IP_NODE)
 375375                                 walkf(ip->ip_node, findaof, addrp);
 376376                 }
 377377         }
 378378         DLIST_FOREACH(ip, &p2e->ipole, qelem)
 379379                 if (ip->type == IP_NODE)
 380380                         walkf(ip->ip_node, deltemp, addrp);
 381381         markfree(&mark);
 382382 
 383383 #ifdef PCC_DEBUG
 384384         if (e2debug) {
 385385                 printf("Efter ADDROF/TEMP\n");
 386386                 printip(&p2e->ipole);
 387387         }
 388388 #endif
 389389 
 390390         DLIST_INIT(&prepole, qelem);
 391391         DLIST_FOREACH(ip, &p2e->ipole, qelem) {
 392392                 if (ip->type != IP_NODE)
 393393                         continue;
 394394                 canon(ip->ip_node);
 395395                 if ((ip->ip_node = deluseless(ip->ip_node)) == NULL) {
 396396                         DLIST_REMOVE(ip, qelem);
 397397                 } else while (!DLIST_ISEMPTY(&prepole, qelem)) {
 398398                         struct interpass *tipp;
 399399 
 400400                         tipp = DLIST_NEXT(&prepole, qelem);
 401401                         DLIST_REMOVE(tipp, qelem);
 402402                         DLIST_INSERT_BEFORE(ip, tipp, qelem);
 403403                 }
 404404         }
 405405 
 406406         fixxasm(p2e); /* setup for extended asm */
 407407 
 408408         optimize(p2e);
 409409         ngenregs(p2e);
 410410 
 411411         if (xtemps && xdeljumps)
 412412                 deljumps(p2e);
 413413 
 414414         DLIST_FOREACH(ip, &p2e->ipole, qelem)
 415415                 emit(ip);
 416416 }
 417417 
 418418 void
 419419 emit(struct interpass *ip)
 420420 {
 421421         NODE *p, *r;
 422422         struct optab *op;
 423423         int o;
 424424 
 425425         switch (ip->type) {
 426426         case IP_NODE:
 427427                 p = ip->ip_node;
 428428 
 429429                 nodepole = p;
 430430                 canon(p); /* may convert stuff after genregs */
 431431                 if (c2debug > 1) {
 432432                         printf("emit IP_NODE:\n");
 433433                         fwalk(p, e2print, 0);
 434434                 }
 435435                 switch (p->n_op) {
 436436                 case CBRANCH:
 437437                         /* Only emit branch insn if RESCC */
 438438                         /* careful when an OPLOG has been elided */
 439439                         if (p->n_left->n_su == 0 && p->n_left->n_left != NULL) {
 440440                                 op = &table[TBLIDX(p->n_left->n_left->n_su)];
 441441                                 r = p->n_left;
 442442                         } else {
 443443                                 op = &table[TBLIDX(p->n_left->n_su)];
 444444                                 r = p;
 445445                         }
 446446                         if (op->rewrite & RESCC) {
 447447                                 o = p->n_left->n_op;
 448448                                 gencode(r, FORCC);
 449449                                 cbgen(o, p->n_right->n_lval);
 450450                         } else {
 451451                                 gencode(r, FORCC);
 452452                         }
 453453                         break;
 454454                 case FORCE:
 455455                         gencode(p->n_left, INREGS);
 456456                         break;
 457457                 case XASM:
 458458                         genxasm(p);
 459459                         break;
 460460                 default:
 461461                         if (p->n_op != REG || p->n_type != VOID) /* XXX */
 462462                                 gencode(p, FOREFF); /* Emit instructions */
 463463                 }
 464464 
 465465                 tfree(p);
 466466                 break;
 467467         case IP_PROLOG:
 468468                 prologue((struct interpass_prolog *)ip);
 469469                 break;
 470470         case IP_EPILOG:
 471471                 eoftn((struct interpass_prolog *)ip);
 472472                 p2maxautooff = p2autooff = AUTOINIT/SZCHAR;
 473473                 break;
 474474         case IP_DEFLAB:
 475475                 deflab(ip->ip_lbl);
 476476                 break;
 477477         case IP_ASM:
 478478                 printf("%s", ip->ip_asm);
 479479                 break;
 480480         default:
 481481                 cerror("emit %d", ip->type);
 482482         }
 483483 }
 484484 
 485485 #ifdef PCC_DEBUG
 486486 char *cnames[] = {
 487487         "SANY",
 488488         "SAREG",
 489489         "SBREG",
 490490         "SCREG",
 491491         "SDREG",
 492492         "SCC",
 493493         "SNAME",
 494494         "SCON",
 495495         "SFLD",
 496496         "SOREG",
 497497         "STARNM",
 498498         "STARREG",
 499499         "INTEMP",
 500500         "FORARG",
 501501         "SWADD",
 502502         0,
 503503 };
 504504 
 505505 /*
 506506  * print a nice-looking description of cookie
 507507  */
 508508 char *
 509509 prcook(int cookie)
 510510 {
 511511         static char buf[50];
 512512         int i, flag;
 513513 
 514514         if (cookie & SPECIAL) {
 515515                 switch (cookie) {
 516516                 case SZERO:
 517517                         return "SZERO";
 518518                 case SONE:
 519519                         return "SONE";
 520520                 case SMONE:
 521521                         return "SMONE";
 522522                 default:
 523523                         snprintf(buf, sizeof(buf), "SPECIAL+%d", cookie & ~SPECIAL);
 524524                         return buf;
 525525                 }
 526526         }
 527527 
 528528         flag = 0;
 529529         buf[0] = 0;
 530530         for (i = 0; cnames[i]; ++i) {
 531531                 if (cookie & (1<<i)) {
 532532                         if (flag)
 533533                                 strlcat(buf, "|", sizeof(buf));
 534534                         ++flag;
 535535                         strlcat(buf, cnames[i], sizeof(buf));
 536536                 }
 537537         }
 538538         return buf;
 539539 }
 540540 #endif
 541541 
 542542 int
 543543 geninsn(NODE *p, int cookie)
 544544 {
 545545         NODE *p1, *p2;
 546546         int q, o, rv = 0;
 547547 
 548548 #ifdef PCC_DEBUG
 549549         if (o2debug) {
 550550                 printf("geninsn(%p, %s)\n", p, prcook(cookie));
 551551                 fwalk(p, e2print, 0);
 552552         }
 553553 #endif
 554554 
 555555         q = cookie & QUIET;
 556556         cookie &= ~QUIET; /* XXX - should not be necessary */
 557557 
 558558 again:  switch (o = p->n_op) {
 559559         case EQ:
 560560         case NE:
 561561         case LE:
 562562         case LT:
 563563         case GE:
 564564         case GT:
 565565         case ULE:
 566566         case ULT:
 567567         case UGE:
 568568         case UGT:
 569569                 p1 = p->n_left;
 570570                 p2 = p->n_right;
 571571                 if (p2->n_op == ICON && p2->n_lval == 0 && *p2->n_name == 0 &&
 572572                     (dope[p1->n_op] & (FLOFLG|DIVFLG|SIMPFLG|SHFFLG))) {
 573573 #ifdef mach_pdp11 /* XXX all targets? */
 574574                         if ((rv = geninsn(p1, FORCC|QUIET)) != FFAIL)
 575575                                 break;
 576576 #else
 577577                         if (findops(p1, FORCC) > 0)
 578578                                 break;
 579579 #endif
 580580                 }
 581581                 rv = relops(p);
 582582                 break;
 583583 
 584584         case PLUS:
 585585         case MINUS:
 586586         case MUL:
 587587         case DIV:
 588588         case MOD:
 589589         case AND:
 590590         case OR:
 591591         case ER:
 592592         case LS:
 593593         case RS:
 594594                 rv = findops(p, cookie);
 595595                 break;
 596596 
 597597         case ASSIGN:
 598598 #ifdef FINDMOPS
 599599                 if ((rv = findmops(p, cookie)) != FFAIL)
 600600                         break;
 601601                 /* FALLTHROUGH */
 602602 #endif
 603603         case STASG:
 604604                 rv = findasg(p, cookie);
 605605                 break;
 606606 
 607607         case UMUL: /* May turn into an OREG */
 608608                 rv = findumul(p, cookie);
 609609                 break;
 610610 
 611611         case REG:
 612612         case TEMP:
 613613         case NAME:
 614614         case ICON:
 615615         case FCON:
 616616         case OREG:
 617617                 rv = findleaf(p, cookie);
 618618                 break;
 619619 
 620620         case STCALL:
 621621         case CALL:
 622622                 /* CALL arguments are handled special */
 623623                 for (p1 = p->n_right; p1->n_op == CM; p1 = p1->n_left)
 624624                         (void)geninsn(p1->n_right, FOREFF);
 625625                 (void)geninsn(p1, FOREFF);
 626626                 /* FALLTHROUGH */
 627627         case FLD:
 628628         case COMPL:
 629629         case UMINUS:
 630630         case PCONV:
 631631         case SCONV:
 632632 /*      case INIT: */
 633633         case GOTO:
 634634         case FUNARG:
 635635         case STARG:
 636636         case UCALL:
 637637         case USTCALL:
 638638         case ADDROF:
 639639                 rv = finduni(p, cookie);
 640640                 break;
 641641 
 642642         case CBRANCH:
 643643                 p1 = p->n_left;
 644644                 p2 = p->n_right;
 645645                 p1->n_label = (int)p2->n_lval;
 646646                 (void)geninsn(p1, FORCC);
 647647                 p->n_su = 0;
 648648                 break;
 649649 
 650650         case FORCE: /* XXX needed? */
 651651                 (void)geninsn(p->n_left, INREGS);
 652652                 p->n_su = 0; /* su calculations traverse left */
 653653                 break;
 654654 
 655655         case XASM:
 656656                 for (p1 = p->n_left; p1->n_op == CM; p1 = p1->n_left)
 657657                         (void)geninsn(p1->n_right, FOREFF);
 658658                 (void)geninsn(p1, FOREFF);
 659659                 break;  /* all stuff already done? */
 660660 
 661661         case XARG:
 662662                 /* generate code for correct class here */
 663663 #if 0
 664664                 geninsn(p->n_left, 1 << p->n_label);
 665665 #endif
 666666                 break;
 667667 
 668668         default:
 669669                 comperr("geninsn: bad op %s, node %p", opst[o], p);
 670670         }
 671671         if (rv == FFAIL && !q)
 672672                 comperr("Cannot generate code, node %p op %s", p,opst[p->n_op]);
 673673         if (rv == FRETRY)
 674674                 goto again;
 675675 #ifdef PCC_DEBUG
 676676         if (o2debug) {
 677677                 printf("geninsn(%p, %s) rv %d\n", p, prcook(cookie), rv);
 678678                 fwalk(p, e2print, 0);
 679679         }
 680680 #endif
 681681         return rv;
 682682 }
 683683 
 684684 /*
 685685  * Store a given subtree in a temporary location.
 686686  * Return an OREG node where it is located.
 687687  */
 688688 NODE *
 689689 store(NODE *p)
 690690 {
 691691         extern struct interpass *storesave;
 692692         struct interpass *ip;
 693693         NODE *q, *r;
 694694         int s;
 695695 
 696696         s = BITOOR(freetemp(szty(p->n_type)));
 697697         q = mklnode(OREG, s, FPREG, p->n_type);
 698698         r = mklnode(OREG, s, FPREG, p->n_type);
 699699         ip = ipnode(mkbinode(ASSIGN, q, p, p->n_type));
 700700 
 701701         storesave = ip;
 702702         return r;
 703703 }
 704704 
 705705 #ifdef PCC_DEBUG
 706706 #define CDEBUG(x) if (c2debug) printf x
 707707 #else
 708708 #define CDEBUG(x)
 709709 #endif
 710710 
 711711 /*
 712712  * Do a register-register move if necessary.
 713713  * Called if a RLEFT or RRIGHT is found.
 714714  */
 715715 static void
 716716 ckmove(NODE *p, NODE *q)
 717717 {
 718718         struct optab *t = &table[TBLIDX(p->n_su)];
 719719         int reg;
 720720 
 721721         if (q->n_op != REG || p->n_reg == -1)
 722722                 return; /* no register */
 723723 
 724724         /* do we have a need for special reg? */
 725725         if ((t->needs & NSPECIAL) &&
 726726             (reg = rspecial(t, p->n_left == q ? NLEFT : NRIGHT)) >= 0)
 727727                 ;
 728728         else
 729729                 reg = DECRA(p->n_reg, 0);
 730730 
 731731         if (reg < 0 || reg == DECRA(q->n_reg, 0))
 732732                 return; /* no move necessary */
 733733 
 734734         CDEBUG(("rmove: node %p, %s -> %s\n", p, rnames[DECRA(q->n_reg, 0)],
 735735             rnames[reg]));
 736736         rmove(DECRA(q->n_reg, 0), reg, p->n_type);
 737737         q->n_reg = q->n_rval = reg;
 738738 }
 739739 
 740740 /*
 741741  * Rewrite node to register after instruction emit.
 742742  */
 743743 static void
 744744 rewrite(NODE *p, int dorewrite, int cookie)
 745745 {
 746746         NODE *l, *r;
 747747         int o;
 748748 
 749749         l = getlr(p, 'L');
 750750         r = getlr(p, 'R');
 751751         o = p->n_op;
 752752         p->n_op = REG;
 753753         p->n_lval = 0;
 754754         p->n_name = "";
 755755 
 756756         if (o == ASSIGN || o == STASG) {
 757757                 /* special rewrite care */
 758758                 int reg = DECRA(p->n_reg, 0);
 759759 #define TL(x) (TBLIDX(x->n_su) || x->n_op == REG)
 760760                 if (p->n_reg == -1)
 761761                         ;
 762762                 else if (TL(l) && (DECRA(l->n_reg, 0) == reg))
 763763                         ;
 764764                 else if (TL(r) && (DECRA(r->n_reg, 0) == reg))
 765765                         ;
 766766                 else if (TL(l))
 767767                         rmove(DECRA(l->n_reg, 0), reg, p->n_type);
 768768                 else if (TL(r))
 769769                         rmove(DECRA(r->n_reg, 0), reg, p->n_type);
 770770 #if 0
 771771                 else
 772772                         comperr("rewrite");
 773773 #endif
 774774 #undef TL
 775775         }
 776776         if (optype(o) != LTYPE)
 777777                 tfree(l);
 778778         if (optype(o) == BITYPE)
 779779                 tfree(r);
 780780         if (dorewrite == 0)
 781781                 return;
 782782         CDEBUG(("rewrite: %p, reg %s\n", p,
 783783             p->n_reg == -1? "<none>" : rnames[DECRA(p->n_reg, 0)]));
 784784         p->n_rval = DECRA(p->n_reg, 0);
 785785 }
 786786 
 787787 #ifndef XASM_TARGARG
 788788 #define XASM_TARGARG(x,y) 0
 789789 #endif
 790790 
 791791 /*
 792792  * printout extended assembler.
 793793  */
 794794 void
 795795 genxasm(NODE *p)
 796796 {
 797797         NODE *q, **nary;
 798798         int n = 1, o = 0;
 799799         char *w;
 800800 
 801801         if (p->n_left->n_op != ICON || p->n_left->n_type != STRTY) {
 802802                 for (q = p->n_left; q->n_op == CM; q = q->n_left)
 803803                         n++;
 804804                 nary = tmpcalloc(sizeof(NODE *)*(n+1));
 805805                 o = n;
 806806                 for (q = p->n_left; q->n_op == CM; q = q->n_left) {
 807807                         gencode(q->n_right->n_left, INREGS);
 808808                         nary[--o] = q->n_right;
 809809                 }
 810810                 gencode(q->n_left, INREGS);
 811811                 nary[--o] = q;
 812812         } else
 813813                 nary = 0;
 814814 
 815815         w = p->n_name;
 816816         putchar('\t');
 817817         while (*w != 0) {
 818818                 if (*w == '%') {
 819819                         if (w[1] == '%')
 820820                                 putchar('%');
 821821                         else if (XASM_TARGARG(w, nary))
 822822                                 ; /* handled by target */
 823823                         else if (w[1] < '0' || w[1] > (n + '0'))
 824824                                 uerror("bad xasm arg number %c", w[1]);
 825825                         else {
 826826                                 if (w[1] == (n + '0'))
 827827                                         q = nary[(int)w[1]-'0' - 1]; /* XXX */
 828828                                 else
 829829                                         q = nary[(int)w[1]-'0'];
 830830                                 adrput(stdout, q->n_left);
 831831                         }
 832832                         w++;
 833833                 } else if (*w == '\\') { /* Always 3-digit octal */
 834834                         int num = *++w - '0';
 835835                         num = (num << 3) + *++w - '0';
 836836                         num = (num << 3) + *++w - '0';
 837837                         putchar(num);
 838838                 } else
 839839                         putchar(*w);
 840840                 w++;
 841841         }
 842842         putchar('\n');
 843843 }
 844844 
 845845 /*
 846846  * Allocate temporary registers for use while emitting this table entry.
 847847  */
 848848 static void
 849849 allo(NODE *p, struct optab *q)
 850850 {
 851851         extern int stktemp;
 852852         int i, n = ncnt(q->needs);
 853853 
 854854         for (i = 0; i < NRESC; i++)
 855855                 if (resc[i].n_op != FREE)
 856856                         comperr("allo: used reg");
 857857         if (n == 0 && (q->needs & NTMASK) == 0)
 858858                 return;
 859859         for (i = 0; i < n+1; i++) {
 860860                 resc[i].n_op = REG;
 861861                 resc[i].n_type = p->n_type; /* XXX should be correct type */
 862862                 resc[i].n_rval = DECRA(p->n_reg, i);
 863863                 resc[i].n_su = p->n_su; /* ??? */
 864864         }
 865865         if (i > NRESC)
 866866                 comperr("allo: too many allocs");
 867867         if (q->needs & NTMASK) {
 868868                 resc[i].n_op = OREG;
 869869                 resc[i].n_lval = stktemp;
 870870                 resc[i].n_rval = FPREG;
 871871                 resc[i].n_su = p->n_su; /* ??? */
 872872                 resc[i].n_name = "";
 873873         }
 874874 }
 875875 
 876876 static void
 877877 afree(void)
 878878 {
 879879         int i;
 880880 
 881881         for (i = 0; i < NRESC; i++)
 882882                 resc[i].n_op = FREE;
 883883 }
 884884 
 885885 void
 886886 gencode(NODE *p, int cookie)
 887887 {
 888888         struct optab *q = &table[TBLIDX(p->n_su)];
 889889         NODE *p1, *l, *r;
 890890         int o = optype(p->n_op);
 891891 #ifdef FINDMOPS
 892892         int ismops = (p->n_op == ASSIGN && (p->n_flags & 1));
 893893 #endif
 894894 
 895895         l = p->n_left;
 896896         r = p->n_right;
 897897 
 898898         if (TBLIDX(p->n_su) == 0) {
 899899                 if (o == BITYPE && (p->n_su & DORIGHT))
 900900                         gencode(r, 0);
 901901                 if (optype(p->n_op) != LTYPE)
 902902                         gencode(l, 0);
 903903                 if (o == BITYPE && !(p->n_su & DORIGHT))
 904904                         gencode(r, 0);
 905905                 return;
 906906         }
 907907 
 908908         CDEBUG(("gencode: node %p\n", p));
 909909 
 910910         if (p->n_op == REG && DECRA(p->n_reg, 0) == p->n_rval)
 911911                 return; /* meaningless move to itself */
 912912 
 913913         if (callop(p->n_op))
 914914                 lastcall(p); /* last chance before function args */
 915915         if (p->n_op == CALL || p->n_op == FORTCALL || p->n_op == STCALL) {
 916916                 /* Print out arguments first */
 917917                 for (p1 = r; p1->n_op == CM; p1 = p1->n_left)
 918918                         gencode(p1->n_right, FOREFF);
 919919                 gencode(p1, FOREFF);
 920920                 o = UTYPE; /* avoid going down again */
 921921         }
 922922 
 923923         if (o == BITYPE && (p->n_su & DORIGHT)) {
 924924                 gencode(r, INREGS);
 925925                 if (q->rewrite & RRIGHT)
 926926                         ckmove(p, r);
 927927         }
 928928         if (o != LTYPE) {
 929929                 gencode(l, INREGS);
 930930 #ifdef FINDMOPS
 931931                 if (ismops)
 932932                         ;
 933933                 else
 934934 #endif
 935935                      if (q->rewrite & RLEFT)
 936936                         ckmove(p, l);
 937937         }
 938938         if (o == BITYPE && !(p->n_su & DORIGHT)) {
 939939                 gencode(r, INREGS);
 940940                 if (q->rewrite & RRIGHT)
 941941                         ckmove(p, r);
 942942         }
 943943 
 944944 #ifdef FINDMOPS
 945945         if (ismops) {
 946946                 /* reduce right tree to make expand() work */
 947947                 if (optype(r->n_op) != LTYPE) {
 948948                         p->n_op = r->n_op;
 949949                         r = tcopy(r->n_right);
 950950                         tfree(p->n_right);
 951951                         p->n_right = r;
 952952                 }
 953953         }
 954954 #endif
 955955 
 956956         canon(p);
 957957 
 958958         if (q->needs & NSPECIAL) {
 959959                 int rr = rspecial(q, NRIGHT);
 960960                 int lr = rspecial(q, NLEFT);
 961961 
 962962                 if (rr >= 0) {
 963963 #ifdef PCC_DEBUG
 964964                         if (optype(p->n_op) != BITYPE)
 965965                                 comperr("gencode: rspecial borked");
 966966 #endif
 967967                         if (r->n_op != REG)
 968968                                 comperr("gencode: rop != REG");
 969969                         if (rr != r->n_rval)
 970970                                 rmove(r->n_rval, rr, r->n_type);
 971971                         r->n_rval = r->n_reg = rr;
 972972                 }
 973973                 if (lr >= 0) {
 974974                         if (l->n_op != REG)
 975975                                 comperr("gencode: %p lop != REG", p);
 976976                         if (lr != l->n_rval)
 977977                                 rmove(l->n_rval, lr, l->n_type);
 978978                         l->n_rval = l->n_reg = lr;
 979979                 }
 980980                 if (rr >= 0 && lr >= 0 && (l->n_reg == rr || r->n_reg == lr))
 981981                         comperr("gencode: cross-reg-move");
 982982         }
 983983 
 984984         if (p->n_op == ASSIGN &&
 985985             p->n_left->n_op == REG && p->n_right->n_op == REG &&
 986986             p->n_left->n_rval == p->n_right->n_rval &&
 987987             (p->n_su & RVCC) == 0) { /* XXX should check if necessary */
 988988                 /* do not emit anything */
 989989                 CDEBUG(("gencode(%p) assign nothing\n", p));
 990990                 rewrite(p, q->rewrite, cookie);
 991991                 return;
 992992         }
 993993 
 994994         CDEBUG(("emitting node %p\n", p));
 995995         if (TBLIDX(p->n_su) == 0)
 996996                 return;
 997997 
 998998         allo(p, q);
 999999         expand(p, cookie, q->cstring);
 10001000 
 10011001 #ifdef FINDMOPS
 10021002         if (ismops && DECRA(p->n_reg, 0) != regno(l) && cookie != FOREFF) {
 10031003                 CDEBUG(("gencode(%p) rmove\n", p));
 10041004                 rmove(regno(l), DECRA(p->n_reg, 0), p->n_type);
 10051005         } else
 10061006 #endif
 10071007         if (callop(p->n_op) && cookie != FOREFF &&
 10081008             DECRA(p->n_reg, 0) != RETREG(p->n_type)) {
 10091009                 CDEBUG(("gencode(%p) retreg\n", p));
 10101010                 rmove(RETREG(p->n_type), DECRA(p->n_reg, 0), p->n_type);
 10111011         } else if (q->needs & NSPECIAL) {
 10121012                 int rr = rspecial(q, NRES);
 10131013 
 10141014                 if (rr >= 0 && DECRA(p->n_reg, 0) != rr) {
 10151015                         CDEBUG(("gencode(%p) nspec retreg\n", p));
 10161016                         rmove(rr, DECRA(p->n_reg, 0), p->n_type);
 10171017                 }
 10181018         } else if ((q->rewrite & RESC1) &&
 10191019             (DECRA(p->n_reg, 1) != DECRA(p->n_reg, 0))) {
 10201020                 CDEBUG(("gencode(%p) RESC1 retreg\n", p));
 10211021                 rmove(DECRA(p->n_reg, 1), DECRA(p->n_reg, 0), p->n_type);
 10221022         }
 10231023 #if 0
 10241024                 /* XXX - kolla upp det h{r */
 10251025            else if (p->n_op == ASSIGN) {
 10261026                 /* may need move added if RLEFT/RRIGHT */
 10271027                 /* XXX should be handled in sucomp() */
 10281028                 if ((q->rewrite & RLEFT) && (p->n_left->n_op == REG) &&
 10291029                     (p->n_left->n_rval != DECRA(p->n_reg, 0)) &&
 10301030                     TCLASS(p->n_su)) {
 10311031                         rmove(p->n_left->n_rval, DECRA(p->n_reg, 0), p->n_type);
 10321032                 } else if ((q->rewrite & RRIGHT) && (p->n_right->n_op == REG) &&
 10331033                     (p->n_right->n_rval != DECRA(p->n_reg, 0)) &&
 10341034                     TCLASS(p->n_su)) {
 10351035                         rmove(p->n_right->n_rval, DECRA(p->n_reg, 0), p->n_type);
 10361036                 }
 10371037         }
 10381038 #endif
 10391039         rewrite(p, q->rewrite, cookie);
 10401040         afree();
 10411041 }
 10421042 
 10431043 int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ;  /* negatives of relationals */
 10441044 size_t negrelsize = sizeof negrel / sizeof negrel[0];
 10451045 
 10461046 #ifdef PCC_DEBUG
 10471047 #undef  PRTABLE
 10481048 void
 10491049 e2print(NODE *p, int down, int *a, int *b)
 10501050 {
 10511051 #ifdef PRTABLE
 10521052         extern int tablesize;
 10531053 #endif
 10541054 
 10551055         *a = *b = down+1;
 10561056         while( down >= 2 ){
 10571057                 printf("\t");
 10581058                 down -= 2;
 10591059                 }
 10601060         if( down-- ) printf("    " );
 10611061 
 10621062 
 10631063         printf("%p) %s", p, opst[p->n_op] );
 10641064         switch( p->n_op ) { /* special cases */
 10651065 
 10661066         case FLD:
 10671067                 printf(" sz=%d, shift=%d",
 10681068                     UPKFSZ(p->n_rval), UPKFOFF(p->n_rval));
 10691069                 break;
 10701070 
 10711071         case REG:
 10721072                 printf(" %s", rnames[p->n_rval] );
 10731073                 break;
 10741074 
 10751075         case TEMP:
 10761076                 printf(" %d", regno(p));
 10771077                 break;
 10781078 
 10791079         case XASM:
 10801080         case XARG:
 10811081                 printf(" '%s'", p->n_name);
 10821082                 break;
 10831083 
 10841084         case ICON:
 10851085         case NAME:
 10861086         case OREG:
 10871087                 printf(" " );
 10881088                 adrput(stdout, p );
 10891089                 break;
 10901090 
 10911091         case STCALL:
 10921092         case USTCALL:
 10931093         case STARG:
 10941094         case STASG:
 10951095                 printf(" size=%d", p->n_stsize );
 10961096                 printf(" align=%d", p->n_stalign );
 10971097                 break;
 10981098                 }
 10991099 
 11001100         printf(", " );
 11011101         tprint(p->n_type, p->n_qual);
 11021102         printf(", " );
 11031103 
 11041104         prtreg(p);
 11051105         printf(", SU= %d(%cREG,%s,%s,%s,%s,%s,%s)\n",
 11061106             TBLIDX(p->n_su),
 11071107             TCLASS(p->n_su)+'@',
 11081108 #ifdef PRTABLE
 11091109             TBLIDX(p->n_su) >= 0 && TBLIDX(p->n_su) <= tablesize ?
 11101110             table[TBLIDX(p->n_su)].cstring : "",
 11111111 #else
 11121112             "",
 11131113 #endif
 11141114             p->n_su & LREG ? "LREG" : "", p->n_su & RREG ? "RREG" : "",
 11151115             p->n_su & RVEFF ? "RVEFF" : "", p->n_su & RVCC ? "RVCC" : "",
 11161116             p->n_su & DORIGHT ? "DORIGHT" : "");
 11171117 }
 11181118 #endif
 11191119 
 11201120 /*
 11211121  * change left TEMPs into OREGs
 11221122  */
 11231123 void
 11241124 deltemp(NODE *p, void *arg)
 11251125 {
 11261126         int (*aor)[2] = arg;
 11271127         NODE *l, *r;
 11281128 
 11291129         if (p->n_op == TEMP) {
 11301130                 if (aor[regno(p)][0] == 0) {
 11311131                         if (xtemps)
 11321132                                 return;
 11331133                         aor[regno(p)][0] = FPREG;
 11341134                         aor[regno(p)][1] = BITOOR(freetemp(szty(p->n_type)));
 11351135                 }
 11361136                 l = mklnode(REG, 0, aor[regno(p)][0], INCREF(p->n_type));
 11371137                 r = mklnode(ICON, aor[regno(p)][1], 0, INT);
 11381138                 p->n_left = mkbinode(PLUS, l, r, INCREF(p->n_type));
 11391139                 p->n_op = UMUL;
 11401140         } else if (p->n_op == ADDROF && p->n_left->n_op == OREG) {
 11411141                 p->n_op = PLUS;
 11421142                 l = p->n_left;
 11431143                 l->n_op = REG;
 11441144                 l->n_type = INCREF(l->n_type);
 11451145                 p->n_right = mklnode(ICON, l->n_lval, 0, INT);
 11461146         } else if (p->n_op == ADDROF && p->n_left->n_op == UMUL) {
 11471147                 l = p->n_left;
 11481148                 *p = *p->n_left->n_left;
 11491149                 nfree(l->n_left);
 11501150                 nfree(l);
 11511151         }
 11521152 }
 11531153 
 11541154 /*
 11551155  * for pointer/integer arithmetic, set pointer at left node
 11561156  */
 11571157 static void
 11581158 setleft(NODE *p, void *arg)
 11591159 {       
 11601160         NODE *q;
 11611161 
 11621162         /* only additions for now */
 11631163         if (p->n_op != PLUS)
 11641164                 return;
 11651165         if (ISPTR(p->n_right->n_type) && !ISPTR(p->n_left->n_type)) {
 11661166                 q = p->n_right;
 11671167                 p->n_right = p->n_left;
 11681168                 p->n_left = q;
 11691169         }
 11701170 }
 11711171 
 11721172 /* It is OK to have these as externals */
 11731173 static int oregr;
 11741174 static CONSZ oregtemp;
 11751175 static char *oregcp;
 11761176 /*
 11771177  * look for situations where we can turn * into OREG
 11781178  * If sharp then do not allow temps.
 11791179  */
 11801180 int
 11811181 oregok(NODE *p, int sharp)
 11821182 {
 11831183 
 11841184         NODE *q;
 11851185         NODE *ql, *qr;
 11861186         int r;
 11871187         CONSZ temp;
 11881188         char *cp;
 11891189 
 11901190         q = p->n_left;
 11911191 #if 0
 11921192         if ((q->n_op == REG || (q->n_op == TEMP && !sharp)) &&
 11931193             q->n_rval == DECRA(q->n_reg, 0)) {
 11941194 #endif
 11951195         if (q->n_op == REG || (q->n_op == TEMP && !sharp)) {
 11961196                 temp = q->n_lval;
 11971197                 r = q->n_rval;
 11981198                 cp = q->n_name;
 11991199                 goto ormake;
 12001200         }
 12011201 
 12021202         if (q->n_op != PLUS && q->n_op != MINUS)
 12031203                 return 0;
 12041204         ql = q->n_left;
 12051205         qr = q->n_right;
 12061206 
 12071207 #ifdef R2REGS
 12081208 
 12091209         /* look for doubly indexed expressions */
 12101210         /* XXX - fix checks */
 12111211 
 12121212         if( q->n_op == PLUS) {
 12131213                 int i;
 12141214                 if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) {
 12151215                         makeor2(p, ql, r, i);
 12161216                         return 1;
 12171217                 } else if((r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) {
 12181218                         makeor2(p, qr, r, i);
 12191219                         return 1;
 12201220                 }
 12211221         }
 12221222 
 12231223 
 12241224 #endif
 12251225 
 12261226 #if 0
 12271227         if( (q->n_op==PLUS || q->n_op==MINUS) && qr->n_op == ICON &&
 12281228                         (ql->n_op==REG || (ql->n_op==TEMP && !sharp)) &&
 12291229                         szty(qr->n_type)==1 &&
 12301230                         (ql->n_rval == DECRA(ql->n_reg, 0) ||
 12311231                         /* XXX */
 12321232                          ql->n_rval == FPREG || ql->n_rval == STKREG)) {
 12331233 #endif
 12341234         if ((q->n_op==PLUS || q->n_op==MINUS) && qr->n_op == ICON &&
 12351235             (ql->n_op==REG || (ql->n_op==TEMP && !sharp))) {
 12361236            
 12371237                 temp = qr->n_lval;
 12381238                 if( q->n_op == MINUS ) temp = -temp;
 12391239                 r = ql->n_rval;
 12401240                 temp += ql->n_lval;
 12411241                 cp = qr->n_name;
 12421242                 if( *cp && ( q->n_op == MINUS || *ql->n_name ) )
 12431243                         return 0;
 12441244                 if( !*cp ) cp = ql->n_name;
 12451245 
 12461246                 ormake:
 12471247                 if( notoff( p->n_type, r, temp, cp ))
 12481248                         return 0;
 12491249                 oregtemp = temp;
 12501250                 oregr = r;
 12511251                 oregcp = cp;
 12521252                 return 1;
 12531253         }
 12541254         return 0;
 12551255 }
 12561256 
 12571257 static void
 12581258 ormake(NODE *p)
 12591259 {
 12601260         NODE *q = p->n_left;
 12611261 
 12621262         p->n_op = OREG;
 12631263         p->n_rval = oregr;
 12641264         p->n_lval = oregtemp;
 12651265         p->n_name = oregcp;
 12661266         tfree(q);
 12671267 }
 12681268 
 12691269 /*
 12701270  * look for situations where we can turn * into OREG
 12711271  */
 12721272 void
 12731273 oreg2(NODE *p, void *arg)
 12741274 {
 12751275         if (p->n_op != UMUL)
 12761276                 return;
 12771277         if (oregok(p, 1))
 12781278                 ormake(p);
 12791279         if (p->n_op == UMUL)
 12801280                 myormake(p);
 12811281 }
 12821282 
 12831283 void
 12841284 canon(NODE *p)
 12851285 {
 12861286         /* put p in canonical form */
 12871287 
 12881288         walkf(p, setleft, 0);   /* ptrs at left node for arithmetic */
 12891289         walkf(p, oreg2, 0);     /* look for and create OREG nodes */
 12901290         mycanon(p);             /* your own canonicalization routine(s) */
 12911291 }
 12921292 
 12931293 void
 12941294 comperr(char *str, ...)
 12951295 {
 12961296         extern char *ftitle;
 12971297         va_list ap;
 12981298 
 12991299         if (nerrors) {
 13001300                 fprintf(stderr,
 13011301                     "cannot recover from earlier errors: goodbye!\n");
 13021302                 exit(1);
 13031303         }
 13041304 
 13051305         va_start(ap, str);
 13061306         fprintf(stderr, "%s, line %d: compiler error: ", ftitle, thisline);
 13071307         vfprintf(stderr, str, ap);
 13081308         fprintf(stderr, "\n");
 13091309         va_end(ap);
 13101310 
 13111311 #ifdef PCC_DEBUG
 13121312         if (nodepole && nodepole->n_op != FREE)
 13131313                 fwalk(nodepole, e2print, 0);
 13141314 #endif
 13151315         exit(1);
 13161316 }
 13171317 
 13181318 /*
 13191319  * allocate k integers worth of temp space
 13201320  * we also make the convention that, if the number of words is
 13211321  * more than 1, it must be aligned for storing doubles...
 13221322  * Returns bits offset from base register.
 13231323  * XXX - redo this.
 13241324  */
 13251325 int
 13261326 freetemp(int k)
 13271327 {
 13281328 #ifndef BACKTEMP
 13291329         int t;
 13301330 
 13311331         if (k > 1) {
 13321332                 SETOFF(p2autooff, ALDOUBLE/ALCHAR);
 13331333         } else {
 13341334                 SETOFF(p2autooff, ALINT/ALCHAR);
 13351335         }
 13361336 
 13371337         t = p2autooff;
 13381338         p2autooff += k*(SZINT/SZCHAR);
 13391339         if (p2autooff > p2maxautooff)
 13401340                 p2maxautooff = p2autooff;
 13411341         return (t);
 13421342 
 13431343 #else
 13441344         p2autooff += k*(SZINT/SZCHAR);
 13451345         if (k > 1) {
 13461346                 SETOFF(p2autooff, ALDOUBLE/ALCHAR);
 13471347         } else {
 13481348                 SETOFF(p2autooff, ALINT/ALCHAR);
 13491349         }
 13501350 
 13511351         if (p2autooff > p2maxautooff)
 13521352                 p2maxautooff = p2autooff;
 13531353         return( -p2autooff );
 13541354 #endif
 13551355 }
 13561356 
 13571357 NODE *
 13581358 mklnode(int op, CONSZ lval, int rval, TWORD type)
 13591359 {
 13601360         NODE *p = talloc();
 13611361 
 13621362         p->n_name = "";
 13631363         p->n_qual = 0;
 13641364         p->n_op = op;
 13651365         p->n_label = 0;
 13661366         p->n_lval = lval;
 13671367         p->n_rval = rval;
 13681368         p->n_type = type;
 13691369         p->n_regw = NULL;
 13701370         p->n_su = 0;
 13711371         return p;
 13721372 }
 13731373 
 13741374 NODE *
 13751375 mkbinode(int op, NODE *left, NODE *right, TWORD type)
 13761376 {
 13771377         NODE *p = talloc();
 13781378 
 13791379         p->n_name = "";
 13801380         p->n_qual = 0;
 13811381         p->n_op = op;
 13821382         p->n_label = 0;
 13831383         p->n_left = left;
 13841384         p->n_right = right;
 13851385         p->n_type = type;
 13861386         p->n_regw = NULL;
 13871387         p->n_su = 0;
 13881388         return p;
 13891389 }
 13901390 
 13911391 NODE *
 13921392 mkunode(int op, NODE *left, int rval, TWORD type)
 13931393 {
 13941394         NODE *p = talloc();
 13951395 
 13961396         p->n_name = "";
 13971397         p->n_qual = 0;
 13981398         p->n_op = op;
 13991399         p->n_label = 0;
 14001400         p->n_left = left;
 14011401         p->n_rval = rval;
 14021402         p->n_type = type;
 14031403         p->n_regw = NULL;
 14041404         p->n_su = 0;
 14051405         return p;
 14061406 }
 14071407 
 14081408 struct interpass *
 14091409 ipnode(NODE *p)
 14101410 {
 14111411         struct interpass *ip = tmpalloc(sizeof(struct interpass));
 14121412 
 14131413         ip->ip_node = p;
 14141414         ip->type = IP_NODE;
 14151415         ip->lineno = thisline;
 14161416         return ip;
 14171417 }
 14181418 
 14191419 int
 14201420 rspecial(struct optab *q, int what)
 14211421 {
 14221422         struct rspecial *r = nspecial(q);
 14231423         while (r->op) {
 14241424                 if (r->op == what)
 14251425                         return r->num;
 14261426                 r++;
 14271427         }
 14281428         return -1;
 14291429 }
 14301430 
 14311431 #ifndef XASM_NUMCONV
 14321432 #define XASM_NUMCONV(x,y,z)     0
 14331433 #endif
 14341434 
 14351435 /*
 14361436  * change numeric argument redirections to the correct node type after
 14371437  * cleaning up the other nodes.
 14381438  * be careful about input operands that may have different value than output.
 14391439  */
 14401440 static void
 14411441 delnums(NODE *p, void *arg)
 14421442 {
 14431443         struct interpass *ip = arg, *ip2;
 14441444         NODE *r = ip->ip_node->n_left;
 14451445         NODE *q;
 14461446         TWORD t;
 14471447         int cnt, num;
 14481448 
 14491449         /* gcc allows % in constraints, but we ignore it */
 14501450         if (p->n_name[0] == '%' && p->n_name[1] >= '0' && p->n_name[1] <= '9')
 14511451                 p->n_name++;
 14521452 
 14531453         if (p->n_name[0] < '0' || p->n_name[0] > '9')
 14541454                 return; /* not numeric */
 14551455         if ((q = listarg(r, p->n_name[0] - '0', &cnt)) == NIL)
 14561456                 comperr("bad delnums");
 14571457 
 14581458         /* target may have opinions whether to do this conversion */
 14591459         if (XASM_NUMCONV(ip, p, q))
 14601460                 return;
 14611461 
 14621462         /* Delete number by adding move-to/from-temp.  Later on */
 14631463         /* the temps may be rewritten to other LTYPEs */
 14641464         num = p2env.epp->ip_tmpnum++;
 14651465 
 14661466         /* pre node */
 14671467         t = p->n_left->n_type;
 14681468         r = mklnode(TEMP, 0, num, t);
 14691469         ip2 = ipnode(mkbinode(ASSIGN, tcopy(r), p->n_left, t));
 14701470         DLIST_INSERT_BEFORE(ip, ip2, qelem);
 14711471         p->n_left = r;
 14721472 
 14731473         /* post node */
 14741474         t = q->n_left->n_type;
 14751475         r = mklnode(TEMP, 0, num, t);
 14761476         ip2 = ipnode(mkbinode(ASSIGN, q->n_left, tcopy(r), t));
 14771477         DLIST_INSERT_AFTER(ip, ip2, qelem);
 14781478         q->n_left = r;
 14791479 
 14801480         p->n_name = tmpstrdup(q->n_name);
 14811481         if (*p->n_name == '=')
 14821482                 p->n_name++;
 14831483 }
 14841484 
 14851485 /*
 14861486  * Ensure that a node is correct for the destination.
 14871487  */
 14881488 static void
 14891489 ltypify(NODE *p, void *arg)
 14901490 {
 14911491         struct interpass *ip = arg;
 14921492         struct interpass *ip2;
 14931493         TWORD t = p->n_left->n_type;
 14941494         NODE *q, *r;
 14951495         int cw, ooff, ww;
 14961496         char *c;
 14971497 
 14981498 again:
 14991499         if (myxasm(ip, p))
 15001500                 return/* handled by target-specific code */
 15011501 
 15021502         cw = xasmcode(p->n_name);
 15031503         switch (ww = XASMVAL(cw)) {
 15041504         case 'p':
 15051505                 /* pointer */
 15061506                 /* just make register of it */
 15071507                 p->n_name = tmpstrdup(p->n_name);
 15081508                 c = strchr(p->n_name, XASMVAL(cw)); /* cannot fail */
 15091509                 *c = 'r';
 15101510                 /* FALLTHROUGH */
 15111511         case 'g'/* general; any operand */
 15121512                 if (ww == 'g' && p->n_left->n_op == ICON) {
 15131513                         /* should only be input */
 15141514                         p->n_name = "i";
 15151515                         break;
 15161516                 }
 15171517                 /* FALLTHROUGH */
 15181518         case 'r': /* general reg */
 15191519                 /* set register class */
 15201520                 p->n_label = gclass(p->n_left->n_type);
<>1521 -                if (p->n_left->n_op == REG)
  1521+                if (p->n_left->n_op == REG || p->n_left->n_op == TEMP)
<_15221522                         break;
 15231523                 q = p->n_left;
 15241524                 r = (cw & XASMINOUT ? tcopy(q) : q);
 15251525                 p->n_left = mklnode(TEMP, 0, p2env.epp->ip_tmpnum++, t);
 15261526                 if ((cw & XASMASG) == 0) {
 15271527                         ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), r, t));
 15281528                         DLIST_INSERT_BEFORE(ip, ip2, qelem);
 15291529                 }
 15301530                 if (cw & (XASMASG|XASMINOUT)) {
 15311531                         /* output parameter */
 15321532                         ip2 = ipnode(mkbinode(ASSIGN, q, tcopy(p->n_left), t));
 15331533                         DLIST_INSERT_AFTER(ip, ip2, qelem);
 15341534                 }
 15351535                 break;
 15361536 
 15371537         case '0': case '1': case '2': case '3': case '4':
 15381538         case '5': case '6': case '7': case '8': case '9':
 15391539                 break;
 15401540 
 15411541         case 'm': /* memory operand */
 15421542                 /* store and reload value */
 15431543                 q = p->n_left;
 15441544                 if (optype(q->n_op) == LTYPE) {
 15451545                         if (q->n_op == TEMP) {
 15461546                                 ooff = BITOOR(freetemp(szty(t)));
 15471547                                 cvtemps(ip, q->n_rval, ooff);
 15481548                         } else if (q->n_op == REG)
 15491549                                 comperr("xasm m and reg");
 15501550                 } else if (q->n_op == UMUL &&
 15511551                     (q->n_left->n_op != TEMP && q->n_left->n_op != REG)) {
 15521552                         t = q->n_left->n_type;
 15531553                         ooff = p2env.epp->ip_tmpnum++;
 15541554                         ip2 = ipnode(mkbinode(ASSIGN,
 15551555                             mklnode(TEMP, 0, ooff, t), q->n_left, t));
 15561556                         q->n_left = mklnode(TEMP, 0, ooff, t);
 15571557                         DLIST_INSERT_BEFORE(ip, ip2, qelem);
 15581558                 }
 15591559                 break;
 15601560 
 15611561         case 'i': /* immediate constant */
 15621562         case 'n': /* numeric constant */
 15631563                 if (p->n_left->n_op == ICON)
 15641564                         break;
 15651565                 p->n_name = tmpstrdup(p->n_name);
 15661566                 c = strchr(p->n_name, XASMVAL(cw)); /* cannot fail */
 15671567                 if (c[1]) {
 15681568                         c[0] = c[1], c[1] = 0;
 15691569                         goto again;
 15701570                 } else
 15711571                         uerror("constant required");
 15721572                 break;
 15731573 
 15741574         default:
 15751575                 uerror("unsupported xasm option string '%s'", p->n_name);
 15761576         }
 15771577 }
 15781578 
 15791579 /* Extended assembler hacks */
 15801580 static void
 15811581 fixxasm(struct p2env *p2e)
 15821582 {
 15831583         struct interpass *pole = &p2e->ipole;
 15841584         struct interpass *ip;
 15851585         NODE *p;
 15861586 
 15871587         DLIST_FOREACH(ip, pole, qelem) {
 15881588                 if (ip->type != IP_NODE || ip->ip_node->n_op != XASM)
 15891589                         continue;
 15901590                 thisline = ip->lineno;
 15911591                 p = ip->ip_node->n_left;
 15921592 
 15931593                 if (p->n_op == ICON && p->n_type == STRTY)
 15941594                         continue;
 15951595 
 15961596                 /* replace numeric redirections with its underlying type */
 15971597                 flist(p, delnums, ip);
 15981598 
 15991599                 /*
 16001600                  * Ensure that the arg nodes can be directly addressable
 16011601                  * We decide that everything shall be LTYPE here.
 16021602                  */
 16031603                 flist(p, ltypify, ip);
 16041604         }
 16051605 }
 16061606 
 16071607 /*
 16081608  * Extract codeword from xasm string */
 16091609 int
 16101610 xasmcode(char *s)
 16111611 {
 16121612         int cw = 0, nm = 0;
 16131613 
 16141614         while (*s) {
 16151615                 switch ((int)*s) {
 16161616                 case '=': cw |= XASMASG; break;
 16171617                 case '&': cw |= XASMCONSTR; break;
 16181618                 case '+': cw |= XASMINOUT; break;
 16191619                 case '%': break;
 16201620                 default:
 16211621                         if ((*s >= 'a' && *s <= 'z') ||
 16221622                             (*s >= 'A' && *s <= 'Z') ||
 16231623                             (*s >= '0' && *s <= '9')) {
 16241624                                 if (nm == 0)
 16251625                                         cw |= *s;
 16261626                                 else
 16271627                                         cw |= (*s << ((nm + 1) * 8));
 16281628                                 nm++;
 16291629                                 break;
 16301630                         }
 16311631                         uerror("bad xasm constraint %c", *s);
 16321632                 }
 16331633                 s++;
 16341634         }
 16351635         return cw;
 16361636 }
 16371637 
 16381638 static int xasnum, xoffnum;
 16391639 
 16401640 static void
 16411641 xconv(NODE *p, void *arg)
 16421642 {
 16431643         if (p->n_op != TEMP || p->n_rval != xasnum)
 16441644                 return;
 16451645         p->n_op = OREG;
 16461646         p->n_rval = FPREG;
 16471647         p->n_lval = xoffnum;
 16481648 }
 16491649 
 16501650 /*
 16511651  * Convert nodes of type TEMP to op with lval off.
 16521652  */
 16531653 static void
 16541654 cvtemps(struct interpass *ipl, int tnum, int off)
 16551655 {
 16561656         struct interpass *ip;
 16571657 
 16581658         xasnum = tnum;
 16591659         xoffnum = off;
 16601660 
 16611661         DLIST_FOREACH(ip, ipl, qelem)
 16621662                 if (ip->type == IP_NODE)
 16631663                         walkf(ip->ip_node, xconv, 0);
 16641664         walkf(ipl->ip_node, xconv, 0);
 16651665 }
FishEye: Open Source License registered to PCC.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-09-01 20:46 +0200