source: mainline/uspace/app/pcc/arch/m16c/local.c@ 2568c94

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2568c94 was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

  • Property mode set to 100644
File size: 10.4 KB
Line 
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.
5 *
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
16 *
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.
27 */
28
29
30# include "pass1.h"
31
32/* this file contains code which is dependent on the target machine */
33
34NODE *
35clocal(NODE *p)
36{
37 /* this is called to do local transformations on
38 an expression tree preparitory to its being
39 written out in intermediate code.
40 */
41
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 */
48
49 struct symtab *q;
50 NODE *l, *r;
51 int o;
52 TWORD ml;
53
54 switch( o = p->n_op ){
55
56 case NAME:
57 if ((q = p->n_sp) == NULL)
58 return p; /* Nothing to care about */
59
60 switch (q->sclass) {
61
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;
70
71 case STATIC:
72 if (q->slevel == 0)
73 break;
74 p->n_lval = 0;
75 p->n_sp = q;
76 break;
77
78 case REGISTER:
79 p->n_op = REG;
80 p->n_lval = 0;
81 p->n_rval = q->soffset;
82 break;
83
84 }
85 break;
86
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));
92
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;
105
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;
111 }
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);
147 }
148 l->n_type = p->n_type;
149 nfree(p);
150 return l;
151 }
152 break;
153
154
155 }
156
157 return(p);
158}
159
160/*ARGSUSED*/
161int
162andable(NODE *p)
163{
164 return(1); /* all names can have & taken on them */
165}
166
167/*
168 * at the end of the arguments of a ftn, set the automatic offset
169 */
170void
171cendarg()
172{
173 autooff = AUTOINIT;
174}
175
176/*
177 * is an automatic variable of type t OK for a register variable
178 */
179int
180cisreg(TWORD t)
181{
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 */
186}
187
188/*
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.
197 */
198NODE *
199offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
200{
201 register NODE *p;
202
203 if (xdebug)
204 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
205 off, t, d, sue->suesize);
206
207 p = bcon(0);
208 p->n_lval = off/SZCHAR; /* Default */
209 return(p);
210}
211
212/*
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.
216 */
217void
218spalloc(NODE *t, NODE *p, OFFSZ off)
219{
220 NODE *sp;
221
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");
234
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! */
241
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));
247}
248
249/*
250 * print out a constant node
251 * mat be associated with a label
252 */
253void
254ninval(NODE *p)
255{
256 struct symtab *q;
257 TWORD t;
258
259 p = p->n_left;
260 t = p->n_type;
261 if (t > BTMASK)
262 t = INT; /* pointer */
263
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));
280 }
281 printf("\n");
282 break;
283 default:
284 fwalk(p, eprint, 0);
285 cerror("ninval");
286 }
287}
288
289/*
290 * print out an integer.
291 */
292void
293inval(CONSZ word)
294{
295 word &= 0xffffffff;
296 printf(" .long 0x%llx\n", word);
297}
298
299/* output code to initialize a floating point value */
300/* the proper alignment has been obtained */
301void
302finval(NODE *p)
303{
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;
314 }
315}
316
317/* make a name look like an external name in the local machine */
318char *
319exname(char *p)
320{
321 if (p == NULL)
322 return "";
323 return p;
324}
325
326/*
327 * map types which are not defined on the local machine
328 */
329TWORD
330ctype(TWORD type)
331{
332 switch (BTYPE(type)) {
333 case SHORT:
334 MODTYPE(type,INT);
335 break;
336
337 case USHORT:
338 MODTYPE(type,UNSIGNED);
339 break;
340
341 case LONGLONG:
342 MODTYPE(type,LONG);
343 break;
344
345 case ULONGLONG:
346 MODTYPE(type,ULONG);
347 break;
348
349 case LDOUBLE:
350 MODTYPE(type,DOUBLE);
351 break;
352 }
353 return (type);
354}
355
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
359 */
360int
361noinit()
362{
363 return(EXTERN);
364}
365
366/*
367 * Extern variable not necessary common.
368 */
369void
370extdec(struct symtab *q)
371{
372 extern void addsym(struct symtab *);
373 addsym(q);
374}
375
376/*
377 * Call to a function
378 */
379void
380calldec(NODE *p, NODE *r)
381{
382 struct symtab *q = p->n_sp;
383 extern void addsym(struct symtab *);
384 addsym(q);
385}
386
387/* make a common declaration for id, if reasonable */
388void
389commdec(struct symtab *q)
390{
391 int off;
392 char *c = q->soname;
393
394 off = tsize(q->stype, q->sdf, q->ssue);
395 off = (off+(SZCHAR-1))/SZCHAR;
396
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");
403}
404
405/* make a local common declaration for id, if reasonable */
406void
407lcommdec(struct symtab *q)
408{
409 int off;
410
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);
417}
418
419/*
420 * print a (non-prog) label.
421 */
422void
423deflab1(int label)
424{
425 printf(LABFMT ":\n", label);
426}
427
428void
429setloc1(int locc)
430{
431 if (locc == lastloc)
432 return;
433 lastloc = locc;
434}
435
436/*
437 * special handling before tree is written out.
438 */
439void
440myp2tree(NODE *p)
441{
442 struct symtab *sp;
443 union dimfun *df;
444 union arglist *al;
445 NODE *q;
446 int i;
447
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;
456 }
457 break;
458
459 case CALL:
460 case STCALL:
461 /*
462 * inform pass2 about varargs.
463 * store first variadic argument number in n_stalign
464 * in the CM node.
465 */
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;
473 }
474 p->n_right->n_stalign = al->type == TELLIPSIS ? i : 0;
475 } else
476 p->n_right->n_stalign = 0;
477 break;
478
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);
489
490 defloc(sp);
491 ninval(0, sp->ssue->suesize, p);
492
493 p->n_op = NAME;
494 p->n_lval = 0;
495 p->n_sp = sp;
496 break;
497 }
498
499}
500/*
501 * Give target the opportunity of handling pragmas.
502 */
503int
504mypragma(char **ary)
505{
506 return 0; }
507
508/*
509 * Called when a identifier has been declared, to give target last word.
510 */
511void
512fixdef(struct symtab *sp)
513{
514}
515
516void
517pass1_lastchance(struct interpass *ip)
518{
519}
Note: See TracBrowser for help on using the repository browser.