source: mainline/uspace/app/pcc/arch/nova/local.c@ 6037308

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6037308 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: 13.7 KB
Line 
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.
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 struct symtab *q;
38 NODE *r, *l;
39 int o;
40
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;
56 }
57 break;
58
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));
64
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;
71
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;
79 }
80
81#if 0
82 register struct symtab *q;
83 register NODE *r, *l;
84 register int o;
85 register int m;
86 TWORD t;
87
88//printf("in:\n");
89//fwalk(p, eprint, 0);
90 switch( o = p->n_op ){
91
92 case NAME:
93 if ((q = p->n_sp) == NULL)
94 return p; /* Nothing to care about */
95
96 switch (q->sclass) {
97
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;
106
107 case STATIC:
108 if (q->slevel == 0)
109 break;
110 p->n_lval = 0;
111 p->n_sp = q;
112 break;
113
114 case REGISTER:
115 p->n_op = REG;
116 p->n_lval = 0;
117 p->n_rval = q->soffset;
118 break;
119
120 }
121 break;
122
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);
132 }
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;
137 }
138 break;
139
140 case CBRANCH:
141 l = p->n_left;
142
143 /*
144 * Remove unnecessary conversion ops.
145 */
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;
159 }
160 }
161 break;
162
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;
169 }
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;
176 }
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;
184
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;
192
193 case SCONV:
194 l = p->n_left;
195
196 if (p->n_type == l->n_type) {
197 nfree(p);
198 return l;
199 }
200
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;
211 }
212 }
213 }
214
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;
220 }
221
222 o = l->n_op;
223 m = p->n_type;
224
225 if (o == ICON) {
226 CONSZ val = l->n_lval;
227
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);
266 }
267 l->n_type = m;
268 l->n_sue = MKSUE(m);
269 nfree(p);
270 return l;
271 }
272 if (DEUNSIGN(p->n_type) == SHORT &&
273 DEUNSIGN(l->n_type) == SHORT) {
274 nfree(p);
275 p = l;
276 }
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;
284 }
285 break;
286
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;
299
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));
305
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;
313
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;
325 }
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;
331 }
332//printf("ut:\n");
333//fwalk(p, eprint, 0);
334
335#endif
336
337 return(p);
338}
339
340void
341myp2tree(NODE *p)
342{
343 struct symtab *sp;
344 int o = p->n_op, i;
345
346 if (o != FCON)
347 return;
348
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);
357
358 defloc(sp);
359 ninval(0, sp->ssue->suesize, p);
360
361 p->n_op = NAME;
362 p->n_lval = 0;
363 p->n_sp = sp;
364
365}
366
367/*ARGSUSED*/
368int
369andable(NODE *p)
370{
371 return(1); /* all names can have & taken on them */
372}
373
374/*
375 * at the end of the arguments of a ftn, set the automatic offset
376 */
377void
378cendarg()
379{
380 autooff = AUTOINIT;
381}
382
383/*
384 * Return 1 if a variable of type type is OK to put in register.
385 */
386int
387cisreg(TWORD t)
388{
389 return 1; /* try to put anything in a register */
390}
391
392/*
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.
401 */
402NODE *
403offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
404{
405 register NODE *p;
406
407 if (xdebug)
408 printf("offcon: OFFSZ %ld type %x dim %p siz %d\n",
409 off, t, d, sue->suesize);
410
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);
418}
419
420/*
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.
424 */
425void
426spalloc(NODE *t, NODE *p, OFFSZ off)
427{
428 NODE *sp;
429
430cerror("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");
443
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! */
450
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));
456}
457
458/*
459 * print out a constant node
460 * mat be associated with a label
461 */
462void
463ninval(NODE *p)
464{
465 struct symtab *q;
466 TWORD t;
467
468 p = p->n_left;
469 t = p->n_type;
470 if (t > BTMASK)
471 t = INT; /* pointer */
472
473 if (p->n_op != ICON)
474 cerror("ninval: init node not constant");
475
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));
490 }
491 printf("\n");
492 break;
493 default:
494 cerror("ninval");
495 }
496}
497
498/*
499 * print out an integer.
500 */
501void
502inval(CONSZ word)
503{
504 word &= 0xffff;
505 printf(" .word 0%o\n", (int)word);
506}
507
508/* output code to initialize a floating point value */
509/* the proper alignment has been obtained */
510void
511finval(NODE *p)
512{
513 union { float f; double d; long double l; int i[3]; } u;
514
515cerror("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;
530 }
531}
532
533/* make a name look like an external name in the local machine */
534char *
535exname(char *p)
536{
537 if (p == NULL)
538 return "";
539 return p;
540}
541
542/*
543 * map types which are not defined on the local machine
544 */
545TWORD
546ctype(TWORD type)
547{
548 switch (BTYPE(type)) {
549 case LONGLONG:
550 MODTYPE(type,LONG);
551 break;
552
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;
562 }
563 return (type);
564}
565
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
569 */
570int
571noinit()
572{
573 return(EXTERN);
574}
575
576void
577calldec(NODE *p, NODE *q)
578{
579}
580
581void
582extdec(struct symtab *q)
583{
584}
585
586/* make a common declaration for id, if reasonable */
587void
588commdec(struct symtab *q)
589{
590 int off;
591
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);
595}
596
597/* make a local common declaration for id, if reasonable */
598void
599lcommdec(struct symtab *q)
600{
601 int off;
602
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);
609}
610
611/*
612 * print a (non-prog) label.
613 */
614void
615deflab1(int label)
616{
617 printf(LABFMT ":\n", label);
618}
619
620static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" };
621
622void
623setloc1(int locc)
624{
625 if (locc == lastloc)
626 return;
627 lastloc = locc;
628 printf(" .%s\n", loctbl[locc]);
629}
630/*
631 * Give target the opportunity of handling pragmas.
632 */
633int
634mypragma(char *str)
635{
636 return 0;
637}
638
639/*
640 * Called when a identifier has been declared, to give target last word.
641 */
642void
643fixdef(struct symtab *sp)
644{
645}
646
647void
648pass1_lastchance(struct interpass *ip)
649{
650}
Note: See TracBrowser for help on using the repository browser.