* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / arch / nova / local.c
blob28c5445dcd6ae12868be008c40320c835089b922
1 /* $Id: local.c,v 1.8 2011/01/21 21:47:58 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.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 # include "pass1.h"
32 /* this file contains code which is dependent on the target machine */
34 NODE *
35 clocal(NODE *p)
37 struct symtab *q;
38 NODE *r, *l;
39 int o;
41 switch( o = p->n_op ){
42 case NAME:
43 /* handle variables */
44 if ((q = p->n_sp) == NULL)
45 return p; /* Nothing to care about */
46 switch (q->sclass) {
47 case AUTO:
48 /* fake up a structure reference */
49 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
50 r->n_lval = 0;
51 r->n_rval = FPREG;
52 p = stref(block(STREF, r, p, 0, 0, 0));
53 break;
54 default:
55 break;
57 break;
59 case PMCONV:
60 case PVCONV:
61 if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0);
62 nfree(p);
63 return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right));
65 case PCONV:
66 l = p->n_left;
67 /* if conversion to another pointer type, just remove */
68 if (p->n_type > BTMASK && l->n_type > BTMASK)
69 goto delp;
70 break;
72 delp: l->n_type = p->n_type;
73 l->n_qual = p->n_qual;
74 l->n_df = p->n_df;
75 l->n_sue = p->n_sue;
76 nfree(p);
77 p = l;
78 break;
81 #if 0
82 register struct symtab *q;
83 register NODE *r, *l;
84 register int o;
85 register int m;
86 TWORD t;
88 //printf("in:\n");
89 //fwalk(p, eprint, 0);
90 switch( o = p->n_op ){
92 case NAME:
93 if ((q = p->n_sp) == NULL)
94 return p; /* Nothing to care about */
96 switch (q->sclass) {
98 case PARAM:
99 case AUTO:
100 /* fake up a structure reference */
101 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
102 r->n_lval = 0;
103 r->n_rval = FPREG;
104 p = stref(block(STREF, r, p, 0, 0, 0));
105 break;
107 case STATIC:
108 if (q->slevel == 0)
109 break;
110 p->n_lval = 0;
111 p->n_sp = q;
112 break;
114 case REGISTER:
115 p->n_op = REG;
116 p->n_lval = 0;
117 p->n_rval = q->soffset;
118 break;
121 break;
123 case STCALL:
124 case CALL:
125 /* Fix function call arguments. On x86, just add funarg */
126 for (r = p->n_right; r->n_op == CM; r = r->n_left) {
127 if (r->n_right->n_op != STARG &&
128 r->n_right->n_op != FUNARG)
129 r->n_right = block(FUNARG, r->n_right, NIL,
130 r->n_right->n_type, r->n_right->n_df,
131 r->n_right->n_sue);
133 if (r->n_op != STARG && r->n_op != FUNARG) {
134 l = talloc();
135 *l = *r;
136 r->n_op = FUNARG; r->n_left = l; r->n_type = l->n_type;
138 break;
140 case CBRANCH:
141 l = p->n_left;
144 * Remove unnecessary conversion ops.
146 if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
147 if (coptype(l->n_op) != BITYPE)
148 break;
149 if (l->n_right->n_op == ICON) {
150 r = l->n_left->n_left;
151 if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
152 break;
153 /* Type must be correct */
154 t = r->n_type;
155 nfree(l->n_left);
156 l->n_left = r;
157 l->n_type = t;
158 l->n_right->n_type = t;
161 break;
163 case PCONV:
164 /* Remove redundant PCONV's. Be careful */
165 l = p->n_left;
166 if (l->n_op == ICON) {
167 l->n_lval = (unsigned)l->n_lval;
168 goto delp;
170 if (l->n_type < INT || l->n_type == LONGLONG ||
171 l->n_type == ULONGLONG) {
172 /* float etc? */
173 p->n_left = block(SCONV, l, NIL,
174 UNSIGNED, 0, MKSUE(UNSIGNED));
175 break;
177 /* if left is SCONV, cannot remove */
178 if (l->n_op == SCONV)
179 break;
180 /* if conversion to another pointer type, just remove */
181 if (p->n_type > BTMASK && l->n_type > BTMASK)
182 goto delp;
183 break;
185 delp: l->n_type = p->n_type;
186 l->n_qual = p->n_qual;
187 l->n_df = p->n_df;
188 l->n_sue = p->n_sue;
189 nfree(p);
190 p = l;
191 break;
193 case SCONV:
194 l = p->n_left;
196 if (p->n_type == l->n_type) {
197 nfree(p);
198 return l;
201 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
202 btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
203 if (p->n_type != FLOAT && p->n_type != DOUBLE &&
204 l->n_type != FLOAT && l->n_type != DOUBLE &&
205 l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
206 if (l->n_op == NAME || l->n_op == UMUL ||
207 l->n_op == TEMP) {
208 l->n_type = p->n_type;
209 nfree(p);
210 return l;
215 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
216 coptype(l->n_op) == BITYPE) {
217 l->n_type = p->n_type;
218 nfree(p);
219 return l;
222 o = l->n_op;
223 m = p->n_type;
225 if (o == ICON) {
226 CONSZ val = l->n_lval;
228 if (!ISPTR(m)) /* Pointers don't need to be conv'd */
229 switch (m) {
230 case CHAR:
231 l->n_lval = (char)val;
232 break;
233 case UCHAR:
234 l->n_lval = val & 0377;
235 break;
236 case SHORT:
237 l->n_lval = (short)val;
238 break;
239 case USHORT:
240 l->n_lval = val & 0177777;
241 break;
242 case ULONG:
243 case UNSIGNED:
244 l->n_lval = val & 0xffffffff;
245 break;
246 case LONG:
247 case INT:
248 l->n_lval = (int)val;
249 break;
250 case LONGLONG:
251 l->n_lval = (long long)val;
252 break;
253 case ULONGLONG:
254 l->n_lval = val;
255 break;
256 case VOID:
257 break;
258 case LDOUBLE:
259 case DOUBLE:
260 case FLOAT:
261 l->n_op = FCON;
262 l->n_dcon = val;
263 break;
264 default:
265 cerror("unknown type %d", m);
267 l->n_type = m;
268 l->n_sue = MKSUE(m);
269 nfree(p);
270 return l;
272 if (DEUNSIGN(p->n_type) == SHORT &&
273 DEUNSIGN(l->n_type) == SHORT) {
274 nfree(p);
275 p = l;
277 if ((p->n_type == CHAR || p->n_type == UCHAR ||
278 p->n_type == SHORT || p->n_type == USHORT) &&
279 (l->n_type == FLOAT || l->n_type == DOUBLE ||
280 l->n_type == LDOUBLE)) {
281 p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue);
282 p->n_left->n_type = INT;
283 return p;
285 break;
287 case MOD:
288 case DIV:
289 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
290 break;
291 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
292 break;
293 /* make it an int division by inserting conversions */
294 p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKSUE(INT));
295 p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKSUE(INT));
296 p = block(SCONV, p, NIL, p->n_type, 0, MKSUE(p->n_type));
297 p->n_left->n_type = INT;
298 break;
300 case PMCONV:
301 case PVCONV:
302 if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0);
303 nfree(p);
304 return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right));
306 case FORCE:
307 /* put return value in return reg */
308 p->n_op = ASSIGN;
309 p->n_right = p->n_left;
310 p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
311 p->n_left->n_rval = RETREG(p->n_type);
312 break;
314 case LS:
315 case RS:
316 /* shift count must be in a char
317 * unless longlong, where it must be int */
318 if (p->n_right->n_op == ICON)
319 break; /* do not do anything */
320 if (p->n_type == LONGLONG || p->n_type == ULONGLONG) {
321 if (p->n_right->n_type != INT)
322 p->n_right = block(SCONV, p->n_right, NIL,
323 INT, 0, MKSUE(INT));
324 break;
326 if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR)
327 break;
328 p->n_right = block(SCONV, p->n_right, NIL,
329 CHAR, 0, MKSUE(CHAR));
330 break;
332 //printf("ut:\n");
333 //fwalk(p, eprint, 0);
335 #endif
337 return(p);
340 void
341 myp2tree(NODE *p)
343 struct symtab *sp;
344 int o = p->n_op, i;
346 if (o != FCON)
347 return;
349 sp = inlalloc(sizeof(struct symtab));
350 sp->sclass = STATIC;
351 sp->ssue = MKSUE(p->n_type);
352 sp->slevel = 1; /* fake numeric label */
353 sp->soffset = getlab();
354 sp->sflags = 0;
355 sp->stype = p->n_type;
356 sp->squal = (CON >> TSHIFT);
358 defloc(sp);
359 ninval(0, sp->ssue->suesize, p);
361 p->n_op = NAME;
362 p->n_lval = 0;
363 p->n_sp = sp;
367 /*ARGSUSED*/
369 andable(NODE *p)
371 return(1); /* all names can have & taken on them */
375 * at the end of the arguments of a ftn, set the automatic offset
377 void
378 cendarg()
380 autooff = AUTOINIT;
384 * Return 1 if a variable of type type is OK to put in register.
387 cisreg(TWORD t)
389 return 1; /* try to put anything in a register */
393 * return a node, for structure references, which is suitable for
394 * being added to a pointer of type t, in order to be off bits offset
395 * into a structure
396 * t, d, and s are the type, dimension offset, and sizeoffset
397 * For nova, return the type-specific index number which calculation
398 * is based on its size. For example, char a[3] would return 3.
399 * Be careful about only handling first-level pointers, the following
400 * indirections must be fullword.
402 NODE *
403 offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
405 register NODE *p;
407 if (xdebug)
408 printf("offcon: OFFSZ %ld type %x dim %p siz %d\n",
409 off, t, d, sue->suesize);
411 p = bcon(0);
412 p->n_lval = off/SZINT; /* Default */
413 if (ISPTR(DECREF(t)))
414 return p;
415 if (t == VOID || t == CHAR || t == UCHAR)
416 p->n_lval = off/SZCHAR; /* pointer to char */
417 return(p);
421 * Allocate off bits on the stack. p is a tree that when evaluated
422 * is the multiply count for off, t is a NAME node where to write
423 * the allocated address.
425 void
426 spalloc(NODE *t, NODE *p, OFFSZ off)
428 NODE *sp;
430 cerror("spalloc");
431 if ((off % SZINT) == 0)
432 p = buildtree(MUL, p, bcon(off/SZINT));
433 else if ((off % SZSHORT) == 0) {
434 p = buildtree(MUL, p, bcon(off/SZSHORT));
435 p = buildtree(PLUS, p, bcon(1));
436 p = buildtree(RS, p, bcon(1));
437 } else if ((off % SZCHAR) == 0) {
438 p = buildtree(MUL, p, bcon(off/SZCHAR));
439 p = buildtree(PLUS, p, bcon(3));
440 p = buildtree(RS, p, bcon(2));
441 } else
442 cerror("roundsp");
444 /* save the address of sp */
445 sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue);
446 sp->n_lval = 0;
447 sp->n_rval = STKREG;
448 t->n_type = sp->n_type;
449 ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
451 /* add the size to sp */
452 sp = block(REG, NIL, NIL, p->n_type, 0, 0);
453 sp->n_lval = 0;
454 sp->n_rval = STKREG;
455 ecomp(buildtree(PLUSEQ, sp, p));
459 * print out a constant node
460 * mat be associated with a label
462 void
463 ninval(NODE *p)
465 struct symtab *q;
466 TWORD t;
468 p = p->n_left;
469 t = p->n_type;
470 if (t > BTMASK)
471 t = INT; /* pointer */
473 if (p->n_op != ICON)
474 cerror("ninval: init node not constant");
476 switch (t) {
477 case LONG:
478 case ULONG:
479 inval(p->n_lval & 0xffff);
480 inval(p->n_lval >> 16);
481 break;
482 case INT:
483 case UNSIGNED:
484 printf("\t.word 0%o", (short)p->n_lval);
485 if ((q = p->n_sp) != NULL) {
486 if ((q->sclass == STATIC && q->slevel > 0)) {
487 printf("+" LABFMT, q->soffset);
488 } else
489 printf("+%s", exname(q->soname));
491 printf("\n");
492 break;
493 default:
494 cerror("ninval");
499 * print out an integer.
501 void
502 inval(CONSZ word)
504 word &= 0xffff;
505 printf(" .word 0%o\n", (int)word);
508 /* output code to initialize a floating point value */
509 /* the proper alignment has been obtained */
510 void
511 finval(NODE *p)
513 union { float f; double d; long double l; int i[3]; } u;
515 cerror("finval");
516 switch (p->n_type) {
517 case LDOUBLE:
518 u.i[2] = 0;
519 u.l = (long double)p->n_dcon;
520 printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]);
521 break;
522 case DOUBLE:
523 u.d = (double)p->n_dcon;
524 printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]);
525 break;
526 case FLOAT:
527 u.f = (float)p->n_dcon;
528 printf("\t.long\t0x%x\n", u.i[0]);
529 break;
533 /* make a name look like an external name in the local machine */
534 char *
535 exname(char *p)
537 if (p == NULL)
538 return "";
539 return p;
543 * map types which are not defined on the local machine
545 TWORD
546 ctype(TWORD type)
548 switch (BTYPE(type)) {
549 case LONGLONG:
550 MODTYPE(type,LONG);
551 break;
553 case ULONGLONG:
554 MODTYPE(type,ULONG);
555 break;
556 case SHORT:
557 MODTYPE(type,INT);
558 break;
559 case USHORT:
560 MODTYPE(type,UNSIGNED);
561 break;
563 return (type);
566 /* curid is a variable which is defined but
567 * is not initialized (and not a function );
568 * This routine returns the storage class for an uninitialized declaration
571 noinit()
573 return(EXTERN);
576 void
577 calldec(NODE *p, NODE *q)
581 void
582 extdec(struct symtab *q)
586 /* make a common declaration for id, if reasonable */
587 void
588 commdec(struct symtab *q)
590 int off;
592 off = tsize(q->stype, q->sdf, q->ssue);
593 off = (off+(SZCHAR-1))/SZCHAR;
594 printf(" .comm %s,0%o\n", exname(q->soname), off);
597 /* make a local common declaration for id, if reasonable */
598 void
599 lcommdec(struct symtab *q)
601 int off;
603 off = tsize(q->stype, q->sdf, q->ssue);
604 off = (off+(SZCHAR-1))/SZCHAR;
605 if (q->slevel == 0)
606 printf(" .lcomm %s,0%o\n", exname(q->soname), off);
607 else
608 printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
612 * print a (non-prog) label.
614 void
615 deflab1(int label)
617 printf(LABFMT ":\n", label);
620 static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" };
622 void
623 setloc1(int locc)
625 if (locc == lastloc)
626 return;
627 lastloc = locc;
628 printf(" .%s\n", loctbl[locc]);
631 * Give target the opportunity of handling pragmas.
634 mypragma(char *str)
636 return 0;
640 * Called when a identifier has been declared, to give target last word.
642 void
643 fixdef(struct symtab *sp)
647 void
648 pass1_lastchance(struct interpass *ip)