source: mainline/uspace/app/pcc/arch/amd64/local.c@ a7de7182

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a7de7182 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: 25.9 KB
Line 
1/* $Id: local.c,v 1.41.2.2 2011/03/02 17:40:07 ragge Exp $ */
2/*
3 * Copyright (c) 2008 Michael Shalayeff
4 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28
29#include "pass1.h"
30
31/* this file contains code which is dependent on the target machine */
32
33/*
34 * Check if a constant is too large for a type.
35 */
36static int
37toolarge(TWORD t, CONSZ con)
38{
39 U_CONSZ ucon = con;
40
41 switch (t) {
42 case ULONG:
43 case LONG:
44 case ULONGLONG:
45 case LONGLONG:
46 break; /* cannot be too large */
47#define SCHK(i) case i: if (con > MAX_##i || con < MIN_##i) return 1; break
48#define UCHK(i) case i: if (ucon > MAX_##i) return 1; break
49 SCHK(INT);
50 SCHK(SHORT);
51 case BOOL:
52 SCHK(CHAR);
53 UCHK(UNSIGNED);
54 UCHK(USHORT);
55 UCHK(UCHAR);
56 default:
57 cerror("toolarge");
58 }
59 return 0;
60}
61
62#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz))
63
64/*
65 * Make a symtab entry for PIC use.
66 */
67static struct symtab *
68picsymtab(char *p, char *s, char *s2)
69{
70 struct symtab *sp = IALLOC(sizeof(struct symtab));
71 size_t len = strlen(p) + strlen(s) + strlen(s2) + 1;
72
73 sp->sname = sp->soname = IALLOC(len);
74 strlcpy(sp->soname, p, len);
75 strlcat(sp->soname, s, len);
76 strlcat(sp->soname, s2, len);
77 sp->sclass = EXTERN;
78 sp->sflags = sp->slevel = 0;
79 return sp;
80}
81
82int gotnr; /* tempnum for GOT register */
83int argstacksize;
84static int ininval;
85
86/*
87 * Create a reference for an extern variable or function.
88 */
89static NODE *
90picext(NODE *p)
91{
92 NODE *q;
93 struct symtab *sp;
94 char *c, *g;
95
96 if (p->n_sp->sflags & SBEENHERE)
97 return p;
98
99 c = p->n_sp->soname ? p->n_sp->soname : exname(p->n_sp->sname);
100#ifdef notdef
101 g = ISFTN(p->n_sp->stype) ? "@PLT" : "@GOTPCREL";
102#endif
103 g = "@GOTPCREL";
104 sp = picsymtab("", c, g);
105 sp->sflags = SBEENHERE;
106 q = block(NAME, NIL, NIL, INCREF(p->n_type), p->n_df, p->n_ap);
107 q->n_sp = sp;
108 q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
109 q->n_sp = sp;
110 nfree(p);
111 return q;
112}
113
114#ifdef notdef
115/*
116 * Create a reference for a static variable.
117 */
118static NODE *
119picstatic(NODE *p)
120{
121 struct symtab *sp;
122 char *c, buf[32];
123
124 if (p->n_sp->slevel > 0)
125 snprintf(c = buf, 32, LABFMT, (int)p->n_sp->soffset);
126 else
127 c = p->n_sp->soname ? p->n_sp->soname : p->n_sp->sname;
128 sp = picsymtab("", c, "");
129 sp->sclass = STATIC;
130 sp->stype = p->n_sp->stype;
131 p->n_sp = sp;
132 return p;
133}
134#endif
135
136static NODE *
137cmop(NODE *l, NODE *r)
138{
139 return block(CM, l, r, INT, 0, MKAP(INT));
140}
141
142static NODE *
143mkx(char *s, NODE *p)
144{
145 p = block(XARG, p, NIL, INT, 0, MKAP(INT));
146 p->n_name = s;
147 return p;
148}
149
150static char *
151mk3str(char *s1, char *s2, char *s3)
152{
153 int len = strlen(s1) + strlen(s2) + strlen(s3) + 1;
154 char *sd;
155
156 sd = inlalloc(len);
157 strlcpy(sd, s1, len);
158 strlcat(sd, s2, len);
159 strlcat(sd, s3, len);
160 return sd;
161}
162
163/*
164 * Create a reference for a TLS variable.
165 * This is the "General dynamic" version.
166 */
167static NODE *
168tlspic(NODE *p)
169{
170 NODE *q, *r, *s;
171 char *s1, *s2;
172
173 /*
174 * .byte 0x66
175 * leaq x@TLSGD(%rip),%rdi
176 * .word 0x6666
177 * rex64
178 * call __tls_get_addr@PLT
179 */
180
181 /* Need the .byte stuff around. Why? */
182 /* Use inline assembler */
183 q = mkx("%rdx", bcon(0));
184 q = cmop(q, mkx("%rcx", bcon(0)));
185 q = cmop(q, mkx("%rsi", bcon(0)));
186 q = cmop(q, mkx("%rdi", bcon(0)));
187 q = cmop(q, mkx("%r8", bcon(0)));
188 q = cmop(q, mkx("%r9", bcon(0)));
189 q = cmop(q, mkx("%r10", bcon(0)));
190 q = cmop(q, mkx("%r11", bcon(0)));
191
192 s = ccopy(r = tempnode(0, INCREF(p->n_type), p->n_df, p->n_ap));
193 r = mkx("=a", r);
194 r = block(XASM, r, q, INT, 0, MKAP(INT));
195
196 /* Create the magic string */
197 s1 = ".byte 0x66\n\tleaq ";
198 s2 = "@TLSGD(%%rip),%%rdi\n"
199 "\t.word 0x6666\n\trex64\n\tcall __tls_get_addr@PLT";
200 if (p->n_sp->soname == NULL)
201 p->n_sp->soname = p->n_sp->sname;
202 r->n_name = mk3str(s1, p->n_sp->soname, s2);
203
204 r = block(COMOP, r, s, INCREF(p->n_type), p->n_df, p->n_ap);
205 r = buildtree(UMUL, r, NIL);
206 tfree(p);
207 return r;
208}
209
210/*
211 * The "initial exec" tls model.
212 */
213static NODE *
214tlsinitialexec(NODE *p)
215{
216 NODE *q, *r, *s;
217 char *s1, *s2;
218
219 /*
220 * movq %fs:0,%rax
221 * addq x@GOTTPOFF(%rip),%rax
222 */
223
224 q = bcon(0);
225 q->n_type = STRTY;
226
227 s = ccopy(r = tempnode(0, INCREF(p->n_type), p->n_df, p->n_ap));
228 r = mkx("=r", r);
229 r = block(XASM, r, q, INT, 0, MKAP(INT));
230
231 s1 = "movq %%fs:0,%0\n\taddq ";
232 s2 = "@GOTTPOFF(%%rip),%0";
233 if (p->n_sp->soname == NULL)
234 p->n_sp->soname = p->n_sp->sname;
235 r->n_name = mk3str(s1, p->n_sp->soname, s2);
236
237 r = block(COMOP, r, s, INCREF(p->n_type), p->n_df, p->n_ap);
238 r = buildtree(UMUL, r, NIL);
239 tfree(p);
240 return r;
241}
242
243static NODE *
244tlsref(NODE *p)
245{
246 struct symtab *sp = p->n_sp;
247 struct attr *ga;
248 char *c;
249
250 if ((ga = attr_find(sp->sap, GCC_ATYP_TLSMODEL)) != NULL) {
251 c = ga->sarg(0);
252 if (strcmp(c, "initial-exec") == 0)
253 return tlsinitialexec(p);
254 else if (strcmp(c, "global-dynamic") == 0)
255 ;
256 else
257 werror("unsupported tls model '%s'", c);
258 }
259 return tlspic(p);
260}
261
262static NODE *
263stkblk(TWORD t)
264{
265 int al, tsz, off, noff;
266 struct attr *bt;
267 NODE *p;
268
269 bt = MKAP(BTYPE(t));
270 al = talign(t, bt);
271 tsz = (int)tsize(t, 0, bt);
272
273 noff = autooff + tsz;
274 SETOFF(noff, al);
275 off = -noff;
276 autooff = noff;
277
278 p = block(REG, NIL, NIL, INCREF(t), 0, bt);
279 p->n_lval = 0;
280 p->n_rval = FPREG;
281 p = buildtree(UMUL, buildtree(PLUS, p, bcon(off/SZLDOUBLE)), NIL);
282 return p;
283}
284
285
286/* clocal() is called to do local transformations on
287 * an expression tree preparitory to its being
288 * written out in intermediate code.
289 *
290 * the major essential job is rewriting the
291 * automatic variables and arguments in terms of
292 * REG and OREG nodes
293 * conversion ops which are not necessary are also clobbered here
294 * in addition, any special features (such as rewriting
295 * exclusive or) are easily handled here as well
296 */
297NODE *
298clocal(NODE *p)
299{
300
301 register struct symtab *q;
302 register NODE *r, *l;
303 register int o;
304 register int m;
305 TWORD t;
306
307#ifdef PCC_DEBUG
308 if (xdebug) {
309 printf("clocal: %p\n", p);
310 fwalk(p, eprint, 0);
311 }
312#endif
313 switch( o = p->n_op ){
314
315 case NAME:
316 if ((q = p->n_sp) == NULL)
317 return p; /* Nothing to care about */
318
319 switch (q->sclass) {
320
321 case PARAM:
322 case AUTO:
323 /* fake up a structure reference */
324 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
325 r->n_lval = 0;
326 r->n_rval = FPREG;
327 p = stref(block(STREF, r, p, 0, 0, 0));
328 break;
329
330 case USTATIC:
331 if (kflag == 0)
332 break;
333 /* FALLTHROUGH */
334 case STATIC:
335#ifdef TLS
336 if (q->sflags & STLS) {
337 p = tlsref(p);
338 break;
339 }
340#endif
341#ifdef notdef
342 if (kflag == 0) {
343 if (q->slevel == 0)
344 break;
345 p->n_lval = 0;
346 } else if (blevel > 0) {
347 if (!ISFTN(q->stype))
348 p = picstatic(p);
349 }
350#endif
351 break;
352
353 case REGISTER:
354 p->n_op = REG;
355 p->n_lval = 0;
356 p->n_rval = q->soffset;
357 break;
358
359 case EXTERN:
360 case EXTDEF:
361 if (q->sflags & STLS) {
362 p = tlsref(p);
363 break;
364 }
365 if (kflag == 0)
366 break;
367 if (blevel > 0)
368 p = picext(p);
369 break;
370 }
371 break;
372
373#if 0
374 case ADDROF:
375 if (kflag == 0 || blevel == 0)
376 break;
377 /* char arrays may end up here */
378 l = p->n_left;
379 if (l->n_op != NAME ||
380 (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE))
381 break;
382 l = p;
383 p = picstatic(p->n_left);
384 nfree(l);
385 if (p->n_op != UMUL)
386 cerror("ADDROF error");
387 l = p;
388 p = p->n_left;
389 nfree(l);
390 break;
391#endif
392
393 case UCALL:
394 case USTCALL:
395 /* For now, always clear eax */
396 l = block(REG, NIL, NIL, INT, 0, MKAP(INT));
397 regno(l) = RAX;
398 p->n_right = clocal(buildtree(ASSIGN, l, bcon(0)));
399 p->n_op -= (UCALL-CALL);
400
401 /* FALLTHROUGH */
402 case CALL:
403 case STCALL:
404 if (p->n_type == VOID)
405 break; /* nothing to do */
406 /* have the call at left of a COMOP to avoid arg trashing */
407 if (p->n_type == LDOUBLE) {
408 r = stkblk(LDOUBLE);
409 } else
410 r = tempnode(0, p->n_type, p->n_df, p->n_ap);
411 l = ccopy(r);
412 p = buildtree(COMOP, buildtree(ASSIGN, r, p), l);
413 break;
414
415#ifdef notyet
416 case CBRANCH:
417 l = p->n_left;
418
419 /*
420 * Remove unnecessary conversion ops.
421 */
422 if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
423 if (coptype(l->n_op) != BITYPE)
424 break;
425 if (l->n_right->n_op == ICON) {
426 r = l->n_left->n_left;
427 if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
428 break;
429 if (ISPTR(r->n_type))
430 break; /* no opt for pointers */
431 if (toolarge(r->n_type, l->n_right->n_lval))
432 break;
433 /* Type must be correct */
434 t = r->n_type;
435 nfree(l->n_left);
436 l->n_left = r;
437 l->n_type = t;
438 l->n_right->n_type = t;
439 }
440 }
441 break;
442#endif
443
444 case PCONV:
445 /* Remove redundant PCONV's. Be careful */
446 l = p->n_left;
447 if (l->n_op == ICON) {
448 goto delp;
449 }
450 if (l->n_type < LONG) {
451 /* float etc? */
452 p->n_left = block(SCONV, l, NIL,
453 UNSIGNED, 0, MKAP(UNSIGNED));
454 break;
455 }
456 /* if left is SCONV, cannot remove */
457 if (l->n_op == SCONV)
458 break;
459
460 /* avoid ADDROF TEMP */
461 if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
462 break;
463
464 if ((l->n_op == REG || l->n_op == TEMP) && ISPTR(l->n_type))
465 goto delp;
466#ifdef notdef
467 /* if conversion to another pointer type, just remove */
468 /* XXX breaks ADDROF NAME */
469 if (p->n_type > BTMASK && l->n_type > BTMASK)
470 goto delp;
471#endif
472 break;
473
474 delp: l->n_type = p->n_type;
475 l->n_qual = p->n_qual;
476 l->n_df = p->n_df;
477 l->n_ap = p->n_ap;
478 nfree(p);
479 p = l;
480 break;
481
482 case SCONV:
483 /* Special-case shifts */
484 if (p->n_type == LONG && (l = p->n_left)->n_op == LS &&
485 l->n_type == INT && l->n_right->n_op == ICON) {
486 p->n_left = l->n_left;
487 p = buildtree(LS, p, l->n_right);
488 nfree(l);
489 break;
490 }
491
492 l = p->n_left;
493
494 /* Float conversions may need extra casts */
495 if (p->n_type == FLOAT || p->n_type == DOUBLE ||
496 p->n_type == LDOUBLE) {
497 if (l->n_type < INT || l->n_type == BOOL) {
498 p->n_left = block(SCONV, l, NIL,
499 ISUNSIGNED(l->n_type) ? UNSIGNED : INT,
500 l->n_df, l->n_ap);
501 break;
502 }
503 }
504
505 if (p->n_type == l->n_type) {
506 nfree(p);
507 return l;
508 }
509
510 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
511 btattr[p->n_type].atypsz == btattr[l->n_type].atypsz) {
512 if (p->n_type != FLOAT && p->n_type != DOUBLE &&
513 l->n_type != FLOAT && l->n_type != DOUBLE &&
514 l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
515 if (l->n_op == NAME || l->n_op == UMUL ||
516 l->n_op == TEMP) {
517 l->n_type = p->n_type;
518 nfree(p);
519 return l;
520 }
521 }
522 }
523
524 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
525 coptype(l->n_op) == BITYPE && l->n_op != COMOP &&
526 l->n_op != QUEST) {
527 l->n_type = p->n_type;
528 nfree(p);
529 return l;
530 }
531
532 o = l->n_op;
533 m = p->n_type;
534
535 if (o == ICON) {
536 CONSZ val = l->n_lval;
537
538 if (!ISPTR(m)) /* Pointers don't need to be conv'd */
539 switch (m) {
540 case BOOL:
541 l->n_lval = nncon(l) ? (l->n_lval != 0) : 1;
542 l->n_sp = NULL;
543 break;
544 case CHAR:
545 l->n_lval = (char)val;
546 break;
547 case UCHAR:
548 l->n_lval = val & 0377;
549 break;
550 case SHORT:
551 l->n_lval = (short)val;
552 break;
553 case USHORT:
554 l->n_lval = val & 0177777;
555 break;
556 case UNSIGNED:
557 l->n_lval = val & 0xffffffff;
558 break;
559 case INT:
560 l->n_lval = (int)val;
561 break;
562 case LONG:
563 case LONGLONG:
564 l->n_lval = (long long)val;
565 break;
566 case ULONG:
567 case ULONGLONG:
568 l->n_lval = val;
569 break;
570 case VOID:
571 break;
572 case LDOUBLE:
573 case DOUBLE:
574 case FLOAT:
575 l->n_op = FCON;
576 l->n_dcon = val;
577 break;
578 default:
579 cerror("unknown type %d", m);
580 }
581 l->n_type = m;
582 l->n_ap = MKAP(m);
583 nfree(p);
584 return l;
585 } else if (l->n_op == FCON) {
586 if (p->n_type == BOOL)
587 l->n_lval = l->n_dcon != 0.0;
588 else
589 l->n_lval = l->n_dcon;
590 l->n_sp = NULL;
591 l->n_op = ICON;
592 l->n_type = m;
593 l->n_ap = MKAP(m);
594 nfree(p);
595 return clocal(l);
596 }
597 if (DEUNSIGN(p->n_type) == SHORT &&
598 DEUNSIGN(l->n_type) == SHORT) {
599 nfree(p);
600 p = l;
601 }
602 if ((p->n_type == CHAR || p->n_type == UCHAR ||
603 p->n_type == SHORT || p->n_type == USHORT) &&
604 (l->n_type == FLOAT || l->n_type == DOUBLE ||
605 l->n_type == LDOUBLE)) {
606 p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap);
607 p->n_left->n_type = INT;
608 return p;
609 }
610 break;
611
612 case MOD:
613 case DIV:
614 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
615 break;
616 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
617 break;
618 /* make it an int division by inserting conversions */
619 p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKAP(INT));
620 p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKAP(INT));
621 p = block(SCONV, p, NIL, p->n_type, 0, MKAP(p->n_type));
622 p->n_left->n_type = INT;
623 break;
624
625 case PMCONV:
626 case PVCONV:
627 r = p;
628 p = buildtree(o == PMCONV ? MUL : DIV, p->n_left, p->n_right);
629 nfree(r);
630 break;
631
632 case FORCE:
633 /* put return value in return reg */
634 p->n_op = ASSIGN;
635 p->n_right = p->n_left;
636 p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKAP(INT));
637 t = p->n_type;
638 if (ISITY(t))
639 t = t - (FIMAG-FLOAT);
640 p->n_left->n_rval = p->n_left->n_type == BOOL ?
641 RETREG(CHAR) : RETREG(t);
642 break;
643
644 case LS:
645 case RS:
646 /* shift count must be in a char */
647 if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR)
648 break;
649 p->n_right = block(SCONV, p->n_right, NIL,
650 CHAR, 0, MKAP(CHAR));
651 break;
652 }
653#ifdef PCC_DEBUG
654 if (xdebug) {
655 printf("clocal end: %p\n", p);
656 fwalk(p, eprint, 0);
657 }
658#endif
659 return(p);
660}
661
662void
663myp2tree(NODE *p)
664{
665 struct symtab *sp, sps;
666 static int dblxor, fltxor;
667
668 if (p->n_op == UMINUS && (p->n_type == FLOAT || p->n_type == DOUBLE)) {
669 /* Store xor code for sign change */
670 if (dblxor == 0) {
671 dblxor = getlab();
672 fltxor = getlab();
673 sps.stype = LDOUBLE;
674 sps.squal = CON >> TSHIFT;
675 sps.sflags = sps.sclass = 0;
676 sps.sname = sps.soname = "";
677 sps.slevel = 1;
678 sps.sap = MKAP(LDOUBLE); /* alignment */
679 sps.soffset = dblxor;
680 defloc(&sps);
681 printf("\t.long 0,0x80000000,0,0\n");
682 printf(LABFMT ":\n", fltxor);
683 printf("\t.long 0x80000000,0,0,0\n");
684 }
685 p->n_label = p->n_type == FLOAT ? fltxor : dblxor;
686 return;
687 }
688 if (p->n_op != FCON)
689 return;
690
691 /* XXX should let float constants follow */
692 sp = IALLOC(sizeof(struct symtab));
693 sp->sclass = STATIC;
694 sp->sap = MKAP(p->n_type);
695 sp->slevel = 1; /* fake numeric label */
696 sp->soffset = getlab();
697 sp->sflags = 0;
698 sp->stype = p->n_type;
699 sp->squal = (CON >> TSHIFT);
700
701 defloc(sp);
702 ninval(0, tsize(sp->stype, sp->sdf, sp->sap), p);
703
704 p->n_op = NAME;
705 p->n_lval = 0;
706 p->n_sp = sp;
707}
708
709/*
710 * Convert ADDROF NAME to ICON?
711 */
712int
713andable(NODE *p)
714{
715 if (ininval)
716 return 1;
717 if (p->n_sp->sclass == STATIC || p->n_sp->sclass == USTATIC)
718 return 0;
719 return 1;
720}
721
722/*
723 * at the end of the arguments of a ftn, set the automatic offset
724 */
725void
726cendarg()
727{
728 autooff = AUTOINIT;
729}
730
731/*
732 * Return 1 if a variable of type type is OK to put in register.
733 */
734int
735cisreg(TWORD t)
736{
737 if (t == LDOUBLE)
738 return 0;
739 return 1;
740}
741
742/*
743 * return a node, for structure references, which is suitable for
744 * being added to a pointer of type t, in order to be off bits offset
745 * into a structure
746 * t, d, and s are the type, dimension offset, and sizeoffset
747 * For pdp10, return the type-specific index number which calculation
748 * is based on its size. For example, short a[3] would return 3.
749 * Be careful about only handling first-level pointers, the following
750 * indirections must be fullword.
751 */
752NODE *
753offcon(OFFSZ off, TWORD t, union dimfun *d, struct attr *ap)
754{
755 register NODE *p;
756
757 if (xdebug)
758 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
759 off, t, d, (int)tsize(t, d, ap));
760
761 p = bcon(0);
762 p->n_lval = off/SZCHAR; /* Default */
763 return(p);
764}
765
766/*
767 * Allocate off bits on the stack. p is a tree that when evaluated
768 * is the multiply count for off, t is a storeable node where to write
769 * the allocated address.
770 */
771void
772spalloc(NODE *t, NODE *p, OFFSZ off)
773{
774 NODE *sp;
775
776 p = buildtree(MUL, p, bcon(off/SZCHAR));
777 p = buildtree(PLUS, p, bcon(30));
778 p = buildtree(AND, p, xbcon(-16, NULL, LONG));
779
780 /* sub the size from sp */
781 sp = block(REG, NIL, NIL, p->n_type, 0, MKAP(LONG));
782 sp->n_lval = 0;
783 sp->n_rval = STKREG;
784 ecomp(buildtree(MINUSEQ, sp, p));
785
786 /* save the address of sp */
787 sp = block(REG, NIL, NIL, PTR+LONG, t->n_df, t->n_ap);
788 sp->n_lval = 0;
789 sp->n_rval = STKREG;
790 t->n_type = sp->n_type;
791 ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
792
793}
794
795/*
796 * Print out a string of characters.
797 * Assume that the assembler understands C-style escape
798 * sequences.
799 */
800void
801instring(struct symtab *sp)
802{
803 char *s, *str = sp->sname;
804
805 defloc(sp);
806
807 /* be kind to assemblers and avoid long strings */
808 printf("\t.ascii \"");
809 for (s = str; *s != 0; ) {
810 if (*s++ == '\\') {
811 (void)esccon(&s);
812 }
813 if (s - str > 60) {
814 fwrite(str, 1, s - str, stdout);
815 printf("\"\n\t.ascii \"");
816 str = s;
817 }
818 }
819 fwrite(str, 1, s - str, stdout);
820 printf("\\0\"\n");
821}
822
823static int inbits, inval;
824
825/*
826 * set fsz bits in sequence to zero.
827 */
828void
829zbits(OFFSZ off, int fsz)
830{
831 int m;
832
833 if (idebug)
834 printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits);
835 if ((m = (inbits % SZCHAR))) {
836 m = SZCHAR - m;
837 if (fsz < m) {
838 inbits += fsz;
839 return;
840 } else {
841 fsz -= m;
842 printf("\t.byte %d\n", inval);
843 inval = inbits = 0;
844 }
845 }
846 if (fsz >= SZCHAR) {
847#ifdef MACHOABI
848 printf("\t.space %d\n", fsz/SZCHAR);
849#else
850 printf("\t.zero %d\n", fsz/SZCHAR);
851#endif
852 fsz -= (fsz/SZCHAR) * SZCHAR;
853 }
854 if (fsz) {
855 inval = 0;
856 inbits = fsz;
857 }
858}
859
860/*
861 * Initialize a bitfield.
862 */
863void
864infld(CONSZ off, int fsz, CONSZ val)
865{
866 if (idebug)
867 printf("infld off %lld, fsz %d, val %lld inbits %d\n",
868 off, fsz, val, inbits);
869 val &= (((((CONSZ)1 << (fsz-1))-1)<<1)|1);
870 while (fsz + inbits >= SZCHAR) {
871 inval |= (val << inbits);
872 printf("\t.byte %d\n", inval & 255);
873 fsz -= (SZCHAR - inbits);
874 val >>= (SZCHAR - inbits);
875 inval = inbits = 0;
876 }
877 if (fsz) {
878 inval |= (val << inbits);
879 inbits += fsz;
880 }
881}
882
883/*
884 * print out a constant node, may be associated with a label.
885 * Do not free the node after use.
886 * off is bit offset from the beginning of the aggregate
887 * fsz is the number of bits this is referring to
888 */
889void
890ninval(CONSZ off, int fsz, NODE *p)
891{
892 union { float f; double d; long double l; int i[3]; } u;
893 struct symtab *q;
894 NODE st, *op = NIL;
895 TWORD t;
896
897 if (coptype(p->n_op) != LTYPE) {
898 ininval = 1;
899 op = p = optim(ccopy(p));
900 ininval = 0;
901 }
902
903 while (p->n_op == PCONV)
904 p = p->n_left;
905
906 t = p->n_type;
907
908 if (kflag && p->n_op == NAME && ISPTR(t) &&
909 (ISFTN(DECREF(t)) || ISSOU(BTYPE(t)))) {
910 /* functions as initializers will be NAME here */
911 if (op == NIL) {
912 st = *p;
913 p = &st;
914 }
915 p->n_op = ICON;
916 }
917
918 if (t > BTMASK)
919 t = LONG; /* pointer */
920
921 if (p->n_op == COMOP) {
922 NODE *r = p->n_right;
923 tfree(p->n_left);
924 nfree(p);
925 p = r;
926 }
927
928 if (p->n_op != ICON && p->n_op != FCON) {
929fwalk(p, eprint, 0);
930 cerror("ninval: init node not constant");
931 }
932
933 if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != LONG)
934 uerror("element not constant");
935
936 switch (t) {
937 case LONG:
938 case ULONG:
939 printf("\t.quad 0x%llx", p->n_lval);
940 if ((q = p->n_sp) != NULL) {
941 if ((q->sclass == STATIC && q->slevel > 0)) {
942 printf("+" LABFMT, q->soffset);
943 } else {
944 char *name;
945 if ((name = q->soname) == NULL)
946 name = q->sname;
947 /* Never any PIC stuff in static init */
948 if (strchr(name, '@')) {
949 name = tmpstrdup(name);
950 *strchr(name, '@') = 0;
951 }
952 printf("+%s", name);
953 }
954 }
955 printf("\n");
956 break;
957 case INT:
958 case UNSIGNED:
959 printf("\t.long 0x%x\n", (int)p->n_lval & 0xffffffff);
960 break;
961 case SHORT:
962 case USHORT:
963 printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff);
964 break;
965 case BOOL:
966 if (p->n_lval > 1)
967 p->n_lval = p->n_lval != 0;
968 /* FALLTHROUGH */
969 case CHAR:
970 case UCHAR:
971 printf("\t.byte %d\n", (int)p->n_lval & 0xff);
972 break;
973 case LDOUBLE:
974 u.i[2] = 0;
975 u.l = (long double)p->n_dcon;
976#if defined(HOST_BIG_ENDIAN)
977 /* XXX probably broken on most hosts */
978 printf("\t.long\t0x%x,0x%x,0x%x,0\n", u.i[2], u.i[1], u.i[0]);
979#else
980 printf("\t.long\t0x%x,0x%x,0x%x,0\n", u.i[0], u.i[1], u.i[2]);
981#endif
982 break;
983 case DOUBLE:
984 u.d = (double)p->n_dcon;
985#if defined(HOST_BIG_ENDIAN)
986 printf("\t.long\t0x%x,0x%x\n", u.i[1], u.i[0]);
987#else
988 printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]);
989#endif
990 break;
991 case FLOAT:
992 u.f = (float)p->n_dcon;
993 printf("\t.long\t0x%x\n", u.i[0]);
994 break;
995 default:
996 cerror("ninval");
997 }
998 if (op)
999 tfree(op);
1000}
1001
1002/* make a name look like an external name in the local machine */
1003char *
1004exname(char *p)
1005{
1006#ifdef MACHOABI
1007
1008#define NCHNAM 256
1009 static char text[NCHNAM+1];
1010 int i;
1011
1012 if (p == NULL)
1013 return "";
1014
1015 text[0] = '_';
1016 for (i=1; *p && i<NCHNAM; ++i)
1017 text[i] = *p++;
1018
1019 text[i] = '\0';
1020 text[NCHNAM] = '\0'; /* truncate */
1021
1022 return (text);
1023#else
1024 return (p == NULL ? "" : p);
1025#endif
1026}
1027
1028/*
1029 * map types which are not defined on the local machine
1030 */
1031TWORD
1032ctype(TWORD type)
1033{
1034 switch (BTYPE(type)) {
1035 case LONGLONG:
1036 MODTYPE(type,LONG);
1037 break;
1038
1039 case ULONGLONG:
1040 MODTYPE(type,ULONG);
1041
1042 }
1043 return (type);
1044}
1045
1046void
1047calldec(NODE *p, NODE *q)
1048{
1049}
1050
1051void
1052extdec(struct symtab *q)
1053{
1054}
1055
1056int tbss;
1057
1058/* make a common declaration for id, if reasonable */
1059void
1060defzero(struct symtab *sp)
1061{
1062 TWORD t;
1063 int off;
1064 char *name;
1065
1066 if (sp->sflags & STLS) {
1067 if (sp->sclass == EXTERN)
1068 sp->sclass = EXTDEF;
1069 tbss = 1;
1070 for (t = sp->stype; ISARY(t); t = DECREF(t))
1071 ;
1072 if (t == STRTY || t == UNIONTY) {
1073 beginit(sp);
1074 endinit();
1075 } else
1076 simpleinit(sp, bcon(0));
1077 return;
1078 }
1079
1080 if ((name = sp->soname) == NULL)
1081 name = exname(sp->sname);
1082 off = tsize(sp->stype, sp->sdf, sp->sap);
1083 off = (off+(SZCHAR-1))/SZCHAR;
1084#ifdef GCC_COMPAT
1085 {
1086 struct attr *ga;
1087 if ((ga = attr_find(sp->sap, GCC_ATYP_VISIBILITY)) &&
1088 strcmp(ga->sarg(0), "default"))
1089 printf("\t.%s %s\n", ga->sarg(0), name);
1090 }
1091#endif
1092 printf(" .%scomm ", sp->sclass == STATIC ? "l" : "");
1093 if (sp->slevel == 0) {
1094 printf("%s,0%o\n", name, off);
1095 } else
1096 printf(LABFMT ",0%o\n", sp->soffset, off);
1097}
1098
1099static char *
1100section2string(char *name, int len)
1101{
1102 char *s;
1103 int n;
1104
1105 if (strncmp(name, "link_set", 8) == 0) {
1106 const char *postfix = ",\"aw\",@progbits";
1107 n = len + strlen(postfix) + 1;
1108 s = IALLOC(n);
1109 strlcpy(s, name, n);
1110 strlcat(s, postfix, n);
1111 return s;
1112 }
1113
1114 return newstring(name, len);
1115}
1116
1117char *nextsect;
1118static int gottls;
1119static char *alias;
1120static int constructor;
1121static int destructor;
1122
1123/*
1124 * Give target the opportunity of handling pragmas.
1125 */
1126int
1127mypragma(char *str)
1128{
1129 char *a2 = pragtok(NULL);
1130
1131 if (strcmp(str, "tls") == 0 && a2 == NULL) {
1132 gottls = 1;
1133 return 1;
1134 }
1135 if (strcmp(str, "constructor") == 0 || strcmp(str, "init") == 0) {
1136 constructor = 1;
1137 return 1;
1138 }
1139 if (strcmp(str, "destructor") == 0 || strcmp(str, "fini") == 0) {
1140 destructor = 1;
1141 return 1;
1142 }
1143 if (strcmp(str, "section") == 0 && a2 != NULL) {
1144 nextsect = section2string(a2, strlen(a2));
1145 return 1;
1146 }
1147 if (strcmp(str, "alias") == 0 && a2 != NULL) {
1148 alias = tmpstrdup(a2);
1149 return 1;
1150 }
1151
1152 return 0;
1153}
1154
1155/*
1156 * Called when a identifier has been declared.
1157 */
1158void
1159fixdef(struct symtab *sp)
1160{
1161 struct attr *ga;
1162
1163 /* may have sanity checks here */
1164 if (gottls)
1165 sp->sflags |= STLS;
1166 gottls = 0;
1167
1168#ifdef HAVE_WEAKREF
1169 /* not many as'es have this directive */
1170 if ((ga = gcc_get_attr(sp->sap, GCC_ATYP_WEAKREF)) != NULL) {
1171 char *wr = ga->a1.sarg;
1172 char *sn = sp->soname ? sp->soname : sp->sname;
1173 if (wr == NULL) {
1174 if ((ga = gcc_get_attr(sp->sap, GCC_ATYP_ALIAS))) {
1175 wr = ga->a1.sarg;
1176 }
1177 }
1178 if (wr == NULL)
1179 printf("\t.weak %s\n", sn);
1180 else
1181 printf("\t.weakref %s,%s\n", sn, wr);
1182 } else
1183#endif
1184 if ((ga = attr_find(sp->sap, GCC_ATYP_ALIAS)) != NULL) {
1185 char *an = ga->sarg(0);
1186 char *sn = sp->soname ? sp->soname : sp->sname;
1187 char *v;
1188
1189 v = attr_find(sp->sap, GCC_ATYP_WEAK) ? "weak" : "globl";
1190 printf("\t.%s %s\n", v, sn);
1191 printf("\t.set %s,%s\n", sn, an);
1192 }
1193 if (alias != NULL && (sp->sclass != PARAM)) {
1194 printf("\t.globl %s\n", exname(sp->soname));
1195 printf("%s = ", exname(sp->soname));
1196 printf("%s\n", exname(alias));
1197 alias = NULL;
1198 }
1199 if ((constructor || destructor) && (sp->sclass != PARAM)) {
1200 NODE *p = talloc();
1201
1202 p->n_op = NAME;
1203 p->n_sp =
1204 (struct symtab *)(constructor ? "constructor" : "destructor");
1205 sp->sap = attr_add(sp->sap, gcc_attr_parse(p));
1206 constructor = destructor = 0;
1207 }
1208}
1209
1210NODE *
1211i386_builtin_return_address(NODE *f, NODE *a, TWORD t)
1212{
1213 int nframes;
1214
1215 if (a == NULL || a->n_op != ICON)
1216 goto bad;
1217
1218 nframes = a->n_lval;
1219
1220 tfree(f);
1221 tfree(a);
1222
1223 f = block(REG, NIL, NIL, PTR+VOID, 0, MKAP(VOID));
1224 regno(f) = FPREG;
1225
1226 while (nframes--)
1227 f = block(UMUL, f, NIL, PTR+VOID, 0, MKAP(VOID));
1228
1229 f = block(PLUS, f, bcon(4), INCREF(PTR+VOID), 0, MKAP(VOID));
1230 f = buildtree(UMUL, f, NIL);
1231
1232 return f;
1233bad:
1234 uerror("bad argument to __builtin_return_address");
1235 return bcon(0);
1236}
1237
1238NODE *
1239i386_builtin_frame_address(NODE *f, NODE *a, TWORD t)
1240{
1241 int nframes;
1242
1243 if (a == NULL || a->n_op != ICON)
1244 goto bad;
1245
1246 nframes = a->n_lval;
1247
1248 tfree(f);
1249 tfree(a);
1250
1251 f = block(REG, NIL, NIL, PTR+VOID, 0, MKAP(VOID));
1252 regno(f) = FPREG;
1253
1254 while (nframes--)
1255 f = block(UMUL, f, NIL, PTR+VOID, 0, MKAP(VOID));
1256
1257 return f;
1258bad:
1259 uerror("bad argument to __builtin_frame_address");
1260 return bcon(0);
1261}
1262
1263void
1264pass1_lastchance(struct interpass *ip)
1265{
1266}
Note: See TracBrowser for help on using the repository browser.