* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / arch / m16c / local.c
blobf9d15e03a96eb54602e918761b5ea6505597f463
1 /* $Id: local.c,v 1.15 2008/12/14 21:16: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 /* this is called to do local transformations on
38 an expression tree preparitory to its being
39 written out in intermediate code.
42 /* the major essential job is rewriting the
43 automatic variables and arguments in terms of
44 REG and OREG nodes */
45 /* conversion ops which are not necessary are also clobbered here */
46 /* in addition, any special features (such as rewriting
47 exclusive or) are easily handled here as well */
49 struct symtab *q;
50 NODE *l, *r;
51 int o;
52 TWORD ml;
54 switch( o = p->n_op ){
56 case NAME:
57 if ((q = p->n_sp) == NULL)
58 return p; /* Nothing to care about */
60 switch (q->sclass) {
62 case PARAM:
63 case AUTO:
64 /* fake up a structure reference */
65 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
66 r->n_lval = 0;
67 r->n_rval = FPREG;
68 p = stref(block(STREF, r, p, 0, 0, 0));
69 break;
71 case STATIC:
72 if (q->slevel == 0)
73 break;
74 p->n_lval = 0;
75 p->n_sp = q;
76 break;
78 case REGISTER:
79 p->n_op = REG;
80 p->n_lval = 0;
81 p->n_rval = q->soffset;
82 break;
85 break;
87 case PMCONV:
88 case PVCONV:
89 if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0);
90 nfree(p);
91 return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right));
93 case PCONV:
94 ml = p->n_left->n_type;
95 l = p->n_left;
96 if ((ml == CHAR || ml == UCHAR) && l->n_op != ICON)
97 break;
98 l->n_type = p->n_type;
99 l->n_qual = p->n_qual;
100 l->n_df = p->n_df;
101 l->n_sue = p->n_sue;
102 nfree(p);
103 p = l;
104 break;
106 case SCONV:
107 l = p->n_left;
108 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT) {
109 nfree(p);
110 return l;
112 if (l->n_op == ICON) {
113 CONSZ val = l->n_lval;
114 switch (p->n_type) {
115 case CHAR:
116 l->n_lval = (char)val;
117 break;
118 case UCHAR:
119 l->n_lval = val & 0377;
120 break;
121 case SHORT:
122 case INT:
123 l->n_lval = (short)val;
124 break;
125 case USHORT:
126 case UNSIGNED:
127 l->n_lval = val & 0177777;
128 break;
129 case ULONG:
130 case ULONGLONG:
131 l->n_lval = val & 0xffffffff;
132 break;
133 case LONG:
134 case LONGLONG:
135 l->n_lval = (int)val;
136 break;
137 case VOID:
138 break;
139 case LDOUBLE:
140 case DOUBLE:
141 case FLOAT:
142 l->n_op = FCON;
143 l->n_dcon = val;
144 break;
145 default:
146 cerror("unknown type %d", p->n_type);
148 l->n_type = p->n_type;
149 nfree(p);
150 return l;
152 break;
157 return(p);
160 /*ARGSUSED*/
162 andable(NODE *p)
164 return(1); /* all names can have & taken on them */
168 * at the end of the arguments of a ftn, set the automatic offset
170 void
171 cendarg()
173 autooff = AUTOINIT;
177 * is an automatic variable of type t OK for a register variable
180 cisreg(TWORD t)
182 if (t == INT || t == UNSIGNED || t == CHAR || t == UCHAR ||
183 ISPTR(t))
184 return(1);
185 return 0; /* XXX - fix reg assignment in pftn.c */
189 * return a node, for structure references, which is suitable for
190 * being added to a pointer of type t, in order to be off bits offset
191 * into a structure
192 * t, d, and s are the type, dimension offset, and sizeoffset
193 * For pdp10, return the type-specific index number which calculation
194 * is based on its size. For example, short a[3] would return 3.
195 * Be careful about only handling first-level pointers, the following
196 * indirections must be fullword.
198 NODE *
199 offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
201 register NODE *p;
203 if (xdebug)
204 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
205 off, t, d, sue->suesize);
207 p = bcon(0);
208 p->n_lval = off/SZCHAR; /* Default */
209 return(p);
213 * Allocate off bits on the stack. p is a tree that when evaluated
214 * is the multiply count for off, t is a NAME node where to write
215 * the allocated address.
217 void
218 spalloc(NODE *t, NODE *p, OFFSZ off)
220 NODE *sp;
222 if ((off % SZINT) == 0)
223 p = buildtree(MUL, p, bcon(off/SZINT));
224 else if ((off % SZSHORT) == 0) {
225 p = buildtree(MUL, p, bcon(off/SZSHORT));
226 p = buildtree(PLUS, p, bcon(1));
227 p = buildtree(RS, p, bcon(1));
228 } else if ((off % SZCHAR) == 0) {
229 p = buildtree(MUL, p, bcon(off/SZCHAR));
230 p = buildtree(PLUS, p, bcon(3));
231 p = buildtree(RS, p, bcon(2));
232 } else
233 cerror("roundsp");
235 /* save the address of sp */
236 sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue);
237 sp->n_lval = 0;
238 sp->n_rval = STKREG;
239 t->n_type = sp->n_type;
240 ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
242 /* add the size to sp */
243 sp = block(REG, NIL, NIL, p->n_type, 0, 0);
244 sp->n_lval = 0;
245 sp->n_rval = STKREG;
246 ecomp(buildtree(PLUSEQ, sp, p));
250 * print out a constant node
251 * mat be associated with a label
253 void
254 ninval(NODE *p)
256 struct symtab *q;
257 TWORD t;
259 p = p->n_left;
260 t = p->n_type;
261 if (t > BTMASK)
262 t = INT; /* pointer */
264 switch (t) {
265 case LONGLONG:
266 case ULONGLONG:
267 inval(p->n_lval & 0xffffffff);
268 inval(p->n_lval >> 32);
269 break;
270 case LONG:
271 case ULONG:
272 case INT:
273 case UNSIGNED:
274 printf("\t.long 0x%x", (int)p->n_lval);
275 if ((q = p->n_sp) != NULL) {
276 if ((q->sclass == STATIC && q->slevel > 0)) {
277 printf("+" LABFMT, q->soffset);
278 } else
279 printf("+%s", exname(q->soname));
281 printf("\n");
282 break;
283 default:
284 fwalk(p, eprint, 0);
285 cerror("ninval");
290 * print out an integer.
292 void
293 inval(CONSZ word)
295 word &= 0xffffffff;
296 printf(" .long 0x%llx\n", word);
299 /* output code to initialize a floating point value */
300 /* the proper alignment has been obtained */
301 void
302 finval(NODE *p)
304 switch (p->n_type) {
305 case LDOUBLE:
306 printf("\t.tfloat\t0t%.20Le\n", p->n_dcon);
307 break;
308 case DOUBLE:
309 printf("\t.dfloat\t0d%.20e\n", (double)p->n_dcon);
310 break;
311 case FLOAT:
312 printf("\t.ffloat\t0f%.20e\n", (float)p->n_dcon);
313 break;
317 /* make a name look like an external name in the local machine */
318 char *
319 exname(char *p)
321 if (p == NULL)
322 return "";
323 return p;
327 * map types which are not defined on the local machine
329 TWORD
330 ctype(TWORD type)
332 switch (BTYPE(type)) {
333 case SHORT:
334 MODTYPE(type,INT);
335 break;
337 case USHORT:
338 MODTYPE(type,UNSIGNED);
339 break;
341 case LONGLONG:
342 MODTYPE(type,LONG);
343 break;
345 case ULONGLONG:
346 MODTYPE(type,ULONG);
347 break;
349 case LDOUBLE:
350 MODTYPE(type,DOUBLE);
351 break;
353 return (type);
356 /* curid is a variable which is defined but
357 * is not initialized (and not a function );
358 * This routine returns the storage class for an uninitialized declaration
361 noinit()
363 return(EXTERN);
367 * Extern variable not necessary common.
369 void
370 extdec(struct symtab *q)
372 extern void addsym(struct symtab *);
373 addsym(q);
377 * Call to a function
379 void
380 calldec(NODE *p, NODE *r)
382 struct symtab *q = p->n_sp;
383 extern void addsym(struct symtab *);
384 addsym(q);
387 /* make a common declaration for id, if reasonable */
388 void
389 commdec(struct symtab *q)
391 int off;
392 char *c = q->soname;
394 off = tsize(q->stype, q->sdf, q->ssue);
395 off = (off+(SZCHAR-1))/SZCHAR;
397 printf(" PUBLIC %s\n", c);
398 /* XXX - NOROOT??? */
399 printf(" RSEG DATA16_Z:NEARDATA:SORT:NOROOT(1)\n");
400 printf("%s:\n", c);
401 printf(" DS8 %d\n", off);
402 printf(" REQUIRE __data16_zero\n");
405 /* make a local common declaration for id, if reasonable */
406 void
407 lcommdec(struct symtab *q)
409 int off;
411 off = tsize(q->stype, q->sdf, q->ssue);
412 off = (off+(SZCHAR-1))/SZCHAR;
413 if (q->slevel == 0)
414 printf(" .lcomm %s,0%o\n", exname(q->soname), off);
415 else
416 printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
420 * print a (non-prog) label.
422 void
423 deflab1(int label)
425 printf(LABFMT ":\n", label);
428 void
429 setloc1(int locc)
431 if (locc == lastloc)
432 return;
433 lastloc = locc;
437 * special handling before tree is written out.
439 void
440 myp2tree(NODE *p)
442 struct symtab *sp;
443 union dimfun *df;
444 union arglist *al;
445 NODE *q;
446 int i;
448 switch (p->n_op) {
449 case MOD:
450 case DIV:
451 if (p->n_type == LONG || p->n_type == ULONG) {
452 /* Swap arguments for hardops() later */
453 q = p->n_left;
454 p->n_left = p->n_right;
455 p->n_right = q;
457 break;
459 case CALL:
460 case STCALL:
462 * inform pass2 about varargs.
463 * store first variadic argument number in n_stalign
464 * in the CM node.
466 if (p->n_right->n_op != CM)
467 break; /* nothing to care about */
468 df = p->n_left->n_df;
469 if (df && (al = df->dfun)) {
470 for (i = 0; i < 6; i++, al++) {
471 if (al->type == TELLIPSIS || al->type == TNULL)
472 break;
474 p->n_right->n_stalign = al->type == TELLIPSIS ? i : 0;
475 } else
476 p->n_right->n_stalign = 0;
477 break;
479 case FCON:
480 /* Write float constants to memory */
481 sp = inlalloc(sizeof(struct symtab));
482 sp->sclass = STATIC;
483 sp->ssue = MKSUE(p->n_type);
484 sp->slevel = 1; /* fake numeric label */
485 sp->soffset = getlab();
486 sp->sflags = 0;
487 sp->stype = p->n_type;
488 sp->squal = (CON >> TSHIFT);
490 defloc(sp);
491 ninval(0, sp->ssue->suesize, p);
493 p->n_op = NAME;
494 p->n_lval = 0;
495 p->n_sp = sp;
496 break;
501 * Give target the opportunity of handling pragmas.
504 mypragma(char **ary)
506 return 0; }
509 * Called when a identifier has been declared, to give target last word.
511 void
512 fixdef(struct symtab *sp)
516 void
517 pass1_lastchance(struct interpass *ip)