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