1 /* Id: local.c,v 1.71 2009/05/07 02:34:11 gmcgarry Exp */ 2 /* $NetBSD: local.c,v 1.1.1.3 2010/06/03 18:57:22 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 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 31 # include "pass1.h" 32 33 /* this file contains code which is dependent on the target machine */ 34 35 static int pointp(TWORD t); 36 static struct symtab *newfun(char *name, TWORD type); 37 38 #define PTRNORMAL 1 39 #define PTRCHAR 2 40 #define PTRSHORT 3 41 static int xptype(TWORD t); 42 43 NODE * 44 clocal(NODE *p) 45 { 46 /* this is called to do local transformations on 47 an expression tree preparitory to its being 48 written out in intermediate code. 49 */ 50 51 /* the major essential job is rewriting the 52 automatic variables and arguments in terms of 53 REG and OREG nodes */ 54 /* conversion ops which are not necessary are also clobbered here */ 55 /* in addition, any special features (such as rewriting 56 exclusive or) are easily handled here as well */ 57 58 register struct symtab *q; 59 register NODE *r, *l, *oop; 60 register int o; 61 register int m, ml; 62 int siz; 63 64 #ifdef PCC_DEBUG 65 if (xdebug) { 66 printf("clocal: %p\n", p); 67 fwalk(p, eprint, 0); 68 } 69 #endif 70 71 switch( o = p->n_op ){ 72 73 case NAME: 74 if ((q = p->n_sp) == NULL) 75 return p; /* Nothing to care about */ 76 77 switch (q->sclass) { 78 79 case PARAM: 80 /* First 7 parameters are in registers */ 81 /* XXX last may be double */ 82 if (q->soffset/SZINT < 7) { 83 p->n_op = REG; 84 p->n_rval = q->soffset/SZINT; 85 break; 86 } else 87 q->soffset -= 7*SZINT; 88 89 case AUTO: 90 /* fake up a structure reference */ 91 if (q->stype == CHAR || q->stype == UCHAR || 92 q->stype == SHORT || q->stype == USHORT) 93 r = block(REG, NIL, NIL, PTR+q->stype, 0, 0); 94 else 95 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); 96 r->n_lval = 0; 97 r->n_rval = FPREG; 98 p = stref(block(STREF, r, p, 0, 0, 0)); 99 break; 100 101 case STATIC: 102 if (q->slevel == 0) 103 break; 104 p->n_lval = 0; 105 break; 106 107 case REGISTER: 108 p->n_op = REG; 109 p->n_lval = 0; 110 p->n_rval = q->soffset; 111 break; 112 113 } 114 break; 115 116 case CALL: 117 /* avoid recursive calls */ 118 r = tempnode(0, p->n_type, p->n_df, p->n_sue); 119 l = tempnode(regno(r), p->n_type, p->n_df, p->n_sue); 120 ecomp(buildtree(ASSIGN, r, p)); 121 p = l; 122 break; 123 124 case PCONV: 125 l = p->n_left; 126 /* 127 * Handle frame pointer directly without conversion, 128 * for efficiency. 129 */ 130 if (l->n_op == REG && l->n_rval == 0) { 131 rmpc: l->n_type = p->n_type; 132 l->n_df = p->n_df; 133 l->n_sue = p->n_sue; 134 nfree(p); 135 return l; 136 } 137 /* Convert ICON with name to new type */ 138 if (l->n_op == ICON && l->n_sp != NULL && 139 l->n_type == INCREF(STRTY) && 140 (p->n_type == INCREF(CHAR) || 141 p->n_type == INCREF(UCHAR) || 142 p->n_type == INCREF(SHORT) || 143 p->n_type == INCREF(USHORT))) { 144 l->n_lval *= (BTYPE(p->n_type) == CHAR || 145 BTYPE(p->n_type) == UCHAR ? 4 : 2); 146 goto rmpc; 147 } 148 /* Convert only address constants, never convert other */ 149 if (l->n_op == ICON) { 150 if (l->n_sp == NULL) 151 goto rmpc; 152 if (p->n_type == INCREF(CHAR) || 153 p->n_type == INCREF(UCHAR) || 154 p->n_type == INCREF(VOID)) 155 l->n_lval = (l->n_lval & 07777777777) | 156 0700000000000LL; 157 else if (p->n_type == INCREF(SHORT) || 158 p->n_type == INCREF(USHORT)) 159 l->n_lval = (l->n_lval & 07777777777) | 160 0750000000000LL; 161 else 162 l->n_lval = l->n_lval & 07777777777; 163 goto rmpc; 164 } 165 166 /* Remove more conversions of identical pointers */ 167 /* Be careful! optim() may do bad things */ 168 if (ISPTR(DECREF(p->n_type))) { 169 if (ISPTR(DECREF(l->n_type))) { 170 if ((coptype(l->n_op) == UTYPE || 171 coptype(l->n_op) == BITYPE) && 172 (l->n_left->n_op == REG)) 173 l->n_left->n_type = p->n_type; 174 goto rmpc; 175 } 176 } 177 178 /* Change PCONV from int to double pointer to right shift */ 179 if (ISPTR(p->n_type) && ISPTR(DECREF(p->n_type)) && 180 (l->n_type == INT || l->n_type == UNSIGNED)) { 181 p->n_op = RS; 182 p->n_right = bcon(2); 183 break; 184 } 185 186 /* Check for cast integral -> pointer */ 187 if (BTYPE(l->n_type) == l->n_type) 188 break; 189 190 /* Remove conversions to identical pointers */ 191 switch (xptype(p->n_type)) { 192 case PTRNORMAL: 193 if (xptype(l->n_type) == PTRNORMAL) 194 goto rmpc; 195 break; 196 197 case PTRSHORT: 198 if (xptype(l->n_type) == PTRSHORT) 199 goto rmpc; 200 break; 201 202 case PTRCHAR: 203 if (xptype(l->n_type) == PTRCHAR) 204 goto rmpc; 205 break; 206 } 207 208 break; 209 210 case SCONV: 211 l = p->n_left; 212 213 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && 214 btdims[p->n_type].suesize == btdims[l->n_type].suesize) { 215 if (p->n_type != FLOAT && p->n_type != DOUBLE && 216 l->n_type != FLOAT && l->n_type != DOUBLE) { 217 nfree(p); 218 return l; 219 } 220 } 221 /* cast to (void) XXX should be removed in MI code */ 222 if (p->n_type == VOID) { 223 nfree(p); 224 return l; 225 } 226 m = p->n_type; 227 ml = l->n_type; 228 if (m == ml) { 229 nfree(p); 230 return l; 231 } 232 o = l->n_op; 233 if (ml == FLOAT || ml == DOUBLE) { 234 if (o != FCON) 235 break; 236 ml = ISUNSIGNED(m) ? UNSIGNED : INT; /* LONG? */ 237 r = xbcon(ml == INT ? (int)p->n_left->n_dcon : 238 (unsigned)p->n_left->n_dcon, 239 NULL, ml); 240 nfree(p->n_left); 241 p->n_left = r; 242 o = ICON; 243 if (m == ml) { 244 r = p->n_left; 245 nfree(p); 246 return r; 247 } 248 } 249 if (o == ICON) { 250 CONSZ val = l->n_lval; 251 252 switch (m) { 253 case CHAR: 254 l->n_lval = val & 0777; 255 if (val & 0400) 256 l->n_lval |= ~((CONSZ)0777); 257 break; 258 case UCHAR: 259 l->n_lval = val & 0777; 260 break; 261 case USHORT: 262 l->n_lval = val & 0777777; 263 break; 264 case SHORT: 265 l->n_lval = val & 0777777; 266 if (val & 0400000) 267 l->n_lval |= ~((CONSZ)0777777); 268 break; 269 case UNSIGNED: 270 l->n_lval = val & 0777777777777LL; 271 break; 272 case INT: 273 l->n_lval = val & 0777777777777LL; 274 if (val & 0400000000000LL) 275 l->n_lval |= ~(0777777777777LL); 276 break; 277 case LONGLONG: /* XXX */ 278 case ULONGLONG: 279 l->n_lval = val; 280 break; 281 case VOID: 282 break; 283 case DOUBLE: 284 case FLOAT: 285 l->n_op = FCON; 286 l->n_dcon = 0; 287 break; 288 default: 289 cerror("unknown type %d", m); 290 } 291 l->n_type = m; 292 l->n_sue = MKSUE(m); 293 nfree(p); 294 return l; 295 } 296 break; 297 298 case PMCONV: 299 case PVCONV: 300 /* if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); */ 301 nfree(p); 302 return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right)); 303 304 case RS: 305 case RSEQ: 306 /* convert >> to << with negative shift count */ 307 /* Beware! constant shifts will be converted back in optim() */ 308 309 if (p->n_right->n_op != UMINUS) { 310 p->n_right = buildtree(UMINUS, p->n_right, NIL); 311 } else { 312 r = p->n_right; 313 p->n_right = p->n_right->n_left; 314 nfree(r); 315 } 316 if (p->n_op == RS) 317 p->n_op = LS; 318 else 319 p->n_op = LSEQ; 320 break; 321 322 case UMUL: /* Convert structure assignment to memcpy() */ 323 if (p->n_left->n_op == PLUS && 324 p->n_left->n_left->n_op == PCONV && 325 p->n_left->n_right->n_op == ICON && 326 (p->n_type == CHAR || p->n_type == UCHAR || 327 p->n_type == SHORT || p->n_type == USHORT)) { 328 /* Can remove the left SCONV */ 329 l = p->n_left->n_left; 330 p->n_left->n_left = l->n_left; 331 nfree(l); 332 break; 333 334 } 335 if (p->n_left->n_op != STASG) 336 break; 337 oop = p; 338 p = p->n_left; 339 siz = p->n_sue->suesize/SZCHAR; 340 l = p->n_left; 341 r = p->n_right; 342 if (l->n_type == STRTY || l->n_type == UNIONTY) { 343 if (l->n_op == UMUL) { 344 p->n_left = l->n_left; 345 nfree(l); 346 l = p->n_left; 347 } else { 348 l = block(ADDROF, l, NIL, INCREF(l->n_type), 349 0, MKSUE(INT)); 350 } 351 } 352 if ((l->n_type != (STRTY+PTR) && l->n_type != (UNIONTY+PTR)) || 353 (r->n_type != (STRTY+PTR) && r->n_type != (UNIONTY+PTR))) 354 cerror("bad stasg, l = %o, r = %o", l->n_type, r->n_type); 355 q = newfun("__structcpy", p->n_type); 356 357 /* structure pointer block */ 358 l = block(CM, l, r, INT, 0, MKSUE(INT)); 359 /* Size block */ 360 r = block(CM, l, bcon(siz), INT, 0, MKSUE(INT)); 361 362 l = xbcon(0, q, q->stype); 363 p->n_left = l; 364 p->n_right = r; 365 p->n_op = CALL; 366 oop->n_left = p; 367 return oop; 368 369 case FORCE: 370 p->n_op = ASSIGN; 371 p->n_right = p->n_left; 372 p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); 373 p->n_left->n_rval = RETREG(p->n_type); 374 break; 375 376 } 377 378 return(p); 379 } 380 381 void 382 myp2tree(NODE *p) 383 { 384 NODE *r; 385 386 switch (p->n_op) { 387 case ULT: /* exor sign bit to avoid unsigned comparitions */ 388 case ULE: 389 case UGT: 390 case UGE: 391 if (ISLONGLONG(p->n_left->n_type)) { 392 /* XXX */ 393 r = xbcon(0x8000000000000000ULL, NULL, LONGLONG); 394 } else 395 r = xbcon(0400000000000LL, NULL, INT); 396 p->n_left = buildtree(ER, p->n_left, r); 397 if (ISUNSIGNED(p->n_left->n_type)) 398 p->n_left->n_type = DEUNSIGN(p->n_left->n_type); 399 400 if (ISLONGLONG(p->n_right->n_type)) { 401 /* XXX */ 402 r = xbcon(0x8000000000000000ULL, NULL, LONGLONG); 403 } else 404 r = xbcon(0400000000000LL, NULL, INT); 405 p->n_right = buildtree(ER, p->n_right, r); 406 if (ISUNSIGNED(p->n_right->n_type)) 407 p->n_right->n_type = DEUNSIGN(p->n_right->n_type); 408 409 p->n_op -= (ULT-LT); 410 break; 411 case FCON: 412 cerror("fix float constants"); 413 } 414 } 415 416 417 struct symtab * 418 newfun(char *name, TWORD type) 419 { 420 struct symtab *sp; 421 422 sp = lookup(name, 0); 423 if (sp->stype == VOID) { 424 sp->stype = INCREF(type | FTN); 425 sp->sclass = EXTERN; 426 sp->soffset = 0; 427 } 428 #ifdef notdef 429 else if (!ISFTN(DECREF(sp->stype))) 430 uerror("reserved name '%s' used illegally", name); 431 #endif 432 return sp; 433 } 434 435 /*ARGSUSED*/ 436 int 437 andable(NODE *p) 438 { 439 return(1); /* all names can have & taken on them */ 440 } 441 442 /* 443 * at the end of the arguments of a ftn, set the automatic offset 444 */ 445 void 446 cendarg() 447 { 448 autooff = AUTOINIT; 449 } 450 451 /* 452 * is an automatic variable of type t OK for a register variable 453 * Everything is trusted to be in register here. 454 */ 455 int 456 cisreg(TWORD t) 457 { 458 return(1); 459 } 460 461 int 462 xptype(TWORD t) 463 { 464 int tt = BTYPE(t); 465 int e, rv; 466 467 if (!ISPTR(t)) 468 cerror("not a pointer"); 469 470 e = t & ~BTMASK; 471 rv = e; 472 while (e) { 473 rv = e; 474 if (DECREF(e) == 0) 475 break; 476 e = DECREF(e); 477 } 478 if (ISFTN(rv)) 479 return PTRNORMAL; 480 481 switch (tt) { 482 case INT: 483 case LONG: 484 case LONGLONG: 485 case FLOAT: 486 case DOUBLE: 487 case STRTY: 488 case UNIONTY: 489 case UNSIGNED: 490 case ULONG: 491 case ULONGLONG: 492 return PTRNORMAL; 493 case VOID: 494 case CHAR: 495 case UCHAR: 496 if (DECREF(t) == tt || ISARY(rv)) 497 return PTRCHAR; 498 return PTRNORMAL; 499 case SHORT: 500 case USHORT: 501 if (DECREF(t) == tt || ISARY(rv)) 502 return PTRSHORT; 503 return PTRNORMAL; 504 default: 505 break; 506 } 507 cerror("unknown type"); 508 return PTRNORMAL; /* XXX */ 509 } 510 511 /* 512 * Help routine to the one below; return true if it's not a word pointer. 513 */ 514 static int 515 pointp(TWORD t) 516 { 517 int rv = 0; 518 519 if (ISPTR(t) && ((t & TMASK1) == 0)) 520 return 1; 521 522 t &= ~BTMASK; 523 while (t) { 524 rv = ISARY(t); 525 t = DECREF(t); 526 } 527 return rv; 528 } 529 530 /* 531 * return a node, for structure references, which is suitable for 532 * being added to a pointer of type t, in order to be off bits offset 533 * into a structure 534 * t, d, and s are the type, dimension offset, and sizeoffset 535 * For pdp10, return the type-specific index number which calculation 536 * is based on its size. For example, short a[3] would return 3. 537 * Be careful about only handling first-level pointers, the following 538 * indirections must be fullword. 539 */ 540 NODE * 541 offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue) 542 { 543 register NODE *p; 544 545 if (xdebug) 546 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n", 547 off, t, d, sue->suesize); 548 549 p = bcon(0); 550 p->n_lval = off/SZINT; /* Default */ 551 if (ISPTR(DECREF(t))) 552 return p; /* Pointer/pointer reference */ 553 switch (BTMASK & t) { 554 case INT: 555 case UNSIGNED: 556 case LONG: 557 case ULONG: 558 case STRTY: 559 case UNIONTY: 560 case LONGLONG: 561 case ULONGLONG: 562 case FLOAT: 563 case DOUBLE: 564 break; 565 566 case SHORT: 567 case USHORT: 568 if (pointp(t)) 569 p->n_lval = off/SZSHORT; 570 break; 571 572 case VOID: /* void pointers */ 573 case CHAR: 574 case UCHAR: 575 if (pointp(t)) 576 p->n_lval = off/SZCHAR; 577 break; 578 579 default: 580 cerror("offcon, off %llo size %d type %x", off, sue->suesize, t); 581 } 582 if (xdebug) 583 printf("offcon return 0%llo\n", p->n_lval); 584 return(p); 585 } 586 587 /* 588 * Allocate off bits on the stack. p is a tree that when evaluated 589 * is the multiply count for off, t is a NAME node where to write 590 * the allocated address. 591 * Be aware that a pointer conversion may be needed when saving 592 * to node t! 593 */ 594 void 595 spalloc(NODE *t, NODE *p, OFFSZ off) 596 { 597 NODE *sp; 598 599 if ((off % SZINT) == 0) 600 p = buildtree(MUL, p, bcon(off/SZINT)); 601 else if ((off % SZSHORT) == 0) { 602 p = buildtree(MUL, p, bcon(off/SZSHORT)); 603 p = buildtree(PLUS, p, bcon(1)); 604 p = buildtree(RS, p, bcon(1)); 605 } else if ((off % SZCHAR) == 0) { 606 p = buildtree(MUL, p, bcon(off/SZCHAR)); 607 p = buildtree(PLUS, p, bcon(3)); 608 p = buildtree(RS, p, bcon(2)); 609 } else 610 cerror("roundsp"); 611 612 /* save the address of sp */ 613 sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue); 614 sp->n_lval = 0; 615 sp->n_rval = STKREG; 616 /* Cast sp to destination type (may be redundant) */ 617 sp = buildtree(CAST, 618 block(NAME, NIL, NIL, t->n_type, t->n_df, t->n_sue), sp); 619 nfree(sp->n_left); 620 nfree(sp); 621 sp = sp->n_right; 622 ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ 623 624 /* add the size to sp */ 625 sp = block(REG, NIL, NIL, p->n_type, 0, 0); 626 sp->n_lval = 0; 627 sp->n_rval = STKREG; 628 ecomp(buildtree(PLUSEQ, sp, p)); 629 } 630 631 #if 0 632 static int inwd; /* current bit offsed in word */ 633 static CONSZ word; /* word being built from fields */ 634 635 /* 636 * Generate initialization code for assigning a constant c 637 * to a field of width sz 638 * we assume that the proper alignment has been obtained 639 * inoff is updated to have the proper final value 640 * we also assume sz < SZINT 641 */ 642 void 643 incode(NODE *p, int sz) 644 { 645 char *s; 646 647 inoff += sz; 648 if ((sz + inwd) > SZINT) 649 cerror("incode: field > int"); 650 651 word |= ((p->n_lval & ((1 << sz) - 1)) << (36 - inwd - sz)); 652 653 inwd += sz; 654 if (inoff % SZINT == 0) { 655 s = isinlining ? permalloc(30) : tmpalloc(30); 656 sprintf(s, " .long 0%llo", word); 657 send_passt(IP_ASM, s); 658 word = inwd = 0; 659 } 660 tfree(p); 661 } 662 663 /* output code to initialize space of size sz to the value d */ 664 /* the proper alignment has been obtained */ 665 /* inoff is updated to have the proper final value */ 666 /* on the target machine, write it out in octal! */ 667 void 668 fincode(NODE *p, int sz) 669 { 670 double d = p->n_dcon; 671 672 if(!nerrors) 673 printf(" %s 0%c%.20e\n", 674 sz == SZDOUBLE ? ".double" : ".float", 675 sz == SZDOUBLE ? 'd' : 'f', d); 676 inoff += sz; 677 } 678 679 void 680 cinit(NODE *p, int sz) 681 { 682 NODE *l; 683 684 /* 685 * as a favor (?) to people who want to write 686 * int i = 9600/134.5; 687 * we will, under the proper circumstances, do 688 * a coercion here. 689 */ 690 switch (p->n_type) { 691 case INT: 692 case UNSIGNED: 693 l = p->n_left; 694 if (l->n_op != SCONV || l->n_left->n_op != FCON) 695 break; 696 nfree(l); 697 l = l->n_left; 698 l->n_lval = (long)(l->n_dcon); 699 l->n_sp = NULL; 700 l->n_op = ICON; 701 l->n_type = INT; 702 p->n_left = l; 703 break; 704 } 705 /* arrange for the initialization of p into a space of size sz */ 706 /* the proper alignment has been opbtained */ 707 /* inoff is updated to have the proper final value */ 708 ecode( p ); 709 inoff += sz; 710 } 711 712 /* 713 * define n bits of zeros in a vfd 714 */ 715 void 716 vfdzero(int n) 717 { 718 char *s; 719 720 inoff += n; 721 inwd += n; 722 if (inoff%ALINT ==0) { 723 s = isinlining ? permalloc(30) : tmpalloc(30); 724 sprintf(s, " .long 0%llo", word); 725 send_passt(IP_ASM, s); 726 word = inwd = 0; 727 } 728 } 729 #endif 730 731 /* make a name look like an external name in the local machine */ 732 char * 733 exname(char *p) 734 { 735 if (p == NULL) 736 return ""; 737 return p; 738 } 739 740 /* 741 * map types which are not defined on the local machine 742 */ 743 TWORD 744 ctype(TWORD type) 745 { 746 switch (BTYPE(type)) { 747 case LONG: 748 MODTYPE(type,INT); 749 break; 750 case ULONG: 751 MODTYPE(type,UNSIGNED); 752 break; 753 case LDOUBLE: 754 MODTYPE(type,DOUBLE); 755 break; 756 } 757 return (type); 758 } 759 760 /* 761 * Print out a string of characters. 762 * Assume that the assembler understands C-style escape 763 * sequences. 764 */ 765 void 766 instring(struct symtab *sp) 767 { 768 char *s, *str; 769 770 defloc(sp); 771 str = sp->sname; 772 773 /* be kind to assemblers and avoid long strings */ 774 printf("\t.ascii \""); 775 for (s = str; *s != 0; ) { 776 if (*s++ == '\\') { 777 (void)esccon(&s); 778 } 779 if (s - str > 60) { 780 fwrite(str, 1, s - str, stdout); 781 printf("\"\n\t.ascii \""); 782 str = s; 783 } 784 } 785 fwrite(str, 1, s - str, stdout); 786 printf("\\0\"\n"); 787 } 788 789 /* curid is a variable which is defined but 790 * is not initialized (and not a function ); 791 * This routine returns the stroage class for an uninitialized declaration 792 */ 793 int 794 noinit() 795 { 796 return(EXTERN); 797 } 798 799 void 800 calldec(NODE *p, NODE *q) 801 { 802 } 803 804 void 805 extdec(struct symtab *q) 806 { 807 } 808 809 /* make a common declaration for id, if reasonable */ 810 void 811 defzero(struct symtab *sp) 812 { 813 int off; 814 815 off = tsize(sp->stype, sp->sdf, sp->ssue); 816 off = (off+(SZINT-1))/SZINT; 817 printf(" .%scomm ", sp->sclass == STATIC ? "l" : ""); 818 if (sp->slevel == 0) 819 printf("%s,0%o\n", exname(sp->soname), off); 820 else 821 printf(LABFMT ",0%o\n", sp->soffset, off); 822 } 823 824 /* 825 * set fsz bits in sequence to zero. 826 */ 827 void 828 zbits(OFFSZ off, int fsz) 829 { 830 cerror("zbits"); 831 } 832 833 /* 834 * Initialize a bitfield. 835 */ 836 void 837 infld(CONSZ off, int fsz, CONSZ val) 838 { 839 // if (idebug) 840 // printf("infld off %lld, fsz %d, val %lld inbits %d\n", 841 // off, fsz, val, inbits); 842 cerror("infld"); 843 } 844 845 /* 846 * print out a constant node, may be associated with a label. 847 * Do not free the node after use. 848 * off is bit offset from the beginning of the aggregate 849 * fsz is the number of bits this is referring to 850 */ 851 void 852 ninval(CONSZ off, int fsz, NODE *p) 853 { 854 cerror("ninval"); 855 } 856 857 858 /* 859 * Give target the opportunity of handling pragmas. 860 */ 861 int 862 mypragma(char **ary) 863 { 864 return 0; } 865 866 /* 867 * Called when a identifier has been declared, to give target last word. 868 */ 869 void 870 fixdef(struct symtab *sp) 871 { 872 } 873 874 void 875 pass1_lastchance(struct interpass *ip) 876 { 877 } 878 879