1 /* $Id: local.c,v 1.183 2014/09/29 16:15:38 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 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27
28 #include "pass1.h"
29
30 /* this file contains code which is dependent on the target machine */
31
32 #ifdef notyet
33 /*
34 * Check if a constant is too large for a type.
35 */
36 static int
toolarge(TWORD t,CONSZ con)37 toolarge(TWORD t, CONSZ con)
38 {
39 U_CONSZ ucon = con;
40
41 switch (t) {
42 case ULONGLONG:
43 case LONGLONG:
44 break; /* cannot be too large */
45 #define SCHK(i) case i: if (con > MAX_##i || con < MIN_##i) return 1; break
46 #define UCHK(i) case i: if (ucon > MAX_##i) return 1; break
47 SCHK(INT);
48 SCHK(SHORT);
49 case BOOL:
50 SCHK(CHAR);
51 UCHK(UNSIGNED);
52 UCHK(USHORT);
53 UCHK(UCHAR);
54 default:
55 cerror("toolarge");
56 }
57 return 0;
58 }
59 #endif
60
61 #if defined(MACHOABI)
62
63 /*
64 * Keep track of PIC stubs.
65 */
66
67 void
addstub(struct stub * list,char * name)68 addstub(struct stub *list, char *name)
69 {
70 struct stub *s;
71
72 DLIST_FOREACH(s, list, link) {
73 if (strcmp(s->name, name) == 0)
74 return;
75 }
76
77 s = permalloc(sizeof(struct stub));
78 s->name = newstring(name, strlen(name));
79 DLIST_INSERT_BEFORE(list, s, link);
80 }
81
82 #endif
83
84 #define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz))
85
86 /*
87 * Make a symtab entry for PIC use.
88 */
89 static struct symtab *
picsymtab(char * p,char * s,char * s2)90 picsymtab(char *p, char *s, char *s2)
91 {
92 struct symtab *sp = IALLOC(sizeof(struct symtab));
93 size_t len = strlen(p) + strlen(s) + strlen(s2) + 1;
94
95 sp->sname = sp->soname = IALLOC(len);
96 strlcpy(sp->soname, p, len);
97 strlcat(sp->soname, s, len);
98 strlcat(sp->soname, s2, len);
99 sp->sap = NULL;
100 sp->sclass = EXTERN;
101 sp->sflags = sp->slevel = 0;
102 sp->stype = 0xdeadbeef;
103 return sp;
104 }
105
106 #ifdef os_win32
107 static NODE *
import(NODE * p)108 import(NODE *p)
109 {
110 NODE *q;
111 char *name;
112 struct symtab *sp;
113
114 if ((name = p->n_sp->soname) == NULL)
115 name = exname(p->n_sp->sname);
116
117 sp = picsymtab("__imp_", name, "");
118 q = xbcon(0, sp, PTR+VOID);
119 q = block(UMUL, q, 0, PTR|VOID, 0, 0);
120 q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
121 q->n_sp = p->n_sp; /* for init */
122 nfree(p);
123
124 return q;
125 }
126 #endif
127
128 int gotnr; /* tempnum for GOT register */
129 int argstacksize;
130
131 /*
132 * Create a reference for an extern variable.
133 */
134 static NODE *
picext(NODE * p)135 picext(NODE *p)
136 {
137
138 #if defined(ELFABI)
139
140 struct attr *ga;
141 NODE *q, *r;
142 struct symtab *sp;
143 char *name;
144
145 q = tempnode(gotnr, PTR|VOID, 0, 0);
146 if ((name = p->n_sp->soname) == NULL)
147 name = p->n_sp->sname;
148
149 if ((ga = attr_find(p->n_sp->sap, GCC_ATYP_VISIBILITY)) &&
150 strcmp(ga->sarg(0), "hidden") == 0) {
151 /* For hidden vars use GOTOFF */
152 sp = picsymtab("", name, "@GOTOFF");
153 r = xbcon(0, sp, INT);
154 q = buildtree(PLUS, q, r);
155 q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
156 q->n_sp = p->n_sp; /* for init */
157 nfree(p);
158 return q;
159 }
160
161 sp = picsymtab("", name, "@GOT");
162 #ifdef GCC_COMPAT
163 if (attr_find(p->n_sp->sap, GCC_ATYP_STDCALL) != NULL)
164 p->n_sp->sflags |= SSTDCALL;
165 #endif
166 sp->sflags = p->n_sp->sflags & SSTDCALL;
167 r = xbcon(0, sp, INT);
168 q = buildtree(PLUS, q, r);
169 q = block(UMUL, q, 0, PTR|VOID, 0, 0);
170 q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
171 q->n_sp = p->n_sp; /* for init */
172 nfree(p);
173 return q;
174
175 #elif defined(MACHOABI)
176
177 NODE *q, *r;
178 struct symtab *sp;
179 char buf2[256], *name, *pspn;
180
181 if ((name = cftnsp->soname) == NULL)
182 name = cftnsp->sname;
183 if ((pspn = p->n_sp->soname) == NULL)
184 pspn = exname(p->n_sp->sname);
185 if (p->n_sp->sclass == EXTDEF) {
186 snprintf(buf2, 256, "-L%s$pb", name);
187 sp = picsymtab("", pspn, buf2);
188 } else {
189 snprintf(buf2, 256, "$non_lazy_ptr-L%s$pb", name);
190 sp = picsymtab("L", pspn, buf2);
191 addstub(&nlplist, pspn);
192 }
193
194 sp->stype = p->n_sp->stype;
195
196 q = tempnode(gotnr, PTR+VOID, 0, 0);
197 r = xbcon(0, sp, INT);
198 q = buildtree(PLUS, q, r);
199
200 if (p->n_sp->sclass != EXTDEF)
201 q = block(UMUL, q, 0, PTR+VOID, 0, 0);
202 q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
203 q->n_sp = p->n_sp; /* for init */
204 nfree(p);
205 return q;
206
207 #else /* defined(PECOFFABI) || defined(AOUTABI) */
208
209 return p;
210
211 #endif
212
213 }
214
215 /*
216 * Create a reference for a static variable.
217 */
218 static NODE *
picstatic(NODE * p)219 picstatic(NODE *p)
220 {
221
222 #if defined(ELFABI)
223
224 NODE *q, *r;
225 struct symtab *sp;
226
227 q = tempnode(gotnr, PTR|VOID, 0, 0);
228 if (p->n_sp->slevel > 0) {
229 char buf[32];
230 snprintf(buf, 32, LABFMT, (int)p->n_sp->soffset);
231 sp = picsymtab("", buf, "@GOTOFF");
232 } else {
233 char *name;
234 if ((name = p->n_sp->soname) == NULL)
235 name = p->n_sp->sname;
236 sp = picsymtab("", name, "@GOTOFF");
237 }
238
239 sp->sclass = STATIC;
240 sp->stype = p->n_sp->stype;
241 r = xbcon(0, sp, INT);
242 q = buildtree(PLUS, q, r);
243 q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
244 q->n_sp = p->n_sp; /* for init */
245 nfree(p);
246 return q;
247
248 #elif defined(MACHOABI)
249
250 NODE *q, *r;
251 struct symtab *sp;
252 char buf2[256];
253
254 snprintf(buf2, 256, "-L%s$pb",
255 cftnsp->soname ? cftnsp->soname : cftnsp->sname);
256
257 if (p->n_sp->slevel > 0) {
258 char buf1[32];
259 snprintf(buf1, 32, LABFMT, (int)p->n_sp->soffset);
260 sp = picsymtab("", buf1, buf2);
261 } else {
262 char *name;
263 if ((name = p->n_sp->soname) == NULL)
264 name = p->n_sp->sname;
265 sp = picsymtab("", exname(name), buf2);
266 }
267 sp->sclass = STATIC;
268 sp->stype = p->n_sp->stype;
269 q = tempnode(gotnr, PTR+VOID, 0, 0);
270 r = xbcon(0, sp, INT);
271 q = buildtree(PLUS, q, r);
272 q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
273 q->n_sp = p->n_sp;
274 nfree(p);
275 return q;
276
277 #else /* defined(PECOFFABI) || defined(AOUTABI) */
278
279 return p;
280
281 #endif
282
283 }
284
285 #ifdef TLS
286 /*
287 * Create a reference for a TLS variable.
288 */
289 static NODE *
tlspic(NODE * p)290 tlspic(NODE *p)
291 {
292 NODE *q, *r;
293 struct symtab *sp, *sp2;
294 char *name;
295
296 /*
297 * creates:
298 * leal var@TLSGD(%ebx),%eax
299 * call ___tls_get_addr@PLT
300 */
301
302 /* calc address of var@TLSGD */
303 q = tempnode(gotnr, PTR|VOID, 0, 0);
304 if ((name = p->n_sp->soname) == NULL)
305 name = p->n_sp->sname;
306 sp = picsymtab("", name, "@TLSGD");
307 r = xbcon(0, sp, INT);
308 q = buildtree(PLUS, q, r);
309
310 /* assign to %eax */
311 r = block(REG, NIL, NIL, PTR|VOID, 0, 0);
312 r->n_rval = EAX;
313 q = buildtree(ASSIGN, r, q);
314
315 /* call ___tls_get_addr */
316 sp2 = lookup("___tls_get_addr@PLT", 0);
317 sp2->stype = EXTERN|INT|FTN;
318 r = nametree(sp2);
319 r = buildtree(ADDROF, r, NIL);
320 r = block(UCALL, r, NIL, INT, 0, 0);
321
322 /* fusion both parts together */
323 q = buildtree(COMOP, q, r);
324 q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
325 q->n_sp = p->n_sp; /* for init */
326
327 nfree(p);
328 return q;
329 }
330
331 static NODE *
tlsnonpic(NODE * p)332 tlsnonpic(NODE *p)
333 {
334 NODE *q, *r;
335 struct symtab *sp, *sp2;
336 int ext = p->n_sp->sclass;
337 char *name;
338
339 if ((name = p->n_sp->soname) == NULL)
340 name = p->n_sp->sname;
341 sp = picsymtab("", name,
342 ext == EXTERN ? "@INDNTPOFF" : "@NTPOFF");
343 q = xbcon(0, sp, INT);
344 if (ext == EXTERN)
345 q = block(UMUL, q, NIL, PTR|VOID, 0, 0);
346
347 sp2 = lookup("%gs:0", 0);
348 sp2->stype = EXTERN|INT;
349 r = nametree(sp2);
350
351 q = buildtree(PLUS, q, r);
352 q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
353 q->n_sp = p->n_sp; /* for init */
354
355 nfree(p);
356 return q;
357 }
358
359 static NODE *
tlsref(NODE * p)360 tlsref(NODE *p)
361 {
362 if (kflag)
363 return (tlspic(p));
364 else
365 return (tlsnonpic(p));
366 }
367 #endif
368
369 /* clocal() is called to do local transformations on
370 * an expression tree preparitory to its being
371 * written out in intermediate code.
372 *
373 * the major essential job is rewriting the
374 * automatic variables and arguments in terms of
375 * REG and OREG nodes
376 * conversion ops which are not necessary are also clobbered here
377 * in addition, any special features (such as rewriting
378 * exclusive or) are easily handled here as well
379 */
380 NODE *
clocal(NODE * p)381 clocal(NODE *p)
382 {
383
384 struct attr *ap;
385 register struct symtab *q;
386 register NODE *r, *l, *n, *s;
387 register int o;
388 register int m;
389
390 #ifdef PCC_DEBUG
391 if (xdebug) {
392 printf("clocal: %p\n", p);
393 fwalk(p, eprint, 0);
394 }
395 #endif
396 switch( o = p->n_op ){
397
398 case NAME:
399 if ((q = p->n_sp) == NULL)
400 return p; /* Nothing to care about */
401
402 switch (q->sclass) {
403
404 case PARAM:
405 case AUTO:
406 /* fake up a structure reference */
407 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
408 r->n_lval = 0;
409 r->n_rval = FPREG;
410 p = stref(block(STREF, r, p, 0, 0, 0));
411 break;
412
413 case USTATIC:
414 if (kflag == 0)
415 break;
416 /* FALLTHROUGH */
417 case STATIC:
418 #ifdef TLS
419 if (q->sflags & STLS) {
420 p = tlsref(p);
421 break;
422 }
423 #endif
424 if (kflag == 0) {
425 if (q->slevel == 0)
426 break;
427 } else if (kflag && !statinit && blevel > 0 &&
428 attr_find(q->sap, GCC_ATYP_WEAKREF)) {
429 /* extern call */
430 p = picext(p);
431 } else if (blevel > 0 && !statinit)
432 p = picstatic(p);
433 break;
434
435 case REGISTER:
436 p->n_op = REG;
437 p->n_lval = 0;
438 p->n_rval = q->soffset;
439 break;
440
441 case EXTERN:
442 case EXTDEF:
443 #ifdef TLS
444 if (q->sflags & STLS) {
445 p = tlsref(p);
446 break;
447 }
448 #endif
449
450 #ifdef os_win32
451 if (q->sflags & SDLLINDIRECT)
452 p = import(p);
453 #endif
454 if ((ap = attr_find(q->sap,
455 GCC_ATYP_VISIBILITY)) != NULL &&
456 strcmp(ap->sarg(0), "hidden") == 0) {
457 char *sn = q->soname ? q->soname : q->sname;
458 printf("\t.hidden %s\n", sn);
459 }
460 if (kflag == 0)
461 break;
462 if (blevel > 0 && !statinit)
463 p = picext(p);
464 break;
465 }
466 break;
467
468 case ADDROF:
469 if (kflag == 0 || blevel == 0 || statinit)
470 break;
471 /* char arrays may end up here */
472 l = p->n_left;
473 if (l->n_op != NAME ||
474 (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE))
475 break;
476 l = p;
477 p = picstatic(p->n_left);
478 nfree(l);
479 if (p->n_op != UMUL)
480 cerror("ADDROF error");
481 l = p;
482 p = p->n_left;
483 nfree(l);
484 break;
485
486 case UCALL:
487 if (kflag == 0)
488 break;
489 l = block(REG, NIL, NIL, INT, 0, 0);
490 l->n_rval = EBX;
491 p->n_right = buildtree(ASSIGN, l, tempnode(gotnr, INT, 0, 0));
492 p->n_op -= (UCALL-CALL);
493 break;
494
495 case USTCALL:
496 #if defined(os_openbsd)
497 ap = strattr(p->n_left->n_ap);
498 if (ap->amsize == SZCHAR || ap->amsize == SZSHORT ||
499 ap->amsize == SZINT || ap->amsize == SZLONGLONG)
500 #else
501 if (attr_find(p->n_left->n_ap, ATTR_COMPLEX) &&
502 (ap = strattr(p->n_left->n_ap)) &&
503 ap->amsize == SZLONGLONG)
504 #endif
505 {
506 /* float complex */
507 /* fake one arg to make pass2 happy */
508 p->n_right = block(FUNARG, bcon(0), NIL, INT, 0, 0);
509 p->n_op -= (UCALL-CALL);
510 break;
511 }
512
513 /* Add hidden arg0 */
514 r = block(REG, NIL, NIL, INCREF(VOID), 0, 0);
515 regno(r) = EBP;
516 if ((ap = attr_find(p->n_ap, GCC_ATYP_REGPARM)) != NULL &&
517 ap->iarg(0) > 0) {
518 l = block(REG, NIL, NIL, INCREF(VOID), 0, 0);
519 regno(l) = EAX;
520 p->n_right = buildtree(ASSIGN, l, r);
521 } else
522 p->n_right = block(FUNARG, r, NIL, INCREF(VOID), 0, 0);
523 p->n_op -= (UCALL-CALL);
524
525 if (kflag == 0)
526 break;
527 l = block(REG, NIL, NIL, INT, 0, 0);
528 regno(l) = EBX;
529 r = buildtree(ASSIGN, l, tempnode(gotnr, INT, 0, 0));
530 p->n_right = block(CM, r, p->n_right, INT, 0, 0);
531 break;
532
533 /* FALLTHROUGH */
534 #if defined(MACHOABI)
535 case CALL:
536 case STCALL:
537 if (p->n_type == VOID)
538 break;
539
540 r = tempnode(0, p->n_type, p->n_df, p->n_ap);
541 l = tcopy(r);
542 p = buildtree(COMOP, buildtree(ASSIGN, r, p), l);
543 #endif
544
545 break;
546
547 #ifdef notyet
548 /* XXX breaks sometimes */
549 case CBRANCH:
550 l = p->n_left;
551
552 /*
553 * Remove unnecessary conversion ops.
554 */
555 if (!clogop(l->n_op) || l->n_left->n_op != SCONV)
556 break;
557 if (coptype(l->n_op) != BITYPE)
558 break;
559 if (l->n_right->n_op != ICON)
560 break;
561 r = l->n_left->n_left;
562 if (r->n_type >= FLOAT)
563 break;
564 if (toolarge(r->n_type, l->n_right->n_lval))
565 break;
566 l->n_right->n_type = r->n_type;
567 if (l->n_op >= ULE && l->n_op <= UGT)
568 l->n_op -= (UGT-ULE);
569 p->n_left = buildtree(l->n_op, r, l->n_right);
570 nfree(l->n_left);
571 nfree(l);
572 break;
573 #endif
574
575 case PCONV:
576 l = p->n_left;
577
578 /* Make int type before pointer */
579 if (l->n_type < INT || l->n_type == LONGLONG ||
580 l->n_type == ULONGLONG || l->n_type == BOOL) {
581 /* float etc? */
582 p->n_left = block(SCONV, l, NIL, UNSIGNED, 0, 0);
583 }
584 break;
585
586 case SCONV:
587 if (p->n_left->n_op == COMOP)
588 break; /* may propagate wrong type later */
589 l = p->n_left;
590
591 if (p->n_type == l->n_type) {
592 nfree(p);
593 return l;
594 }
595
596 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
597 tsize(p->n_type, p->n_df, p->n_ap) ==
598 tsize(l->n_type, l->n_df, l->n_ap)) {
599 if (p->n_type != FLOAT && p->n_type != DOUBLE &&
600 l->n_type != FLOAT && l->n_type != DOUBLE &&
601 l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
602 if (l->n_op == NAME || l->n_op == UMUL ||
603 l->n_op == TEMP) {
604 l->n_type = p->n_type;
605 nfree(p);
606 return l;
607 }
608 }
609 }
610
611 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
612 coptype(l->n_op) == BITYPE && l->n_op != COMOP &&
613 l->n_op != QUEST && l->n_op != ASSIGN) {
614 l->n_type = p->n_type;
615 nfree(p);
616 return l;
617 }
618
619 o = l->n_op;
620 m = p->n_type;
621
622 if (o == ICON) {
623 /*
624 * Can only end up here if o is an address,
625 * and in that case the only compile-time conversion
626 * possible is to int.
627 */
628 if ((TMASK & l->n_type) == 0 && l->n_sp == NULL)
629 cerror("SCONV ICON");
630 if (l->n_sp == 0) {
631 p->n_type = UNSIGNED;
632 concast(l, m);
633 } else if (m != INT && m != UNSIGNED)
634 break;
635 l->n_type = m;
636 l->n_ap = 0;
637 nfree(p);
638 return l;
639 } else if (l->n_op == FCON)
640 cerror("SCONV FCON");
641 if ((p->n_type == CHAR || p->n_type == UCHAR ||
642 p->n_type == SHORT || p->n_type == USHORT) &&
643 (l->n_type == FLOAT || l->n_type == DOUBLE ||
644 l->n_type == LDOUBLE)) {
645 p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap);
646 p->n_left->n_type = INT;
647 return p;
648 }
649 break;
650
651 case MOD:
652 case DIV:
653 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
654 break;
655 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
656 break;
657 /* make it an int division by inserting conversions */
658 p->n_left = makety(p->n_left, INT, 0, 0, 0);
659 p->n_right = makety(p->n_right, INT, 0, 0, 0);
660 o = p->n_type;
661 p->n_type = INT;
662 p = makety(p, o, 0, 0, 0);
663 break;
664
665 case FORCE:
666 /* put return value in return reg */
667 p->n_op = ASSIGN;
668 p->n_right = p->n_left;
669 p->n_left = block(REG, NIL, NIL, p->n_type, 0, 0);
670 p->n_left->n_rval = p->n_left->n_type == BOOL ?
671 RETREG(CHAR) : RETREG(p->n_type);
672 break;
673
674 case LS:
675 case RS:
676 /* shift count must be in a char */
677 if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR)
678 break;
679 p->n_right = block(SCONV, p->n_right, NIL, CHAR, 0, 0);
680 break;
681
682 /* If not using pcc struct return */
683 case STASG:
684 r = p->n_right;
685 if (r->n_op != STCALL && r->n_op != USTCALL)
686 break;
687 m = tsize(BTYPE(r->n_type), r->n_df, r->n_ap);
688 if (m == SZCHAR)
689 m = CHAR;
690 else if (m == SZSHORT)
691 m = SHORT;
692 else if (m == SZINT)
693 m = INT;
694 else if (m == SZLONGLONG)
695 m = LONGLONG;
696 else
697 break;
698 #if !defined(os_openbsd)
699 if (attr_find(r->n_ap, ATTR_COMPLEX) == 0)
700 break; /* float _Complex always in regs */
701 #endif
702 l = buildtree(ADDROF, p->n_left, NIL);
703 nfree(p);
704
705 r->n_op -= (STCALL-CALL);
706 r->n_type = m;
707
708 /* r = long, l = &struct */
709
710 n = tempnode(0, m, r->n_df, r->n_ap);
711 r = buildtree(ASSIGN, ccopy(n), r);
712
713 s = tempnode(0, l->n_type, l->n_df, l->n_ap);
714 l = buildtree(ASSIGN, ccopy(s), l);
715
716 p = buildtree(COMOP, r, l);
717
718 l = buildtree(CAST,
719 block(NAME, NIL, NIL, m|PTR, 0, 0), ccopy(s));
720 r = l->n_right;
721 nfree(l->n_left);
722 nfree(l);
723
724 r = buildtree(ASSIGN, buildtree(UMUL, r, NIL), n);
725 p = buildtree(COMOP, p, r);
726 p = buildtree(COMOP, p, s);
727 break;
728 }
729 #ifdef PCC_DEBUG
730 if (xdebug) {
731 printf("clocal end: %p\n", p);
732 fwalk(p, eprint, 0);
733 }
734 #endif
735 return(p);
736 }
737
738 /*
739 * Change CALL references to either direct (static) or PLT.
740 */
741 static void
fixnames(NODE * p,void * arg)742 fixnames(NODE *p, void *arg)
743 {
744 #if defined(ELFABI) || defined(MACHOABI)
745
746 struct symtab *sp;
747 struct attr *ap;
748 NODE *q;
749 char *c;
750 int isu;
751
752 if ((cdope(p->n_op) & CALLFLG) == 0)
753 return;
754 isu = 0;
755 q = p->n_left;
756 ap = q->n_ap;
757 if (q->n_op == UMUL)
758 q = q->n_left, isu = 1;
759
760 if (q->n_op == PLUS && q->n_left->n_op == TEMP &&
761 q->n_right->n_op == ICON) {
762 sp = q->n_right->n_sp;
763
764 if (sp == NULL)
765 return; /* nothing to do */
766 if (sp->sclass == STATIC && !ISFTN(sp->stype))
767 return; /* function pointer */
768
769 if (sp->sclass != STATIC && sp->sclass != EXTERN &&
770 sp->sclass != EXTDEF)
771 cerror("fixnames");
772 c = NULL;
773 #if defined(ELFABI)
774
775 if (sp->soname == NULL ||
776 (c = strstr(sp->soname, "@GOT")) == NULL)
777 cerror("fixnames2");
778 if (isu) {
779 memcpy(c, "@PLT", sizeof("@PLT"));
780 } else
781 *c = 0;
782
783 #elif defined(MACHOABI)
784
785 if (sp->soname == NULL ||
786 ((c = strstr(sp->soname, "$non_lazy_ptr")) == NULL &&
787 (c = strstr(sp->soname, "-L")) == NULL))
788 cerror("fixnames2");
789
790 if (!ISFTN(sp->stype))
791 return; /* function pointer */
792
793 if (isu) {
794 *c = 0;
795 addstub(&stublist, sp->soname+1);
796 memcpy(c, "$stub", sizeof("$stub"));
797 } else
798 *c = 0;
799
800 #endif
801
802 nfree(q->n_left);
803 q = q->n_right;
804 if (isu)
805 nfree(p->n_left->n_left);
806 nfree(p->n_left);
807 p->n_left = q;
808 q->n_ap = ap;
809 }
810 #endif
811 }
812
813 static void mangle(NODE *p);
814
815 void
myp2tree(NODE * p)816 myp2tree(NODE *p)
817 {
818 struct symtab *sp;
819
820 if (kflag)
821 fixnames(p, 0);
822
823 mangle(p);
824
825 if ((p->n_op == STCALL || p->n_op == USTCALL) &&
826 p->n_left->n_op == ICON &&
827 attr_find(p->n_left->n_ap, ATTR_COMPLEX) &&
828 tsize(DECREF(DECREF(p->n_left->n_type)),
829 p->n_left->n_df, p->n_left->n_ap) == SZLONGLONG) {
830 p->n_su = 42;
831 }
832
833 if (p->n_op != FCON)
834 return;
835
836 sp = IALLOC(sizeof(struct symtab));
837 sp->sclass = STATIC;
838 sp->sap = 0;
839 sp->slevel = 1; /* fake numeric label */
840 sp->soffset = getlab();
841 sp->sflags = 0;
842 sp->stype = p->n_type;
843 sp->squal = (CON >> TSHIFT);
844 sp->sname = sp->soname = NULL;
845
846 locctr(DATA, sp);
847 defloc(sp);
848 ninval(0, tsize(sp->stype, sp->sdf, sp->sap), p);
849
850 p->n_op = NAME;
851 p->n_lval = 0;
852 p->n_sp = sp;
853
854 if (kflag) {
855 NODE *q = optim(picstatic(tcopy(p)));
856 *p = *q;
857 nfree(q);
858 }
859 }
860
861 /*ARGSUSED*/
862 int
andable(NODE * p)863 andable(NODE *p)
864 {
865 return(1); /* all names can have & taken on them */
866 }
867
868 /*
869 * Return 1 if a variable of type type is OK to put in register.
870 */
871 int
cisreg(TWORD t)872 cisreg(TWORD t)
873 {
874 if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
875 return 0; /* not yet */
876 return 1;
877 }
878
879 /*
880 * Allocate off bits on the stack. p is a tree that when evaluated
881 * is the multiply count for off, t is a storeable node where to write
882 * the allocated address.
883 */
884 void
spalloc(NODE * t,NODE * p,OFFSZ off)885 spalloc(NODE *t, NODE *p, OFFSZ off)
886 {
887 NODE *sp;
888
889 p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */
890
891 /* sub the size from sp */
892 sp = block(REG, NIL, NIL, p->n_type, 0, 0);
893 sp->n_lval = 0;
894 sp->n_rval = STKREG;
895 ecomp(buildtree(MINUSEQ, sp, p));
896
897 #ifdef MACHOABI
898 /* align to 16 bytes */
899 sp = block(REG, NIL, NIL, p->n_type, 0, 0);
900 sp->n_lval = 0;
901 sp->n_rval = STKREG;
902 ecomp(buildtree(PLUSEQ, sp, bcon(15)));
903
904 sp = block(REG, NIL, NIL, p->n_type, 0, 0);
905 sp->n_lval = 0;
906 sp->n_rval = STKREG;
907 ecomp(buildtree(RSEQ, sp, bcon(4)));
908
909 sp = block(REG, NIL, NIL, p->n_type, 0, 0);
910 sp->n_lval = 0;
911 sp->n_rval = STKREG;
912 ecomp(buildtree(LSEQ, sp, bcon(4)));
913 #endif
914
915
916 /* save the address of sp */
917 sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_ap);
918 sp->n_lval = 0;
919 sp->n_rval = STKREG;
920 t->n_type = sp->n_type;
921 ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
922
923 }
924
925 /*
926 * print out a constant node, may be associated with a label.
927 * Do not free the node after use.
928 * off is bit offset from the beginning of the aggregate
929 * fsz is the number of bits this is referring to
930 */
931 int
ninval(CONSZ off,int fsz,NODE * p)932 ninval(CONSZ off, int fsz, NODE *p)
933 {
934 union { float f; double d; long double l; int i[3]; } u;
935 int i;
936
937 switch (p->n_type) {
938 case LONGLONG:
939 case ULONGLONG:
940 i = (int)(p->n_lval >> 32);
941 p->n_lval &= 0xffffffff;
942 p->n_type = INT;
943 inval(off, 32, p);
944 p->n_lval = i;
945 inval(off+32, 32, p);
946 break;
947 case LDOUBLE:
948 u.i[2] = 0;
949 u.l = (long double)p->n_dcon;
950 #if defined(HOST_BIG_ENDIAN)
951 /* XXX probably broken on most hosts */
952 printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[2], u.i[1], u.i[0]);
953 #else
954 printf("\t.long\t%d,%d,%d\n", u.i[0], u.i[1], u.i[2] & 0177777);
955 #endif
956 break;
957 case DOUBLE:
958 u.d = (double)p->n_dcon;
959 #if defined(HOST_BIG_ENDIAN)
960 printf("\t.long\t0x%x,0x%x\n", u.i[1], u.i[0]);
961 #else
962 printf("\t.long\t%d,%d\n", u.i[0], u.i[1]);
963 #endif
964 break;
965 case FLOAT:
966 u.f = (float)p->n_dcon;
967 printf("\t.long\t%d\n", u.i[0]);
968 break;
969 default:
970 return 0;
971 }
972 return 1;
973 }
974
975 /* make a name look like an external name in the local machine */
976 char *
exname(char * p)977 exname(char *p)
978 {
979 #if !defined(ELFABI)
980
981 #define NCHNAM 256
982 static char text[NCHNAM+1];
983 int i;
984
985 if (p == NULL)
986 return "";
987
988 text[0] = '_';
989 for (i=1; *p && i<NCHNAM; ++i)
990 text[i] = *p++;
991
992 text[i] = '\0';
993 text[NCHNAM] = '\0'; /* truncate */
994
995 return (text);
996
997 #else
998
999 return (p == NULL ? "" : p);
1000
1001 #endif
1002 }
1003
1004 /*
1005 * map types which are not defined on the local machine
1006 */
1007 TWORD
ctype(TWORD type)1008 ctype(TWORD type)
1009 {
1010 switch (BTYPE(type)) {
1011 case LONG:
1012 MODTYPE(type,INT);
1013 break;
1014
1015 case ULONG:
1016 MODTYPE(type,UNSIGNED);
1017
1018 }
1019 return (type);
1020 }
1021
1022 void
calldec(NODE * p,NODE * q)1023 calldec(NODE *p, NODE *q)
1024 {
1025 }
1026
1027 void
extdec(struct symtab * q)1028 extdec(struct symtab *q)
1029 {
1030 }
1031
1032 /* make a common declaration for id, if reasonable */
1033 void
defzero(struct symtab * sp)1034 defzero(struct symtab *sp)
1035 {
1036 int off;
1037 int al;
1038 char *name;
1039
1040 if ((name = sp->soname) == NULL)
1041 name = exname(sp->sname);
1042 al = talign(sp->stype, sp->sap)/SZCHAR;
1043 off = (int)tsize(sp->stype, sp->sdf, sp->sap);
1044 SETOFF(off,SZCHAR);
1045 off /= SZCHAR;
1046 #if defined(MACHOABI)
1047 al = ispow2(al);
1048 if (sp->sclass == STATIC) {
1049 if (sp->slevel == 0)
1050 printf("\t.lcomm %s,0%o,%d\n", name, off, al);
1051 else
1052 printf("\t.lcomm " LABFMT ",0%o,%d\n", sp->soffset, off, al);
1053 } else {
1054 if (sp->slevel == 0)
1055 printf("\t.comm %s,0%o,%d\n", name, off, al);
1056 else
1057 printf("\t.comm " LABFMT ",0%o,%d\n", sp->soffset, off, al);
1058 }
1059 #else
1060 if (attr_find(sp->sap, GCC_ATYP_WEAKREF) != NULL)
1061 return;
1062 if (sp->sclass == STATIC) {
1063 if (sp->slevel == 0) {
1064 printf("\t.local %s\n", name);
1065 } else
1066 printf("\t.local " LABFMT "\n", sp->soffset);
1067 }
1068 if (sp->slevel == 0)
1069 printf("\t.comm %s,0%o,%d\n", name, off, al);
1070 else
1071 printf("\t.comm " LABFMT ",0%o,%d\n", sp->soffset, off, al);
1072 #endif
1073 }
1074
1075 #ifdef TLS
1076 static int gottls;
1077 #endif
1078 static int stdcall;
1079 #ifdef os_win32
1080 static int dllindirect;
1081 #endif
1082 static char *alias;
1083 static int constructor;
1084 static int destructor;
1085
1086 /*
1087 * Give target the opportunity of handling pragmas.
1088 */
1089 int
mypragma(char * str)1090 mypragma(char *str)
1091 {
1092 char *a2 = pragtok(NULL);
1093
1094 #ifdef TLS
1095 if (strcmp(str, "tls") == 0 && a2 == NULL) {
1096 gottls = 1;
1097 return 1;
1098 }
1099 #endif
1100 if (strcmp(str, "stdcall") == 0) {
1101 stdcall = 1;
1102 return 1;
1103 }
1104 if (strcmp(str, "cdecl") == 0) {
1105 stdcall = 0;
1106 return 1;
1107 }
1108 #ifdef os_win32
1109 if (strcmp(str, "fastcall") == 0) {
1110 stdcall = 2;
1111 return 1;
1112 }
1113 if (strcmp(str, "dllimport") == 0) {
1114 dllindirect = 1;
1115 return 1;
1116 }
1117 if (strcmp(str, "dllexport") == 0) {
1118 dllindirect = 1;
1119 return 1;
1120 }
1121 #endif
1122 #ifndef AOUTABI
1123 if (strcmp(str, "constructor") == 0 || strcmp(str, "init") == 0) {
1124 constructor = 1;
1125 return 1;
1126 }
1127 if (strcmp(str, "destructor") == 0 || strcmp(str, "fini") == 0) {
1128 destructor = 1;
1129 return 1;
1130 }
1131 #endif
1132 if (strcmp(str, "alias") == 0 && a2 != NULL) {
1133 alias = tmpstrdup(a2);
1134 return 1;
1135 }
1136
1137 return 0;
1138 }
1139
1140 /*
1141 * Called when a identifier has been declared.
1142 */
1143 void
fixdef(struct symtab * sp)1144 fixdef(struct symtab *sp)
1145 {
1146 #ifdef GCC_COMPAT
1147 struct attr *ap;
1148 #endif
1149 #ifdef TLS
1150 /* may have sanity checks here */
1151 if (gottls)
1152 sp->sflags |= STLS;
1153 gottls = 0;
1154 #endif
1155 #ifdef GCC_COMPAT
1156 #ifdef HAVE_WEAKREF
1157 /* not many as'es have this directive */
1158 if ((ap = attr_find(sp->sap, GCC_ATYP_WEAKREF)) != NULL) {
1159 char *wr = ap->sarg(0);
1160 char *sn = sp->soname ? sp->soname : sp->sname;
1161 if (sp->sclass != STATIC && sp->sclass != USTATIC)
1162 uerror("weakref %s must be static", sp->sname);
1163 if (wr == NULL) {
1164 if ((ap = attr_find(sp->sap, GCC_ATYP_ALIAS))) {
1165 wr = ap->sarg(0);
1166 }
1167 }
1168 if (wr == NULL)
1169 printf("\t.weak %s\n", sn);
1170 else
1171 printf("\t.weakref %s,%s\n", sn, wr);
1172 } else
1173 #endif
1174 if ((ap = attr_find(sp->sap, GCC_ATYP_ALIAS)) != NULL) {
1175 char *an = ap->sarg(0);
1176 char *sn = sp->soname ? sp->soname : sp->sname;
1177 char *v;
1178
1179 v = attr_find(sp->sap, GCC_ATYP_WEAK) ? "weak" : "globl";
1180 printf("\t.%s %s\n", v, sn);
1181 printf("\t.set %s,%s\n", sn, an);
1182 }
1183 #endif
1184 if (alias != NULL && (sp->sclass != PARAM)) {
1185 char *name;
1186 if ((name = sp->soname) == NULL)
1187 name = exname(sp->sname);
1188 printf("\t.globl %s\n", name);
1189 printf("%s = ", name);
1190 printf("%s\n", exname(alias));
1191 alias = NULL;
1192 }
1193 if ((constructor || destructor) && (sp->sclass != PARAM)) {
1194 #if defined(ELFABI)
1195 printf("\t.section .%ctors,\"aw\",@progbits\n",
1196 constructor ? 'c' : 'd');
1197 #elif defined(PECOFFABI)
1198 printf("\t.section .%ctors,\"w\"\n",
1199 constructor ? 'c' : 'd');
1200 #elif defined(MACHOABI)
1201 if (kflag) {
1202 if (constructor)
1203 printf("\t.mod_init_func\n");
1204 else
1205 printf("\t.mod_term_func\n");
1206 } else {
1207 if (constructor)
1208 printf("\t.constructor\n");
1209 else
1210 printf("\t.destructor\n");
1211 }
1212 #elif defined(AOUTABI)
1213 uerror("constructor/destructor are not supported for this target");
1214 #endif
1215 printf("\t.p2align 2\n");
1216 printf("\t.long %s\n", exname(sp->sname));
1217 #ifdef MACHOABI
1218 printf("\t.text\n");
1219 #else
1220 printf("\t.previous\n");
1221 #endif
1222 constructor = destructor = 0;
1223 }
1224 if (stdcall && (sp->sclass != PARAM)) {
1225 sp->sflags |= SSTDCALL;
1226 stdcall = 0;
1227 }
1228 #ifdef os_win32
1229 if (dllindirect && (sp->sclass != PARAM)) {
1230 sp->sflags |= SDLLINDIRECT;
1231 dllindirect = 0;
1232 }
1233 #endif
1234 }
1235
1236 /*
1237 * Postfix external functions with the arguments size.
1238 */
1239 static void
mangle(NODE * p)1240 mangle(NODE *p)
1241 {
1242 NODE *l;
1243
1244 if (p->n_op == NAME || p->n_op == ICON) {
1245 p->n_flags = 0; /* for later setting of STDCALL */
1246 if (p->n_sp) {
1247 if (p->n_sp->sflags & SSTDCALL)
1248 p->n_flags = FSTDCALL;
1249 }
1250 } else if (p->n_op == TEMP)
1251 p->n_flags = 0; /* STDCALL fun ptr not allowed */
1252
1253 if (p->n_op != CALL && p->n_op != STCALL &&
1254 p->n_op != UCALL && p->n_op != USTCALL)
1255 return;
1256
1257 p->n_flags = 0;
1258
1259 l = p->n_left;
1260 while (cdope(l->n_op) & CALLFLG)
1261 l = l->n_left;
1262 if (l->n_op == TEMP)
1263 return;
1264 if (l->n_op == ADDROF)
1265 l = l->n_left;
1266 if (l->n_sp == NULL)
1267 return;
1268 #ifdef GCC_COMPAT
1269 if (attr_find(l->n_sp->sap, GCC_ATYP_STDCALL) != NULL)
1270 l->n_sp->sflags |= SSTDCALL;
1271 #endif
1272 #ifdef os_win32
1273 if (l->n_sp->sflags & SSTDCALL) {
1274 if (strchr(l->n_name, '@') == NULL) {
1275 int size = 0;
1276 char buf[256];
1277 NODE *r;
1278 TWORD t;
1279
1280 if (p->n_op == CALL || p->n_op == STCALL) {
1281 for (r = p->n_right;
1282 r->n_op == CM; r = r->n_left) {
1283 t = r->n_type;
1284 if (t == STRTY || t == UNIONTY)
1285 size += tsize(t, r->n_df, r->n_ap);
1286 else
1287 size += szty(t) * SZINT / SZCHAR;
1288 }
1289 t = r->n_type;
1290 if (t == STRTY || t == UNIONTY)
1291 size += tsize(t, r->n_df, r->n_ap);
1292 else
1293 size += szty(t) * SZINT / SZCHAR;
1294 }
1295 size = snprintf(buf, 256, "%s@%d", l->n_name, size) + 1;
1296 l->n_name = IALLOC(size);
1297 memcpy(l->n_name, buf, size);
1298 }
1299 }
1300 #endif
1301 }
1302
1303 /*
1304 * find struct return functions and clear stalign field if float _Complex.
1305 */
1306 static void
fixstcall(NODE * p,void * arg)1307 fixstcall(NODE *p, void *arg)
1308 {
1309 if (p->n_op != STCALL && p->n_op != USTCALL)
1310 return;
1311 if (p->n_su == 42)
1312 p->n_stalign = 42;
1313 }
1314
1315
1316 void
pass1_lastchance(struct interpass * ip)1317 pass1_lastchance(struct interpass *ip)
1318 {
1319 if (ip->type == IP_NODE &&
1320 (ip->ip_node->n_op == CALL || ip->ip_node->n_op == UCALL) &&
1321 ISFTY(ip->ip_node->n_type))
1322 ip->ip_node->n_flags = FFPPOP;
1323 if (ip->type == IP_NODE)
1324 walkf(ip->ip_node, fixstcall, 0);
1325
1326 if (ip->type == IP_EPILOG) {
1327 struct interpass_prolog *ipp = (struct interpass_prolog *)ip;
1328 ipp->ipp_argstacksize = argstacksize;
1329 }
1330 }
1331