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