1/* Id: reader.c,v 1.299 2015/11/17 19:19:40 ragge Exp */ 2/* $NetBSD: reader.c,v 1.1.1.8 2016/02/09 20:29:20 plunky Exp $ */ 3/* 4 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28/* 29 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 35 * Redistributions of source code and documentation must retain the above 36 * copyright notice, this list of conditions and the following disclaimer. 37 * Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditionsand the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * All advertising materials mentioning features or use of this software 41 * must display the following acknowledgement: 42 * This product includes software developed or owned by Caldera 43 * International, Inc. 44 * Neither the name of Caldera International, Inc. nor the names of other 45 * contributors may be used to endorse or promote products derived from 46 * this software without specific prior written permission. 47 * 48 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 49 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 50 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 51 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 52 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE 53 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, 57 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 58 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 59 * POSSIBILITY OF SUCH DAMAGE. 60 */ 61 62/* 63 * Everything is entered via pass2_compile(). No functions are 64 * allowed to recurse back into pass2_compile(). 65 */ 66 67# include "pass2.h" 68 69#include <string.h> 70#include <stdarg.h> 71#include <stdlib.h> 72 73/* some storage declarations */ 74int nrecur; 75int thisline; 76int fregs; 77int p2autooff, p2maxautooff; 78 79NODE *nodepole; 80struct interpass prepole; 81 82void saveip(struct interpass *ip); 83void deltemp(NODE *p, void *); 84static void cvtemps(struct interpass *ipole, int op, int off); 85static void fixxasm(struct p2env *); 86 87static void gencode(NODE *p, int cookie); 88static void genxasm(NODE *p); 89static void afree(void); 90 91struct p2env p2env; 92 93int crslab2 = 11; 94/* 95 * Return a number for internal labels. 96 */ 97int 98getlab2(void) 99{ 100 crslab2++; 101 if (crslab2 < p2env.ipp->ip_lblnum) 102 comperr("getlab2 %d outside boundaries %d-%d", 103 crslab2, p2env.ipp->ip_lblnum, p2env.epp->ip_lblnum); 104 if (crslab2 >= p2env.epp->ip_lblnum) 105 p2env.epp->ip_lblnum = crslab2+1; 106 return crslab2++; 107} 108 109 110#ifdef PCC_DEBUG 111static int *lbldef, *lbluse; 112static void 113cktree(NODE *p, void *arg) 114{ 115 int i; 116 117 if (p->n_op > MAXOP) 118 cerror("%p) op %d slipped through", p, p->n_op); 119#ifndef FIELDOPS 120 if (p->n_op == FLD) 121 cerror("%p) FLD slipped through", p); 122#endif 123 if (BTYPE(p->n_type) > MAXTYPES) 124 cerror("%p) type %x slipped through", p, p->n_type); 125 if (p->n_op == CBRANCH) { 126 if (!logop(p->n_left->n_op)) 127 cerror("%p) not logop branch", p); 128 i = (int)getlval(p->n_right); 129 if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum) 130 cerror("%p) label %d outside boundaries %d-%d", 131 p, i, p2env.ipp->ip_lblnum, p2env.epp->ip_lblnum); 132 lbluse[i-p2env.ipp->ip_lblnum] = 1; 133 } 134 if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN) 135 cerror("%p) asgop %d slipped through", p, p->n_op); 136 if (p->n_op == TEMP && 137 (regno(p) < p2env.ipp->ip_tmpnum || regno(p) >= p2env.epp->ip_tmpnum)) 138 cerror("%p) temporary %d outside boundaries %d-%d", 139 p, regno(p), p2env.ipp->ip_tmpnum, p2env.epp->ip_tmpnum); 140 if (p->n_op == GOTO && p->n_left->n_op == ICON) { 141 i = (int)getlval(p->n_left); 142 if (i < p2env.ipp->ip_lblnum || i >= p2env.epp->ip_lblnum) 143 cerror("%p) label %d outside boundaries %d-%d", 144 p, i, p2env.ipp->ip_lblnum, p2env.epp->ip_lblnum); 145 lbluse[i-p2env.ipp->ip_lblnum] = 1; 146 } 147} 148 149/* 150 * Check that the trees are in a suitable state for pass2. 151 */ 152static void 153sanitychecks(struct p2env *p2e) 154{ 155 struct interpass *ip; 156 int i, sz; 157 158 sz = sizeof(int) * (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum); 159 lbldef = xcalloc(sz, 1); 160 lbluse = xcalloc(sz, 1); 161 162 DLIST_FOREACH(ip, &p2env.ipole, qelem) { 163 if (ip->type == IP_DEFLAB) { 164 i = ip->ip_lbl; 165 if (i < p2e->ipp->ip_lblnum || i >= p2e->epp->ip_lblnum) 166 cerror("label %d outside boundaries %d-%d", 167 i, p2e->ipp->ip_lblnum, p2e->epp->ip_lblnum); 168 lbldef[i-p2e->ipp->ip_lblnum] = 1; 169 } 170 if (ip->type == IP_NODE) 171 walkf(ip->ip_node, cktree, 0); 172 } 173 for (i = 0; i < (p2e->epp->ip_lblnum - p2e->ipp->ip_lblnum); i++) 174 if (lbluse[i] != 0 && lbldef[i] == 0) 175 cerror("internal label %d not defined", 176 i + p2e->ipp->ip_lblnum); 177 178 free(lbldef); 179 free(lbluse); 180} 181#endif 182 183/* 184 * Look if a temporary comes from a on-stack argument, in that case 185 * use the already existing stack position instead of moving it to 186 * a new place, and remove the move-to-temp statement. 187 */ 188static int 189stkarg(int tnr, int (*soff)[2]) 190{ 191 struct p2env *p2e = &p2env; 192 struct interpass *ip; 193 NODE *p; 194 195 ip = DLIST_NEXT((struct interpass *)p2e->ipp, qelem); 196 while (ip->type != IP_DEFLAB) /* search for first DEFLAB */ 197 ip = DLIST_NEXT(ip, qelem); 198 199 ip = DLIST_NEXT(ip, qelem); /* first NODE */ 200 201 for (; ip->type != IP_DEFLAB; ip = DLIST_NEXT(ip, qelem)) { 202 if (ip->type != IP_NODE) 203 continue; 204 205 p = ip->ip_node; 206 if (p->n_op == XASM) 207 continue; /* XXX - hack for x86 PIC */ 208#ifdef notdef 209 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP) 210 comperr("temparg"); 211#endif 212 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP) 213 continue; /* unknown tree */ 214 215 if (p->n_right->n_op != OREG && p->n_right->n_op != UMUL) 216 continue; /* arg in register */ 217 if (tnr != regno(p->n_left)) 218 continue; /* wrong assign */ 219 p = p->n_right; 220 if (p->n_op == UMUL && 221 p->n_left->n_op == PLUS && 222 p->n_left->n_left->n_op == REG && 223 p->n_left->n_right->n_op == ICON) { 224 soff[0][0] = regno(p->n_left->n_left); 225 soff[0][1] = (int)getlval(p->n_left->n_right); 226 } else if (p->n_op == OREG) { 227 soff[0][0] = regno(p); 228 soff[0][1] = (int)getlval(p); 229 } else 230 comperr("stkarg: bad arg"); 231 tfree(ip->ip_node); 232 DLIST_REMOVE(ip, qelem); 233 return 1; 234 } 235 return 0; 236} 237 238/* 239 * See if an ADDROF is somewhere inside the expression tree. 240 * If so, fill in the offset table. 241 */ 242static void 243findaof(NODE *p, void *arg) 244{ 245 int (*aof)[2] = arg; 246 int tnr; 247 248 if (p->n_op != ADDROF || p->n_left->n_op != TEMP) 249 return; 250 tnr = regno(p->n_left); 251 if (aof[tnr][0]) 252 return; /* already gotten stack address */ 253 if (stkarg(tnr, &aof[tnr])) 254 return; /* argument was on stack */ 255 aof[tnr][0] = FPREG; 256 aof[tnr][1] = freetemp(szty(p->n_left->n_type)); 257} 258 259/* 260 * Check if a node has side effects. 261 */ 262static int 263isuseless(NODE *n) 264{ 265 switch (n->n_op) { 266 case XASM: 267 case FUNARG: 268 case UCALL: 269 case UFORTCALL: 270 case FORCE: 271 case ASSIGN: 272 case CALL: 273 case FORTCALL: 274 case CBRANCH: 275 case RETURN: 276 case GOTO: 277 case STCALL: 278 case USTCALL: 279 case STASG: 280 case STARG: 281 return 0; 282 default: 283 return 1; 284 } 285} 286 287/* 288 * Delete statements with no meaning (like a+b; or 513.4;) 289 */ 290NODE * 291deluseless(NODE *p) 292{ 293 struct interpass *ip; 294 NODE *l, *r; 295 296 if (optype(p->n_op) == LTYPE) { 297 nfree(p); 298 return NULL; 299 } 300 if (isuseless(p) == 0) 301 return p; 302 303 if (optype(p->n_op) == UTYPE) { 304 l = p->n_left; 305 nfree(p); 306 return deluseless(l); 307 } 308 309 /* Be sure that both leaves may be valid */ 310 l = deluseless(p->n_left); 311 r = deluseless(p->n_right); 312 nfree(p); 313 if (l && r) { 314 ip = ipnode(l); 315 DLIST_INSERT_AFTER(&prepole, ip, qelem); 316 return r; 317 } else if (l) 318 return l; 319 else if (r) 320 return r; 321 return NULL; 322} 323 324#ifdef PASS2 325 326#define SKIPWS(p) while (*p == ' ') p++ 327#define SZIBUF 256 328static int inpline; 329static char inpbuf[SZIBUF]; 330static char * 331rdline(void) 332{ 333 int l; 334 335 if (fgets(inpbuf, sizeof(inpbuf), stdin) == NULL) 336 return NULL; 337 inpline++; 338 l = strlen(inpbuf); 339 if (inpbuf[0] < 33 || inpbuf[1] != ' ' || inpbuf[l-1] != '\n') 340 comperr("sync error in-line %d string '%s'", inpline, inpbuf); 341 inpbuf[l-1] = 0; 342 return inpbuf; 343} 344 345/* 346 * Read an int and traverse over it. count up s. 347 */ 348static int 349rdint(char **s) 350{ 351 char *p = *s; 352 int rv; 353 354 SKIPWS(p); 355 rv = atoi(p); 356 if (*p == '-' || *p == '+') p++; 357 while (*p >= '0' && *p <= '9') p++; 358 *s = p; 359 return rv; 360} 361 362static struct attr * 363rdattr(char **p) 364{ 365 struct attr *ap, *app = NULL; 366 int i, a, sz; 367 368 (*p)++; /* skip + */ 369onemore: 370 a = rdint(p); 371 sz = rdint(p); 372 ap = attr_new(a, sz); 373 for (i = 0; i < sz; i++) 374 ap->iarg(i) = rdint(p); 375 ap->next = app; 376 app = ap; 377 SKIPWS((*p)); 378 if (**p != 0) 379 goto onemore; 380 381 return app; 382} 383 384/* 385 * Read in an indentifier and save on tmp heap. Return saved string. 386 */ 387static char * 388rdstr(char **p) 389{ 390 char *t, *s = *p; 391 int sz; 392 393 SKIPWS(s); 394 *p = s; 395 for (sz = 0; *s && *s != ' '; s++, sz++) 396 ; 397 t = tmpalloc(sz+1); 398 memcpy(t, *p, sz); 399 t[sz] = 0; 400 *p = s; 401 return t; 402} 403 404/* 405 * Read and check node structs from pass1. 406 */ 407static NODE * 408rdnode(char *s) 409{ 410 NODE *p = talloc(); 411 int ty; 412 413 if (s[0] != '"') 414 comperr("rdnode sync error"); 415 s++; s++; 416 p->n_regw = NULL; 417 p->n_ap = NULL; 418 p->n_su = p->n_lval = p->n_rval = 0; 419 p->n_op = rdint(&s); 420 p->n_type = rdint(&s); 421 p->n_qual = rdint(&s); 422 p->n_name = ""; 423 SKIPWS(s); 424 ty = optype(p->n_op); 425 if (p->n_op == XASM) { 426 int i = strlen(s); 427 p->n_name = tmpalloc(i+1); 428 memcpy(p->n_name, s, i); 429 p->n_name[i] = 0; 430 s += i; 431 } 432 if (ty == UTYPE) { 433 p->n_rval = rdint(&s); 434 } else if (ty == LTYPE) { 435 p->n_lval = strtoll(s, &s, 10); 436 if (p->n_op == NAME || p->n_op == ICON) { 437 SKIPWS(s); 438 if (*s && *s != '+') 439 p->n_name = rdstr(&s); 440 } else 441 p->n_rval = rdint(&s); 442 } 443 SKIPWS(s); 444 if (p->n_op == XARG) { 445 int i = strlen(s); 446 p->n_name = tmpalloc(i+1); 447 memcpy(p->n_name, s, i); 448 p->n_name[i] = 0; 449 s += i; 450 } 451 if (*s == '+') 452 p->n_ap = rdattr(&s); 453 SKIPWS(s); 454 if (*s) 455 comperr("in-line %d failed read, buf '%s'", inpline, inpbuf); 456 if (ty != LTYPE) 457 p->n_left = rdnode(rdline()); 458 if (ty == BITYPE) 459 p->n_right = rdnode(rdline()); 460 return p; 461} 462 463/* 464 * Read everything from pass1. 465 */ 466void 467mainp2() 468{ 469 static int foo[] = { 0 }; 470 struct interpass_prolog *ipp; 471 struct interpass *ip; 472 char nam[SZIBUF], *p, *b; 473 extern char *ftitle; 474 475 while ((p = rdline()) != NULL) { 476 b = p++; 477 p++; 478 479 switch (*b) { 480 case '*': /* pass thru line */ 481 printf("%s\n", p); 482 break; 483 case '&': /* current filename */ 484 free(ftitle); 485 ftitle = xstrdup(p); 486 break; 487 case '#': 488 lineno = atoi(p); 489 break; 490 case '"': 491 ip = malloc(sizeof(struct interpass)); 492 ip->type = IP_NODE; 493 ip->ip_node = rdnode(b); 494 pass2_compile(ip); 495 break; 496 case '^': 497 ip = malloc(sizeof(struct interpass)); 498 ip->type = IP_DEFLAB; 499 ip->ip_lbl = atoi(p); 500 pass2_compile(ip); 501 break; 502 case '!': /* prolog */ 503 ipp = malloc(sizeof(struct interpass_prolog)); 504 ip = (void *)ipp; 505 ip->type = IP_PROLOG; 506 sscanf(p, "%d %d %d %d %d %s", &ipp->ipp_type, 507 &ipp->ipp_vis, &ip->ip_lbl, &ipp->ip_tmpnum, 508 &ipp->ip_lblnum, nam); 509 ipp->ipp_name = xstrdup(nam); 510 memset(ipp->ipp_regs, -1, sizeof(ipp->ipp_regs)); 511 ipp->ipp_autos = -1; 512 ipp->ip_labels = foo; 513#ifdef TARGET_IPP_MEMBERS 514 if (*(p = rdline()) != '(') 515 comperr("target member error"); 516 p += 2; 517 target_members_read_prolog(ipp); 518 SKIPWS(p); 519 if (*p) 520 comperr("bad prolog '%s' '%s'", p, inpbuf); 521#endif 522 pass2_compile((struct interpass *)ipp); 523 break; 524 525 case '%': /* epilog */ 526 ipp = malloc(sizeof(struct interpass_prolog)); 527 ip = (void *)ipp; 528 ip->type = IP_EPILOG; 529 ipp->ipp_autos = rdint(&p); 530 ip->ip_lbl = rdint(&p); 531 ipp->ip_tmpnum = rdint(&p); 532 ipp->ip_lblnum = rdint(&p); 533 ipp->ipp_name = rdstr(&p); 534 memset(ipp->ipp_regs, 0, sizeof(ipp->ipp_regs)); 535 SKIPWS(p); 536 if (*p == '+') { 537 int num, i; 538 p++; 539 num = rdint(&p) + 1; 540 ipp->ip_labels = tmpalloc(sizeof(int)*num); 541 for (i = 0; i < num; i++) 542 ipp->ip_labels[i] = rdint(&p); 543 ipp->ip_labels[num] = 0; 544 } else 545 ipp->ip_labels = foo; 546 SKIPWS(p); 547 if (*p) 548 comperr("bad epilog '%s' '%s'", p, inpbuf); 549#ifdef TARGET_IPP_MEMBERS 550 if (*(p = rdline()) != ')') 551 comperr("target epi member error"); 552 p += 2; 553 target_members_read_epilog(ipp); 554 SKIPWS(p); 555 if (*p) 556 comperr("bad epilog2 '%s' '%s'", p, inpbuf); 557#endif 558 pass2_compile((struct interpass *)ipp); 559 break; 560 561 default: 562 comperr("bad string %s", b); 563 } 564 } 565} 566 567 568#endif 569 570/* 571 * Receives interpass structs from pass1. 572 */ 573void 574pass2_compile(struct interpass *ip) 575{ 576 void deljumps(struct p2env *); 577 struct p2env *p2e = &p2env; 578 int (*addrp)[2]; 579 580 if (ip->type == IP_PROLOG) { 581 memset(p2e, 0, sizeof(struct p2env)); 582 p2e->ipp = (struct interpass_prolog *)ip; 583 if (crslab2 < p2e->ipp->ip_lblnum) 584 crslab2 = p2e->ipp->ip_lblnum; 585 DLIST_INIT(&p2e->ipole, qelem); 586 } 587 DLIST_INSERT_BEFORE(&p2e->ipole, ip, qelem); 588 if (ip->type != IP_EPILOG) 589 return; 590 591#ifdef PCC_DEBUG 592 if (e2debug) { 593 printf("Entering pass2\n"); 594 printip(&p2e->ipole); 595 } 596#endif 597 598 afree(); 599 p2e->epp = (struct interpass_prolog *)DLIST_PREV(&p2e->ipole, qelem); 600 p2maxautooff = p2autooff = p2e->epp->ipp_autos; 601 602#ifdef PCC_DEBUG 603 sanitychecks(p2e); 604#endif 605 myreader(&p2e->ipole); /* local massage of input */ 606 607 /* 608 * Do initial modification of the trees. Two loops; 609 * - first, search for ADDROF of TEMPs, these must be 610 * converterd to OREGs on stack. 611 * - second, do the actual conversions, in case of not xtemps 612 * convert all temporaries to stack references. 613 */ 614 615 if (p2e->epp->ip_tmpnum != p2e->ipp->ip_tmpnum) { 616 addrp = xcalloc(sizeof(*addrp), 617 (p2e->epp->ip_tmpnum - p2e->ipp->ip_tmpnum)); 618 addrp -= p2e->ipp->ip_tmpnum; 619 } else 620 addrp = NULL; 621 if (xtemps) { 622 DLIST_FOREACH(ip, &p2e->ipole, qelem) { 623 if (ip->type == IP_NODE) 624 walkf(ip->ip_node, findaof, addrp); 625 } 626 } 627 DLIST_FOREACH(ip, &p2e->ipole, qelem) 628 if (ip->type == IP_NODE) 629 walkf(ip->ip_node, deltemp, addrp); 630 if (addrp) 631 free(addrp + p2e->ipp->ip_tmpnum); 632 633#ifdef PCC_DEBUG 634 if (e2debug) { 635 printf("Efter ADDROF/TEMP\n"); 636 printip(&p2e->ipole); 637 } 638#endif 639 640 DLIST_INIT(&prepole, qelem); 641 DLIST_FOREACH(ip, &p2e->ipole, qelem) { 642 if (ip->type != IP_NODE) 643 continue; 644 canon(ip->ip_node); 645 if ((ip->ip_node = deluseless(ip->ip_node)) == NULL) { 646 DLIST_REMOVE(ip, qelem); 647 } else while (!DLIST_ISEMPTY(&prepole, qelem)) { 648 struct interpass *tipp; 649 650 tipp = DLIST_NEXT(&prepole, qelem); 651 DLIST_REMOVE(tipp, qelem); 652 DLIST_INSERT_BEFORE(ip, tipp, qelem); 653 } 654 } 655 656 fixxasm(p2e); /* setup for extended asm */ 657 658 optimize(p2e); 659 ngenregs(p2e); 660 661 if (xtemps && xdeljumps) 662 deljumps(p2e); 663 664 DLIST_FOREACH(ip, &p2e->ipole, qelem) 665 emit(ip); 666} 667 668void 669emit(struct interpass *ip) 670{ 671 NODE *p, *r; 672 struct optab *op; 673 int o; 674 675 switch (ip->type) { 676 case IP_NODE: 677 p = ip->ip_node; 678 679 nodepole = p; 680 canon(p); /* may convert stuff after genregs */ 681#ifdef PCC_DEBUG 682 if (c2debug > 1) { 683 printf("emit IP_NODE:\n"); 684 fwalk(p, e2print, 0); 685 } 686#endif 687 switch (p->n_op) { 688 case CBRANCH: 689 /* Only emit branch insn if RESCC */ 690 /* careful when an OPLOG has been elided */ 691 if (p->n_left->n_su == 0 && p->n_left->n_left != NULL) { 692 op = &table[TBLIDX(p->n_left->n_left->n_su)]; 693 r = p->n_left; 694 } else { 695 op = &table[TBLIDX(p->n_left->n_su)]; 696 r = p; 697 } 698 if (op->rewrite & RESCC) { 699 o = p->n_left->n_op; 700 gencode(r, FORCC); 701 cbgen(o, getlval(p->n_right)); 702 } else { 703 gencode(r, FORCC); 704 } 705 break; 706 case FORCE: 707 gencode(p->n_left, INREGS); 708 break; 709 case XASM: 710 genxasm(p); 711 break; 712 default: 713 if (p->n_op != REG || p->n_type != VOID) /* XXX */ 714 gencode(p, FOREFF); /* Emit instructions */ 715 } 716 717 tfree(p); 718 break; 719 case IP_PROLOG: 720 prologue((struct interpass_prolog *)ip); 721 break; 722 case IP_EPILOG: 723 eoftn((struct interpass_prolog *)ip); 724 p2maxautooff = p2autooff = AUTOINIT/SZCHAR; 725 break; 726 case IP_DEFLAB: 727 deflab(ip->ip_lbl); 728 break; 729 case IP_ASM: 730 printf("%s", ip->ip_asm); 731 break; 732 default: 733 cerror("emit %d", ip->type); 734 } 735} 736 737#ifdef PCC_DEBUG 738char *cnames[] = { 739 "SANY", 740 "SAREG", 741 "SBREG", 742 "SCREG", 743 "SDREG", 744 "SCC", 745 "SNAME", 746 "SCON", 747 "SFLD", 748 "SOREG", 749 "STARNM", 750 "STARREG", 751 "INTEMP", 752 "FORARG", 753 "SWADD", 754 0, 755}; 756 757/* 758 * print a nice-looking description of cookie 759 */ 760char * 761prcook(int cookie) 762{ 763 static char buf[50]; 764 int i, flag; 765 766 if (cookie & SPECIAL) { 767 switch (cookie) { 768 case SZERO: 769 return "SZERO"; 770 case SONE: 771 return "SONE"; 772 case SMONE: 773 return "SMONE"; 774 default: 775 snprintf(buf, sizeof(buf), "SPECIAL+%d", cookie & ~SPECIAL); 776 return buf; 777 } 778 } 779 780 flag = 0; 781 buf[0] = 0; 782 for (i = 0; cnames[i]; ++i) { 783 if (cookie & (1<<i)) { 784 if (flag) 785 strlcat(buf, "|", sizeof(buf)); 786 ++flag; 787 strlcat(buf, cnames[i], sizeof(buf)); 788 } 789 } 790 return buf; 791} 792#endif 793 794int 795geninsn(NODE *p, int cookie) 796{ 797 NODE *p1, *p2; 798 int q, o, rv = 0; 799 800#ifdef PCC_DEBUG 801 if (o2debug) { 802 printf("geninsn(%p, %s)\n", p, prcook(cookie)); 803 fwalk(p, e2print, 0); 804 } 805#endif 806 807 q = cookie & QUIET; 808 cookie &= ~QUIET; /* XXX - should not be necessary */ 809 810again: switch (o = p->n_op) { 811 case EQ: 812 case NE: 813 case LE: 814 case LT: 815 case GE: 816 case GT: 817 case ULE: 818 case ULT: 819 case UGE: 820 case UGT: 821 p1 = p->n_left; 822 p2 = p->n_right; 823 if (p2->n_op == ICON && getlval(p2) == 0 && *p2->n_name == 0 && 824 (dope[p1->n_op] & (FLOFLG|DIVFLG|SIMPFLG|SHFFLG))) { 825#ifdef mach_pdp11 /* XXX all targets? */ 826 if ((rv = geninsn(p1, FORCC|QUIET)) != FFAIL) 827 break; 828#else 829 if (findops(p1, FORCC) > 0) 830 break; 831#endif 832 } 833 rv = relops(p); 834 break; 835 836 case PLUS: 837 case MINUS: 838 case MUL: 839 case DIV: 840 case MOD: 841 case AND: 842 case OR: 843 case ER: 844 case LS: 845 case RS: 846 rv = findops(p, cookie); 847 break; 848 849 case ASSIGN: 850#ifdef FINDMOPS 851 if ((rv = findmops(p, cookie)) != FFAIL) 852 break; 853 /* FALLTHROUGH */ 854#endif 855 case STASG: 856 rv = findasg(p, cookie); 857 break; 858 859 case UMUL: /* May turn into an OREG */ 860 rv = findumul(p, cookie); 861 break; 862 863 case REG: 864 case TEMP: 865 case NAME: 866 case ICON: 867 case FCON: 868 case OREG: 869 rv = findleaf(p, cookie); 870 break; 871 872 case STCALL: 873 case CALL: 874 /* CALL arguments are handled special */ 875 for (p1 = p->n_right; p1->n_op == CM; p1 = p1->n_left) 876 (void)geninsn(p1->n_right, FOREFF); 877 (void)geninsn(p1, FOREFF); 878 /* FALLTHROUGH */ 879 case FLD: 880 case COMPL: 881 case UMINUS: 882 case PCONV: 883 case SCONV: 884/* case INIT: */ 885 case GOTO: 886 case FUNARG: 887 case STARG: 888 case UCALL: 889 case USTCALL: 890 case ADDROF: 891 rv = finduni(p, cookie); 892 break; 893 894 case CBRANCH: 895 p1 = p->n_left; 896 p2 = p->n_right; 897 p1->n_label = (int)getlval(p2); 898 (void)geninsn(p1, FORCC); 899 p->n_su = 0; 900 break; 901 902 case FORCE: /* XXX needed? */ 903 (void)geninsn(p->n_left, INREGS); 904 p->n_su = 0; /* su calculations traverse left */ 905 break; 906 907 case XASM: 908 for (p1 = p->n_left; p1->n_op == CM; p1 = p1->n_left) 909 (void)geninsn(p1->n_right, FOREFF); 910 (void)geninsn(p1, FOREFF); 911 break; /* all stuff already done? */ 912 913 case XARG: 914 /* generate code for correct class here */ 915 break; 916 917 default: 918 comperr("geninsn: bad op %s, node %p", opst[o], p); 919 } 920 if (rv == FFAIL && !q) 921 comperr("Cannot generate code, node %p op %s", p,opst[p->n_op]); 922 if (rv == FRETRY) 923 goto again; 924#ifdef PCC_DEBUG 925 if (o2debug) { 926 printf("geninsn(%p, %s) rv %d\n", p, prcook(cookie), rv); 927 fwalk(p, e2print, 0); 928 } 929#endif 930 return rv; 931} 932 933#ifdef PCC_DEBUG 934#define CDEBUG(x) if (c2debug) printf x 935#else 936#define CDEBUG(x) 937#endif 938 939/* 940 * Do a register-register move if necessary. 941 * Called if a RLEFT or RRIGHT is found. 942 */ 943static void 944ckmove(NODE *p, NODE *q) 945{ 946 struct optab *t = &table[TBLIDX(p->n_su)]; 947 int reg; 948 949 if (q->n_op != REG || p->n_reg == -1) 950 return; /* no register */ 951 952 /* do we have a need for special reg? */ 953 if ((t->needs & NSPECIAL) && 954 (reg = rspecial(t, p->n_left == q ? NLEFT : NRIGHT)) >= 0) 955 ; 956 else 957 reg = DECRA(p->n_reg, 0); 958 959 if (reg < 0 || reg == DECRA(q->n_reg, 0)) 960 return; /* no move necessary */ 961 962 CDEBUG(("rmove: node %p, %s -> %s\n", p, rnames[DECRA(q->n_reg, 0)], 963 rnames[reg])); 964 rmove(DECRA(q->n_reg, 0), reg, p->n_type); 965 q->n_reg = q->n_rval = reg; 966} 967 968/* 969 * Rewrite node to register after instruction emit. 970 */ 971static void 972rewrite(NODE *p, int dorewrite, int cookie) 973{ 974 NODE *l, *r; 975 int o; 976 977 l = getlr(p, 'L'); 978 r = getlr(p, 'R'); 979 o = p->n_op; 980 p->n_op = REG; 981 setlval(p, 0); 982 p->n_name = ""; 983 984 if (o == ASSIGN || o == STASG) { 985 /* special rewrite care */ 986 int reg = DECRA(p->n_reg, 0); 987#define TL(x) (TBLIDX(x->n_su) || x->n_op == REG) 988 if (p->n_reg == -1) 989 ; 990 else if (TL(l) && (DECRA(l->n_reg, 0) == reg)) 991 ; 992 else if (TL(r) && (DECRA(r->n_reg, 0) == reg)) 993 ; 994 else if (TL(l)) 995 rmove(DECRA(l->n_reg, 0), reg, p->n_type); 996 else if (TL(r)) 997 rmove(DECRA(r->n_reg, 0), reg, p->n_type); 998#if 0 999 else 1000 comperr("rewrite"); 1001#endif 1002#undef TL 1003 } 1004 if (optype(o) != LTYPE) 1005 tfree(l); 1006 if (optype(o) == BITYPE) 1007 tfree(r); 1008 if (dorewrite == 0) 1009 return; 1010 CDEBUG(("rewrite: %p, reg %s\n", p, 1011 p->n_reg == -1? "<none>" : rnames[DECRA(p->n_reg, 0)])); 1012 p->n_rval = DECRA(p->n_reg, 0); 1013} 1014 1015#ifndef XASM_TARGARG 1016#define XASM_TARGARG(x,y) 0 1017#endif 1018 1019/* 1020 * printout extended assembler. 1021 */ 1022void 1023genxasm(NODE *p) 1024{ 1025 NODE *q, **nary; 1026 int n = 1, o = 0, v = 0; 1027 char *w; 1028 1029 if (p->n_left->n_op != ICON || p->n_left->n_type != STRTY) { 1030 for (q = p->n_left; q->n_op == CM; q = q->n_left) 1031 n++; 1032 nary = tmpcalloc(sizeof(NODE *)*(n+1)); 1033 o = n; 1034 for (q = p->n_left; q->n_op == CM; q = q->n_left) { 1035 gencode(q->n_right->n_left, INREGS); 1036 nary[--o] = q->n_right; 1037 } 1038 gencode(q->n_left, INREGS); 1039 nary[--o] = q; 1040 } else 1041 nary = 0; 1042 1043 w = p->n_name; 1044 putchar('\t'); 1045 while (*w != 0) { 1046 if (*w == '%') { 1047 if (w[1] == '%') 1048 putchar('%'); 1049 else if (XASM_TARGARG(w, nary)) 1050 ; /* handled by target */ 1051 else if (w[1] == '=') { 1052 if (v == 0) v = getlab2(); 1053 printf("%d", v); 1054 } else if (w[1] == 'c') { 1055 q = nary[(int)w[2]-'0']; 1056 if (q->n_left->n_op != ICON) 1057 uerror("impossible constraint"); 1058 printf(CONFMT, getlval(q->n_left)); 1059 w++; 1060 } else if (w[1] < '0' || w[1] > (n + '0')) 1061 uerror("bad xasm arg number %c", w[1]); 1062 else { 1063 if (w[1] == (n + '0')) 1064 q = nary[(int)w[1]-'0' - 1]; /* XXX */ 1065 else 1066 q = nary[(int)w[1]-'0']; 1067 adrput(stdout, q->n_left); 1068 } 1069 w++; 1070 } else if (*w == '\\') { /* Always 3-digit octal */ 1071 int num = *++w - '0'; 1072 num = (num << 3) + *++w - '0'; 1073 num = (num << 3) + *++w - '0'; 1074 putchar(num); 1075 } else 1076 putchar(*w); 1077 w++; 1078 } 1079 putchar('\n'); 1080} 1081 1082/* 1083 * Allocate temporary registers for use while emitting this table entry. 1084 */ 1085static void 1086allo(NODE *p, struct optab *q) 1087{ 1088 extern int stktemp; 1089 int i, n = ncnt(q->needs); 1090 1091 for (i = 0; i < NRESC; i++) 1092 if (resc[i].n_op != FREE) 1093 comperr("allo: used reg"); 1094 if (n == 0 && (q->needs & NTMASK) == 0) 1095 return; 1096 for (i = 0; i < n+1; i++) { 1097 resc[i].n_op = REG; 1098 resc[i].n_type = p->n_type; /* XXX should be correct type */ 1099 resc[i].n_rval = DECRA(p->n_reg, i); 1100 resc[i].n_su = p->n_su; /* ??? */ 1101 } 1102 if (i > NRESC) 1103 comperr("allo: too many allocs"); 1104 if (q->needs & NTMASK) { 1105#ifdef MYALLOTEMP 1106 MYALLOTEMP(resc[i], stktemp); 1107#else 1108 resc[i].n_op = OREG; 1109 setlval(&resc[i], stktemp); 1110 resc[i].n_rval = FPREG; 1111 resc[i].n_su = p->n_su; /* ??? */ 1112 resc[i].n_name = ""; 1113#endif 1114 } 1115} 1116 1117static void 1118afree(void) 1119{ 1120 int i; 1121 1122 for (i = 0; i < NRESC; i++) 1123 resc[i].n_op = FREE; 1124} 1125 1126void 1127gencode(NODE *p, int cookie) 1128{ 1129 struct optab *q = &table[TBLIDX(p->n_su)]; 1130 NODE *p1, *l, *r; 1131 int o = optype(p->n_op); 1132#ifdef FINDMOPS 1133 int ismops = (p->n_op == ASSIGN && (p->n_su & ISMOPS)); 1134#endif 1135 1136 l = p->n_left; 1137 r = p->n_right; 1138 1139 if (TBLIDX(p->n_su) == 0) { 1140 if (o == BITYPE && (p->n_su & DORIGHT)) 1141 gencode(r, 0); 1142 if (optype(p->n_op) != LTYPE) 1143 gencode(l, 0); 1144 if (o == BITYPE && !(p->n_su & DORIGHT)) 1145 gencode(r, 0); 1146 return; 1147 } 1148 1149 CDEBUG(("gencode: node %p\n", p)); 1150 1151 if (p->n_op == REG && DECRA(p->n_reg, 0) == p->n_rval) 1152 return; /* meaningless move to itself */ 1153 1154 if (callop(p->n_op)) 1155 lastcall(p); /* last chance before function args */ 1156 if (p->n_op == CALL || p->n_op == FORTCALL || p->n_op == STCALL) { 1157 /* Print out arguments first */ 1158 for (p1 = r; p1->n_op == CM; p1 = p1->n_left) 1159 gencode(p1->n_right, FOREFF); 1160 gencode(p1, FOREFF); 1161 o = UTYPE; /* avoid going down again */ 1162 } 1163 1164 if (o == BITYPE && (p->n_su & DORIGHT)) { 1165 gencode(r, INREGS); 1166 if (q->rewrite & RRIGHT) 1167 ckmove(p, r); 1168 } 1169 if (o != LTYPE) { 1170 gencode(l, INREGS); 1171#ifdef FINDMOPS 1172 if (ismops) 1173 ; 1174 else 1175#endif 1176 if (q->rewrite & RLEFT) 1177 ckmove(p, l); 1178 } 1179 if (o == BITYPE && !(p->n_su & DORIGHT)) { 1180 gencode(r, INREGS); 1181 if (q->rewrite & RRIGHT) 1182 ckmove(p, r); 1183 } 1184 1185#ifdef FINDMOPS 1186 if (ismops) { 1187 /* reduce right tree to make expand() work */ 1188 if (optype(r->n_op) != LTYPE) { 1189 p->n_op = r->n_op; 1190 r = tcopy(r->n_right); 1191 tfree(p->n_right); 1192 p->n_right = r; 1193 } 1194 } 1195#endif 1196 1197 canon(p); 1198 1199 if (q->needs & NSPECIAL) { 1200 int rr = rspecial(q, NRIGHT); 1201 int lr = rspecial(q, NLEFT); 1202 1203 if (rr >= 0) { 1204#ifdef PCC_DEBUG 1205 if (optype(p->n_op) != BITYPE) 1206 comperr("gencode: rspecial borked"); 1207#endif 1208 if (r->n_op != REG) 1209 comperr("gencode: rop != REG"); 1210 if (rr != r->n_rval) 1211 rmove(r->n_rval, rr, r->n_type); 1212 r->n_rval = r->n_reg = rr; 1213 } 1214 if (lr >= 0) { 1215 if (l->n_op != REG) 1216 comperr("gencode: %p lop != REG", p); 1217 if (lr != l->n_rval) 1218 rmove(l->n_rval, lr, l->n_type); 1219 l->n_rval = l->n_reg = lr; 1220 } 1221 if (rr >= 0 && lr >= 0 && (l->n_reg == rr || r->n_reg == lr)) 1222 comperr("gencode: cross-reg-move"); 1223 } 1224 1225 if (p->n_op == ASSIGN && 1226 p->n_left->n_op == REG && p->n_right->n_op == REG && 1227 p->n_left->n_rval == p->n_right->n_rval && 1228 (p->n_su & RVCC) == 0) { /* XXX should check if necessary */ 1229 /* do not emit anything */ 1230 CDEBUG(("gencode(%p) assign nothing\n", p)); 1231 rewrite(p, q->rewrite, cookie); 1232 return; 1233 } 1234 1235 CDEBUG(("emitting node %p\n", p)); 1236 if (TBLIDX(p->n_su) == 0) 1237 return; 1238 1239 allo(p, q); 1240 expand(p, cookie, q->cstring); 1241 1242#ifdef FINDMOPS 1243 if (ismops && DECRA(p->n_reg, 0) != regno(l) && cookie != FOREFF) { 1244 CDEBUG(("gencode(%p) rmove\n", p)); 1245 rmove(regno(l), DECRA(p->n_reg, 0), p->n_type); 1246 } else 1247#endif 1248 if (callop(p->n_op) && cookie != FOREFF && 1249 DECRA(p->n_reg, 0) != RETREG(p->n_type)) { 1250 CDEBUG(("gencode(%p) retreg\n", p)); 1251 rmove(RETREG(p->n_type), DECRA(p->n_reg, 0), p->n_type); 1252 } else if (q->needs & NSPECIAL) { 1253 int rr = rspecial(q, NRES); 1254 1255 if (rr >= 0 && DECRA(p->n_reg, 0) != rr) { 1256 CDEBUG(("gencode(%p) nspec retreg\n", p)); 1257 rmove(rr, DECRA(p->n_reg, 0), p->n_type); 1258 } 1259 } else if ((q->rewrite & RESC1) && 1260 (DECRA(p->n_reg, 1) != DECRA(p->n_reg, 0))) { 1261 CDEBUG(("gencode(%p) RESC1 retreg\n", p)); 1262 rmove(DECRA(p->n_reg, 1), DECRA(p->n_reg, 0), p->n_type); 1263 } 1264#if 0 1265 /* XXX - kolla upp det h{r */ 1266 else if (p->n_op == ASSIGN) { 1267 /* may need move added if RLEFT/RRIGHT */ 1268 /* XXX should be handled in sucomp() */ 1269 if ((q->rewrite & RLEFT) && (p->n_left->n_op == REG) && 1270 (p->n_left->n_rval != DECRA(p->n_reg, 0)) && 1271 TCLASS(p->n_su)) { 1272 rmove(p->n_left->n_rval, DECRA(p->n_reg, 0), p->n_type); 1273 } else if ((q->rewrite & RRIGHT) && (p->n_right->n_op == REG) && 1274 (p->n_right->n_rval != DECRA(p->n_reg, 0)) && 1275 TCLASS(p->n_su)) { 1276 rmove(p->n_right->n_rval, DECRA(p->n_reg, 0), p->n_type); 1277 } 1278 } 1279#endif 1280 rewrite(p, q->rewrite, cookie); 1281 afree(); 1282} 1283 1284int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ; /* negatives of relationals */ 1285size_t negrelsize = sizeof negrel / sizeof negrel[0]; 1286 1287#ifdef PCC_DEBUG 1288#undef PRTABLE 1289void 1290e2print(NODE *p, int down, int *a, int *b) 1291{ 1292 struct attr *ap; 1293#ifdef PRTABLE 1294 extern int tablesize; 1295#endif 1296 1297 *a = *b = down+1; 1298 while( down >= 2 ){ 1299 printf("\t"); 1300 down -= 2; 1301 } 1302 if( down-- ) printf(" " ); 1303 1304 1305 printf("%p) %s", p, opst[p->n_op] ); 1306 switch( p->n_op ) { /* special cases */ 1307 1308 case FLD: 1309 printf(" sz=%d, shift=%d", 1310 UPKFSZ(p->n_rval), UPKFOFF(p->n_rval)); 1311 break; 1312 1313 case REG: 1314 printf(" %s", rnames[p->n_rval] ); 1315 break; 1316 1317 case TEMP: 1318 printf(" %d", regno(p)); 1319 break; 1320 1321 case XASM: 1322 case XARG: 1323 printf(" '%s'", p->n_name); 1324 break; 1325 1326 case ICON: 1327 case NAME: 1328 case OREG: 1329 printf(" " ); 1330 adrput(stdout, p ); 1331 break; 1332 1333 case STCALL: 1334 case USTCALL: 1335 case STARG: 1336 case STASG: 1337 ap = attr_find(p->n_ap, ATTR_P2STRUCT); 1338 printf(" size=%d", ap->iarg(0)); 1339 printf(" align=%d", ap->iarg(1)); 1340 break; 1341 } 1342 1343 printf(", " ); 1344 tprint(p->n_type, p->n_qual); 1345 printf(", " ); 1346 1347 prtreg(p); 1348 printf(", SU= %d(%cREG,%s,%s,%s,%s)\n", 1349 TBLIDX(p->n_su), 1350 TCLASS(p->n_su)+'@', 1351#ifdef PRTABLE 1352 TBLIDX(p->n_su) >= 0 && TBLIDX(p->n_su) <= tablesize ? 1353 table[TBLIDX(p->n_su)].cstring : "", 1354#else 1355 "", 1356#endif 1357 p->n_su & RVEFF ? "RVEFF" : "", p->n_su & RVCC ? "RVCC" : "", 1358 p->n_su & DORIGHT ? "DORIGHT" : ""); 1359} 1360#endif 1361 1362/* 1363 * change left TEMPs into OREGs 1364 */ 1365void 1366deltemp(NODE *p, void *arg) 1367{ 1368 int (*aor)[2] = arg; 1369 NODE *l; 1370 1371 if (p->n_op == TEMP) { 1372 if (aor[regno(p)][0] == 0) { 1373 if (xtemps) 1374 return; 1375 aor[regno(p)][0] = FPREG; 1376 aor[regno(p)][1] = freetemp(szty(p->n_type)); 1377 } 1378 storemod(p, aor[regno(p)][1], aor[regno(p)][0]); 1379 } else if (p->n_op == ADDROF && p->n_left->n_op == OREG) { 1380 p->n_op = PLUS; 1381 l = p->n_left; 1382 l->n_op = REG; 1383 l->n_type = INCREF(l->n_type); 1384 p->n_right = mklnode(ICON, getlval(l), 0, INT); 1385 } else if (p->n_op == ADDROF && p->n_left->n_op == UMUL) { 1386 l = p->n_left; 1387 *p = *p->n_left->n_left; 1388 nfree(l->n_left); 1389 nfree(l); 1390 } 1391} 1392 1393/* 1394 * for pointer/integer arithmetic, set pointer at left node 1395 */ 1396static void 1397setleft(NODE *p, void *arg) 1398{ 1399 NODE *q; 1400 1401 /* only additions for now */ 1402 if (p->n_op != PLUS) 1403 return; 1404 if (ISPTR(p->n_right->n_type) && !ISPTR(p->n_left->n_type)) { 1405 q = p->n_right; 1406 p->n_right = p->n_left; 1407 p->n_left = q; 1408 } 1409} 1410 1411/* It is OK to have these as externals */ 1412static int oregr; 1413static CONSZ oregtemp; 1414static char *oregcp; 1415/* 1416 * look for situations where we can turn * into OREG 1417 * If sharp then do not allow temps. 1418 */ 1419int 1420oregok(NODE *p, int sharp) 1421{ 1422 1423 NODE *q; 1424 NODE *ql, *qr; 1425 int r; 1426 CONSZ temp; 1427 char *cp; 1428 1429 q = p->n_left; 1430#if 0 1431 if ((q->n_op == REG || (q->n_op == TEMP && !sharp)) && 1432 q->n_rval == DECRA(q->n_reg, 0)) { 1433#endif 1434 if (q->n_op == REG || (q->n_op == TEMP && !sharp)) { 1435 temp = getlval(q); 1436 r = q->n_rval; 1437 cp = q->n_name; 1438 goto ormake; 1439 } 1440 1441 if (q->n_op != PLUS && q->n_op != MINUS) 1442 return 0; 1443 ql = q->n_left; 1444 qr = q->n_right; 1445 1446#ifdef R2REGS 1447 1448 /* look for doubly indexed expressions */ 1449 /* XXX - fix checks */ 1450 1451 if( q->n_op == PLUS) { 1452 int i; 1453 if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) { 1454 makeor2(p, ql, r, i); 1455 return 1; 1456 } else if((r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) { 1457 makeor2(p, qr, r, i); 1458 return 1; 1459 } 1460 } 1461 1462 1463#endif 1464 1465#if 0 1466 if( (q->n_op==PLUS || q->n_op==MINUS) && qr->n_op == ICON && 1467 (ql->n_op==REG || (ql->n_op==TEMP && !sharp)) && 1468 szty(qr->n_type)==1 && 1469 (ql->n_rval == DECRA(ql->n_reg, 0) || 1470 /* XXX */ 1471 ql->n_rval == FPREG || ql->n_rval == STKREG)) { 1472#endif 1473 if ((q->n_op==PLUS || q->n_op==MINUS) && qr->n_op == ICON && 1474 (ql->n_op==REG || (ql->n_op==TEMP && !sharp))) { 1475 1476 temp = getlval(qr); 1477 if( q->n_op == MINUS ) temp = -temp; 1478 r = ql->n_rval; 1479 temp += getlval(ql); 1480 cp = qr->n_name; 1481 if( *cp && ( q->n_op == MINUS || *ql->n_name ) ) 1482 return 0; 1483 if( !*cp ) cp = ql->n_name; 1484 1485 ormake: 1486 if( notoff( p->n_type, r, temp, cp )) 1487 return 0; 1488 oregtemp = temp; 1489 oregr = r; 1490 oregcp = cp; 1491 return 1; 1492 } 1493 return 0; 1494} 1495 1496static void 1497ormake(NODE *p) 1498{ 1499 NODE *q = p->n_left; 1500 1501 p->n_op = OREG; 1502 p->n_rval = oregr; 1503 setlval(p, oregtemp); 1504 p->n_name = oregcp; 1505 tfree(q); 1506} 1507 1508/* 1509 * look for situations where we can turn * into OREG 1510 */ 1511void 1512oreg2(NODE *p, void *arg) 1513{ 1514 if (p->n_op != UMUL) 1515 return; 1516 if (oregok(p, 1)) 1517 ormake(p); 1518 if (p->n_op == UMUL) 1519 myormake(p); 1520} 1521 1522void 1523canon(NODE *p) 1524{ 1525 /* put p in canonical form */ 1526 1527 walkf(p, setleft, 0); /* ptrs at left node for arithmetic */ 1528 walkf(p, oreg2, 0); /* look for and create OREG nodes */ 1529 mycanon(p); /* your own canonicalization routine(s) */ 1530} 1531 1532void 1533comperr(char *str, ...) 1534{ 1535 extern char *ftitle; 1536 va_list ap; 1537 1538 if (nerrors) { 1539 fprintf(stderr, 1540 "cannot recover from earlier errors: goodbye!\n"); 1541 exit(1); 1542 } 1543 1544 va_start(ap, str); 1545 fprintf(stderr, "%s, line %d: compiler error: ", ftitle, thisline); 1546 vfprintf(stderr, str, ap); 1547 fprintf(stderr, "\n"); 1548 va_end(ap); 1549 1550#ifdef PCC_DEBUG 1551 if (nodepole && nodepole->n_op != FREE) 1552 fwalk(nodepole, e2print, 0); 1553#endif 1554 exit(1); 1555} 1556 1557/* 1558 * allocate k integers worth of temp space 1559 * we also make the convention that, if the number of words is 1560 * more than 1, it must be aligned for storing doubles... 1561 * Returns bytes offset from base register. 1562 */ 1563int 1564freetemp(int k) 1565{ 1566 int t, al, sz; 1567 1568 al = (k > 1 ? ALDOUBLE/ALCHAR : ALINT/ALCHAR); 1569 sz = k * (SZINT/SZCHAR); 1570 1571#ifndef BACKTEMP 1572 SETOFF(p2autooff, al); 1573 t = p2autooff; 1574 p2autooff += sz; 1575#else 1576 p2autooff += sz; 1577 SETOFF(p2autooff, al); 1578 t = ( -p2autooff ); 1579#endif 1580 if (p2autooff > p2maxautooff) 1581 p2maxautooff = p2autooff; 1582 return (t); 1583} 1584 1585NODE * 1586storenode(TWORD t, int off) 1587{ 1588 NODE *p; 1589 1590 p = talloc(); 1591 p->n_type = t; 1592 storemod(p, off, FPREG); /* XXX */ 1593 return p; 1594} 1595 1596#ifndef MYSTOREMOD 1597void 1598storemod(NODE *q, int off, int reg) 1599{ 1600 NODE *l, *r, *p; 1601 1602 l = mklnode(REG, 0, reg, INCREF(q->n_type)); 1603 r = mklnode(ICON, off, 0, INT); 1604 p = mkbinode(PLUS, l, r, INCREF(q->n_type)); 1605 q->n_op = UMUL; 1606 q->n_left = p; 1607 q->n_rval = q->n_su = 0; 1608} 1609#endif 1610 1611NODE * 1612mklnode(int op, CONSZ lval, int rval, TWORD type) 1613{ 1614 NODE *p = talloc(); 1615 1616 p->n_name = ""; 1617 p->n_qual = 0; 1618 p->n_ap = 0; 1619 p->n_op = op; 1620 setlval(p, lval); 1621 p->n_rval = rval; 1622 p->n_type = type; 1623 p->n_regw = NULL; 1624 p->n_su = 0; 1625 return p; 1626} 1627 1628NODE * 1629mkbinode(int op, NODE *left, NODE *right, TWORD type) 1630{ 1631 NODE *p = talloc(); 1632 1633 p->n_name = ""; 1634 p->n_qual = 0; 1635 p->n_ap = 0; 1636 p->n_op = op; 1637 p->n_left = left; 1638 p->n_right = right; 1639 p->n_type = type; 1640 p->n_regw = NULL; 1641 p->n_su = 0; 1642 return p; 1643} 1644 1645NODE * 1646mkunode(int op, NODE *left, int rval, TWORD type) 1647{ 1648 NODE *p = talloc(); 1649 1650 p->n_name = ""; 1651 p->n_qual = 0; 1652 p->n_ap = 0; 1653 p->n_op = op; 1654 p->n_left = left; 1655 p->n_rval = rval; 1656 p->n_type = type; 1657 p->n_regw = NULL; 1658 p->n_su = 0; 1659 return p; 1660} 1661 1662struct interpass * 1663ipnode(NODE *p) 1664{ 1665 struct interpass *ip = tmpalloc(sizeof(struct interpass)); 1666 1667 ip->ip_node = p; 1668 ip->type = IP_NODE; 1669 ip->lineno = thisline; 1670 return ip; 1671} 1672 1673int 1674rspecial(struct optab *q, int what) 1675{ 1676 struct rspecial *r = nspecial(q); 1677 while (r->op) { 1678 if (r->op == what) 1679 return r->num; 1680 r++; 1681 } 1682 return -1; 1683} 1684 1685#ifndef XASM_NUMCONV 1686#define XASM_NUMCONV(x,y,z) 0 1687#endif 1688 1689/* 1690 * change numeric argument redirections to the correct node type after 1691 * cleaning up the other nodes. 1692 * be careful about input operands that may have different value than output. 1693 */ 1694static void 1695delnums(NODE *p, void *arg) 1696{ 1697 struct interpass *ip = arg, *ip2; 1698 NODE *r = ip->ip_node->n_left; 1699 NODE *q; 1700 TWORD t; 1701 int cnt, num; 1702 1703 /* gcc allows % in constraints, but we ignore it */ 1704 if (p->n_name[0] == '%' && p->n_name[1] >= '0' && p->n_name[1] <= '9') 1705 p->n_name++; 1706 1707 if (p->n_name[0] < '0' || p->n_name[0] > '9') 1708 return; /* not numeric */ 1709 if ((q = listarg(r, p->n_name[0] - '0', &cnt)) == NIL) 1710 comperr("bad delnums"); 1711 1712 /* target may have opinions whether to do this conversion */ 1713 if (XASM_NUMCONV(ip, p, q)) 1714 return; 1715 1716 /* Delete number by adding move-to/from-temp. Later on */ 1717 /* the temps may be rewritten to other LTYPEs */ 1718 num = p2env.epp->ip_tmpnum++; 1719 1720 /* pre node */ 1721 t = p->n_left->n_type; 1722 r = mklnode(TEMP, 0, num, t); 1723 ip2 = ipnode(mkbinode(ASSIGN, tcopy(r), p->n_left, t)); 1724 DLIST_INSERT_BEFORE(ip, ip2, qelem); 1725 p->n_left = r; 1726 1727 /* post node */ 1728 t = q->n_left->n_type; 1729 r = mklnode(TEMP, 0, num, t); 1730 ip2 = ipnode(mkbinode(ASSIGN, q->n_left, tcopy(r), t)); 1731 DLIST_INSERT_AFTER(ip, ip2, qelem); 1732 q->n_left = r; 1733 1734 p->n_name = tmpstrdup(q->n_name); 1735 if (*p->n_name == '=') 1736 p->n_name++; 1737} 1738 1739/* 1740 * Ensure that a node is correct for the destination. 1741 */ 1742static void 1743ltypify(NODE *p, void *arg) 1744{ 1745 struct interpass *ip = arg; 1746 struct interpass *ip2; 1747 TWORD t = p->n_left->n_type; 1748 NODE *q, *r; 1749 int cw, ooff, ww; 1750 char *c; 1751 1752again: 1753 if (myxasm(ip, p)) 1754 return; /* handled by target-specific code */ 1755 1756 cw = xasmcode(p->n_name); 1757 switch (ww = XASMVAL(cw)) { 1758 case 'p': 1759 /* pointer */ 1760 /* just make register of it */ 1761 p->n_name = tmpstrdup(p->n_name); 1762 c = strchr(p->n_name, XASMVAL(cw)); /* cannot fail */ 1763 *c = 'r'; 1764 /* FALLTHROUGH */ 1765 case 'g': /* general; any operand */ 1766 if (ww == 'g' && p->n_left->n_op == ICON) { 1767 /* should only be input */ 1768 p->n_name = "i"; 1769 break; 1770 } 1771 /* FALLTHROUGH */ 1772 case 'r': /* general reg */ 1773 /* set register class */ 1774 if (p->n_left->n_op == REG || p->n_left->n_op == TEMP) 1775 break; 1776 q = p->n_left; 1777 r = (cw & XASMINOUT ? tcopy(q) : q); 1778 p->n_left = mklnode(TEMP, 0, p2env.epp->ip_tmpnum++, t); 1779 if ((cw & XASMASG) == 0) { 1780 ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), r, t)); 1781 DLIST_INSERT_BEFORE(ip, ip2, qelem); 1782 } 1783 if (cw & (XASMASG|XASMINOUT)) { 1784 /* output parameter */ 1785 ip2 = ipnode(mkbinode(ASSIGN, q, tcopy(p->n_left), t)); 1786 DLIST_INSERT_AFTER(ip, ip2, qelem); 1787 } 1788 break; 1789 1790 case '0': case '1': case '2': case '3': case '4': 1791 case '5': case '6': case '7': case '8': case '9': 1792 break; 1793 1794 case 'm': /* memory operand */ 1795 /* store and reload value */ 1796 q = p->n_left; 1797 if (optype(q->n_op) == LTYPE) { 1798 if (q->n_op == TEMP) { 1799 ooff = freetemp(szty(t)); 1800 cvtemps(ip, q->n_rval, ooff); 1801 } else if (q->n_op == REG) 1802 comperr("xasm m and reg"); 1803 } else if (q->n_op == UMUL && 1804 (q->n_left->n_op != TEMP && q->n_left->n_op != REG)) { 1805 t = q->n_left->n_type; 1806 ooff = p2env.epp->ip_tmpnum++; 1807 ip2 = ipnode(mkbinode(ASSIGN, 1808 mklnode(TEMP, 0, ooff, t), q->n_left, t)); 1809 q->n_left = mklnode(TEMP, 0, ooff, t); 1810 DLIST_INSERT_BEFORE(ip, ip2, qelem); 1811 } 1812 break; 1813 1814 case 'i': /* immediate constant */ 1815 case 'n': /* numeric constant */ 1816 if (p->n_left->n_op == ICON) 1817 break; 1818 p->n_name = tmpstrdup(p->n_name); 1819 c = strchr(p->n_name, XASMVAL(cw)); /* cannot fail */ 1820 if (c[1]) { 1821 c[0] = c[1], c[1] = 0; 1822 goto again; 1823 } else 1824 uerror("constant required"); 1825 break; 1826 1827 default: 1828 uerror("unsupported xasm option string '%s'", p->n_name); 1829 } 1830} 1831 1832/* Extended assembler hacks */ 1833static void 1834fixxasm(struct p2env *p2e) 1835{ 1836 struct interpass *pole = &p2e->ipole; 1837 struct interpass *ip; 1838 NODE *p; 1839 1840 DLIST_FOREACH(ip, pole, qelem) { 1841 if (ip->type != IP_NODE || ip->ip_node->n_op != XASM) 1842 continue; 1843 thisline = ip->lineno; 1844 p = ip->ip_node->n_left; 1845 1846 if (p->n_op == ICON && p->n_type == STRTY) 1847 continue; 1848 1849 /* replace numeric redirections with its underlying type */ 1850 flist(p, delnums, ip); 1851 1852 /* 1853 * Ensure that the arg nodes can be directly addressable 1854 * We decide that everything shall be LTYPE here. 1855 */ 1856 flist(p, ltypify, ip); 1857 } 1858} 1859 1860/* 1861 * Extract codeword from xasm string */ 1862int 1863xasmcode(char *s) 1864{ 1865 int cw = 0, nm = 0; 1866 1867 while (*s) { 1868 switch ((int)*s) { 1869 case '=': cw |= XASMASG; break; 1870 case '&': cw |= XASMCONSTR; break; 1871 case '+': cw |= XASMINOUT; break; 1872 case '%': break; 1873 default: 1874 if ((*s >= 'a' && *s <= 'z') || 1875 (*s >= 'A' && *s <= 'Z') || 1876 (*s >= '0' && *s <= '9')) { 1877 if (nm == 0) 1878 cw |= *s; 1879 else 1880 cw |= (*s << ((nm + 1) * 8)); 1881 nm++; 1882 break; 1883 } 1884 uerror("bad xasm constraint %c", *s); 1885 } 1886 s++; 1887 } 1888 return cw; 1889} 1890 1891static int xasnum, xoffnum; 1892 1893static void 1894xconv(NODE *p, void *arg) 1895{ 1896 if (p->n_op != TEMP || p->n_rval != xasnum) 1897 return; 1898 storemod(p, xoffnum, FPREG); /* XXX */ 1899} 1900 1901/* 1902 * Convert nodes of type TEMP to op with lval off. 1903 */ 1904static void 1905cvtemps(struct interpass *ipl, int tnum, int off) 1906{ 1907 struct interpass *ip; 1908 1909 xasnum = tnum; 1910 xoffnum = off; 1911 1912 DLIST_FOREACH(ip, ipl, qelem) 1913 if (ip->type == IP_NODE) 1914 walkf(ip->ip_node, xconv, 0); 1915 walkf(ipl->ip_node, xconv, 0); 1916} 1917