Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.285
 
1.286
 
MAIN:ragge:20121228160403
 
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;
<>798 -        int n = 1, o = 0;
  798+        int n = 1, o = 0, v = 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 */
<>823 -                        else if (w[1] < '0' || w[1] > (n + '0'))
  823+                        else if (w[1] == '=') {
  824+                                if (v == 0) v = getlab2();
  825+                                printf("%d", v);
  826+                        } else if (w[1] == 'c') {
  827+                                q = nary[(int)w[2]-'0'];
  828+                                if (q->n_left->n_op != ICON)
  829+                                        uerror("impossible constraint");
  830+                                printf(CONFMT, q->n_left->n_lval);
  831+                                w++;
  832+                        } else if (w[1] < '0' || w[1] > (n + '0'))
<_824833                                 uerror("bad xasm arg number %c", w[1]);
 825834                         else {
 826835                                 if (w[1] == (n + '0'))
 827836                                         q = nary[(int)w[1]-'0' - 1]; /* XXX */
 828837                                 else
 829838                                         q = nary[(int)w[1]-'0'];
 830839                                 adrput(stdout, q->n_left);
 831840                         }
 832841                         w++;
 833842                 } else if (*w == '\\') { /* Always 3-digit octal */
 834843                         int num = *++w - '0';
 835844                         num = (num << 3) + *++w - '0';
 836845                         num = (num << 3) + *++w - '0';
 837846                         putchar(num);
 838847                 } else
 839848                         putchar(*w);
 840849                 w++;
 841850         }
 842851         putchar('\n');
 843852 }
 844853 
 845854 /*
 846855  * Allocate temporary registers for use while emitting this table entry.
 847856  */
 848857 static void
 849858 allo(NODE *p, struct optab *q)
 850859 {
 851860         extern int stktemp;
 852861         int i, n = ncnt(q->needs);
 853862 
 854863         for (i = 0; i < NRESC; i++)
 855864                 if (resc[i].n_op != FREE)
 856865                         comperr("allo: used reg");
 857866         if (n == 0 && (q->needs & NTMASK) == 0)
 858867                 return;
 859868         for (i = 0; i < n+1; i++) {
 860869                 resc[i].n_op = REG;
 861870                 resc[i].n_type = p->n_type; /* XXX should be correct type */
 862871                 resc[i].n_rval = DECRA(p->n_reg, i);
 863872                 resc[i].n_su = p->n_su; /* ??? */
 864873         }
 865874         if (i > NRESC)
 866875                 comperr("allo: too many allocs");
 867876         if (q->needs & NTMASK) {
 868877                 resc[i].n_op = OREG;
 869878                 resc[i].n_lval = stktemp;
 870879                 resc[i].n_rval = FPREG;
 871880                 resc[i].n_su = p->n_su; /* ??? */
 872881                 resc[i].n_name = "";
 873882         }
 874883 }
 875884 
 876885 static void
 877886 afree(void)
 878887 {
 879888         int i;
 880889 
 881890         for (i = 0; i < NRESC; i++)
 882891                 resc[i].n_op = FREE;
 883892 }
 884893 
 885894 void
 886895 gencode(NODE *p, int cookie)
 887896 {
 888897         struct optab *q = &table[TBLIDX(p->n_su)];
 889898         NODE *p1, *l, *r;
 890899         int o = optype(p->n_op);
 891900 #ifdef FINDMOPS
 892901         int ismops = (p->n_op == ASSIGN && (p->n_flags & 1));
 893902 #endif
 894903 
 895904         l = p->n_left;
 896905         r = p->n_right;
 897906 
 898907         if (TBLIDX(p->n_su) == 0) {
 899908                 if (o == BITYPE && (p->n_su & DORIGHT))
 900909                         gencode(r, 0);
 901910                 if (optype(p->n_op) != LTYPE)
 902911                         gencode(l, 0);
 903912                 if (o == BITYPE && !(p->n_su & DORIGHT))
 904913                         gencode(r, 0);
 905914                 return;
 906915         }
 907916 
 908917         CDEBUG(("gencode: node %p\n", p));
 909918 
 910919         if (p->n_op == REG && DECRA(p->n_reg, 0) == p->n_rval)
 911920                 return; /* meaningless move to itself */
 912921 
 913922         if (callop(p->n_op))
 914923                 lastcall(p); /* last chance before function args */
 915924         if (p->n_op == CALL || p->n_op == FORTCALL || p->n_op == STCALL) {
 916925                 /* Print out arguments first */
 917926                 for (p1 = r; p1->n_op == CM; p1 = p1->n_left)
 918927                         gencode(p1->n_right, FOREFF);
 919928                 gencode(p1, FOREFF);
 920929                 o = UTYPE; /* avoid going down again */
 921930         }
 922931 
 923932         if (o == BITYPE && (p->n_su & DORIGHT)) {
 924933                 gencode(r, INREGS);
 925934                 if (q->rewrite & RRIGHT)
 926935                         ckmove(p, r);
 927936         }
 928937         if (o != LTYPE) {
 929938                 gencode(l, INREGS);
 930939 #ifdef FINDMOPS
 931940                 if (ismops)
 932941                         ;
 933942                 else
 934943 #endif
 935944                      if (q->rewrite & RLEFT)
 936945                         ckmove(p, l);
 937946         }
 938947         if (o == BITYPE && !(p->n_su & DORIGHT)) {
 939948                 gencode(r, INREGS);
 940949                 if (q->rewrite & RRIGHT)
 941950                         ckmove(p, r);
 942951         }
 943952 
 944953 #ifdef FINDMOPS
 945954         if (ismops) {
 946955                 /* reduce right tree to make expand() work */
 947956                 if (optype(r->n_op) != LTYPE) {
 948957                         p->n_op = r->n_op;
 949958                         r = tcopy(r->n_right);
 950959                         tfree(p->n_right);
 951960                         p->n_right = r;
 952961                 }
 953962         }
 954963 #endif
 955964 
 956965         canon(p);
 957966 
 958967         if (q->needs & NSPECIAL) {
 959968                 int rr = rspecial(q, NRIGHT);
 960969                 int lr = rspecial(q, NLEFT);
 961970 
 962971                 if (rr >= 0) {
 963972 #ifdef PCC_DEBUG
 964973                         if (optype(p->n_op) != BITYPE)
 965974                                 comperr("gencode: rspecial borked");
 966975 #endif
 967976                         if (r->n_op != REG)
 968977                                 comperr("gencode: rop != REG");
 969978                         if (rr != r->n_rval)
 970979                                 rmove(r->n_rval, rr, r->n_type);
 971980                         r->n_rval = r->n_reg = rr;
 972981                 }
 973982                 if (lr >= 0) {
 974983                         if (l->n_op != REG)
 975984                                 comperr("gencode: %p lop != REG", p);
 976985                         if (lr != l->n_rval)
 977986                                 rmove(l->n_rval, lr, l->n_type);
 978987                         l->n_rval = l->n_reg = lr;
 979988                 }
 980989                 if (rr >= 0 && lr >= 0 && (l->n_reg == rr || r->n_reg == lr))
 981990                         comperr("gencode: cross-reg-move");
 982991         }
 983992 
 984993         if (p->n_op == ASSIGN &&
 985994             p->n_left->n_op == REG && p->n_right->n_op == REG &&
 986995             p->n_left->n_rval == p->n_right->n_rval &&
 987996             (p->n_su & RVCC) == 0) { /* XXX should check if necessary */
 988997                 /* do not emit anything */
 989998                 CDEBUG(("gencode(%p) assign nothing\n", p));
 990999                 rewrite(p, q->rewrite, cookie);
 9911000                 return;
 9921001         }
 9931002 
 9941003         CDEBUG(("emitting node %p\n", p));
 9951004         if (TBLIDX(p->n_su) == 0)
 9961005                 return;
 9971006 
 9981007         allo(p, q);
 9991008         expand(p, cookie, q->cstring);
 10001009 
 10011010 #ifdef FINDMOPS
 10021011         if (ismops && DECRA(p->n_reg, 0) != regno(l) && cookie != FOREFF) {
 10031012                 CDEBUG(("gencode(%p) rmove\n", p));
 10041013                 rmove(regno(l), DECRA(p->n_reg, 0), p->n_type);
 10051014         } else
 10061015 #endif
 10071016         if (callop(p->n_op) && cookie != FOREFF &&
 10081017             DECRA(p->n_reg, 0) != RETREG(p->n_type)) {
 10091018                 CDEBUG(("gencode(%p) retreg\n", p));
 10101019                 rmove(RETREG(p->n_type), DECRA(p->n_reg, 0), p->n_type);
 10111020         } else if (q->needs & NSPECIAL) {
 10121021                 int rr = rspecial(q, NRES);
 10131022 
 10141023                 if (rr >= 0 && DECRA(p->n_reg, 0) != rr) {
 10151024                         CDEBUG(("gencode(%p) nspec retreg\n", p));
 10161025                         rmove(rr, DECRA(p->n_reg, 0), p->n_type);
 10171026                 }
 10181027         } else if ((q->rewrite & RESC1) &&
 10191028             (DECRA(p->n_reg, 1) != DECRA(p->n_reg, 0))) {
 10201029                 CDEBUG(("gencode(%p) RESC1 retreg\n", p));
 10211030                 rmove(DECRA(p->n_reg, 1), DECRA(p->n_reg, 0), p->n_type);
 10221031         }
 10231032 #if 0
 10241033                 /* XXX - kolla upp det h{r */
 10251034            else if (p->n_op == ASSIGN) {
 10261035                 /* may need move added if RLEFT/RRIGHT */
 10271036                 /* XXX should be handled in sucomp() */
 10281037                 if ((q->rewrite & RLEFT) && (p->n_left->n_op == REG) &&
 10291038                     (p->n_left->n_rval != DECRA(p->n_reg, 0)) &&
 10301039                     TCLASS(p->n_su)) {
 10311040                         rmove(p->n_left->n_rval, DECRA(p->n_reg, 0), p->n_type);
 10321041                 } else if ((q->rewrite & RRIGHT) && (p->n_right->n_op == REG) &&
 10331042                     (p->n_right->n_rval != DECRA(p->n_reg, 0)) &&
 10341043                     TCLASS(p->n_su)) {
 10351044                         rmove(p->n_right->n_rval, DECRA(p->n_reg, 0), p->n_type);
 10361045                 }
 10371046         }
 10381047 #endif
 10391048         rewrite(p, q->rewrite, cookie);
 10401049         afree();
 10411050 }
 10421051 
 10431052 int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ;  /* negatives of relationals */
 10441053 size_t negrelsize = sizeof negrel / sizeof negrel[0];
 10451054 
 10461055 #ifdef PCC_DEBUG
 10471056 #undef  PRTABLE
 10481057 void
 10491058 e2print(NODE *p, int down, int *a, int *b)
 10501059 {
 10511060 #ifdef PRTABLE
 10521061         extern int tablesize;
 10531062 #endif
 10541063 
 10551064         *a = *b = down+1;
 10561065         while( down >= 2 ){
 10571066                 printf("\t");
 10581067                 down -= 2;
 10591068                 }
 10601069         if( down-- ) printf("    " );
 10611070 
 10621071 
 10631072         printf("%p) %s", p, opst[p->n_op] );
 10641073         switch( p->n_op ) { /* special cases */
 10651074 
 10661075         case FLD:
 10671076                 printf(" sz=%d, shift=%d",
 10681077                     UPKFSZ(p->n_rval), UPKFOFF(p->n_rval));
 10691078                 break;
 10701079 
 10711080         case REG:
 10721081                 printf(" %s", rnames[p->n_rval] );
 10731082                 break;
 10741083 
 10751084         case TEMP:
 10761085                 printf(" %d", regno(p));
 10771086                 break;
 10781087 
 10791088         case XASM:
 10801089         case XARG:
 10811090                 printf(" '%s'", p->n_name);
 10821091                 break;
 10831092 
 10841093         case ICON:
 10851094         case NAME:
 10861095         case OREG:
 10871096                 printf(" " );
 10881097                 adrput(stdout, p );
 10891098                 break;
 10901099 
 10911100         case STCALL:
 10921101         case USTCALL:
 10931102         case STARG:
 10941103         case STASG:
 10951104                 printf(" size=%d", p->n_stsize );
 10961105                 printf(" align=%d", p->n_stalign );
 10971106                 break;
 10981107                 }
 10991108 
 11001109         printf(", " );
 11011110         tprint(p->n_type, p->n_qual);
 11021111         printf(", " );
 11031112 
 11041113         prtreg(p);
 11051114         printf(", SU= %d(%cREG,%s,%s,%s,%s,%s,%s)\n",
 11061115             TBLIDX(p->n_su),
 11071116             TCLASS(p->n_su)+'@',
 11081117 #ifdef PRTABLE
 11091118             TBLIDX(p->n_su) >= 0 && TBLIDX(p->n_su) <= tablesize ?
 11101119             table[TBLIDX(p->n_su)].cstring : "",
 11111120 #else
 11121121             "",
 11131122 #endif
 11141123             p->n_su & LREG ? "LREG" : "", p->n_su & RREG ? "RREG" : "",
 11151124             p->n_su & RVEFF ? "RVEFF" : "", p->n_su & RVCC ? "RVCC" : "",
 11161125             p->n_su & DORIGHT ? "DORIGHT" : "");
 11171126 }
 11181127 #endif
 11191128 
 11201129 /*
 11211130  * change left TEMPs into OREGs
 11221131  */
 11231132 void
 11241133 deltemp(NODE *p, void *arg)
 11251134 {
 11261135         int (*aor)[2] = arg;
 11271136         NODE *l, *r;
 11281137 
 11291138         if (p->n_op == TEMP) {
 11301139                 if (aor[regno(p)][0] == 0) {
 11311140                         if (xtemps)
 11321141                                 return;
 11331142                         aor[regno(p)][0] = FPREG;
 11341143                         aor[regno(p)][1] = BITOOR(freetemp(szty(p->n_type)));
 11351144                 }
 11361145                 l = mklnode(REG, 0, aor[regno(p)][0], INCREF(p->n_type));
 11371146                 r = mklnode(ICON, aor[regno(p)][1], 0, INT);
 11381147                 p->n_left = mkbinode(PLUS, l, r, INCREF(p->n_type));
 11391148                 p->n_op = UMUL;
 11401149         } else if (p->n_op == ADDROF && p->n_left->n_op == OREG) {
 11411150                 p->n_op = PLUS;
 11421151                 l = p->n_left;
 11431152                 l->n_op = REG;
 11441153                 l->n_type = INCREF(l->n_type);
 11451154                 p->n_right = mklnode(ICON, l->n_lval, 0, INT);
 11461155         } else if (p->n_op == ADDROF && p->n_left->n_op == UMUL) {
 11471156                 l = p->n_left;
 11481157                 *p = *p->n_left->n_left;
 11491158                 nfree(l->n_left);
 11501159                 nfree(l);
 11511160         }
 11521161 }
 11531162 
 11541163 /*
 11551164  * for pointer/integer arithmetic, set pointer at left node
 11561165  */
 11571166 static void
 11581167 setleft(NODE *p, void *arg)
 11591168 {       
 11601169         NODE *q;
 11611170 
 11621171         /* only additions for now */
 11631172         if (p->n_op != PLUS)
 11641173                 return;
 11651174         if (ISPTR(p->n_right->n_type) && !ISPTR(p->n_left->n_type)) {
 11661175                 q = p->n_right;
 11671176                 p->n_right = p->n_left;
 11681177                 p->n_left = q;
 11691178         }
 11701179 }
 11711180 
 11721181 /* It is OK to have these as externals */
 11731182 static int oregr;
 11741183 static CONSZ oregtemp;
 11751184 static char *oregcp;
 11761185 /*
 11771186  * look for situations where we can turn * into OREG
 11781187  * If sharp then do not allow temps.
 11791188  */
 11801189 int
 11811190 oregok(NODE *p, int sharp)
 11821191 {
 11831192 
 11841193         NODE *q;
 11851194         NODE *ql, *qr;
 11861195         int r;
 11871196         CONSZ temp;
 11881197         char *cp;
 11891198 
 11901199         q = p->n_left;
 11911200 #if 0
 11921201         if ((q->n_op == REG || (q->n_op == TEMP && !sharp)) &&
 11931202             q->n_rval == DECRA(q->n_reg, 0)) {
 11941203 #endif
 11951204         if (q->n_op == REG || (q->n_op == TEMP && !sharp)) {
 11961205                 temp = q->n_lval;
 11971206                 r = q->n_rval;
 11981207                 cp = q->n_name;
 11991208                 goto ormake;
 12001209         }
 12011210 
 12021211         if (q->n_op != PLUS && q->n_op != MINUS)
 12031212                 return 0;
 12041213         ql = q->n_left;
 12051214         qr = q->n_right;
 12061215 
 12071216 #ifdef R2REGS
 12081217 
 12091218         /* look for doubly indexed expressions */
 12101219         /* XXX - fix checks */
 12111220 
 12121221         if( q->n_op == PLUS) {
 12131222                 int i;
 12141223                 if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) {
 12151224                         makeor2(p, ql, r, i);
 12161225                         return 1;
 12171226                 } else if((r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) {
 12181227                         makeor2(p, qr, r, i);
 12191228                         return 1;
 12201229                 }
 12211230         }
 12221231 
 12231232 
 12241233 #endif
 12251234 
 12261235 #if 0
 12271236         if( (q->n_op==PLUS || q->n_op==MINUS) && qr->n_op == ICON &&
 12281237                         (ql->n_op==REG || (ql->n_op==TEMP && !sharp)) &&
 12291238                         szty(qr->n_type)==1 &&
 12301239                         (ql->n_rval == DECRA(ql->n_reg, 0) ||
 12311240                         /* XXX */
 12321241                          ql->n_rval == FPREG || ql->n_rval == STKREG)) {
 12331242 #endif
 12341243         if ((q->n_op==PLUS || q->n_op==MINUS) && qr->n_op == ICON &&
 12351244             (ql->n_op==REG || (ql->n_op==TEMP && !sharp))) {
 12361245            
 12371246                 temp = qr->n_lval;
 12381247                 if( q->n_op == MINUS ) temp = -temp;
 12391248                 r = ql->n_rval;
 12401249                 temp += ql->n_lval;
 12411250                 cp = qr->n_name;
 12421251                 if( *cp && ( q->n_op == MINUS || *ql->n_name ) )
 12431252                         return 0;
 12441253                 if( !*cp ) cp = ql->n_name;
 12451254 
 12461255                 ormake:
 12471256                 if( notoff( p->n_type, r, temp, cp ))
 12481257                         return 0;
 12491258                 oregtemp = temp;
 12501259                 oregr = r;
 12511260                 oregcp = cp;
 12521261                 return 1;
 12531262         }
 12541263         return 0;
 12551264 }
 12561265 
 12571266 static void
 12581267 ormake(NODE *p)
 12591268 {
 12601269         NODE *q = p->n_left;
 12611270 
 12621271         p->n_op = OREG;
 12631272         p->n_rval = oregr;
 12641273         p->n_lval = oregtemp;
 12651274         p->n_name = oregcp;
 12661275         tfree(q);
 12671276 }
 12681277 
 12691278 /*
 12701279  * look for situations where we can turn * into OREG
 12711280  */
 12721281 void
 12731282 oreg2(NODE *p, void *arg)
 12741283 {
 12751284         if (p->n_op != UMUL)
 12761285                 return;
 12771286         if (oregok(p, 1))
 12781287                 ormake(p);
 12791288         if (p->n_op == UMUL)
 12801289                 myormake(p);
 12811290 }
 12821291 
 12831292 void
 12841293 canon(NODE *p)
 12851294 {
 12861295         /* put p in canonical form */
 12871296 
 12881297         walkf(p, setleft, 0);   /* ptrs at left node for arithmetic */
 12891298         walkf(p, oreg2, 0);     /* look for and create OREG nodes */
 12901299         mycanon(p);             /* your own canonicalization routine(s) */
 12911300 }
 12921301 
 12931302 void
 12941303 comperr(char *str, ...)
 12951304 {
 12961305         extern char *ftitle;
 12971306         va_list ap;
 12981307 
 12991308         if (nerrors) {
 13001309                 fprintf(stderr,
 13011310                     "cannot recover from earlier errors: goodbye!\n");
 13021311                 exit(1);
 13031312         }
 13041313 
 13051314         va_start(ap, str);
 13061315         fprintf(stderr, "%s, line %d: compiler error: ", ftitle, thisline);
 13071316         vfprintf(stderr, str, ap);
 13081317         fprintf(stderr, "\n");
 13091318         va_end(ap);
 13101319 
 13111320 #ifdef PCC_DEBUG
 13121321         if (nodepole && nodepole->n_op != FREE)
 13131322                 fwalk(nodepole, e2print, 0);
 13141323 #endif
 13151324         exit(1);
 13161325 }
 13171326 
 13181327 /*
 13191328  * allocate k integers worth of temp space
 13201329  * we also make the convention that, if the number of words is
 13211330  * more than 1, it must be aligned for storing doubles...
 13221331  * Returns bits offset from base register.
 13231332  * XXX - redo this.
 13241333  */
 13251334 int
 13261335 freetemp(int k)
 13271336 {
 13281337 #ifndef BACKTEMP
 13291338         int t;
 13301339 
 13311340         if (k > 1) {
 13321341                 SETOFF(p2autooff, ALDOUBLE/ALCHAR);
 13331342         } else {
 13341343                 SETOFF(p2autooff, ALINT/ALCHAR);
 13351344         }
 13361345 
 13371346         t = p2autooff;
 13381347         p2autooff += k*(SZINT/SZCHAR);
 13391348         if (p2autooff > p2maxautooff)
 13401349                 p2maxautooff = p2autooff;
 13411350         return (t);
 13421351 
 13431352 #else
 13441353         p2autooff += k*(SZINT/SZCHAR);
 13451354         if (k > 1) {
 13461355                 SETOFF(p2autooff, ALDOUBLE/ALCHAR);
 13471356         } else {
 13481357                 SETOFF(p2autooff, ALINT/ALCHAR);
 13491358         }
 13501359 
 13511360         if (p2autooff > p2maxautooff)
 13521361                 p2maxautooff = p2autooff;
 13531362         return( -p2autooff );
 13541363 #endif
 13551364 }
 13561365 
 13571366 NODE *
 13581367 mklnode(int op, CONSZ lval, int rval, TWORD type)
 13591368 {
 13601369         NODE *p = talloc();
 13611370 
 13621371         p->n_name = "";
 13631372         p->n_qual = 0;
 13641373         p->n_op = op;
 13651374         p->n_label = 0;
 13661375         p->n_lval = lval;
 13671376         p->n_rval = rval;
 13681377         p->n_type = type;
 13691378         p->n_regw = NULL;
 13701379         p->n_su = 0;
 13711380         return p;
 13721381 }
 13731382 
 13741383 NODE *
 13751384 mkbinode(int op, NODE *left, NODE *right, TWORD type)
 13761385 {
 13771386         NODE *p = talloc();
 13781387 
 13791388         p->n_name = "";
 13801389         p->n_qual = 0;
 13811390         p->n_op = op;
 13821391         p->n_label = 0;
 13831392         p->n_left = left;
 13841393         p->n_right = right;
 13851394         p->n_type = type;
 13861395         p->n_regw = NULL;
 13871396         p->n_su = 0;
 13881397         return p;
 13891398 }
 13901399 
 13911400 NODE *
 13921401 mkunode(int op, NODE *left, int rval, TWORD type)
 13931402 {
 13941403         NODE *p = talloc();
 13951404 
 13961405         p->n_name = "";
 13971406         p->n_qual = 0;
 13981407         p->n_op = op;
 13991408         p->n_label = 0;
 14001409         p->n_left = left;
 14011410         p->n_rval = rval;
 14021411         p->n_type = type;
 14031412         p->n_regw = NULL;
 14041413         p->n_su = 0;
 14051414         return p;
 14061415 }
 14071416 
 14081417 struct interpass *
 14091418 ipnode(NODE *p)
 14101419 {
 14111420         struct interpass *ip = tmpalloc(sizeof(struct interpass));
 14121421 
 14131422         ip->ip_node = p;
 14141423         ip->type = IP_NODE;
 14151424         ip->lineno = thisline;
 14161425         return ip;
 14171426 }
 14181427 
 14191428 int
 14201429 rspecial(struct optab *q, int what)
 14211430 {
 14221431         struct rspecial *r = nspecial(q);
 14231432         while (r->op) {
 14241433                 if (r->op == what)
 14251434                         return r->num;
 14261435                 r++;
 14271436         }
 14281437         return -1;
 14291438 }
 14301439 
 14311440 #ifndef XASM_NUMCONV
 14321441 #define XASM_NUMCONV(x,y,z)     0
 14331442 #endif
 14341443 
 14351444 /*
 14361445  * change numeric argument redirections to the correct node type after
 14371446  * cleaning up the other nodes.
 14381447  * be careful about input operands that may have different value than output.
 14391448  */
 14401449 static void
 14411450 delnums(NODE *p, void *arg)
 14421451 {
 14431452         struct interpass *ip = arg, *ip2;
 14441453         NODE *r = ip->ip_node->n_left;
 14451454         NODE *q;
 14461455         TWORD t;
 14471456         int cnt, num;
 14481457 
 14491458         /* gcc allows % in constraints, but we ignore it */
 14501459         if (p->n_name[0] == '%' && p->n_name[1] >= '0' && p->n_name[1] <= '9')
 14511460                 p->n_name++;
 14521461 
 14531462         if (p->n_name[0] < '0' || p->n_name[0] > '9')
 14541463                 return; /* not numeric */
 14551464         if ((q = listarg(r, p->n_name[0] - '0', &cnt)) == NIL)
 14561465                 comperr("bad delnums");
 14571466 
 14581467         /* target may have opinions whether to do this conversion */
 14591468         if (XASM_NUMCONV(ip, p, q))
 14601469                 return;
 14611470 
 14621471         /* Delete number by adding move-to/from-temp.  Later on */
 14631472         /* the temps may be rewritten to other LTYPEs */
 14641473         num = p2env.epp->ip_tmpnum++;
 14651474 
 14661475         /* pre node */
 14671476         t = p->n_left->n_type;
 14681477         r = mklnode(TEMP, 0, num, t);
 14691478         ip2 = ipnode(mkbinode(ASSIGN, tcopy(r), p->n_left, t));
 14701479         DLIST_INSERT_BEFORE(ip, ip2, qelem);
 14711480         p->n_left = r;
 14721481 
 14731482         /* post node */
 14741483         t = q->n_left->n_type;
 14751484         r = mklnode(TEMP, 0, num, t);
 14761485         ip2 = ipnode(mkbinode(ASSIGN, q->n_left, tcopy(r), t));
 14771486         DLIST_INSERT_AFTER(ip, ip2, qelem);
 14781487         q->n_left = r;
 14791488 
 14801489         p->n_name = tmpstrdup(q->n_name);
 14811490         if (*p->n_name == '=')
 14821491                 p->n_name++;
 14831492 }
 14841493 
 14851494 /*
 14861495  * Ensure that a node is correct for the destination.
 14871496  */
 14881497 static void
 14891498 ltypify(NODE *p, void *arg)
 14901499 {
 14911500         struct interpass *ip = arg;
 14921501         struct interpass *ip2;
 14931502         TWORD t = p->n_left->n_type;
 14941503         NODE *q, *r;
 14951504         int cw, ooff, ww;
 14961505         char *c;
 14971506 
 14981507 again:
 14991508         if (myxasm(ip, p))
 15001509                 return/* handled by target-specific code */
 15011510 
 15021511         cw = xasmcode(p->n_name);
 15031512         switch (ww = XASMVAL(cw)) {
 15041513         case 'p':
 15051514                 /* pointer */
 15061515                 /* just make register of it */
 15071516                 p->n_name = tmpstrdup(p->n_name);
 15081517                 c = strchr(p->n_name, XASMVAL(cw)); /* cannot fail */
 15091518                 *c = 'r';
 15101519                 /* FALLTHROUGH */
 15111520         case 'g'/* general; any operand */
 15121521                 if (ww == 'g' && p->n_left->n_op == ICON) {
 15131522                         /* should only be input */
 15141523                         p->n_name = "i";
 15151524                         break;
 15161525                 }
 15171526                 /* FALLTHROUGH */
 15181527         case 'r': /* general reg */
 15191528                 /* set register class */
 15201529                 p->n_label = gclass(p->n_left->n_type);
 15211530                 if (p->n_left->n_op == REG || p->n_left->n_op == TEMP)
 15221531                         break;
 15231532                 q = p->n_left;
 15241533                 r = (cw & XASMINOUT ? tcopy(q) : q);
 15251534                 p->n_left = mklnode(TEMP, 0, p2env.epp->ip_tmpnum++, t);
 15261535                 if ((cw & XASMASG) == 0) {
 15271536                         ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), r, t));
 15281537                         DLIST_INSERT_BEFORE(ip, ip2, qelem);
 15291538                 }
 15301539                 if (cw & (XASMASG|XASMINOUT)) {
 15311540                         /* output parameter */
 15321541                         ip2 = ipnode(mkbinode(ASSIGN, q, tcopy(p->n_left), t));
 15331542                         DLIST_INSERT_AFTER(ip, ip2, qelem);
 15341543                 }
 15351544                 break;
 15361545 
 15371546         case '0': case '1': case '2': case '3': case '4':
 15381547         case '5': case '6': case '7': case '8': case '9':
 15391548                 break;
 15401549 
 15411550         case 'm': /* memory operand */
 15421551                 /* store and reload value */
 15431552                 q = p->n_left;
 15441553                 if (optype(q->n_op) == LTYPE) {
 15451554                         if (q->n_op == TEMP) {
 15461555                                 ooff = BITOOR(freetemp(szty(t)));
 15471556                                 cvtemps(ip, q->n_rval, ooff);
 15481557                         } else if (q->n_op == REG)
 15491558                                 comperr("xasm m and reg");
 15501559                 } else if (q->n_op == UMUL &&
 15511560                     (q->n_left->n_op != TEMP && q->n_left->n_op != REG)) {
 15521561                         t = q->n_left->n_type;
 15531562                         ooff = p2env.epp->ip_tmpnum++;
 15541563                         ip2 = ipnode(mkbinode(ASSIGN,
 15551564                             mklnode(TEMP, 0, ooff, t), q->n_left, t));
 15561565                         q->n_left = mklnode(TEMP, 0, ooff, t);
 15571566                         DLIST_INSERT_BEFORE(ip, ip2, qelem);
 15581567                 }
 15591568                 break;
 15601569 
 15611570         case 'i': /* immediate constant */
 15621571         case 'n': /* numeric constant */
 15631572                 if (p->n_left->n_op == ICON)
 15641573                         break;
 15651574                 p->n_name = tmpstrdup(p->n_name);
 15661575                 c = strchr(p->n_name, XASMVAL(cw)); /* cannot fail */
 15671576                 if (c[1]) {
 15681577                         c[0] = c[1], c[1] = 0;
 15691578                         goto again;
 15701579                 } else
 15711580                         uerror("constant required");
 15721581                 break;
 15731582 
 15741583         default:
 15751584                 uerror("unsupported xasm option string '%s'", p->n_name);
 15761585         }
 15771586 }
 15781587 
 15791588 /* Extended assembler hacks */
 15801589 static void
 15811590 fixxasm(struct p2env *p2e)
 15821591 {
 15831592         struct interpass *pole = &p2e->ipole;
 15841593         struct interpass *ip;
 15851594         NODE *p;
 15861595 
 15871596         DLIST_FOREACH(ip, pole, qelem) {
 15881597                 if (ip->type != IP_NODE || ip->ip_node->n_op != XASM)
 15891598                         continue;
 15901599                 thisline = ip->lineno;
 15911600                 p = ip->ip_node->n_left;
 15921601 
 15931602                 if (p->n_op == ICON && p->n_type == STRTY)
 15941603                         continue;
 15951604 
 15961605                 /* replace numeric redirections with its underlying type */
 15971606                 flist(p, delnums, ip);
 15981607 
 15991608                 /*
 16001609                  * Ensure that the arg nodes can be directly addressable
 16011610                  * We decide that everything shall be LTYPE here.
 16021611                  */
 16031612                 flist(p, ltypify, ip);
 16041613         }
 16051614 }
 16061615 
 16071616 /*
 16081617  * Extract codeword from xasm string */
 16091618 int
 16101619 xasmcode(char *s)
 16111620 {
 16121621         int cw = 0, nm = 0;
 16131622 
 16141623         while (*s) {
 16151624                 switch ((int)*s) {
 16161625                 case '=': cw |= XASMASG; break;
 16171626                 case '&': cw |= XASMCONSTR; break;
 16181627                 case '+': cw |= XASMINOUT; break;
 16191628                 case '%': break;
 16201629                 default:
 16211630                         if ((*s >= 'a' && *s <= 'z') ||
 16221631                             (*s >= 'A' && *s <= 'Z') ||
 16231632                             (*s >= '0' && *s <= '9')) {
 16241633                                 if (nm == 0)
 16251634                                         cw |= *s;
 16261635                                 else
 16271636                                         cw |= (*s << ((nm + 1) * 8));
 16281637                                 nm++;
 16291638                                 break;
 16301639                         }
 16311640                         uerror("bad xasm constraint %c", *s);
 16321641                 }
 16331642                 s++;
 16341643         }
 16351644         return cw;
 16361645 }
 16371646 
 16381647 static int xasnum, xoffnum;
 16391648 
 16401649 static void
 16411650 xconv(NODE *p, void *arg)
 16421651 {
 16431652         if (p->n_op != TEMP || p->n_rval != xasnum)
 16441653                 return;
 16451654         p->n_op = OREG;
 16461655         p->n_rval = FPREG;
 16471656         p->n_lval = xoffnum;
 16481657 }
 16491658 
 16501659 /*
 16511660  * Convert nodes of type TEMP to op with lval off.
 16521661  */
 16531662 static void
 16541663 cvtemps(struct interpass *ipl, int tnum, int off)
 16551664 {
 16561665         struct interpass *ip;
 16571666 
 16581667         xasnum = tnum;
 16591668         xoffnum = off;
 16601669 
 16611670         DLIST_FOREACH(ip, ipl, qelem)
 16621671                 if (ip->type == IP_NODE)
 16631672                         walkf(ip->ip_node, xconv, 0);
 16641673         walkf(ipl->ip_node, xconv, 0);
 16651674 }
FishEye: Open Source License registered to PCC.
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-12-21 21:10 +0100