1 /*	$Id: local.c,v 1.40 2012/09/06 11:32:32 plunky Exp $	*/
2 /*	$OpenBSD: local.c,v 1.2 2007/11/18 17:39:55 ragge Exp $	*/
3 
4 /*
5  * Copyright (c) 2007 Michael Shalayeff
6  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 
31 #include "pass1.h"
32 #include "pass2.h"
33 
34 /*	this file contains code which is dependent on the target machine */
35 
36 #define	IALLOC(sz)	(isinlining ? permalloc(sz) : tmpalloc(sz))
37 
38 struct symtab *makememcpy(void);
39 
40 /* clocal() is called to do local transformations on
41  * an expression tree preparitory to its being
42  * written out in intermediate code.
43  *
44  * the major essential job is rewriting the
45  * automatic variables and arguments in terms of
46  * REG and OREG nodes
47  * conversion ops which are not necessary are also clobbered here
48  * in addition, any special features (such as rewriting
49  * exclusive or) are easily handled here as well
50  */
51 NODE *
clocal(NODE * p)52 clocal(NODE *p)
53 {
54 	register struct symtab *q, *sp;
55 	register NODE *r, *l, *s;
56 	register int o, m, rn;
57 	char *ch, name[16], *n;
58 	TWORD t;
59 
60 #ifdef PCC_DEBUG
61 	if (xdebug) {
62 		printf("clocal: %p\n", p);
63 		fwalk(p, eprint, 0);
64 	}
65 #endif
66 	switch (o = p->n_op) {
67 
68 	case NAME:
69 		if ((q = p->n_sp) == NULL)
70 			break;	/* Nothing to care about */
71 
72 		switch (q->sclass) {
73 
74 		case PARAM:
75 			/* first four integral args are in regs */
76 			rn = (q->soffset >> 5) - 8;
77 			if (rn < 4) {
78 				r = block(REG, NIL, NIL, p->n_type, 0, 0);
79 				r->n_lval = 0;
80 				switch (p->n_type) {
81 				case FLOAT:
82 					r->n_rval = FR7L - rn;
83 					break;
84 				case DOUBLE:
85 				case LDOUBLE:
86 					r->n_rval = FR6 - rn;
87 					break;
88 				case LONGLONG:
89 				case ULONGLONG:
90 					r->n_rval = AD1 - rn / 2;
91 					break;
92 				default:
93 					r->n_rval = ARG0 - rn;
94 				}
95 				r->n_sue = p->n_sue;
96 				p->n_sue = NULL;
97 				nfree(p);
98 				p = r;
99 				break;
100 			}
101 			/* FALLTHROUGH */
102 
103 		case AUTO:
104 			/* fake up a structure reference */
105 			r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
106 			r->n_lval = 0;
107 			r->n_rval = FPREG;
108 			p = stref(block(STREF, r, p, 0, 0, 0));
109 			break;
110 
111 		case REGISTER:
112 			p->n_op = REG;
113 			p->n_lval = 0;
114 			p->n_rval = q->soffset;
115 			break;
116 
117 		case STATIC:
118 		case EXTERN:
119 			if (p->n_sp->sflags & SSTRING)
120 				break;
121 
122 			n = p->n_sp->soname ? p->n_sp->soname : p->n_sp->sname;
123 			if (strncmp(n, "__builtin", 9) == 0)
124 				break;
125 
126 			l = block(REG, NIL, NIL, INT, 0, 0);
127 			l->n_lval = 0;
128 			l->n_rval = R1;
129 			l = block(ASSIGN, l, p, INT, 0, 0);
130 			r = xbcon(0, p->n_sp, INT);
131 			p = block(UMUL,
132 			    block(PLUS, l, r, INT, 0, 0),
133 			    NIL, p->n_type, p->n_df, p->n_sue);
134 			break;
135 		}
136 		break;
137 
138 	case ADDROF:
139 		l = p->n_left;
140 		if (!l->n_sp)
141 			break;
142 
143 		if (l->n_sp->sclass != EXTERN &&
144 		    l->n_sp->sclass != STATIC &&
145 		    l->n_sp->sclass != USTATIC &&
146 		    l->n_sp->sclass != EXTDEF)
147 			break;
148 
149 		l = block(REG, NIL, NIL, INT, 0, 0);
150 		l->n_lval = 0;
151 		l->n_rval = R1;
152 		l = block(ASSIGN, l, p->n_left, INT, 0, 0);
153 		r = xbcon(0, p->n_left->n_sp, INT);
154 		l = block(PLUS, l, r, p->n_type, p->n_df, p->n_sue);
155 		nfree(p);
156 		p = l;
157 		break;
158 
159 	case CBRANCH:
160 		l = p->n_left;
161 
162 		/*
163 		 * Remove unnecessary conversion ops.
164 		 */
165 		if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
166 			if (coptype(l->n_op) != BITYPE)
167 				break;
168 			if (l->n_right->n_op == ICON) {
169 				r = l->n_left->n_left;
170 				if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
171 					break;
172 				/* Type must be correct */
173 				t = r->n_type;
174 				nfree(l->n_left);
175 				l->n_left = r;
176 				l->n_type = t;
177 				l->n_right->n_type = t;
178 			}
179 		}
180 		break;
181 
182 	case PCONV:
183 		/* Remove redundant PCONV's. Be careful */
184 		l = p->n_left;
185 		if (l->n_op == ICON) {
186 			l->n_lval = (unsigned)l->n_lval;
187 			goto delp;
188 		}
189 		if (l->n_type < INT || l->n_type == LONGLONG ||
190 		    l->n_type == ULONGLONG) {
191 			/* float etc? */
192 			p->n_left = block(SCONV, l, NIL, UNSIGNED, 0, 0);
193 			break;
194 		}
195 		/* if left is SCONV, cannot remove */
196 		if (l->n_op == SCONV)
197 			break;
198 
199 		/* avoid ADDROF TEMP */
200 		if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
201 			break;
202 
203 		/* if conversion to another pointer type, just remove */
204 		if (p->n_type > BTMASK && l->n_type > BTMASK)
205 			goto delp;
206 		break;
207 
208 	delp:	l->n_type = p->n_type;
209 		l->n_qual = p->n_qual;
210 		l->n_df = p->n_df;
211 		l->n_sue = p->n_sue;
212 		nfree(p);
213 		p = l;
214 		break;
215 
216 	case SCONV:
217 		l = p->n_left;
218 
219 		if (p->n_type == l->n_type) {
220 			nfree(p);
221 			p = l;
222 			break;
223 		}
224 
225 		if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
226 		    btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
227 			if (p->n_type != FLOAT && p->n_type != DOUBLE &&
228 			    l->n_type != FLOAT && l->n_type != DOUBLE &&
229 			    l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
230 				if (l->n_op == UMUL || l->n_op == TEMP ||
231 				    l->n_op == NAME) {
232 					l->n_type = p->n_type;
233 					nfree(p);
234 					p = l;
235 					break;
236 				}
237 			}
238 		}
239 
240 		if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
241 		    coptype(l->n_op) == BITYPE) {
242 			l->n_type = p->n_type;
243 			nfree(p);
244 			p = l;
245 			break;
246 		}
247 
248 		o = l->n_op;
249 		m = p->n_type;
250 
251 		if (o == ICON) {
252 			CONSZ val = l->n_lval;
253 
254 			if (!ISPTR(m)) /* Pointers don't need to be conv'd */
255 			    switch (m) {
256 			case BOOL:
257 				l->n_lval = l->n_lval != 0;
258 				break;
259 			case CHAR:
260 				l->n_lval = (char)val;
261 				break;
262 			case UCHAR:
263 				l->n_lval = val & 0377;
264 				break;
265 			case SHORT:
266 				l->n_lval = (short)val;
267 				break;
268 			case USHORT:
269 				l->n_lval = val & 0177777;
270 				break;
271 			case ULONG:
272 			case UNSIGNED:
273 				l->n_lval = val & 0xffffffff;
274 				break;
275 			case LONG:
276 			case INT:
277 				l->n_lval = (int)val;
278 				break;
279 			case LONGLONG:
280 				l->n_lval = (long long)val;
281 				break;
282 			case ULONGLONG:
283 				l->n_lval = val;
284 				break;
285 			case VOID:
286 				break;
287 			case LDOUBLE:
288 			case DOUBLE:
289 			case FLOAT:
290 				l->n_op = FCON;
291 				l->n_dcon = val;
292 				break;
293 			default:
294 				cerror("unknown type %d", m);
295 			}
296 			l->n_type = m;
297 			l->n_sue = 0;
298 			nfree(p);
299 			return l;
300                 } else if (l->n_op == FCON) {
301 			l->n_lval = l->n_dcon;
302 			l->n_sp = NULL;
303 			l->n_op = ICON;
304 			l->n_type = m;
305 			l->n_sue = 0;
306 			nfree(p);
307 			return clocal(l);
308 		}
309 
310 		if (DEUNSIGN(p->n_type) == SHORT &&
311 		    DEUNSIGN(l->n_type) == SHORT) {
312 			nfree(p);
313 			p = l;
314 		}
315 		if ((p->n_type == CHAR || p->n_type == UCHAR ||
316 		    p->n_type == SHORT || p->n_type == USHORT) &&
317 		    (l->n_type == FLOAT || l->n_type == DOUBLE ||
318 		    l->n_type == LDOUBLE)) {
319 			p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue);
320 			p->n_left->n_type = INT;
321 			break;
322 		}
323 		break;
324 
325 	case MOD:
326 	case DIV:
327 		if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
328 			break;
329 		if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
330 			break;
331 		/* make it an int division by inserting conversions */
332 		p->n_left = block(SCONV, p->n_left, NIL, INT, 0, 0);
333 		p->n_right = block(SCONV, p->n_right, NIL, INT, 0, 0);
334 		p = block(SCONV, p, NIL, p->n_type, 0, 0);
335 		p->n_left->n_type = INT;
336 		break;
337 
338 	case LS:
339 	case RS:
340 		/* shift count must be in an int */
341 		if (p->n_right->n_op == ICON || p->n_right->n_lval <= 32)
342 			break;	/* do not do anything */
343 		if (p->n_right->n_type != INT || p->n_right->n_lval > 32)
344 			p->n_right = block(SCONV, p->n_right, NIL, INT, 0, 0);
345 		break;
346 
347 #if 0
348 	case FLD:
349 		/* already rewritten (in ASSIGN) */
350 		if (p->n_left->n_op == TEMP)
351 			break;
352 
353 		r = tempnode(0, p->n_type, p->n_df, p->n_sue);
354 		l = block(ASSIGN, r, p->n_left, p->n_type, p->n_df, p->n_sue);
355 		p->n_left = tcopy(r);
356 		p = block(COMOP, l, p, p->n_type, p->n_df, p->n_sue);
357 		break;
358 #endif
359 
360 	case FORCE:
361 		/* put return value in return reg */
362 		p->n_op = ASSIGN;
363 		p->n_right = p->n_left;
364 		p->n_left = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue);
365 		p->n_left->n_rval = p->n_left->n_type == BOOL ?
366 		    RETREG(CHAR) : RETREG(p->n_type);
367 		if (p->n_right->n_op != FLD)
368 			break;
369 		break;
370 
371 	case ASSIGN:
372 		r = p->n_right;
373 		l = p->n_left;
374 
375 		/* rewrite ICON#0 into %r0 */
376 		if (r->n_op == ICON && r->n_lval == 0 &&
377 		    (l->n_op == REG || l->n_op == OREG)) {
378 			r->n_op = REG;
379 			r->n_rval = R0;
380 		}
381 
382 		/* rewrite FCON#0 into %fr0 */
383 		if (r->n_op == FCON && r->n_lval == 0 && l->n_op == REG) {
384 			r->n_op = REG;
385 			r->n_rval = r->n_type == FLOAT? FR0L : FR0;
386 		}
387 
388 		if (p->n_left->n_op != FLD)
389 			break;
390 
391 		r = tempnode(0, l->n_type, l->n_df, l->n_sue);
392 		p = block(COMOP,
393 		    block(ASSIGN, r, l->n_left, l->n_type, l->n_df, l->n_sue),
394 		    p, p->n_type, p->n_df, p->n_sue);
395 		s = tcopy(l->n_left);
396 		p = block(COMOP, p,
397 		    block(ASSIGN, s, tcopy(r), l->n_type, l->n_df, l->n_sue),
398 		    p->n_type, p->n_df, p->n_sue);
399 		l->n_left = tcopy(r);
400 		break;
401 
402 	case STASG:
403 		/* memcpy(left, right, size) */
404 		sp = makememcpy();
405 		l = p->n_left;
406 		/* guess struct return */
407 		if (l->n_op == NAME && ISFTN(l->n_sp->stype)) {
408 			l = block(REG, NIL, NIL, VOID|PTR, 0, 0);
409 			l->n_lval = 0;
410 			l->n_rval = RET0;
411 		} else if (l->n_op == UMUL)
412 			l = tcopy(l->n_left);
413 		else if (l->n_op == NAME)
414 			l = block(ADDROF,tcopy(l),NIL,PTR|STRTY,0,0);
415 		l = block(CALL, block(ADDROF,
416 		    (s = block(NAME, NIL, NIL, FTN, 0, 0)),
417 		    NIL, PTR|FTN, 0, 0),
418 		    block(CM, block(CM, l, tcopy(p->n_right),
419 		    STRTY|PTR, 0, 0),
420 		    (r = block(ICON, NIL, NIL, INT, 0, 0)), 0, 0, 0),
421 		    INT, 0, 0);
422 		r->n_lval = p->n_sue->suesize/SZCHAR;
423 		s->n_sp = sp;
424 		s->n_df = s->n_sp->sdf;
425 		defid(s, EXTERN);
426 		tfree(p);
427 		p = l;
428 		p->n_left = clocal(p->n_left);
429 		p->n_right = clocal(p->n_right);
430 		calldec(p->n_left, p->n_right);
431 		funcode(p);
432 		break;
433 
434 	case STARG:
435 		/* arg = memcpy(argN-size, src, size) */
436 		sp = makememcpy();
437 		l = block(CALL, block(ADDROF,
438 		    (s = block(NAME, NIL, NIL, FTN, 0, 0)),NIL,0,0,0),
439 		    block(CM, block(CM, tcopy(p), tcopy(p->n_left), 0, 0, 0),
440 		    (r = block(ICON, NIL, NIL, INT, 0, 0)), 0, 0, 0),
441 		    INT, 0, 0);
442 		r->n_lval = p->n_sue->suesize/SZCHAR;
443 		s->n_sp = sp;
444 		s->n_df = s->n_sp->sdf;
445 		defid(s, EXTERN);
446 		tfree(p);
447 		p = l;
448 		p->n_left = clocal(p->n_left);
449 		calldec(p->n_left, p->n_right);
450 		funcode(p);
451 		break;
452 
453 	case STCALL:
454 	case CALL:
455 		for (r = p->n_right; r->n_op == CM; r = r->n_left) {
456 			if (r->n_right->n_op == ASSIGN &&
457 			    r->n_right->n_right->n_op == CALL) {
458 				s = r->n_right->n_right;
459 				l = tempnode(0, s->n_type, s->n_df, s->n_sue);
460 				ecode(buildtree(ASSIGN, l, s));
461 				r->n_right->n_right = tcopy(l);
462 			}
463 			if (r->n_left->n_op == ASSIGN &&
464 			    r->n_left->n_right->n_op == CALL) {
465 				s = r->n_left->n_right;
466 				l = tempnode(0, s->n_type, s->n_df, s->n_sue);
467 				ecode(buildtree(ASSIGN, l, s));
468 				r->n_left->n_right = tcopy(l);
469 			}
470 		}
471 		break;
472 	}
473 
474 	/* second pass - rewrite long ops */
475 	switch (o) {
476 	case DIV:
477 	case MOD:
478 	case MUL:
479 	case RS:
480 	case LS:
481 		if (!(p->n_type == LONGLONG || p->n_type == ULONGLONG) ||
482 		    !((o == DIV || o == MOD || o == MUL) &&
483 		      p->n_type < FLOAT))
484 			break;
485 		if (o == DIV && p->n_type == ULONGLONG) ch = "udiv";
486 		else if (o == DIV) ch = "div";
487 		else if (o == MUL) ch = "mul";
488 		else if (o == MOD && p->n_type == ULONGLONG) ch = "umod";
489 		else if (o == MOD) ch = "mod";
490 		else if (o == RS && p->n_type == ULONGLONG) ch = "lshr";
491 		else if (o == RS) ch = "ashr";
492 		else if (o == LS) ch = "ashl";
493 		else break;
494 		snprintf(name, sizeof(name), "__%sdi3", ch);
495 		p->n_right = block(CM, p->n_left, p->n_right, 0, 0, 0);
496 		p->n_left = block(ADDROF,
497 		    block(NAME, NIL, NIL, FTN, 0, 0), NIL, PTR|FTN, 0, 0);
498 		p->n_left->n_left->n_sp = lookup(addname(name), 0);
499 		defid(p->n_left->n_left, EXTERN);
500 		p->n_left = clocal(p->n_left);
501 		calldec(p->n_left, p->n_right);
502 		p->n_op = CALL;
503 		funcode(p);
504 		break;
505 	}
506 
507 #ifdef PCC_DEBUG
508 	if (xdebug) {
509 		printf("clocal end: %p\n", p);
510 		fwalk(p, eprint, 0);
511 	}
512 #endif
513 	return(p);
514 }
515 
516 struct symtab *
makememcpy(void)517 makememcpy(void)
518 {
519 	NODE *memcpy, *args, *t, *u;
520 	struct symtab *sp;
521 
522 	/* TODO check that it's a func proto */
523 	if ((sp = lookup(addname("memcpy"), SNORMAL)))
524 		return sp;
525 
526 	memcpy = block(NAME, NIL, NIL, 0, 0, 0);
527 	memcpy->n_sp = sp = lookup(addname("memcpy"), SNORMAL);
528 	defid(memcpy, EXTERN);
529 
530 	args = block(CM, block(CM,
531 	    block(NAME, NIL, NIL, VOID|PTR, 0, 0),
532 	    block(NAME, NIL, NIL, VOID|PTR, 0, 0), 0, 0, 0),
533 	    block(NAME, NIL, NIL, LONG, 0, 0), 0, 0, 0);
534 
535 	tymerge(t = block(TYPE, NIL, NIL, VOID|PTR, 0, 0),
536 	    (u = block(UMUL, block(CALL, memcpy, args, LONG, 0, 0),
537 	    NIL, LONG, 0, 0)));
538 	tfree(t);
539 	tfree(u);
540 
541 	return sp;
542 }
543 
544 void
myp2tree(NODE * p)545 myp2tree(NODE *p)
546 {
547 	struct symtab *sp;
548 	int o = p->n_op;
549 
550 	if (o != FCON)
551 		return;
552 
553 	/* Write float constants to memory */
554 	/* Should be volontary per architecture */
555 
556 #if 0
557 	setloc1(RDATA);
558 	defalign(p->n_type == FLOAT ? ALFLOAT : p->n_type == DOUBLE ?
559 	    ALDOUBLE : ALLDOUBLE );
560 	deflab1(i = getlab());
561 #endif
562 	sp = inlalloc(sizeof(struct symtab));
563 	sp->sclass = STATIC;
564 	sp->ssue = 0;
565 	sp->slevel = 1; /* fake numeric label */
566 	sp->soffset = getlab();
567 	sp->sflags = 0;
568 	sp->stype = p->n_type;
569 	sp->squal = (CON >> TSHIFT);
570 
571 	defloc(sp);
572 	ninval(0, btdims[p->n_type].suesize, p);
573 
574 	p->n_op = NAME;
575 	p->n_lval = 0;
576 	p->n_sp = sp;
577 
578 }
579 
580 /*ARGSUSED*/
581 int
andable(NODE * p)582 andable(NODE *p)
583 {
584 	return(1);  /* all names can have & taken on them */
585 }
586 
587 /*
588  * Return 1 if a variable of type "t" is OK to put in register.
589  */
590 int
cisreg(TWORD t)591 cisreg(TWORD t)
592 {
593 	return 1;
594 }
595 
596 /*
597  * Allocate off bits on the stack.  p is a tree that when evaluated
598  * is the multiply count for off, t is a storeable node where to write
599  * the allocated address.
600  */
601 void
spalloc(NODE * t,NODE * p,OFFSZ off)602 spalloc(NODE *t, NODE *p, OFFSZ off)
603 {
604 	NODE *sp;
605 
606 	p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */
607 
608 	/* sub the size from sp */
609 	sp = block(REG, NIL, NIL, p->n_type, 0, 0);
610 	sp->n_lval = 0;
611 	sp->n_rval = STKREG;
612 	ecomp(buildtree(PLUSEQ, sp, p));
613 
614 	/* save the address of sp */
615 	sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue);
616 	sp->n_lval = 0;
617 	sp->n_rval = STKREG;
618 	t->n_type = sp->n_type;
619 	ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
620 
621 }
622 
623 /*
624  * print out a constant node, may be associated with a label.
625  * Do not free the node after use.
626  * off is bit offset from the beginning of the aggregate
627  * fsz is the number of bits this is referring to
628  *
629  * XXX this relies on the host fp numbers representation
630  */
631 int
ninval(CONSZ off,int fsz,NODE * p)632 ninval(CONSZ off, int fsz, NODE *p)
633 {
634 	union { float f; double d; long double l; int i[3]; } u;
635 	struct symtab *q;
636 	TWORD t;
637 	int i;
638 
639 	t = p->n_type;
640 	if (t > BTMASK)
641 		p->n_type = t = INT; /* pointer */
642 
643 	if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
644 		uerror("element not constant");
645 
646 	switch (t) {
647 	case LONGLONG:
648 	case ULONGLONG:
649 		i = (p->n_lval >> 32);
650 		p->n_lval &= 0xffffffff;
651 		p->n_type = INT;
652 		ninval(off, 32, p);
653 		p->n_lval = i;
654 		ninval(off+32, 32, p);
655 		break;
656 	case INT:
657 	case UNSIGNED:
658 		printf("\t.long 0x%x", (int)p->n_lval);
659 		if ((q = p->n_sp) != NULL) {
660 			if ((q->sclass == STATIC && q->slevel > 0)) {
661 				printf("+" LABFMT, q->soffset);
662 			} else
663 				printf("+%s",
664 				    q->soname ? q->soname : exname(q->sname));
665 		}
666 		printf("\n");
667 		break;
668 	case LDOUBLE:
669 	case DOUBLE:
670 		u.d = (double)p->n_dcon;
671 		printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]);
672 		break;
673 	case FLOAT:
674 		u.f = (float)p->n_dcon;
675 		printf("\t.long\t0x%x\n", u.i[0]);
676 		break;
677 	default:
678 		return 0;
679 	}
680 	return 1;
681 }
682 
683 /* make a name look like an external name in the local machine */
684 char *
exname(char * p)685 exname(char *p)
686 {
687 	if (p == NULL)
688 		return "";
689 	return p;
690 }
691 
692 /*
693  * map types which are not defined on the local machine
694  */
695 TWORD
ctype(TWORD type)696 ctype(TWORD type)
697 {
698 	switch (BTYPE(type)) {
699 	case LONG:
700 		MODTYPE(type,INT);
701 		break;
702 
703 	case ULONG:
704 		MODTYPE(type,UNSIGNED);
705 	}
706 
707 	return (type);
708 }
709 
710 void
calldec(NODE * f,NODE * a)711 calldec(NODE *f, NODE *a)
712 {
713 	struct symtab *q;
714 	if (f->n_op == UMUL && f->n_left->n_op == PLUS &&
715 	    f->n_left->n_right->n_op == ICON)
716 		q = f->n_left->n_right->n_sp;
717 	else if (f->n_op == PLUS && f->n_right->n_op == ICON)
718 		q = f->n_right->n_sp;
719 	else {
720 		fwalk(f, eprint, 0);
721 		cerror("unknown function");
722 		return;
723 	}
724 
725 	printf("\t.import\t%s,code\n", q->soname ? q->soname : exname(q->sname));
726 }
727 
728 void
extdec(struct symtab * q)729 extdec(struct symtab *q)
730 {
731 	printf("\t.import\t%s,data\n", q->soname ? q->soname : exname(q->sname));
732 }
733 
734 /* make a common declaration for id, if reasonable */
735 void
defzero(struct symtab * sp)736 defzero(struct symtab *sp)
737 {
738 	int off;
739 
740 	off = tsize(sp->stype, sp->sdf, sp->ssue);
741 	off = (off + (SZCHAR - 1)) / SZCHAR;
742 	printf("\t.%scomm\t", sp->sclass == STATIC ? "l" : "");
743 	if (sp->slevel == 0)
744 		printf("%s,0%o\n", sp->soname ? sp->soname : exname(sp->sname), off);
745 	else
746 		printf(LABFMT ",0%o\n", sp->soffset, off);
747 }
748 
749 static char *
section2string(char * name)750 section2string(char *name)
751 {
752 	int len = strlen(name);
753 
754 	if (strncmp(name, "link_set", 8) == 0) {
755 		const char postfix[] = ",\"aw\",@progbits";
756 		char *s;
757 
758 		s = IALLOC(len + sizeof(postfix));
759 		memcpy(s, name, len);
760 		memcpy(s + len, postfix, sizeof(postfix));
761 		return s;
762 	}
763 
764 	return newstring(name, len);
765 }
766 
767 char *nextsect;
768 char *alias;
769 int constructor;
770 int destructor;
771 
772 #define	SSECTION	010000
773 
774 /*
775  * Give target the opportunity of handling pragmas.
776  */
777 int
mypragma(char * str)778 mypragma(char *str)
779 {
780 	char *a2 = pragtok(NULL);
781 
782 	if (strcmp(str, "constructor") == 0 || strcmp(str, "init") == 0) {
783 		constructor = 1;
784 		return 1;
785 	}
786 	if (strcmp(str, "destructor") == 0 || strcmp(str, "fini") == 0) {
787 		destructor = 1;
788 		return 1;
789 	}
790 	if (strcmp(str, "section") == 0 && a2 != NULL) {
791 		nextsect = section2string(a2);
792 		return 1;
793 	}
794 	if (strcmp(str, "alias") == 0 && a2 != NULL) {
795 		alias = tmpstrdup(a2);
796 		return 1;
797 	}
798 	return 0;
799 }
800 
801 /*
802  * Called when a identifier has been declared, to give target last word.
803  */
804 void
fixdef(struct symtab * sp)805 fixdef(struct symtab *sp)
806 {
807 	if (alias != NULL && (sp->sclass != PARAM)) {
808 		printf("\t.globl %s\n%s = %s\n", exname(sp->soname),
809 		    exname(sp->soname), exname(alias));
810 		alias = NULL;
811 	}
812 	if ((constructor || destructor) && (sp->sclass != PARAM)) {
813 		printf("\t.section .%ctors,\"aw\",@progbits\n"
814 		    "\t.p2align 2\n\t.long %s\n\t.previous\n",
815 		    constructor ? 'c' : 'd', exname(sp->sname));
816 		constructor = destructor = 0;
817 	}
818 }
819 
820 void
pass1_lastchance(struct interpass * ip)821 pass1_lastchance(struct interpass *ip)
822 {
823 }
824