1 /* Id: local.c,v 1.33 2015/01/07 05:20:48 gmcgarry Exp */
2 /* $NetBSD: local.c,v 1.1.1.6 2016/02/09 20:28:11 plunky Exp $ */
3 /*
4 * Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org).
5 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
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 * We define location operations which operate on the expression tree
31 * during the first pass (before sending to the backend for code generation.)
32 */
33
34 #include <assert.h>
35
36 #include "pass1.h"
37
38 extern void defalign(int);
39
40 /*
41 * clocal() is called to do local transformations on
42 * an expression tree before being sent to the backend.
43 */
44 NODE *
clocal(NODE * p)45 clocal(NODE *p)
46 {
47 struct symtab *q;
48 NODE *l, *r, *t;
49 int o;
50 int ty;
51 int tmpnr, isptrvoid = 0;
52 char *n;
53
54 o = p->n_op;
55 switch (o) {
56
57 case STASG:
58
59 l = p->n_left;
60 r = p->n_right;
61 if (r->n_op != STCALL && r->n_op != USTCALL)
62 return p;
63
64 /* assign left node as first argument to function */
65 nfree(p);
66 t = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_ap);
67 l->n_rval = R0;
68 l = buildtree(ADDROF, l, NIL);
69 l = buildtree(ASSIGN, t, l);
70
71 if (r->n_right->n_op != CM) {
72 r->n_right = block(CM, l, r->n_right, INT, 0, 0);
73 } else {
74 for (t = r->n_right; t->n_left->n_op == CM;
75 t = t->n_left)
76 ;
77 t->n_left = block(CM, l, t->n_left, INT, 0, 0);
78 }
79 return r;
80
81 case CALL:
82 case STCALL:
83 case USTCALL:
84 if (p->n_type == VOID)
85 break;
86 /*
87 * if the function returns void*, ecode() invokes
88 * delvoid() to convert it to uchar*.
89 * We just let this happen on the ASSIGN to the temp,
90 * and cast the pointer back to void* on access
91 * from the temp.
92 */
93 if (p->n_type == PTR+VOID)
94 isptrvoid = 1;
95 r = tempnode(0, p->n_type, p->n_df, p->n_ap);
96 tmpnr = regno(r);
97 r = block(ASSIGN, r, p, p->n_type, p->n_df, p->n_ap);
98
99 p = tempnode(tmpnr, r->n_type, r->n_df, r->n_ap);
100 if (isptrvoid) {
101 p = block(PCONV, p, NIL, PTR+VOID, p->n_df, 0);
102 }
103 p = buildtree(COMOP, r, p);
104 break;
105
106 case NAME:
107 if ((q = p->n_sp) == NULL)
108 return p;
109 if (blevel == 0)
110 return p;
111
112 switch (q->sclass) {
113 case PARAM:
114 case AUTO:
115 /* fake up a structure reference */
116 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
117 r->n_lval = 0;
118 r->n_rval = FPREG;
119 p = stref(block(STREF, r, p, 0, 0, 0));
120 break;
121 case REGISTER:
122 p->n_op = REG;
123 p->n_lval = 0;
124 p->n_rval = q->soffset;
125 break;
126 case STATIC:
127 if (q->slevel > 0) {
128 p->n_lval = 0;
129 p->n_sp = q;
130 }
131 /* FALL-THROUGH */
132 default:
133 ty = p->n_type;
134 n = p->n_sp->soname ? p->n_sp->soname : p->n_sp->sname;
135 if (strncmp(n, "__builtin", 9) == 0)
136 break;
137 p = block(ADDROF, p, NIL, INCREF(ty), p->n_df, p->n_ap);
138 p = block(UMUL, p, NIL, ty, p->n_df, p->n_ap);
139 break;
140 }
141 break;
142
143 case STNAME:
144 if ((q = p->n_sp) == NULL)
145 return p;
146 if (q->sclass != STNAME)
147 return p;
148 ty = p->n_type;
149 p = block(ADDROF, p, NIL, INCREF(ty),
150 p->n_df, p->n_ap);
151 p = block(UMUL, p, NIL, ty, p->n_df, p->n_ap);
152 break;
153
154 case FORCE:
155 /* put return value in return reg */
156 p->n_op = ASSIGN;
157 p->n_right = p->n_left;
158 p->n_left = block(REG, NIL, NIL, p->n_type, 0, 0);
159 p->n_left->n_rval = p->n_left->n_type == BOOL ?
160 RETREG(BOOL_TYPE) : RETREG(p->n_type);
161 break;
162
163 case SCONV:
164 l = p->n_left;
165 if (p->n_type == l->n_type) {
166 nfree(p);
167 return l;
168 }
169 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
170 tsize(p->n_type, p->n_df, p->n_ap) == tsize(l->n_type, l->n_df, l->n_ap)) {
171 if (p->n_type != FLOAT && p->n_type != DOUBLE &&
172 l->n_type != FLOAT && l->n_type != DOUBLE &&
173 l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
174 if (l->n_op == NAME || l->n_op == UMUL ||
175 l->n_op == TEMP) {
176 l->n_type = p->n_type;
177 nfree(p);
178 return l;
179 }
180 }
181 }
182
183 if (l->n_op == ICON) {
184 CONSZ val = l->n_lval;
185
186 if (!ISPTR(p->n_type)) /* Pointers don't need to be conv'd */
187 switch (p->n_type) {
188 case BOOL:
189 l->n_lval = l->n_lval != 0;
190 break;
191 case CHAR:
192 l->n_lval = (char)val;
193 break;
194 case UCHAR:
195 l->n_lval = val & 0377;
196 break;
197 case SHORT:
198 l->n_lval = (short)val;
199 break;
200 case USHORT:
201 l->n_lval = val & 0177777;
202 break;
203 case ULONG:
204 case UNSIGNED:
205 l->n_lval = val & 0xffffffff;
206 break;
207 case LONG:
208 case INT:
209 l->n_lval = (int)val;
210 break;
211 case LONGLONG:
212 l->n_lval = (long long)val;
213 break;
214 case ULONGLONG:
215 l->n_lval = val;
216 break;
217 case VOID:
218 break;
219 case LDOUBLE:
220 case DOUBLE:
221 case FLOAT:
222 l->n_op = FCON;
223 l->n_dcon = val;
224 break;
225 default:
226 cerror("unknown type %d", l->n_type);
227 }
228 l->n_type = p->n_type;
229 l->n_ap = 0;
230 nfree(p);
231 return l;
232 } else if (p->n_op == FCON) {
233 l->n_lval = l->n_dcon;
234 l->n_sp = NULL;
235 l->n_op = ICON;
236 l->n_type = p->n_type;
237 l->n_ap = 0;
238 nfree(p);
239 return clocal(l);
240 }
241 if ((DEUNSIGN(p->n_type) == CHAR ||
242 DEUNSIGN(p->n_type) == SHORT) &&
243 (l->n_type == FLOAT || l->n_type == DOUBLE ||
244 l->n_type == LDOUBLE)) {
245 p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap);
246 p->n_left->n_type = INT;
247 return p;
248 }
249 break;
250
251 case PCONV:
252 l = p->n_left;
253 if (l->n_op == ICON) {
254 l->n_lval = (unsigned)l->n_lval;
255 goto delp;
256 }
257 if (l->n_type < INT || DEUNSIGN(l->n_type) == LONGLONG) {
258 p->n_left = block(SCONV, l, NIL, UNSIGNED, 0, 0);
259 break;
260 }
261 if (l->n_op == SCONV)
262 break;
263 if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
264 goto delp;
265 if (p->n_type > BTMASK && l->n_type > BTMASK)
266 goto delp;
267 break;
268
269 delp:
270 l->n_type = p->n_type;
271 l->n_qual = p->n_qual;
272 l->n_df = p->n_df;
273 l->n_ap = p->n_ap;
274 nfree(p);
275 p = l;
276 break;
277 }
278
279 return p;
280 }
281
282 /*
283 * Called before sending the tree to the backend.
284 */
285 void
myp2tree(NODE * p)286 myp2tree(NODE *p)
287 {
288 struct symtab *sp;
289
290 if (p->n_op != FCON)
291 return;
292
293 #define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz))
294
295 sp = IALLOC(sizeof(struct symtab));
296 sp->sclass = STATIC;
297 sp->sap = 0;
298 sp->slevel = 1; /* fake numeric label */
299 sp->soffset = getlab();
300 sp->sflags = 0;
301 sp->stype = p->n_type;
302 sp->squal = (CON >> TSHIFT);
303
304 defloc(sp);
305 ninval(0, tsize(sp->stype, sp->sdf, sp->sap), p);
306
307 p->n_op = NAME;
308 p->n_lval = 0;
309 p->n_sp = sp;
310 }
311
312 /*
313 * Called during the first pass to determine if a NAME can be addressed.
314 *
315 * Return nonzero if supported, otherwise return 0.
316 */
317 int
andable(NODE * p)318 andable(NODE *p)
319 {
320 if (blevel == 0)
321 return 1;
322 if (ISFTN(p->n_type))
323 return 1;
324 return 0;
325 }
326
327 /*
328 * Return 1 if a variable of type 't' is OK to put in register.
329 */
330 int
cisreg(TWORD t)331 cisreg(TWORD t)
332 {
333 if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
334 return 0; /* not yet */
335 return 1;
336 }
337
338 /*
339 * Allocate bits from the stack for dynamic-sized arrays.
340 *
341 * 'p' is the tree which represents the type being allocated.
342 * 'off' is the number of 'p's to be allocated.
343 * 't' is the storeable node where the address is written.
344 */
345 void
spalloc(NODE * t,NODE * p,OFFSZ off)346 spalloc(NODE *t, NODE *p, OFFSZ off)
347 {
348 NODE *sp;
349
350 p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */
351
352 /* sub the size from sp */
353 sp = block(REG, NIL, NIL, p->n_type, 0, 0);
354 sp->n_lval = 0;
355 sp->n_rval = SP;
356 ecomp(buildtree(MINUSEQ, sp, p));
357
358 /* save the address of sp */
359 sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_ap);
360 sp->n_lval = 0;
361 sp->n_rval = SP;
362 t->n_type = sp->n_type;
363 ecomp(buildtree(ASSIGN, t, sp));
364 }
365
366 /*
367 * Print an integer constant node, may be associated with a label.
368 * Do not free the node after use.
369 * 'off' is bit offset from the beginning of the aggregate
370 * 'fsz' is the number of bits this is referring to
371 */
372 int
ninval(CONSZ off,int fsz,NODE * p)373 ninval(CONSZ off, int fsz, NODE *p)
374 {
375 union { float f; double d; int i[2]; } u;
376 struct symtab *q;
377 TWORD t;
378 int i, j;
379
380 t = p->n_type;
381 if (t > BTMASK)
382 t = p->n_type = INT; /* pointer */
383
384 if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
385 uerror("element not constant");
386
387 switch (t) {
388 case LONGLONG:
389 case ULONGLONG:
390 i = (p->n_lval >> 32);
391 j = (p->n_lval & 0xffffffff);
392 p->n_type = INT;
393 if (features(FEATURE_BIGENDIAN)) {
394 p->n_lval = i;
395 ninval(off+32, 32, p);
396 p->n_lval = j;
397 ninval(off, 32, p);
398 } else {
399 p->n_lval = j;
400 ninval(off, 32, p);
401 p->n_lval = i;
402 ninval(off+32, 32, p);
403 }
404 break;
405 case INT:
406 case UNSIGNED:
407 printf("\t.word 0x%x", (int)p->n_lval);
408 if ((q = p->n_sp) != NULL) {
409 if ((q->sclass == STATIC && q->slevel > 0)) {
410 printf("+" LABFMT, q->soffset);
411 } else
412 printf("+%s",
413 q->soname ? q->soname : exname(q->sname));
414 }
415 printf("\n");
416 break;
417 case LDOUBLE:
418 case DOUBLE:
419 u.d = (double)p->n_dcon;
420 #if defined(HOST_BIG_ENDIAN)
421 if (features(FEATURE_BIGENDIAN))
422 #else
423 if (!features(FEATURE_BIGENDIAN))
424 #endif
425 printf("\t.word\t0x%x\n\t.word\t0x%x\n",
426 u.i[0], u.i[1]);
427 else
428 printf("\t.word\t0x%x\n\t.word\t0x%x\n",
429 u.i[1], u.i[0]);
430 break;
431 case FLOAT:
432 u.f = (float)p->n_dcon;
433 printf("\t.word\t0x%x\n", u.i[0]);
434 break;
435 default:
436 return 0;
437 }
438 return 1;
439 }
440
441 /*
442 * Prefix a leading underscore to a global variable (if necessary).
443 */
444 char *
exname(char * p)445 exname(char *p)
446 {
447 return (p == NULL ? "" : p);
448 }
449
450 /*
451 * Map types which are not defined on the local machine.
452 */
453 TWORD
ctype(TWORD type)454 ctype(TWORD type)
455 {
456 switch (BTYPE(type)) {
457 case LONG:
458 MODTYPE(type,INT);
459 break;
460 case ULONG:
461 MODTYPE(type,UNSIGNED);
462 break;
463 }
464 return (type);
465 }
466
467 /*
468 * Before calling a function do any tree re-writing for the local machine.
469 *
470 * 'p' is the function tree (NAME)
471 * 'q' is the CM-separated list of arguments.
472 */
473 void
calldec(NODE * p,NODE * q)474 calldec(NODE *p, NODE *q)
475 {
476 }
477
478 /*
479 * While handling uninitialised variables, handle variables marked extern.
480 */
481 void
extdec(struct symtab * q)482 extdec(struct symtab *q)
483 {
484 }
485
486 /* make a common declaration for id, if reasonable */
487 void
defzero(struct symtab * sp)488 defzero(struct symtab *sp)
489 {
490 int off;
491
492 off = tsize(sp->stype, sp->sdf, sp->sap);
493 off = (off+(SZCHAR-1))/SZCHAR;
494 printf(" .%scomm ", sp->sclass == STATIC ? "l" : "");
495 if (sp->slevel == 0)
496 printf("%s,0%o\n",
497 sp->soname ? sp->soname : exname(sp->sname), off);
498 else
499 printf(LABFMT ",0%o\n", sp->soffset, off);
500 }
501
502 /*
503 * va_start(ap, last) implementation.
504 *
505 * f is the NAME node for this builtin function.
506 * a is the argument list containing:
507 * CM
508 * ap last
509 */
510 NODE *
arm_builtin_stdarg_start(const struct bitable * bt,NODE * a)511 arm_builtin_stdarg_start(const struct bitable *bt, NODE *a)
512 {
513 NODE *p, *q;
514 int sz = 1;
515
516 /* check num args and type */
517 if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
518 !ISPTR(a->n_left->n_type))
519 goto bad;
520
521 /* must first deal with argument size; use int size */
522 p = a->n_right;
523 if (p->n_type < INT) {
524 /* round up to word */
525 sz = SZINT / tsize(p->n_type, p->n_df, p->n_ap);
526 }
527
528 p = buildtree(ADDROF, p, NIL); /* address of last arg */
529 p = optim(buildtree(PLUS, p, bcon(sz)));
530 q = block(NAME, NIL, NIL, PTR+VOID, 0, 0);
531 q = buildtree(CAST, q, p);
532 p = q->n_right;
533 nfree(q->n_left);
534 nfree(q);
535 p = buildtree(ASSIGN, a->n_left, p);
536 nfree(a);
537
538 return p;
539
540 bad:
541 uerror("bad argument to __builtin_stdarg_start");
542 return bcon(0);
543 }
544
545 NODE *
arm_builtin_va_arg(const struct bitable * bt,NODE * a)546 arm_builtin_va_arg(const struct bitable *bt, NODE *a)
547 {
548 NODE *p, *q, *r;
549 int sz, tmpnr;
550
551 /* check num args and type */
552 if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
553 !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE)
554 goto bad;
555
556 r = a->n_right;
557
558 /* get type size */
559 sz = tsize(r->n_type, r->n_df, r->n_ap) / SZCHAR;
560 if (sz < SZINT/SZCHAR) {
561 werror("%s%s promoted to int when passed through ...",
562 ISUNSIGNED(r->n_type) ? "unsigned " : "",
563 DEUNSIGN(r->n_type) == SHORT ? "short" : "char");
564 sz = SZINT/SZCHAR;
565 }
566
567 /* alignment */
568 p = tcopy(a->n_left);
569 if (sz > SZINT/SZCHAR && r->n_type != UNIONTY && r->n_type != STRTY) {
570 p = buildtree(PLUS, p, bcon(ALSTACK/8 - 1));
571 p = block(AND, p, bcon(-ALSTACK/8), p->n_type, p->n_df, p->n_ap);
572 }
573
574 /* create a copy to a temp node */
575 q = tempnode(0, p->n_type, p->n_df, p->n_ap);
576 tmpnr = regno(q);
577 p = buildtree(ASSIGN, q, p);
578
579 q = tempnode(tmpnr, p->n_type, p->n_df,p->n_ap);
580 q = buildtree(PLUS, q, bcon(sz));
581 q = buildtree(ASSIGN, a->n_left, q);
582
583 q = buildtree(COMOP, p, q);
584
585 nfree(a->n_right);
586 nfree(a);
587
588 p = tempnode(tmpnr, INCREF(r->n_type), r->n_df, r->n_ap);
589 p = buildtree(UMUL, p, NIL);
590 p = buildtree(COMOP, q, p);
591
592 return p;
593
594 bad:
595 uerror("bad argument to __builtin_va_arg");
596 return bcon(0);
597 }
598
599 NODE *
arm_builtin_va_end(const struct bitable * bt,NODE * a)600 arm_builtin_va_end(const struct bitable *bt, NODE *a)
601 {
602 tfree(a);
603
604 return bcon(0);
605 }
606
607 NODE *
arm_builtin_va_copy(const struct bitable * bt,NODE * a)608 arm_builtin_va_copy(const struct bitable *bt, NODE *a)
609 {
610 NODE *f;
611
612 if (a == NULL || a->n_op != CM || a->n_left->n_op == CM)
613 goto bad;
614 f = buildtree(ASSIGN, a->n_left, a->n_right);
615 nfree(a);
616 return f;
617
618 bad:
619 uerror("bad argument to __buildtin_va_copy");
620 return bcon(0);
621 }
622
623 char *nextsect;
624 static int constructor;
625 static int destructor;
626
627 /*
628 * Give target the opportunity of handling pragmas.
629 */
630 int
mypragma(char * str)631 mypragma(char *str)
632 {
633 char *a2 = pragtok(NULL);
634
635 if (strcmp(str, "tls") == 0) {
636 uerror("thread-local storage not supported for this target");
637 return 1;
638 }
639 if (strcmp(str, "constructor") == 0 || strcmp(str, "init") == 0) {
640 constructor = 1;
641 return 1;
642 }
643 if (strcmp(str, "destructor") == 0 || strcmp(str, "fini") == 0) {
644 destructor = 1;
645 return 1;
646 }
647 if (strcmp(str, "section") == 0 && a2 != NULL) {
648 nextsect = newstring(a2, strlen(a2));
649 return 1;
650 }
651
652 return 0;
653 }
654
655 /*
656 * Called when a identifier has been declared, to give target last word.
657 */
658 void
fixdef(struct symtab * sp)659 fixdef(struct symtab *sp)
660 {
661 if ((constructor || destructor) && (sp->sclass != PARAM)) {
662 printf("\t.section .%ctors,\"aw\",@progbits\n",
663 constructor ? 'c' : 'd');
664 printf("\t.p2align 2\n");
665 printf("\t.long %s\n", exname(sp->sname));
666 printf("\t.previous\n");
667 constructor = destructor = 0;
668 }
669 }
670
671 void
pass1_lastchance(struct interpass * ip)672 pass1_lastchance(struct interpass *ip)
673 {
674 }
675