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