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