source: mainline/uspace/app/pcc/arch/pdp11/local.c@ a7de7182

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a7de7182 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.3 KB
Line 
1/* $Id: local.c,v 1.7 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
34/* clocal() is called to do local transformations on
35 * an expression tree preparitory to its being
36 * written out in intermediate code.
37 *
38 * the major essential job is rewriting the
39 * automatic variables and arguments in terms of
40 * REG and OREG nodes
41 * conversion ops which are not necessary are also clobbered here
42 * in addition, any special features (such as rewriting
43 * exclusive or) are easily handled here as well
44 */
45NODE *
46clocal(NODE *p)
47{
48
49 register struct symtab *q;
50 register NODE *r, *l;
51 register int o;
52 int m;
53
54#ifdef PCC_DEBUG
55 if (xdebug) {
56 printf("clocal: %p\n", p);
57 fwalk(p, eprint, 0);
58 }
59#endif
60 switch( o = p->n_op ){
61
62 case NAME:
63 if ((q = p->n_sp) == NULL)
64 return p; /* Nothing to care about */
65
66 switch (q->sclass) {
67
68 case PARAM:
69 case AUTO:
70 /* fake up a structure reference */
71 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
72 r->n_lval = 0;
73 r->n_rval = FPREG;
74 p = stref(block(STREF, r, p, 0, 0, 0));
75 break;
76
77 case STATIC:
78 if (q->slevel == 0)
79 break;
80 p->n_lval = 0;
81 break;
82
83 case REGISTER:
84 p->n_op = REG;
85 p->n_lval = 0;
86 p->n_rval = q->soffset;
87 break;
88
89 case EXTERN:
90 case EXTDEF:
91 break;
92 }
93 break;
94
95 case PCONV:
96 /* Remove redundant PCONV's. Be careful */
97 l = p->n_left;
98 if (l->n_op == ICON) {
99 l->n_lval = (unsigned)l->n_lval;
100 goto delp;
101 }
102 if (l->n_type < INT || l->n_type == LONGLONG ||
103 l->n_type == ULONGLONG) {
104 /* float etc? */
105 p->n_left = block(SCONV, l, NIL,
106 UNSIGNED, 0, MKSUE(UNSIGNED));
107 break;
108 }
109 /* if left is SCONV, cannot remove */
110 if (l->n_op == SCONV)
111 break;
112
113 /* avoid ADDROF TEMP */
114 if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
115 break;
116
117 /* if conversion to another pointer type, just remove */
118 if (p->n_type > BTMASK && l->n_type > BTMASK)
119 goto delp;
120 break;
121
122 delp: l->n_type = p->n_type;
123 l->n_qual = p->n_qual;
124 l->n_df = p->n_df;
125 l->n_sue = p->n_sue;
126 nfree(p);
127 p = l;
128 break;
129
130 case SCONV:
131 l = p->n_left;
132
133#if 0
134 if (p->n_type == l->n_type) {
135 nfree(p);
136 return l;
137 }
138
139 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
140 btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
141 if (p->n_type != FLOAT && p->n_type != DOUBLE &&
142 l->n_type != FLOAT && l->n_type != DOUBLE &&
143 l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
144 if (l->n_op == NAME || l->n_op == UMUL ||
145 l->n_op == TEMP) {
146 l->n_type = p->n_type;
147 nfree(p);
148 return l;
149 }
150 }
151 }
152
153 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
154 coptype(l->n_op) == BITYPE) {
155 l->n_type = p->n_type;
156 nfree(p);
157 return l;
158 }
159#endif
160 o = l->n_op;
161 m = p->n_type;
162
163 if (o == ICON) {
164 CONSZ val = l->n_lval;
165
166 if (!ISPTR(m)) /* Pointers don't need to be conv'd */
167 switch (m) {
168 case BOOL:
169 l->n_lval = l->n_lval != 0;
170 break;
171 case CHAR:
172 l->n_lval = (char)val;
173 break;
174 case UCHAR:
175 l->n_lval = val & 0377;
176 break;
177 case INT:
178 l->n_lval = (short)val;
179 break;
180 case UNSIGNED:
181 l->n_lval = val & 0177777;
182 break;
183 case ULONG:
184 l->n_lval = val & 0xffffffff;
185 break;
186 case LONG:
187 l->n_lval = (long)val;
188 break;
189 case LONGLONG:
190 l->n_lval = (long long)val;
191 break;
192 case ULONGLONG:
193 l->n_lval = val;
194 break;
195 case VOID:
196 break;
197 case LDOUBLE:
198 case DOUBLE:
199 case FLOAT:
200 l->n_op = FCON;
201 l->n_dcon = FLOAT_CAST(val, l->n_type);
202 break;
203 default:
204 cerror("unknown type %d", m);
205 }
206 l->n_type = m;
207 l->n_sue = MKSUE(m);
208 nfree(p);
209 return l;
210 } else if (l->n_op == FCON) {
211 l->n_lval = FLOAT_VAL(l->n_dcon);
212 l->n_sp = NULL;
213 l->n_op = ICON;
214 l->n_type = m;
215 l->n_sue = MKSUE(m);
216 nfree(p);
217 return clocal(l);
218 }
219 if (DEUNSIGN(p->n_type) == INT &&
220 DEUNSIGN(l->n_type) == INT) {
221 nfree(p);
222 p = l;
223 }
224 break;
225
226 case CBRANCH:
227 l = p->n_left;
228 if (coptype(l->n_op) != BITYPE)
229 break;
230 if (l->n_left->n_op != SCONV || l->n_right->n_op != ICON)
231 break;
232 if ((r = l->n_left->n_left)->n_type > INT)
233 break;
234 /* compare with constant without casting */
235 nfree(l->n_left);
236 l->n_left = r;
237 l->n_right->n_type = l->n_left->n_type;
238 break;
239
240 case STASG: /* struct assignment, modify left */
241 l = p->n_left;
242 if (l->n_type == STRTY)
243 p->n_left = buildtree(ADDROF, l, NIL);
244 break;
245
246 case PMCONV:
247 case PVCONV:
248 r = p;
249 p = buildtree(o == PMCONV ? MUL : DIV, p->n_left, p->n_right);
250 nfree(r);
251 break;
252
253 case FORCE:
254 /* put return value in return reg */
255 p->n_op = ASSIGN;
256 p->n_right = p->n_left;
257 p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
258 p->n_left->n_rval = p->n_left->n_type == BOOL ?
259 RETREG(CHAR) : RETREG(p->n_type);
260 break;
261
262 }
263#ifdef PCC_DEBUG
264 if (xdebug) {
265 printf("clocal end: %p\n", p);
266 fwalk(p, eprint, 0);
267 }
268#endif
269 return(p);
270}
271
272void
273myp2tree(NODE *p)
274{
275 struct symtab *sp;
276
277 if (p->n_op != FCON)
278 return;
279
280 sp = inlalloc(sizeof(struct symtab));
281 sp->sclass = STATIC;
282 sp->ssue = MKSUE(p->n_type);
283 sp->slevel = 1; /* fake numeric label */
284 sp->soffset = getlab();
285 sp->sflags = 0;
286 sp->stype = p->n_type;
287 sp->squal = (CON >> TSHIFT);
288
289 defloc(sp);
290 ninval(0, sp->ssue->suesize, p);
291
292 p->n_op = NAME;
293 p->n_lval = 0;
294 p->n_sp = sp;
295}
296
297/*ARGSUSED*/
298int
299andable(NODE *p)
300{
301 return(1); /* all names can have & taken on them */
302}
303
304/*
305 * at the end of the arguments of a ftn, set the automatic offset
306 */
307void
308cendarg()
309{
310 autooff = AUTOINIT;
311}
312
313/*
314 * Return 1 if a variable of type type is OK to put in register.
315 */
316int
317cisreg(TWORD t)
318{
319 if (t == FLOAT || t == DOUBLE || t == LDOUBLE ||
320 t == LONGLONG || t == ULONGLONG)
321 return 0; /* not yet */
322 return 1;
323}
324
325/*
326 * return a node, for structure references, which is suitable for
327 * being added to a pointer of type t, in order to be off bits offset
328 * into a structure
329 * t, d, and s are the type, dimension offset, and sizeoffset
330 * For pdp10, return the type-specific index number which calculation
331 * is based on its size. For example, short a[3] would return 3.
332 * Be careful about only handling first-level pointers, the following
333 * indirections must be fullword.
334 */
335NODE *
336offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
337{
338 register NODE *p;
339
340 if (xdebug)
341 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
342 off, t, d, sue->suesize);
343
344 p = bcon(0);
345 p->n_lval = off/SZCHAR; /* Default */
346 return(p);
347}
348
349/*
350 * Allocate off bits on the stack. p is a tree that when evaluated
351 * is the multiply count for off, t is a storeable node where to write
352 * the allocated address.
353 */
354void
355spalloc(NODE *t, NODE *p, OFFSZ off)
356{
357 NODE *sp;
358
359 p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */
360
361 /* sub the size from sp */
362 sp = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
363 sp->n_lval = 0;
364 sp->n_rval = STKREG;
365 ecomp(buildtree(MINUSEQ, sp, p));
366
367 /* save the address of sp */
368 sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue);
369 sp->n_lval = 0;
370 sp->n_rval = STKREG;
371 t->n_type = sp->n_type;
372 ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
373
374}
375
376/*
377 * Print out a string of characters.
378 * Assume that the assembler understands C-style escape
379 * sequences.
380 */
381void
382instring(struct symtab *sp)
383{
384 char *s;
385 int val, cnt;
386
387 defloc(sp);
388
389 for (cnt = 0, s = sp->sname; *s != 0; ) {
390 if (cnt++ == 0)
391 printf(".byte ");
392 if (*s++ == '\\')
393 val = esccon(&s);
394 else
395 val = s[-1];
396 printf("%o", val & 0377);
397 if (cnt > 15) {
398 cnt = 0;
399 printf("\n");
400 } else
401 printf(",");
402 }
403 printf("%s0\n", cnt ? "" : ".byte ");
404}
405
406static int inbits, inval;
407
408/*
409 * set fsz bits in sequence to zero.
410 */
411void
412zbits(OFFSZ off, int fsz)
413{
414 int m;
415
416 if (idebug)
417 printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits);
418 if ((m = (inbits % SZCHAR))) {
419 m = SZCHAR - m;
420 if (fsz < m) {
421 inbits += fsz;
422 return;
423 } else {
424 fsz -= m;
425 printf("\t.byte %d\n", inval);
426 inval = inbits = 0;
427 }
428 }
429 if (fsz >= SZCHAR) {
430 printf(".=.+%o\n", fsz/SZCHAR);
431 fsz -= (fsz/SZCHAR) * SZCHAR;
432 }
433 if (fsz) {
434 inval = 0;
435 inbits = fsz;
436 }
437}
438
439/*
440 * Initialize a bitfield.
441 */
442void
443infld(CONSZ off, int fsz, CONSZ val)
444{
445 if (idebug)
446 printf("infld off %lld, fsz %d, val %lld inbits %d\n",
447 off, fsz, val, inbits);
448 val &= ((CONSZ)1 << fsz)-1;
449 while (fsz + inbits >= SZCHAR) {
450 inval |= (val << inbits);
451 printf("\t.byte %d\n", inval & 255);
452 fsz -= (SZCHAR - inbits);
453 val >>= (SZCHAR - inbits);
454 inval = inbits = 0;
455 }
456 if (fsz) {
457 inval |= (val << inbits);
458 inbits += fsz;
459 }
460}
461
462/*
463 * print out a constant node, may be associated with a label.
464 * Do not free the node after use.
465 * off is bit offset from the beginning of the aggregate
466 * fsz is the number of bits this is referring to
467 */
468void
469ninval(CONSZ off, int fsz, NODE *p)
470{
471#ifdef __pdp11__
472 union { float f; double d; short s[4]; int i[2]; } u;
473#endif
474 struct symtab *q;
475 TWORD t;
476 int i;
477
478 t = p->n_type;
479 if (t > BTMASK)
480 t = INT; /* pointer */
481
482 while (p->n_op == SCONV || p->n_op == PCONV) {
483 NODE *l = p->n_left;
484 l->n_type = p->n_type;
485 p = l;
486 }
487
488 if (p->n_op != ICON && p->n_op != FCON)
489 cerror("ninval: init node not constant");
490
491 if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
492 uerror("element not constant");
493
494 switch (t) {
495 case LONGLONG:
496 case ULONGLONG:
497 i = (p->n_lval >> 32);
498 p->n_lval &= 0xffffffff;
499 p->n_type = INT;
500 ninval(off, 32, p);
501 p->n_lval = i;
502 ninval(off+32, 32, p);
503 break;
504 case LONG:
505 case ULONG:
506 printf("%o ; %o\n", (int)((p->n_lval >> 16) & 0177777),
507 (int)(p->n_lval & 0177777));
508 break;
509 case INT:
510 case UNSIGNED:
511 printf("%o", (int)(p->n_lval & 0177777));
512 if ((q = p->n_sp) != NULL) {
513 if ((q->sclass == STATIC && q->slevel > 0)) {
514 printf("+" LABFMT, q->soffset);
515 } else {
516 printf("+%s", q->soname ? q->soname : exname(q->sname));
517 }
518 }
519 printf("\n");
520 break;
521 case BOOL:
522 if (p->n_lval > 1)
523 p->n_lval = p->n_lval != 0;
524 /* FALLTHROUGH */
525 case CHAR:
526 case UCHAR:
527 printf("\t.byte %o\n", (int)p->n_lval & 0xff);
528 break;
529#ifdef __pdp11__
530 case FLOAT:
531 u.f = (float)p->n_dcon;
532 printf("%o ; %o\n", u.i[0], u.i[1]);
533 break;
534 case LDOUBLE:
535 case DOUBLE:
536 u.d = (double)p->n_dcon;
537 printf("%o ; %o ; %o ; %o\n", u.i[0], u.i[1], u.i[2], u.i[3]);
538 break;
539#else
540 /* cross-compiling */
541 case FLOAT:
542 printf("%o ; %o\n", p->n_dcon.fd1, p->n_dcon.fd2);
543 break;
544 case LDOUBLE:
545 case DOUBLE:
546 printf("%o ; %o ; %o ; %o\n", p->n_dcon.fd1, p->n_dcon.fd2,
547 p->n_dcon.fd3, p->n_dcon.fd4);
548 break;
549#endif
550 default:
551 cerror("ninval");
552 }
553}
554
555/* make a name look like an external name in the local machine */
556char *
557exname(char *p)
558{
559#define NCHNAM 256
560 static char text[NCHNAM+1];
561 int i;
562
563 if (p == NULL)
564 return "";
565
566 text[0] = '_';
567 for (i=1; *p && i<NCHNAM; ++i)
568 text[i] = *p++;
569
570 text[i] = '\0';
571 text[NCHNAM] = '\0'; /* truncate */
572
573 return (text);
574
575}
576
577/*
578 * map types which are not defined on the local machine
579 */
580TWORD
581ctype(TWORD type)
582{
583 switch (BTYPE(type)) {
584 case SHORT:
585 MODTYPE(type,INT);
586 break;
587
588 case USHORT:
589 MODTYPE(type,UNSIGNED);
590 break;
591
592 case LDOUBLE:
593 MODTYPE(type,DOUBLE);
594 break;
595
596 }
597 return (type);
598}
599
600void
601calldec(NODE *p, NODE *q)
602{
603}
604
605void
606extdec(struct symtab *q)
607{
608}
609
610/* make a common declaration for id, if reasonable */
611void
612defzero(struct symtab *sp)
613{
614 extern int lastloc;
615 char *n;
616 int off;
617
618 off = tsize(sp->stype, sp->sdf, sp->ssue);
619 off = (off+(SZCHAR-1))/SZCHAR;
620 n = sp->soname ? sp->soname : exname(sp->sname);
621 if (sp->sclass == STATIC) {
622 printf(".bss\n");
623 if (sp->slevel == 0)
624 printf("%s:", n);
625 else
626 printf(LABFMT ":", sp->soffset);
627 printf(" .=.+%o\n", off);
628 lastloc = -1;
629 return;
630 }
631 printf(".comm ");
632 if (sp->slevel == 0)
633 printf("%s,0%o\n", n, off);
634 else
635 printf(LABFMT ",0%o\n", sp->soffset, off);
636}
637
638/*
639 * Give target the opportunity of handling pragmas.
640 */
641int
642mypragma(char *str)
643{
644 return 0;
645}
646
647/*
648 * Called when a identifier has been declared.
649 */
650void
651fixdef(struct symtab *sp)
652{
653}
654
655void
656pass1_lastchance(struct interpass *ip)
657{
658}
Note: See TracBrowser for help on using the repository browser.