* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / mip / common.c
blob85d0078746460f266129e0a75218a56912bbc8d3
1 /* $Id: common.c,v 1.93 2011/01/22 22:08:23 ragge Exp $ */
2 /*
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
34 * Redistributions of source code and documentation must retain the above
35 * copyright notice, this list of conditions and the following disclaimer.
36 * Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditionsand the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed or owned by Caldera
42 * International, Inc.
43 * Neither the name of Caldera International, Inc. nor the names of other
44 * contributors may be used to endorse or promote products derived from
45 * this software without specific prior written permission.
47 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
48 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
49 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
51 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
52 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
56 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
57 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58 * POSSIBILITY OF SUCH DAMAGE.
61 #include <stdarg.h>
62 #include <stdlib.h>
63 #include <stdio.h>
64 #include <string.h>
66 #include "pass2.h"
68 # ifndef EXIT
69 # define EXIT exit
70 # endif
72 int nerrors = 0; /* number of errors */
73 extern char *ftitle;
74 int lineno;
76 int warniserr = 0;
78 #ifndef WHERE
79 #define WHERE(ch) fprintf(stderr, "%s, line %d: ", ftitle, lineno);
80 #endif
82 static void
83 incerr(void)
85 if (++nerrors > 30)
86 cerror("too many errors");
90 * nonfatal error message
91 * the routine where is different for pass 1 and pass 2;
92 * it tells where the error took place
94 void
95 uerror(char *s, ...)
97 va_list ap;
99 va_start(ap, s);
100 WHERE('u');
101 vfprintf(stderr, s, ap);
102 fprintf(stderr, "\n");
103 va_end(ap);
104 incerr();
108 * compiler error: die
110 void
111 cerror(char *s, ...)
113 va_list ap;
115 va_start(ap, s);
116 WHERE('c');
118 /* give the compiler the benefit of the doubt */
119 if (nerrors && nerrors <= 30) {
120 fprintf(stderr,
121 "cannot recover from earlier errors: goodbye!\n");
122 } else {
123 fprintf(stderr, "compiler error: ");
124 vfprintf(stderr, s, ap);
125 fprintf(stderr, "\n");
127 va_end(ap);
128 EXIT(1);
132 * warning
134 void
135 werror(char *s, ...)
137 va_list ap;
139 va_start(ap, s);
140 WHERE('w');
141 fprintf(stderr, "warning: ");
142 vfprintf(stderr, s, ap);
143 fprintf(stderr, "\n");
144 va_end(ap);
145 if (warniserr)
146 incerr();
149 #ifndef MKEXT
151 bittype warnary[(NUMW/NUMBITS)+1], werrary[(NUMW/NUMBITS)+1];
153 static char *warntxt[] = {
154 "conversion to '%s' from '%s' may alter its value",
155 "function declaration isn't a prototype", /* Wstrict_prototypes */
156 "no previous prototype for `%s'", /* Wmissing_prototypes */
157 "return type defaults to `int'", /* Wimplicit_int */
158 /* Wimplicit_function_declaration */
159 "implicit declaration of function '%s'",
160 "declaration of '%s' shadows a %s declaration", /* Wshadow */
161 "illegal pointer combination", /* Wpointer_sign */
162 "comparison between signed and unsigned", /* Wsign_compare */
163 "ignoring #pragma %s %s", /* Wunknown_pragmas */
164 "statement not reached", /* Wunreachable_code */
167 char *flagstr[] = {
168 "truncate", "strict-prototypes", "missing-prototypes",
169 "implicit-int", "implicit-function-declaration", "shadow",
170 "pointer-sign", "sign-compare", "unknown-pragmas",
171 "unreachable-code",
175 * "emulate" the gcc warning flags.
177 void
178 Wflags(char *str)
180 int i, flagval;
182 if (strncmp("no-", str, 3) == 0) {
183 str += 3;
184 flagval = 0;
185 } else
186 flagval = 1;
187 if (strcmp(str, "error") == 0) {
188 /* special */
189 for (i = 0; i < NUMW; i++)
190 BITSET(werrary, i);
191 return;
193 for (i = 0; i < NUMW; i++) {
194 if (strcmp(flagstr[i], str) != 0)
195 continue;
196 if (flagval)
197 BITSET(warnary, i);
198 else
199 BITCLEAR(warnary, i);
200 return;
202 fprintf(stderr, "unrecognised warning option '%s'\n", str);
206 * Deal with gcc warnings.
208 void
209 warner(int type, ...)
211 va_list ap;
212 char *w;
214 if (TESTBIT(warnary, type) == 0)
215 return; /* no warning */
216 if (TESTBIT(werrary, type)) {
217 w = "error";
218 incerr();
219 } else
220 w = "warning";
222 va_start(ap, type);
223 fprintf(stderr, "%s:%d: %s: ", ftitle, lineno, w);
224 vfprintf(stderr, warntxt[type], ap);
225 fprintf(stderr, "\n");
226 va_end(ap);
228 #endif /* MKEXT */
230 #ifndef MKEXT
231 static NODE *freelink;
232 static int usednodes;
234 #ifndef LANG_F77
235 NODE *
236 talloc()
238 register NODE *p;
240 usednodes++;
242 if (freelink != NULL) {
243 p = freelink;
244 freelink = p->next;
245 if (p->n_op != FREE)
246 cerror("node not FREE: %p", p);
247 if (nflag)
248 printf("alloc node %p from freelist\n", p);
249 return p;
252 p = permalloc(sizeof(NODE));
253 p->n_op = FREE;
254 if (nflag)
255 printf("alloc node %p from memory\n", p);
256 return p;
258 #endif
261 * make a fresh copy of p
263 NODE *
264 tcopy(NODE *p)
266 NODE *q;
268 q = talloc();
269 *q = *p;
271 switch (optype(q->n_op)) {
272 case BITYPE:
273 q->n_right = tcopy(p->n_right);
274 case UTYPE:
275 q->n_left = tcopy(p->n_left);
278 return(q);
281 #ifndef LANG_F77
283 * ensure that all nodes have been freed
285 void
286 tcheck()
288 extern int inlnodecnt;
290 if (nerrors)
291 return;
293 if ((usednodes - inlnodecnt) != 0)
294 cerror("usednodes == %d, inlnodecnt %d", usednodes, inlnodecnt);
296 #endif
299 * free the tree p
301 void
302 tfree(NODE *p)
304 if (p->n_op != FREE)
305 walkf(p, (void (*)(NODE *, void *))nfree, 0);
309 * Free a node, and return its left descendant.
310 * It is up to the caller to know whether the return value is usable.
312 NODE *
313 nfree(NODE *p)
315 NODE *l;
316 #ifdef PCC_DEBUG_NODES
317 NODE *q;
318 #endif
320 if (p == NULL)
321 cerror("freeing blank node!");
323 l = p->n_left;
324 if (p->n_op == FREE)
325 cerror("freeing FREE node", p);
326 #ifdef PCC_DEBUG_NODES
327 q = freelink;
328 while (q != NULL) {
329 if (q == p)
330 cerror("freeing free node %p", p);
331 q = q->next;
333 #endif
335 if (nflag)
336 printf("freeing node %p\n", p);
337 p->n_op = FREE;
338 p->next = freelink;
339 freelink = p;
340 usednodes--;
341 return l;
343 #endif
345 #ifdef LANG_F77
346 #define OPTYPE(x) optype(x)
347 #else
348 #define OPTYPE(x) coptype(x)
349 #endif
351 #ifdef MKEXT
352 #define coptype(o) (dope[o]&TYFLG)
353 #else
354 int cdope(int);
355 #define coptype(o) (cdope(o)&TYFLG)
356 #endif
358 void
359 fwalk(NODE *t, void (*f)(NODE *, int, int *, int *), int down)
362 int down1, down2;
364 more:
365 down1 = down2 = 0;
367 (*f)(t, down, &down1, &down2);
369 switch (OPTYPE( t->n_op )) {
371 case BITYPE:
372 fwalk( t->n_left, f, down1 );
373 t = t->n_right;
374 down = down2;
375 goto more;
377 case UTYPE:
378 t = t->n_left;
379 down = down1;
380 goto more;
385 void
386 walkf(NODE *t, void (*f)(NODE *, void *), void *arg)
388 int opty;
391 opty = OPTYPE(t->n_op);
393 if (opty != LTYPE)
394 walkf( t->n_left, f, arg );
395 if (opty == BITYPE)
396 walkf( t->n_right, f, arg );
397 (*f)(t, arg);
400 int dope[DSIZE];
401 char *opst[DSIZE];
403 struct dopest {
404 int dopeop;
405 char opst[8];
406 int dopeval;
407 } indope[] = {
408 { NAME, "NAME", LTYPE, },
409 { REG, "REG", LTYPE, },
410 { OREG, "OREG", LTYPE, },
411 { TEMP, "TEMP", LTYPE, },
412 { ICON, "ICON", LTYPE, },
413 { FCON, "FCON", LTYPE, },
414 { CCODES, "CCODES", LTYPE, },
415 { UMINUS, "U-", UTYPE, },
416 { UMUL, "U*", UTYPE, },
417 { FUNARG, "FUNARG", UTYPE, },
418 { UCALL, "UCALL", UTYPE|CALLFLG, },
419 { UFORTCALL, "UFCALL", UTYPE|CALLFLG, },
420 { COMPL, "~", UTYPE, },
421 { FORCE, "FORCE", UTYPE, },
422 { XARG, "XARG", UTYPE, },
423 { XASM, "XASM", BITYPE, },
424 { SCONV, "SCONV", UTYPE, },
425 { PCONV, "PCONV", UTYPE, },
426 { PLUS, "+", BITYPE|FLOFLG|SIMPFLG|COMMFLG, },
427 { MINUS, "-", BITYPE|FLOFLG|SIMPFLG, },
428 { MUL, "*", BITYPE|FLOFLG|MULFLG, },
429 { AND, "&", BITYPE|SIMPFLG|COMMFLG, },
430 { CM, ",", BITYPE, },
431 { ASSIGN, "=", BITYPE|ASGFLG, },
432 { DIV, "/", BITYPE|FLOFLG|MULFLG|DIVFLG, },
433 { MOD, "%", BITYPE|DIVFLG, },
434 { LS, "<<", BITYPE|SHFFLG, },
435 { RS, ">>", BITYPE|SHFFLG, },
436 { OR, "|", BITYPE|COMMFLG|SIMPFLG, },
437 { ER, "^", BITYPE|COMMFLG|SIMPFLG, },
438 { STREF, "->", BITYPE, },
439 { CALL, "CALL", BITYPE|CALLFLG, },
440 { FORTCALL, "FCALL", BITYPE|CALLFLG, },
441 { EQ, "==", BITYPE|LOGFLG, },
442 { NE, "!=", BITYPE|LOGFLG, },
443 { LE, "<=", BITYPE|LOGFLG, },
444 { LT, "<", BITYPE|LOGFLG, },
445 { GE, ">=", BITYPE|LOGFLG, },
446 { GT, ">", BITYPE|LOGFLG, },
447 { UGT, "UGT", BITYPE|LOGFLG, },
448 { UGE, "UGE", BITYPE|LOGFLG, },
449 { ULT, "ULT", BITYPE|LOGFLG, },
450 { ULE, "ULE", BITYPE|LOGFLG, },
451 { CBRANCH, "CBRANCH", BITYPE, },
452 { FLD, "FLD", UTYPE, },
453 { PMCONV, "PMCONV", BITYPE, },
454 { PVCONV, "PVCONV", BITYPE, },
455 { RETURN, "RETURN", BITYPE|ASGFLG|ASGOPFLG, },
456 { GOTO, "GOTO", UTYPE, },
457 { STASG, "STASG", BITYPE|ASGFLG, },
458 { STARG, "STARG", UTYPE, },
459 { STCALL, "STCALL", BITYPE|CALLFLG, },
460 { USTCALL, "USTCALL", UTYPE|CALLFLG, },
461 { ADDROF, "U&", UTYPE, },
463 { -1, "", 0 },
466 void
467 mkdope()
469 struct dopest *q;
471 for( q = indope; q->dopeop >= 0; ++q ){
472 dope[q->dopeop] = q->dopeval;
473 opst[q->dopeop] = q->opst;
478 * output a nice description of the type of t
480 void
481 tprint(FILE *fp, TWORD t, TWORD q)
483 static char * tnames[] = {
484 "undef",
485 "farg",
486 "char",
487 "uchar",
488 "short",
489 "ushort",
490 "int",
491 "unsigned",
492 "long",
493 "ulong",
494 "longlong",
495 "ulonglong",
496 "float",
497 "double",
498 "ldouble",
499 "strty",
500 "unionty",
501 "enumty",
502 "moety",
503 "void",
504 "signed", /* pass1 */
505 "bool", /* pass1 */
506 "fimag", /* pass1 */
507 "dimag", /* pass1 */
508 "limag", /* pass1 */
509 "fcomplex", /* pass1 */
510 "dcomplex", /* pass1 */
511 "lcomplex", /* pass1 */
512 "enumty", /* pass1 */
513 "?", "?"
516 for(;; t = DECREF(t), q = DECREF(q)) {
517 if (ISCON(q))
518 fputc('C', fp);
519 if (ISVOL(q))
520 fputc('V', fp);
522 if (ISPTR(t))
523 fprintf(fp, "PTR ");
524 else if (ISFTN(t))
525 fprintf(fp, "FTN ");
526 else if (ISARY(t))
527 fprintf(fp, "ARY ");
528 else {
529 fprintf(fp, "%s%s%s", ISCON(q << TSHIFT) ? "const " : "",
530 ISVOL(q << TSHIFT) ? "volatile " : "", tnames[t]);
531 return;
537 * Memory allocation routines.
538 * Memory are allocated from the system in MEMCHUNKSZ blocks.
539 * permalloc() returns a bunch of memory that is never freed.
540 * Memory allocated through tmpalloc() will be released the
541 * next time a function is ended (via tmpfree()).
544 #define MEMCHUNKSZ 8192 /* 8k per allocation */
545 struct balloc {
546 char a1;
547 union {
548 long long l;
549 long double d;
550 } a2;
553 #define ALIGNMENT ((long)&((struct balloc *)0)->a2)
554 #define ROUNDUP(x) (((x) + ((ALIGNMENT)-1)) & ~((ALIGNMENT)-1))
556 static char *allocpole;
557 static int allocleft;
558 int permallocsize, tmpallocsize, lostmem;
560 void *
561 permalloc(int size)
563 void *rv;
565 if (size > MEMCHUNKSZ) {
566 if ((rv = malloc(size)) == NULL)
567 cerror("permalloc: missing %d bytes", size);
568 return rv;
570 if (size <= 0)
571 cerror("permalloc2");
572 if (allocleft < size) {
573 /* looses unused bytes */
574 lostmem += allocleft;
575 if ((allocpole = malloc(MEMCHUNKSZ)) == NULL)
576 cerror("permalloc: out of memory");
577 allocleft = MEMCHUNKSZ;
579 size = ROUNDUP(size);
580 rv = &allocpole[MEMCHUNKSZ-allocleft];
581 allocleft -= size;
582 permallocsize += size;
583 return rv;
586 void *
587 tmpcalloc(int size)
589 void *rv;
591 rv = tmpalloc(size);
592 memset(rv, 0, size);
593 return rv;
597 * Duplicate a string onto the temporary heap.
599 char *
600 tmpstrdup(char *str)
602 int len;
604 len = strlen(str) + 1;
605 return memcpy(tmpalloc(len), str, len);
609 * Allocation routines for temporary memory.
611 #if 0
612 #define ALLDEBUG(x) printf x
613 #else
614 #define ALLDEBUG(x)
615 #endif
617 #define NELEM ((MEMCHUNKSZ-ROUNDUP(sizeof(struct xalloc *)))/ALIGNMENT)
618 #define ELEMSZ (ALIGNMENT)
619 #define MAXSZ (NELEM*ELEMSZ)
620 struct xalloc {
621 struct xalloc *next;
622 union {
623 struct balloc b; /* for initial alignment */
624 char elm[MAXSZ];
625 } u;
626 } *tapole, *tmpole;
627 int uselem = NELEM; /* next unused element */
629 void *
630 tmpalloc(int size)
632 struct xalloc *xp;
633 void *rv;
634 size_t nelem;
636 nelem = ROUNDUP(size)/ELEMSZ;
637 ALLDEBUG(("tmpalloc(%ld,%ld) %d (%zd) ", ELEMSZ, NELEM, size, nelem));
638 if (nelem > NELEM/2) {
639 xp = malloc(size + ROUNDUP(sizeof(struct xalloc *)));
640 if (xp == NULL)
641 cerror("out of memory");
642 ALLDEBUG(("XMEM! (%ld,%p) ",
643 size + ROUNDUP(sizeof(struct xalloc *)), xp));
644 xp->next = tmpole;
645 tmpole = xp;
646 ALLDEBUG(("rv %p\n", &xp->u.elm[0]));
647 return &xp->u.elm[0];
649 if (nelem + uselem >= NELEM) {
650 ALLDEBUG(("MOREMEM! "));
651 /* alloc more */
652 if ((xp = malloc(sizeof(struct xalloc))) == NULL)
653 cerror("out of memory");
654 xp->next = tapole;
655 tapole = xp;
656 uselem = 0;
657 } else
658 xp = tapole;
659 rv = &xp->u.elm[uselem * ELEMSZ];
660 ALLDEBUG(("elemno %d ", uselem));
661 uselem += nelem;
662 ALLDEBUG(("new %d rv %p\n", uselem, rv));
663 return rv;
666 void
667 tmpfree()
669 struct xalloc *x1;
671 while (tmpole) {
672 x1 = tmpole;
673 tmpole = tmpole->next;
674 ALLDEBUG(("XMEM! free %p\n", x1));
675 free(x1);
677 while (tapole && tapole->next) {
678 x1 = tapole;
679 tapole = tapole->next;
680 ALLDEBUG(("MOREMEM! free %p\n", x1));
681 free(x1);
683 if (tapole)
684 uselem = 0;
688 * Set a mark for later removal from the temp heap.
690 void
691 markset(struct mark *m)
693 m->tmsav = tmpole;
694 m->tasav = tapole;
695 m->elem = uselem;
699 * Remove everything on tmp heap from a mark.
701 void
702 markfree(struct mark *m)
704 struct xalloc *x1;
706 while (tmpole != m->tmsav) {
707 x1 = tmpole;
708 tmpole = tmpole->next;
709 free(x1);
711 while (tapole != m->tasav) {
712 x1 = tapole;
713 tapole = tapole->next;
714 free(x1);
716 uselem = m->elem;
720 * Allocate space on the permanent stack for a string of length len+1
721 * and copy it there.
722 * Return the new address.
724 char *
725 newstring(char *s, int len)
727 char *u, *c;
729 len++;
730 if (allocleft < len) {
731 u = c = permalloc(len);
732 } else {
733 u = c = &allocpole[MEMCHUNKSZ-allocleft];
734 allocleft -= ROUNDUP(len+1);
736 while (len--)
737 *c++ = *s++;
738 return u;
742 * Do a preorder walk of the CM list p and apply function f on each element.
744 void
745 flist(NODE *p, void (*f)(NODE *, void *), void *arg)
747 if (p->n_op == CM) {
748 (*f)(p->n_right, arg);
749 flist(p->n_left, f, arg);
750 } else
751 (*f)(p, arg);
755 * The same as flist but postorder.
757 void
758 listf(NODE *p, void (*f)(NODE *))
760 if (p->n_op == CM) {
761 listf(p->n_left, f);
762 (*f)(p->n_right);
763 } else
764 (*f)(p);
768 * Get list argument number n from list, or NIL if out of list.
770 NODE *
771 listarg(NODE *p, int n, int *cnt)
773 NODE *r;
775 if (p->n_op == CM) {
776 r = listarg(p->n_left, n, cnt);
777 if (n == ++(*cnt))
778 r = p->n_right;
779 } else {
780 *cnt = 0;
781 r = n == 0 ? p : NIL;
783 return r;