xref: /netbsd/external/bsd/pcc/dist/pcc/arch/i386/local.c (revision 6935091c)
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