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