source: mainline/uspace/app/pcc/arch/hppa/local.c@ 0395a7b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0395a7b was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

  • Property mode set to 100644
File size: 22.3 KB
Line 
1/* $OpenBSD: local.c,v 1.2 2007/11/18 17:39:55 ragge Exp $ */
2
3/*
4 * Copyright (c) 2007 Michael Shalayeff
5 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission
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
39struct symtab *makememcpy(void);
40char *section2string(char *, int);
41
42/* clocal() is called to do local transformations on
43 * an expression tree preparitory to its being
44 * written out in intermediate code.
45 *
46 * the major essential job is rewriting the
47 * automatic variables and arguments in terms of
48 * REG and OREG nodes
49 * conversion ops which are not necessary are also clobbered here
50 * in addition, any special features (such as rewriting
51 * exclusive or) are easily handled here as well
52 */
53NODE *
54clocal(NODE *p)
55{
56 register struct symtab *q, *sp;
57 register NODE *r, *l, *s;
58 register int o, m, rn;
59 char *ch, name[16], *n;
60 TWORD t;
61
62#ifdef PCC_DEBUG
63 if (xdebug) {
64 printf("clocal: %p\n", p);
65 fwalk(p, eprint, 0);
66 }
67#endif
68 switch (o = p->n_op) {
69
70 case NAME:
71 if ((q = p->n_sp) == NULL)
72 break; /* Nothing to care about */
73
74 switch (q->sclass) {
75
76 case PARAM:
77 /* first four integral args are in regs */
78 rn = (q->soffset >> 5) - 8;
79 if (rn < 4) {
80 r = block(REG, NIL, NIL, p->n_type, 0, 0);
81 r->n_lval = 0;
82 switch (p->n_type) {
83 case FLOAT:
84 r->n_rval = FR7L - rn;
85 break;
86 case DOUBLE:
87 case LDOUBLE:
88 r->n_rval = FR6 - rn;
89 break;
90 case LONGLONG:
91 case ULONGLONG:
92 r->n_rval = AD1 - rn / 2;
93 break;
94 default:
95 r->n_rval = ARG0 - rn;
96 }
97 r->n_sue = p->n_sue;
98 p->n_sue = NULL;
99 nfree(p);
100 p = r;
101 break;
102 }
103 /* FALLTHROUGH */
104
105 case AUTO:
106 /* fake up a structure reference */
107 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
108 r->n_lval = 0;
109 r->n_rval = FPREG;
110 p = stref(block(STREF, r, p, 0, 0, 0));
111 break;
112
113 case REGISTER:
114 p->n_op = REG;
115 p->n_lval = 0;
116 p->n_rval = q->soffset;
117 break;
118
119 case STATIC:
120 case EXTERN:
121 if (p->n_sp->sflags & SSTRING)
122 break;
123
124 n = p->n_sp->soname ? p->n_sp->soname : p->n_sp->sname;
125 if (strncmp(n, "__builtin", 9) == 0)
126 break;
127
128 l = block(REG, NIL, NIL, INT, 0, 0);
129 l->n_lval = 0;
130 l->n_rval = R1;
131 l = block(ASSIGN, l, p, INT, 0, 0);
132 r = xbcon(0, p->n_sp, INT);
133 p = block(UMUL,
134 block(PLUS, l, r, INT, 0, 0),
135 NIL, p->n_type, p->n_df, p->n_sue);
136 break;
137 }
138 break;
139
140 case ADDROF:
141 l = p->n_left;
142 if (!l->n_sp)
143 break;
144
145 if (l->n_sp->sclass != EXTERN &&
146 l->n_sp->sclass != STATIC &&
147 l->n_sp->sclass != USTATIC &&
148 l->n_sp->sclass != EXTDEF)
149 break;
150
151 l = block(REG, NIL, NIL, INT, 0, 0);
152 l->n_lval = 0;
153 l->n_rval = R1;
154 l = block(ASSIGN, l, p->n_left, INT, 0, 0);
155 r = xbcon(0, p->n_left->n_sp, INT);
156 l = block(PLUS, l, r, p->n_type, p->n_df, p->n_sue);
157 nfree(p);
158 p = l;
159 break;
160
161 case CBRANCH:
162 l = p->n_left;
163
164 /*
165 * Remove unnecessary conversion ops.
166 */
167 if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
168 if (coptype(l->n_op) != BITYPE)
169 break;
170 if (l->n_right->n_op == ICON) {
171 r = l->n_left->n_left;
172 if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
173 break;
174 /* Type must be correct */
175 t = r->n_type;
176 nfree(l->n_left);
177 l->n_left = r;
178 l->n_type = t;
179 l->n_right->n_type = t;
180 }
181 }
182 break;
183
184 case PCONV:
185 /* Remove redundant PCONV's. Be careful */
186 l = p->n_left;
187 if (l->n_op == ICON) {
188 l->n_lval = (unsigned)l->n_lval;
189 goto delp;
190 }
191 if (l->n_type < INT || l->n_type == LONGLONG ||
192 l->n_type == ULONGLONG) {
193 /* float etc? */
194 p->n_left = block(SCONV, l, NIL,
195 UNSIGNED, 0, MKSUE(UNSIGNED));
196 break;
197 }
198 /* if left is SCONV, cannot remove */
199 if (l->n_op == SCONV)
200 break;
201
202 /* avoid ADDROF TEMP */
203 if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
204 break;
205
206 /* if conversion to another pointer type, just remove */
207 if (p->n_type > BTMASK && l->n_type > BTMASK)
208 goto delp;
209 break;
210
211 delp: l->n_type = p->n_type;
212 l->n_qual = p->n_qual;
213 l->n_df = p->n_df;
214 l->n_sue = p->n_sue;
215 nfree(p);
216 p = l;
217 break;
218
219 case SCONV:
220 l = p->n_left;
221
222 if (p->n_type == l->n_type) {
223 nfree(p);
224 p = l;
225 break;
226 }
227
228 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
229 btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
230 if (p->n_type != FLOAT && p->n_type != DOUBLE &&
231 l->n_type != FLOAT && l->n_type != DOUBLE &&
232 l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
233 if (l->n_op == UMUL || l->n_op == TEMP ||
234 l->n_op == NAME) {
235 l->n_type = p->n_type;
236 nfree(p);
237 p = l;
238 break;
239 }
240 }
241 }
242
243 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
244 coptype(l->n_op) == BITYPE) {
245 l->n_type = p->n_type;
246 nfree(p);
247 p = l;
248 break;
249 }
250
251 o = l->n_op;
252 m = p->n_type;
253
254 if (o == ICON) {
255 CONSZ val = l->n_lval;
256
257 if (!ISPTR(m)) /* Pointers don't need to be conv'd */
258 switch (m) {
259 case BOOL:
260 l->n_lval = l->n_lval != 0;
261 break;
262 case CHAR:
263 l->n_lval = (char)val;
264 break;
265 case UCHAR:
266 l->n_lval = val & 0377;
267 break;
268 case SHORT:
269 l->n_lval = (short)val;
270 break;
271 case USHORT:
272 l->n_lval = val & 0177777;
273 break;
274 case ULONG:
275 case UNSIGNED:
276 l->n_lval = val & 0xffffffff;
277 break;
278 case LONG:
279 case INT:
280 l->n_lval = (int)val;
281 break;
282 case LONGLONG:
283 l->n_lval = (long long)val;
284 break;
285 case ULONGLONG:
286 l->n_lval = val;
287 break;
288 case VOID:
289 break;
290 case LDOUBLE:
291 case DOUBLE:
292 case FLOAT:
293 l->n_op = FCON;
294 l->n_dcon = val;
295 break;
296 default:
297 cerror("unknown type %d", m);
298 }
299 l->n_type = m;
300 l->n_sue = MKSUE(m);
301 nfree(p);
302 return l;
303 } else if (l->n_op == FCON) {
304 l->n_lval = l->n_dcon;
305 l->n_sp = NULL;
306 l->n_op = ICON;
307 l->n_type = m;
308 l->n_sue = MKSUE(m);
309 nfree(p);
310 return clocal(l);
311 }
312
313 if (DEUNSIGN(p->n_type) == SHORT &&
314 DEUNSIGN(l->n_type) == SHORT) {
315 nfree(p);
316 p = l;
317 }
318 if ((p->n_type == CHAR || p->n_type == UCHAR ||
319 p->n_type == SHORT || p->n_type == USHORT) &&
320 (l->n_type == FLOAT || l->n_type == DOUBLE ||
321 l->n_type == LDOUBLE)) {
322 p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue);
323 p->n_left->n_type = INT;
324 break;
325 }
326 break;
327
328 case MOD:
329 case DIV:
330 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
331 break;
332 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
333 break;
334 /* make it an int division by inserting conversions */
335 p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKSUE(INT));
336 p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKSUE(INT));
337 p = block(SCONV, p, NIL, p->n_type, 0, MKSUE(p->n_type));
338 p->n_left->n_type = INT;
339 break;
340
341 case PMCONV:
342 case PVCONV:
343 if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0);
344 nfree(p);
345 return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right));
346
347 case LS:
348 case RS:
349 /* shift count must be in an int */
350 if (p->n_right->n_op == ICON || p->n_right->n_lval <= 32)
351 break; /* do not do anything */
352 if (p->n_right->n_type != INT || p->n_right->n_lval > 32)
353 p->n_right = block(SCONV, p->n_right, NIL,
354 INT, 0, MKSUE(INT));
355 break;
356
357#if 0
358 case FLD:
359 /* already rewritten (in ASSIGN) */
360 if (p->n_left->n_op == TEMP)
361 break;
362
363 r = tempnode(0, p->n_type, p->n_df, p->n_sue);
364 l = block(ASSIGN, r, p->n_left, p->n_type, p->n_df, p->n_sue);
365 p->n_left = tcopy(r);
366 p = block(COMOP, l, p, p->n_type, p->n_df, p->n_sue);
367 break;
368#endif
369
370 case FORCE:
371 /* put return value in return reg */
372 p->n_op = ASSIGN;
373 p->n_right = p->n_left;
374 p->n_left = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue);
375 p->n_left->n_rval = p->n_left->n_type == BOOL ?
376 RETREG(CHAR) : RETREG(p->n_type);
377 if (p->n_right->n_op != FLD)
378 break;
379 break;
380
381 case ASSIGN:
382 r = p->n_right;
383 l = p->n_left;
384
385 /* rewrite ICON#0 into %r0 */
386 if (r->n_op == ICON && r->n_lval == 0 &&
387 (l->n_op == REG || l->n_op == OREG)) {
388 r->n_op = REG;
389 r->n_rval = R0;
390 }
391
392 /* rewrite FCON#0 into %fr0 */
393 if (r->n_op == FCON && r->n_lval == 0 && l->n_op == REG) {
394 r->n_op = REG;
395 r->n_rval = r->n_type == FLOAT? FR0L : FR0;
396 }
397
398 if (p->n_left->n_op != FLD)
399 break;
400
401 r = tempnode(0, l->n_type, l->n_df, l->n_sue);
402 p = block(COMOP,
403 block(ASSIGN, r, l->n_left, l->n_type, l->n_df, l->n_sue),
404 p, p->n_type, p->n_df, p->n_sue);
405 s = tcopy(l->n_left);
406 p = block(COMOP, p,
407 block(ASSIGN, s, tcopy(r), l->n_type, l->n_df, l->n_sue),
408 p->n_type, p->n_df, p->n_sue);
409 l->n_left = tcopy(r);
410 break;
411
412 case STASG:
413 /* memcpy(left, right, size) */
414 sp = makememcpy();
415 l = p->n_left;
416 /* guess struct return */
417 if (l->n_op == NAME && ISFTN(l->n_sp->stype)) {
418 l = block(REG, NIL, NIL, VOID|PTR, 0, MKSUE(LONG));
419 l->n_lval = 0;
420 l->n_rval = RET0;
421 } else if (l->n_op == UMUL)
422 l = tcopy(l->n_left);
423 else if (l->n_op == NAME)
424 l = block(ADDROF,tcopy(l),NIL,PTR|STRTY,0,MKSUE(LONG));
425 l = block(CALL, block(ADDROF,
426 (s = block(NAME, NIL, NIL, FTN, 0, MKSUE(LONG))),
427 NIL, PTR|FTN, 0, MKSUE(LONG)),
428 block(CM, block(CM, l, tcopy(p->n_right),
429 STRTY|PTR, 0, MKSUE(LONG)),
430 (r = block(ICON, NIL, NIL, INT, 0, MKSUE(LONG))), 0, 0, 0),
431 INT, 0, MKSUE(LONG));
432 r->n_lval = p->n_sue->suesize/SZCHAR;
433 s->n_sp = sp;
434 s->n_df = s->n_sp->sdf;
435 defid(s, EXTERN);
436 tfree(p);
437 p = l;
438 p->n_left = clocal(p->n_left);
439 p->n_right = clocal(p->n_right);
440 calldec(p->n_left, p->n_right);
441 funcode(p);
442 break;
443
444 case STARG:
445 /* arg = memcpy(argN-size, src, size) */
446 sp = makememcpy();
447 l = block(CALL, block(ADDROF,
448 (s = block(NAME, NIL, NIL, FTN, 0, MKSUE(LONG))),NIL,0,0,0),
449 block(CM, block(CM, tcopy(p), tcopy(p->n_left), 0, 0, 0),
450 (r = block(ICON, NIL, NIL, INT, 0, MKSUE(LONG))), 0, 0, 0),
451 INT, 0, MKSUE(LONG));
452 r->n_lval = p->n_sue->suesize/SZCHAR;
453 s->n_sp = sp;
454 s->n_df = s->n_sp->sdf;
455 defid(s, EXTERN);
456 tfree(p);
457 p = l;
458 p->n_left = clocal(p->n_left);
459 calldec(p->n_left, p->n_right);
460 funcode(p);
461 break;
462
463 case STCALL:
464 case CALL:
465 for (r = p->n_right; r->n_op == CM; r = r->n_left) {
466 if (r->n_right->n_op == ASSIGN &&
467 r->n_right->n_right->n_op == CALL) {
468 s = r->n_right->n_right;
469 l = tempnode(0, s->n_type, s->n_df, s->n_sue);
470 ecode(buildtree(ASSIGN, l, s));
471 r->n_right->n_right = tcopy(l);
472 }
473 if (r->n_left->n_op == ASSIGN &&
474 r->n_left->n_right->n_op == CALL) {
475 s = r->n_left->n_right;
476 l = tempnode(0, s->n_type, s->n_df, s->n_sue);
477 ecode(buildtree(ASSIGN, l, s));
478 r->n_left->n_right = tcopy(l);
479 }
480 }
481 break;
482 }
483
484 /* second pass - rewrite long ops */
485 switch (o) {
486 case DIV:
487 case MOD:
488 case MUL:
489 case RS:
490 case LS:
491 if (!(p->n_type == LONGLONG || p->n_type == ULONGLONG) ||
492 !((o == DIV || o == MOD || o == MUL) &&
493 p->n_type < FLOAT))
494 break;
495 if (o == DIV && p->n_type == ULONGLONG) ch = "udiv";
496 else if (o == DIV) ch = "div";
497 else if (o == MUL) ch = "mul";
498 else if (o == MOD && p->n_type == ULONGLONG) ch = "umod";
499 else if (o == MOD) ch = "mod";
500 else if (o == RS && p->n_type == ULONGLONG) ch = "lshr";
501 else if (o == RS) ch = "ashr";
502 else if (o == LS) ch = "ashl";
503 else break;
504 snprintf(name, sizeof(name), "__%sdi3", ch);
505 p->n_right = block(CM, p->n_left, p->n_right, 0, 0, 0);
506 p->n_left = block(ADDROF,
507 block(NAME, NIL, NIL, FTN, 0, MKSUE(INT)), NIL,
508 PTR|FTN, 0, MKSUE(INT));
509 p->n_left->n_left->n_sp = lookup(addname(name), 0);
510 defid(p->n_left->n_left, EXTERN);
511 p->n_left = clocal(p->n_left);
512 calldec(p->n_left, p->n_right);
513 p->n_op = CALL;
514 funcode(p);
515 break;
516 }
517
518#ifdef PCC_DEBUG
519 if (xdebug) {
520 printf("clocal end: %p\n", p);
521 fwalk(p, eprint, 0);
522 }
523#endif
524 return(p);
525}
526
527struct symtab *
528makememcpy()
529{
530 NODE *memcpy, *args, *t, *u;
531 struct symtab *sp;
532
533 /* TODO check that it's a func proto */
534 if ((sp = lookup(addname("memcpy"), SNORMAL)))
535 return sp;
536
537 memcpy = block(NAME, NIL, NIL, 0, 0, MKSUE(LONG));
538 memcpy->n_sp = sp = lookup(addname("memcpy"), SNORMAL);
539 defid(memcpy, EXTERN);
540
541 args = block(CM, block(CM,
542 block(NAME, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)),
543 block(NAME, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)), 0, 0, 0),
544 block(NAME, NIL, NIL, LONG, 0, MKSUE(LONG)), 0, 0, 0);
545
546 tymerge(t = block(TYPE, NIL, NIL, VOID|PTR, 0, 0),
547 (u = block(UMUL, block(CALL, memcpy, args, LONG, 0, 0),
548 NIL, LONG, 0, 0)));
549 tfree(t);
550 tfree(u);
551
552 return sp;
553}
554
555void
556myp2tree(NODE *p)
557{
558 struct symtab *sp;
559 int o = p->n_op;
560
561 if (o != FCON)
562 return;
563
564 /* Write float constants to memory */
565 /* Should be volontary per architecture */
566
567#if 0
568 setloc1(RDATA);
569 defalign(p->n_type == FLOAT ? ALFLOAT : p->n_type == DOUBLE ?
570 ALDOUBLE : ALLDOUBLE );
571 deflab1(i = getlab());
572#endif
573 sp = inlalloc(sizeof(struct symtab));
574 sp->sclass = STATIC;
575 sp->ssue = MKSUE(p->n_type);
576 sp->slevel = 1; /* fake numeric label */
577 sp->soffset = getlab();
578 sp->sflags = 0;
579 sp->stype = p->n_type;
580 sp->squal = (CON >> TSHIFT);
581
582 defloc(sp);
583 ninval(0, btdims[p->n_type].suesize, p);
584
585 p->n_op = NAME;
586 p->n_lval = 0;
587 p->n_sp = sp;
588
589}
590
591/*ARGSUSED*/
592int
593andable(NODE *p)
594{
595 return(1); /* all names can have & taken on them */
596}
597
598/*
599 * at the end of the arguments of a ftn, set the automatic offset
600 */
601void
602cendarg()
603{
604 /* TODO can use to generate sp/rp tree ops? */
605 autooff = AUTOINIT;
606}
607
608/*
609 * Return 1 if a variable of type "t" is OK to put in register.
610 */
611int
612cisreg(TWORD t)
613{
614 return 1;
615}
616
617/*
618 * return a node, for structure references, which is suitable for
619 * being added to a pointer of type t, in order to be off bits offset
620 * into a structure
621 * t, d, and s are the type, dimension offset, and sizeoffset
622 * For pdp10, return the type-specific index number which calculation
623 * is based on its size. For example, short a[3] would return 3.
624 * Be careful about only handling first-level pointers, the following
625 * indirections must be fullword.
626 */
627NODE *
628offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
629{
630 register NODE *p;
631
632 if (xdebug)
633 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
634 off, t, d, sue->suesize);
635
636 p = bcon(0);
637 p->n_lval = off/SZCHAR; /* Default */
638 return(p);
639}
640
641/*
642 * Allocate off bits on the stack. p is a tree that when evaluated
643 * is the multiply count for off, t is a storeable node where to write
644 * the allocated address.
645 */
646void
647spalloc(NODE *t, NODE *p, OFFSZ off)
648{
649 NODE *sp;
650
651 p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */
652
653 /* sub the size from sp */
654 sp = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
655 sp->n_lval = 0;
656 sp->n_rval = STKREG;
657 ecomp(buildtree(PLUSEQ, sp, p));
658
659 /* save the address of sp */
660 sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue);
661 sp->n_lval = 0;
662 sp->n_rval = STKREG;
663 t->n_type = sp->n_type;
664 ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
665
666}
667
668#if 0
669/*
670 * Print out an integer constant of size size.
671 * can only be sizes <= SZINT.
672 */
673void
674indata(CONSZ val, int size)
675{
676 switch (size) {
677 case SZCHAR:
678 printf("\t.byte %d\n", (int)val & 0xff);
679 break;
680 case SZSHORT:
681 printf("\t.word %d\n", (int)val & 0xffff);
682 break;
683 case SZINT:
684 printf("\t.long %d\n", (int)val & 0xffffffff);
685 break;
686 default:
687 cerror("indata");
688 }
689}
690#endif
691
692/*
693 * Print out a string of characters.
694 * Assume that the assembler understands C-style escape
695 * sequences. Location is already set.
696 */
697void
698instring(struct symtab *sp)
699{
700 char *s, *str;
701
702 defloc(sp);
703 str = sp->sname;
704
705 /* be kind to assemblers and avoid long strings */
706 printf("\t.ascii\t\"");
707 for (s = str; *s != 0; ) {
708 if (*s++ == '\\') {
709 (void)esccon(&s);
710 }
711 if (s - str > 64) {
712 fwrite(str, 1, s - str, stdout);
713 printf("\"\n\t.ascii\t\"");
714 str = s;
715 }
716 }
717 fwrite(str, 1, s - str, stdout);
718 printf("\\0\"\n");
719}
720
721static int inbits, inval;
722
723/*
724 * set fsz bits in sequence to zero.
725 */
726void
727zbits(OFFSZ off, int fsz)
728{
729 int m;
730
731 if (idebug)
732 printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits);
733 if ((m = (inbits % SZCHAR))) {
734 m = SZCHAR - m;
735 if (fsz < m) {
736 inbits += fsz;
737 return;
738 } else {
739 fsz -= m;
740 printf("\t.byte %d\n", inval);
741 inval = inbits = 0;
742 }
743 }
744 if (fsz >= SZCHAR) {
745 printf("\t.zero %d\n", fsz/SZCHAR);
746 fsz -= (fsz/SZCHAR) * SZCHAR;
747 }
748 if (fsz) {
749 inval = 0;
750 inbits = fsz;
751 }
752}
753
754/*
755 * Initialize a bitfield.
756 */
757void
758infld(CONSZ off, int fsz, CONSZ val)
759{
760 if (idebug)
761 printf("infld off %lld, fsz %d, val %lld inbits %d\n",
762 off, fsz, val, inbits);
763 val &= (1 << fsz)-1;
764 while (fsz + inbits >= SZCHAR) {
765 inval |= (val << inbits);
766 printf("\t.byte %d\n", inval & 255);
767 fsz -= (SZCHAR - inbits);
768 val >>= (SZCHAR - inbits);
769 inval = inbits = 0;
770 }
771 if (fsz) {
772 inval |= (val << inbits);
773 inbits += fsz;
774 }
775}
776
777/*
778 * print out a constant node, may be associated with a label.
779 * Do not free the node after use.
780 * off is bit offset from the beginning of the aggregate
781 * fsz is the number of bits this is referring to
782 *
783 * XXX this relies on the host fp numbers representation
784 */
785void
786ninval(CONSZ off, int fsz, NODE *p)
787{
788 union { float f; double d; long double l; int i[3]; } u;
789 struct symtab *q;
790 TWORD t;
791 int i;
792
793 t = p->n_type;
794 if (t > BTMASK)
795 t = INT; /* pointer */
796
797 if (p->n_op != ICON && p->n_op != FCON)
798 cerror("ninval: init node not constant");
799
800 if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
801 uerror("element not constant");
802
803 switch (t) {
804 case LONGLONG:
805 case ULONGLONG:
806 i = (p->n_lval >> 32);
807 p->n_lval &= 0xffffffff;
808 p->n_type = INT;
809 ninval(off, 32, p);
810 p->n_lval = i;
811 ninval(off+32, 32, p);
812 break;
813 case INT:
814 case UNSIGNED:
815 printf("\t.long 0x%x", (int)p->n_lval);
816 if ((q = p->n_sp) != NULL) {
817 if ((q->sclass == STATIC && q->slevel > 0)) {
818 printf("+" LABFMT, q->soffset);
819 } else
820 printf("+%s",
821 q->soname ? q->soname : exname(q->sname));
822 }
823 printf("\n");
824 break;
825 case SHORT:
826 case USHORT:
827 printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff);
828 break;
829 case BOOL:
830 if (p->n_lval > 1)
831 p->n_lval = p->n_lval != 0;
832 /* FALLTHROUGH */
833 case CHAR:
834 case UCHAR:
835 /* TODO make the upper layer give an .asciz */
836 printf("\t.byte %d\n", (int)p->n_lval & 0xff);
837 break;
838 case LDOUBLE:
839 case DOUBLE:
840 u.d = (double)p->n_dcon;
841 printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]);
842 break;
843 case FLOAT:
844 u.f = (float)p->n_dcon;
845 printf("\t.long\t0x%x\n", u.i[0]);
846 break;
847 default:
848 cerror("ninval");
849 }
850}
851
852/* make a name look like an external name in the local machine */
853char *
854exname(char *p)
855{
856 if (p == NULL)
857 return "";
858 return p;
859}
860
861/*
862 * map types which are not defined on the local machine
863 */
864TWORD
865ctype(TWORD type)
866{
867 switch (BTYPE(type)) {
868 case LONG:
869 MODTYPE(type,INT);
870 break;
871
872 case ULONG:
873 MODTYPE(type,UNSIGNED);
874 }
875
876 return (type);
877}
878
879void
880calldec(NODE *f, NODE *a)
881{
882 struct symtab *q;
883 if (f->n_op == UMUL && f->n_left->n_op == PLUS &&
884 f->n_left->n_right->n_op == ICON)
885 q = f->n_left->n_right->n_sp;
886 else if (f->n_op == PLUS && f->n_right->n_op == ICON)
887 q = f->n_right->n_sp;
888 else {
889 fwalk(f, eprint, 0);
890 cerror("unknown function");
891 return;
892 }
893
894 printf("\t.import\t%s,code\n", q->soname ? q->soname : exname(q->sname));
895}
896
897void
898extdec(struct symtab *q)
899{
900 printf("\t.import\t%s,data\n", q->soname ? q->soname : exname(q->sname));
901}
902
903/* make a common declaration for id, if reasonable */
904void
905defzero(struct symtab *sp)
906{
907 int off;
908
909 off = tsize(sp->stype, sp->sdf, sp->ssue);
910 off = (off + (SZCHAR - 1)) / SZCHAR;
911 printf("\t.%scomm\t", sp->sclass == STATIC ? "l" : "");
912 if (sp->slevel == 0)
913 printf("%s,0%o\n", sp->soname ? sp->soname : exname(sp->sname), off);
914 else
915 printf(LABFMT ",0%o\n", sp->soffset, off);
916}
917
918char *
919section2string(char *name, int len)
920{
921 char *s;
922 int n;
923
924 if (strncmp(name, "link_set", 8) == 0) {
925 const char *postfix = ",\"aw\",@progbits";
926 n = len + strlen(postfix) + 1;
927 s = IALLOC(n);
928 strlcpy(s, name, n);
929 strlcat(s, postfix, n);
930 return s;
931 }
932
933 return newstring(name, len);
934}
935
936char *nextsect;
937char *alias;
938int constructor;
939int destructor;
940
941#define SSECTION 010000
942
943/*
944 * Give target the opportunity of handling pragmas.
945 */
946int
947mypragma(char *str)
948{
949 char *a2 = pragtok(NULL);
950
951 if (strcmp(str, "constructor") == 0 || strcmp(str, "init") == 0) {
952 constructor = 1;
953 return 1;
954 }
955 if (strcmp(str, "destructor") == 0 || strcmp(str, "fini") == 0) {
956 destructor = 1;
957 return 1;
958 }
959 if (strcmp(str, "section") == 0 && a2 != NULL) {
960 nextsect = section2string(a2, strlen(a2));
961 return 1;
962 }
963 if (strcmp(str, "alias") == 0 && a2 != NULL) {
964 alias = tmpstrdup(a2);
965 return 1;
966 }
967 if (strcmp(str, "ident") == 0)
968 return 1; /* Just ignore */
969 return 0;
970}
971
972/*
973 * Called when a identifier has been declared, to give target last word.
974 */
975void
976fixdef(struct symtab *sp)
977{
978 if (alias != NULL && (sp->sclass != PARAM)) {
979 printf("\t.globl %s\n%s = %s\n", exname(sp->soname),
980 exname(sp->soname), exname(alias));
981 alias = NULL;
982 }
983 if ((constructor || destructor) && (sp->sclass != PARAM)) {
984 printf("\t.section .%ctors,\"aw\",@progbits\n"
985 "\t.p2align 2\n\t.long %s\n\t.previous\n",
986 constructor ? 'c' : 'd', exname(sp->sname));
987 constructor = destructor = 0;
988 }
989}
990
991void
992pass1_lastchance(struct interpass *ip)
993{
994}
Note: See TracBrowser for help on using the repository browser.