Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:gmcgarry:20110527072739

Diff

Diff from 1.50 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/arch/amd64/local.c

Annotated File View

gmcgarry
1.50
1 /*      $Id: local.c,v 1.50 2011/05/27 07:27:39 gmcgarry Exp $  */
mickey
1.1
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  */
plunky
1.48
36 #ifdef notyet
mickey
1.1
37 static int
38 toolarge(TWORD tCONSZ con)
39 {
40         U_CONSZ ucon = con;
41
42         switch (t) {
43         case ULONG:
44         case LONG:
45         case ULONGLONG:
46         case LONGLONG:
47                 break/* cannot be too large */
48 #define SCHK(i) case i: if (con > MAX_##i || con < MIN_##i) return 1; break
49 #define UCHK(i) case i: if (ucon > MAX_##i) return 1; break
50         SCHK(INT);
51         SCHK(SHORT);
52         case BOOL:
53         SCHK(CHAR);
54         UCHK(UNSIGNED);
55         UCHK(USHORT);
56         UCHK(UCHAR);
57         default:
58                 cerror("toolarge");
59         }
60         return 0;
61 }
plunky
1.48
62 #endif
mickey
1.1
63
64 #define IALLOC(sz)      (isinlining ? permalloc(sz) : tmpalloc(sz))
65
66 /*
67  * Make a symtab entry for PIC use.
68  */
69 static struct symtab *
70 picsymtab(char *pchar *schar *s2)
71 {
72         struct symtab *sp = IALLOC(sizeof(struct symtab));
73         size_t len = strlen(p) + strlen(s) + strlen(s2) + 1;
ragge
1.22
74
mickey
1.1
75         sp->sname = sp->soname = IALLOC(len);
76         strlcpy(sp->sonameplen);
77         strlcat(sp->sonameslen);
78         strlcat(sp->sonames2len);
79         sp->sclass = EXTERN;
80         sp->sflags = sp->slevel = 0;
81         return sp;
82 }
83
84 int gotnr/* tempnum for GOT register */
85 int argstacksize;
ragge
1.22
86 static int ininval;
mickey
1.1
87
88 /*
ragge
1.22
89  * Create a reference for an extern variable or function.
mickey
1.1
90  */
91 static NODE *
92 picext(NODE *p)
93 {
gmcgarry
1.50
94 #if defined(ELFABI)
95
ragge
1.9
96         NODE *q;
mickey
1.1
97         struct symtab *sp;
ragge
1.22
98         char *c, *g;
99
100         if (p->n_sp->sflags & SBEENHERE)
101                 return p;
mickey
1.1
102
ragge
1.31
103         c = p->n_sp->soname ? p->n_sp->soname : exname(p->n_sp->sname);
ragge
1.22
104 #ifdef notdef
105         g = ISFTN(p->n_sp->stype) ? "@PLT" : "@GOTPCREL";
106 #endif
107         g = "@GOTPCREL";
108         sp = picsymtab(""cg);
109         sp->sflags = SBEENHERE;
ragge
1.18
110         q = block(NAMENILNILINCREF(p->n_type), p->n_dfp->n_ap);
ragge
1.9
111         q->n_sp = sp;
ragge
1.18
112         q = block(UMULq0p->n_typep->n_dfp->n_ap);
ragge
1.9
113         q->n_sp = sp;
mickey
1.1
114         nfree(p);
115         return q;
gmcgarry
1.50
116
117 #elif defined(MACHOABI)
118
119         return p;
120
121 #endif
mickey
1.1
122 }
123
ragge
1.27
124 #ifdef notdef
mickey
1.1
125 /*
126  * Create a reference for a static variable.
127  */
128 static NODE *
129 picstatic(NODE *p)
130 {
131         struct symtab *sp;
ragge
1.9
132         char *cbuf[32];
mickey
1.1
133
ragge
1.9
134         if (p->n_sp->slevel > 0)
135                 snprintf(c = buf32LABFMT, (int)p->n_sp->soffset);
136         else
137                 c = p->n_sp->soname ? p->n_sp->soname : p->n_sp->sname;
ragge
1.22
138         sp = picsymtab(""c"");
mickey
1.1
139         sp->sclass = STATIC;
140         sp->stype = p->n_sp->stype;
ragge
1.9
141         p->n_sp = sp;
142         return p;
mickey
1.1
143 }
ragge
1.27
144 #endif
145
146 static NODE *
147 cmop(NODE *lNODE *r)
148 {
ragge
1.45
149         return block(CMlrINT00);
ragge
1.27
150 }
151
152 static NODE *
153 mkx(char *sNODE *p)
154 {
ragge
1.45
155         p = block(XARGpNILINT00);
ragge
1.27
156         p->n_name = s;
157         return p;
158 }
159
160 static char *
161 mk3str(char *s1char *s2char *s3)
162 {
163         int len = strlen(s1) + strlen(s2) + strlen(s3) + 1;
164         char *sd;
165
ragge
1.39
166         sd = inlalloc(len);
ragge
1.27
167         strlcpy(sds1len);
168         strlcat(sds2len);
169         strlcat(sds3len);
170         return sd;
171 }
mickey
1.1
172
173 /*
174  * Create a reference for a TLS variable.
ragge
1.27
175  * This is the "General dynamic" version.
mickey
1.1
176  */
177 static NODE *
178 tlspic(NODE *p)
179 {
ragge
1.27
180         NODE *q, *r, *s;
181         char *s1, *s2;
mickey
1.1
182
183         /*
ragge
1.27
184          * .byte   0x66
185          * leaq x@TLSGD(%rip),%rdi
186          * .word   0x6666
187          * rex64
188          * call __tls_get_addr@PLT
mickey
1.1
189          */
190
ragge
1.27
191         /* Need the .byte stuff around.  Why? */
192         /* Use inline assembler */
193         q = mkx("%rdx"bcon(0));
194         q = cmop(qmkx("%rcx"bcon(0)));
195         q = cmop(qmkx("%rsi"bcon(0)));
196         q = cmop(qmkx("%rdi"bcon(0)));
197         q = cmop(qmkx("%r8"bcon(0)));
198         q = cmop(qmkx("%r9"bcon(0)));
199         q = cmop(qmkx("%r10"bcon(0)));
200         q = cmop(qmkx("%r11"bcon(0)));
201
202         s = ccopy(r = tempnode(0INCREF(p->n_type), p->n_dfp->n_ap));
203         r = mkx("=a"r);
ragge
1.45
204         r = block(XASMrqINT00);
ragge
1.27
205
206         /* Create the magic string */
207         s1 = ".byte 0x66\n\tleaq ";
208         s2 = "@TLSGD(%%rip),%%rdi\n"
209             "\t.word 0x6666\n\trex64\n\tcall __tls_get_addr@PLT";
210         if (p->n_sp->soname == NULL)
211                 p->n_sp->soname = p->n_sp->sname;
212         r->n_name = mk3str(s1p->n_sp->sonames2);
213
214         r = block(COMOPrsINCREF(p->n_type), p->n_dfp->n_ap);
215         r = buildtree(UMULrNIL);
216         tfree(p);
217         return r;
mickey
1.1
218 }
219
ragge
1.27
220 /*
221  * The "initial exec" tls model.
222  */
mickey
1.1
223 static NODE *
ragge
1.27
224 tlsinitialexec(NODE *p)
mickey
1.1
225 {
ragge
1.27
226         NODE *q, *r, *s;
227         char *s1, *s2;
mickey
1.1
228
ragge
1.27
229         /*
230          * movq %fs:0,%rax
231          * addq x@GOTTPOFF(%rip),%rax
232          */
233
234         q = bcon(0);
235         q->n_type = STRTY;
mickey
1.1
236
ragge
1.27
237         s = ccopy(r = tempnode(0INCREF(p->n_type), p->n_dfp->n_ap));
238         r = mkx("=r"r);
ragge
1.45
239         r = block(XASMrqINT00);
ragge
1.27
240
241         s1 = "movq %%fs:0,%0\n\taddq ";
242         s2 = "@GOTTPOFF(%%rip),%0";
243         if (p->n_sp->soname == NULL)
244                 p->n_sp->soname = p->n_sp->sname;
245         r->n_name = mk3str(s1p->n_sp->sonames2);
246
247         r = block(COMOPrsINCREF(p->n_type), p->n_dfp->n_ap);
248         r = buildtree(UMULrNIL);
249         tfree(p);
250         return r;
mickey
1.1
251 }
252
253 static NODE *
254 tlsref(NODE *p)
255 {
ragge
1.27
256         struct symtab *sp = p->n_sp;
257         struct attr *ga;
258         char *c;
259
260         if ((ga = attr_find(sp->sapGCC_ATYP_TLSMODEL)) != NULL) {
261                 c = ga->sarg(0);
262                 if (strcmp(c"initial-exec") == 0)
263                         return tlsinitialexec(p);
264                 else if (strcmp(c"global-dynamic") == 0)
265                         ;
266                 else
267                         werror("unsupported tls model '%s'"c);
268         }
269         return tlspic(p);
mickey
1.1
270 }
271
ragge
1.25
272 static NODE *
273 stkblk(TWORD t)
274 {
275         int altszoffnoff;
276         NODE *p;
277
ragge
1.45
278         al = talign(t0);
279         tsz = (int)tsize(t00);
ragge
1.25
280
281         noff = autooff + tsz;
282         SETOFF(noffal);
283         off = -noff;
284         autooff = noff;
285
ragge
1.45
286         p = block(REGNILNILINCREF(t), 00);
ragge
1.25
287         p->n_lval = 0;
288         p->n_rval = FPREG;
289         p = buildtree(UMULbuildtree(PLUSpbcon(off/SZLDOUBLE)), NIL);
290         return p;
291 }
292
293
mickey
1.1
294 /* clocal() is called to do local transformations on
295  * an expression tree preparitory to its being
296  * written out in intermediate code.
297  *
298  * the major essential job is rewriting the
299  * automatic variables and arguments in terms of
300  * REG and OREG nodes
301  * conversion ops which are not necessary are also clobbered here
302  * in addition, any special features (such as rewriting
303  * exclusive or) are easily handled here as well
304  */
305 NODE *
306 clocal(NODE *p)
307 {
308
309         register struct symtab *q;
310         register NODE *r, *l;
311         register int o;
312         register int m;
313         TWORD t;
314
315 #ifdef PCC_DEBUG
316         if (xdebug) {
317                 printf("clocal: %p\n"p);
318                 fwalk(peprint0);
319         }
320 #endif
321         switcho = p->n_op ){
322
323         case NAME:
324                 if ((q = p->n_sp) == NULL)
325                         return p/* Nothing to care about */
326
327                 switch (q->sclass) {
328
329                 case PARAM:
330                 case AUTO:
331                         /* fake up a structure reference */
332                         r = block(REGNILNILPTR+STRTY00);
333                         r->n_lval = 0;
334                         r->n_rval = FPREG;
335                         p = stref(block(STREFrp000));
336                         break;
337
338                 case USTATIC:
339                         if (kflag == 0)
340                                 break;
341                         /* FALLTHROUGH */
342                 case STATIC:
343 #ifdef TLS
344                         if (q->sflags & STLS) {
345                                 p = tlsref(p);
346                                 break;
347                         }
348 #endif
ragge
1.22
349 #ifdef notdef
mickey
1.1
350                         if (kflag == 0) {
351                                 if (q->slevel == 0)
352                                         break;
353                                 p->n_lval = 0;
ragge
1.22
354                         } else if (blevel > 0) {
355                                 if (!ISFTN(q->stype))
356                                         p = picstatic(p);
357                         }
358 #endif
mickey
1.1
359                         break;
360
361                 case REGISTER:
362                         p->n_op = REG;
363                         p->n_lval = 0;
364                         p->n_rval = q->soffset;
365                         break;
366
367                 case EXTERN:
368                 case EXTDEF:
369                         if (q->sflags & STLS) {
370                                 p = tlsref(p);
371                                 break;
372                         }
373                         if (kflag == 0)
374                                 break;
375                         if (blevel > 0)
376                                 p = picext(p);
377                         break;
378                 }
379                 break;
380
ragge
1.27
381 #if 0
mickey
1.1
382         case ADDROF:
383                 if (kflag == 0 || blevel == 0)
384                         break;
385                 /* char arrays may end up here */
386                 l = p->n_left;
387                 if (l->n_op != NAME ||
388                     (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE))
389                         break;
390                 l = p;
391                 p = picstatic(p->n_left);
392                 nfree(l);
393                 if (p->n_op != UMUL)
394                         cerror("ADDROF error");
395                 l = p;
396                 p = p->n_left;
397                 nfree(l);
398                 break;
ragge
1.27
399 #endif
mickey
1.1
400
ragge
1.24
401         case UCALL:
402         case USTCALL:
403                 /* For now, always clear eax */
ragge
1.45
404                 l = block(REGNILNILINT00);
ragge
1.24
405                 regno(l) = RAX;
406                 p->n_right = clocal(buildtree(ASSIGNlbcon(0)));
407                 p->n_op -= (UCALL-CALL);
408
409                 /* FALLTHROUGH */
ragge
1.7
410         case CALL:
411         case STCALL:
412                 if (p->n_type == VOID)
413                         break/* nothing to do */
414                 /* have the call at left of a COMOP to avoid arg trashing */
ragge
1.25
415                 if (p->n_type == LDOUBLE) {
416                         r = stkblk(LDOUBLE);
417                 } else
418                         r = tempnode(0p->n_typep->n_dfp->n_ap);
419                 l = ccopy(r);
420                 p = buildtree(COMOPbuildtree(ASSIGNrp), l);
ragge
1.7
421                 break;
422
ragge
1.43
423 #ifdef notyet
mickey
1.1
424         case CBRANCH:
425                 l = p->n_left;
426
427                 /*
428                  * Remove unnecessary conversion ops.
429                  */
430                 if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
431                         if (coptype(l->n_op) != BITYPE)
432                                 break;
433                         if (l->n_right->n_op == ICON) {
434                                 r = l->n_left->n_left;
435                                 if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
436                                         break;
437                                 if (ISPTR(r->n_type))
438                                         break/* no opt for pointers */
439                                 if (toolarge(r->n_typel->n_right->n_lval))
440                                         break;
441                                 /* Type must be correct */
442                                 t = r->n_type;
443                                 nfree(l->n_left);
444                                 l->n_left = r;
445                                 l->n_type = t;
446                                 l->n_right->n_type = t;
447                         }
448                 }
449                 break;
ragge
1.43
450 #endif
mickey
1.1
451
452         case PCONV:
453                 /* Remove redundant PCONV's. Be careful */
454                 l = p->n_left;
455                 if (l->n_op == ICON) {
456                         goto delp;
457                 }
ragge
1.47
458                 if (l->n_type < LONG || l->n_type == BOOL) {
mickey
1.1
459                         /* float etc? */
ragge
1.45
460                         p->n_left = block(SCONVlNILUNSIGNED00);
mickey
1.1
461                         break;
462                 }
463                 /* if left is SCONV, cannot remove */
464                 if (l->n_op == SCONV)
465                         break;
466
467                 /* avoid ADDROF TEMP */
468                 if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
469                         break;
470
ragge
1.23
471                 if ((l->n_op == REG || l->n_op == TEMP) && ISPTR(l->n_type))
472                         goto delp;
ragge
1.22
473 #ifdef notdef
mickey
1.1
474                 /* if conversion to another pointer type, just remove */
ragge
1.22
475                 /* XXX breaks ADDROF NAME */
mickey
1.1
476                 if (p->n_type > BTMASK && l->n_type > BTMASK)
477                         goto delp;
ragge
1.22
478 #endif
mickey
1.1
479                 break;
480
481         delp:   l->n_type = p->n_type;
482                 l->n_qual = p->n_qual;
483                 l->n_df = p->n_df;
ragge
1.18
484                 l->n_ap = p->n_ap;
mickey
1.1
485                 nfree(p);
486                 p = l;
487                 break;
488                 
489         case SCONV:
ragge
1.15
490                 /* Special-case shifts */
491                 if (p->n_type == LONG && (l = p->n_left)->n_op == LS && 
492                     l->n_type == INT && l->n_right->n_op == ICON) {
493                         p->n_left = l->n_left;
494                         p = buildtree(LSpl->n_right);
495                         nfree(l);
496                         break;
497                 }
498
mickey
1.1
499                 l = p->n_left;
500
ragge
1.5
501                 /* Float conversions may need extra casts */
ragge
1.37
502                 if (p->n_type == FLOAT || p->n_type == DOUBLE ||
503                     p->n_type == LDOUBLE) {
ragge
1.41
504                         if (l->n_type < INT || l->n_type == BOOL) {
ragge
1.5
505                                 p->n_left = block(SCONVlNIL,
506                                     ISUNSIGNED(l->n_type) ? UNSIGNED : INT,
ragge
1.18
507                                     l->n_dfl->n_ap);
ragge
1.5
508                                 break;
509                         }
510                 }
511
mickey
1.1
512                 if (p->n_type == l->n_type) {
513                         nfree(p);
514                         return l;
515                 }
516
517                 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
ragge
1.45
518                     tsize(p->n_typep->n_dfp->n_ap) ==
519                     tsize(l->n_typel->n_dfl->n_ap)) {
mickey
1.1
520                         if (p->n_type != FLOAT && p->n_type != DOUBLE &&
521                             l->n_type != FLOAT && l->n_type != DOUBLE &&
522                             l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
523                                 if (l->n_op == NAME || l->n_op == UMUL ||
524                                     l->n_op == TEMP) {
525                                         l->n_type = p->n_type;
526                                         nfree(p);
527                                         return l;
528                                 }
529                         }
530                 }
531
532                 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
ragge
1.42
533                     coptype(l->n_op) == BITYPE && l->n_op != COMOP &&
534                     l->n_op != QUEST) {
mickey
1.1
535                         l->n_type = p->n_type;
536                         nfree(p);
537                         return l;
538                 }
539
540                 o = l->n_op;
541                 m = p->n_type;
542
543                 if (o == ICON) {
544                         CONSZ val = l->n_lval;
545
546                         if (!ISPTR(m)) /* Pointers don't need to be conv'd */
547                             switch (m) {
548                         case BOOL:
ragge
1.30
549                                 l->n_lval = nncon(l) ? (l->n_lval != 0) : 1;
550                                 l->n_sp = NULL;
mickey
1.1
551                                 break;
552                         case CHAR:
553                                 l->n_lval = (char)val;
554                                 break;
555                         case UCHAR:
556                                 l->n_lval = val & 0377;
557                                 break;
558                         case SHORT:
559                                 l->n_lval = (short)val;
560                                 break;
561                         case USHORT:
562                                 l->n_lval = val & 0177777;
563                                 break;
564                         case UNSIGNED:
565                                 l->n_lval = val & 0xffffffff;
566                                 break;
567                         case INT:
568                                 l->n_lval = (int)val;
569                                 break;
570                         case LONG:
571                         case LONGLONG:
572                                 l->n_lval = (long long)val;
573                                 break;
574                         case ULONG:
575                         case ULONGLONG:
576                                 l->n_lval = val;
577                                 break;
578                         case VOID:
579                                 break;
580                         case LDOUBLE:
581                         case DOUBLE:
582                         case FLOAT:
583                                 l->n_op = FCON;
584                                 l->n_dcon = val;
585                                 break;
586                         default:
587                                 cerror("unknown type %d"m);
588                         }
589                         l->n_type = m;
ragge
1.45
590                         l->n_ap = NULL;
mickey
1.1
591                         nfree(p);
592                         return l;
593                 } else if (l->n_op == FCON) {
ragge
1.29
594                         if (p->n_type == BOOL)
595                                 l->n_lval = l->n_dcon != 0.0;
596                         else
597                                 l->n_lval = l->n_dcon;
mickey
1.1
598                         l->n_sp = NULL;
599                         l->n_op = ICON;
600                         l->n_type = m;
ragge
1.45
601                         l->n_ap = NULL;
mickey
1.1
602                         nfree(p);
603                         return clocal(l);
604                 }
605                 if ((p->n_type == CHAR || p->n_type == UCHAR ||
606                     p->n_type == SHORT || p->n_type == USHORT) &&
607                     (l->n_type == FLOAT || l->n_type == DOUBLE ||
608                     l->n_type == LDOUBLE)) {
ragge
1.18
609                         p = block(SCONVpNILp->n_typep->n_dfp->n_ap);
mickey
1.1
610                         p->n_left->n_type = INT;
611                         return p;
612                 }
613                 break;
614
615         case MOD:
616         case DIV:
617                 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
618                         break;
619                 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
620                         break;
621                 /* make it an int division by inserting conversions */
ragge
1.45
622                 p->n_left = block(SCONVp->n_leftNILINT00);
623                 p->n_right = block(SCONVp->n_rightNILINT00);
624                 p = block(SCONVpNILp->n_type00);
mickey
1.1
625                 p->n_left->n_type = INT;
626                 break;
627
628         case PMCONV:
629         case PVCONV:
630                 r = p;
631                 p = buildtree(o == PMCONV ? MUL : DIVp->n_leftp->n_right);
632                 nfree(r);
633                 break;
634
635         case FORCE:
636                 /* put return value in return reg */
637                 p->n_op = ASSIGN;
638                 p->n_right = p->n_left;
ragge
1.45
639                 p->n_left = block(REGNILNILp->n_type00);
ragge
1.34
640                 t = p->n_type;
641                 if (ISITY(t))
642                         t = t - (FIMAG-FLOAT);
mickey
1.1
643                 p->n_left->n_rval = p->n_left->n_type == BOOL ? 
ragge
1.34
644                     RETREG(CHAR) : RETREG(t);
mickey
1.1
645                 break;
646
647         case LS:
648         case RS:
ragge
1.15
649                 /* shift count must be in a char */
mickey
1.1
650                 if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR)
651                         break;
ragge
1.45
652                 p->n_right = block(SCONVp->n_rightNILCHAR00);
mickey
1.1
653                 break;
654         }
655 #ifdef PCC_DEBUG
656         if (xdebug) {
657                 printf("clocal end: %p\n"p);
658                 fwalk(peprint0);
659         }
660 #endif
661         return(p);
662 }
663
664 void
665 myp2tree(NODE *p)
666 {
ragge
1.28
667         struct symtab *spsps;
668         static int dblxorfltxor;
mickey
1.1
669
ragge
1.28
670         if (p->n_op == UMINUS && (p->n_type == FLOAT || p->n_type == DOUBLE)) {
671                 /* Store xor code for sign change */
672                 if (dblxor == 0) {
673                         dblxor = getlab();
674                         fltxor = getlab();
675                         sps.stype = LDOUBLE;
676                         sps.squal = CON >> TSHIFT;
677                         sps.sflags = sps.sclass = 0;
678                         sps.sname = sps.soname = "";
679                         sps.slevel = 1;
ragge
1.45
680                         sps.sap = NULL;
ragge
1.28
681                         sps.soffset = dblxor;
682                         defloc(&sps);
683                         printf("\t.long 0,0x80000000,0,0\n");
684                         printf(LABFMT ":\n"fltxor);
685                         printf("\t.long 0x80000000,0,0,0\n");
686                 }
687                 p->n_label = p->n_type == FLOAT ? fltxor : dblxor;
688                 return;
689         }
mickey
1.1
690         if (p->n_op != FCON)
691                 return;
692
ragge
1.22
693         /* XXX should let float constants follow */
mickey
1.1
694         sp = IALLOC(sizeof(struct symtab));
695         sp->sclass = STATIC;
ragge
1.45
696         sp->sap = NULL;
mickey
1.1
697         sp->slevel = 1/* fake numeric label */
698         sp->soffset = getlab();
699         sp->sflags = 0;
700         sp->stype = p->n_type;
701         sp->squal = (CON >> TSHIFT);
gmcgarry
1.49
702         sp->sname = sp->soname = NULL;
mickey
1.1
703
704         defloc(sp);
ragge
1.18
705         ninval(0tsize(sp->stypesp->sdfsp->sap), p);
mickey
1.1
706
707         p->n_op = NAME;
708         p->n_lval = 0;
709         p->n_sp = sp;
710 }
711
ragge
1.22
712 /*
713  * Convert ADDROF NAME to ICON?
714  */
mickey
1.1
715 int
716 andable(NODE *p)
717 {
ragge
1.22
718         if (ininval)
719                 return 1;
720         if (p->n_sp->sclass == STATIC || p->n_sp->sclass == USTATIC)
721                 return 0;
722         return 1;
mickey
1.1
723 }
724
725 /*
726  * at the end of the arguments of a ftn, set the automatic offset
727  */
728 void
729 cendarg()
730 {
731         autooff = AUTOINIT;
732 }
733
734 /*
735  * Return 1 if a variable of type type is OK to put in register.
736  */
737 int
738 cisreg(TWORD t)
739 {
ragge
1.14
740         if (t == LDOUBLE)
741                 return 0;
mickey
1.1
742         return 1;
743 }
744
745 /*
746  * return a node, for structure references, which is suitable for
747  * being added to a pointer of type t, in order to be off bits offset
748  * into a structure
749  * t, d, and s are the type, dimension offset, and sizeoffset
750  * For pdp10, return the type-specific index number which calculation
751  * is based on its size. For example, short a[3] would return 3.
752  * Be careful about only handling first-level pointers, the following
753  * indirections must be fullword.
754  */
755 NODE *
ragge
1.18
756 offcon(OFFSZ offTWORD tunion dimfun *dstruct attr *ap)
mickey
1.1
757 {
758         register NODE *p;
759
760         if (xdebug)
761                 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
ragge
1.18
762                     offtd, (int)tsize(tdap));
mickey
1.1
763
764         p = bcon(0);
765         p->n_lval = off/SZCHAR/* Default */
766         return(p);
767 }
768
769 /*
770  * Allocate off bits on the stack.  p is a tree that when evaluated
771  * is the multiply count for off, t is a storeable node where to write
772  * the allocated address.
773  */
774 void
775 spalloc(NODE *tNODE *pOFFSZ off)
776 {
777         NODE *sp;
778
ragge
1.20
779         p = buildtree(MULpbcon(off/SZCHAR));
780         p = buildtree(PLUSpbcon(30));
781         p = buildtree(ANDpxbcon(-16NULLLONG));
mickey
1.1
782
783         /* sub the size from sp */
ragge
1.45
784         sp = block(REGNILNILp->n_type00);
mickey
1.1
785         sp->n_lval = 0;
786         sp->n_rval = STKREG;
787         ecomp(buildtree(MINUSEQspp));
788
789         /* save the address of sp */
ragge
1.22
790         sp = block(REGNILNILPTR+LONGt->n_dft->n_ap);
mickey
1.1
791         sp->n_lval = 0;
792         sp->n_rval = STKREG;
793         t->n_type = sp->n_type;
794         ecomp(buildtree(ASSIGNtsp)); /* Emit! */
795
796 }
797
798 /*
799  * Print out a string of characters.
800  * Assume that the assembler understands C-style escape
801  * sequences.
802  */
803 void
804 instring(struct symtab *sp)
805 {
806         char *s, *str = sp->sname;
807
808         defloc(sp);
809
810         /* be kind to assemblers and avoid long strings */
811         printf("\t.ascii \"");
812         for (s = str; *s != 0; ) {
813                 if (*s++ == '\\') {
814                         (void)esccon(&s);
815                 }
816                 if (s - str > 60) {
817                         fwrite(str1s - strstdout);
818                         printf("\"\n\t.ascii \"");
819                         str = s;
820                 }
821         }
822         fwrite(str1s - strstdout);
823         printf("\\0\"\n");
824 }
825
826 static int inbitsinval;
827
828 /*
829  * set fsz bits in sequence to zero.
830  */
831 void
832 zbits(OFFSZ offint fsz)
833 {
834         int m;
835
836         if (idebug)
837                 printf("zbits off %lld, fsz %d inbits %d\n"offfszinbits);
838         if ((m = (inbits % SZCHAR))) {
839                 m = SZCHAR - m;
840                 if (fsz < m) {
841                         inbits += fsz;
842                         return;
843                 } else {
844                         fsz -= m;
845                         printf("\t.byte %d\n"inval);
846                         inval = inbits = 0;
847                 }
848         }
849         if (fsz >= SZCHAR) {
ragge
1.32
850 #ifdef MACHOABI
851                 printf("\t.space %d\n"fsz/SZCHAR);
852 #else
mickey
1.1
853                 printf("\t.zero %d\n"fsz/SZCHAR);
ragge
1.32
854 #endif
mickey
1.1
855                 fsz -= (fsz/SZCHAR) * SZCHAR;
856         }
857         if (fsz) {
858                 inval = 0;
859                 inbits = fsz;
860         }
861 }
862
863 /*
864  * Initialize a bitfield.
865  */
866 void
867 infld(CONSZ offint fszCONSZ val)
868 {
869         if (idebug)
870                 printf("infld off %lld, fsz %d, val %lld inbits %d\n",
871                     offfszvalinbits);
ragge
1.25
872         val &= (((((CONSZ)1 << (fsz-1))-1)<<1)|1);
mickey
1.1
873         while (fsz + inbits >= SZCHAR) {
874                 inval |= (val << inbits);
875                 printf("\t.byte %d\n"inval & 255);
876                 fsz -= (SZCHAR - inbits);
877                 val >>= (SZCHAR - inbits);
878                 inval = inbits = 0;
879         }
880         if (fsz) {
881                 inval |= (val << inbits);
882                 inbits += fsz;
883         }
884 }
885
886 /*
887  * print out a constant node, may be associated with a label.
888  * Do not free the node after use.
889  * off is bit offset from the beginning of the aggregate
890  * fsz is the number of bits this is referring to
891  */
892 void
893 ninval(CONSZ offint fszNODE *p)
894 {
895         union { float fdouble dlong double lint i[3]; } u;
896         struct symtab *q;
ragge
1.33
897         NODE st, *op = NIL;
mickey
1.1
898         TWORD t;
ragge
1.22
899
900         if (coptype(p->n_op) != LTYPE) {
901                 ininval = 1;
ragge
1.33
902                 op = p = optim(ccopy(p));
ragge
1.22
903                 ininval = 0;
904         }
mickey
1.1
905
ragge
1.33
906         while (p->n_op == PCONV)
907                 p = p->n_left;
908
mickey
1.1
909         t = p->n_type;
ragge
1.26
910
ragge
1.40
911         if (kflag && p->n_op == NAME && ISPTR(t) &&
912             (ISFTN(DECREF(t)) || ISSOU(BTYPE(t)))) {
ragge
1.26
913                 /* functions as initializers will be NAME here */
ragge
1.33
914                 if (op == NIL) {
915                         st = *p;
916                         p = &st;
917                 }
918                 p->n_op = ICON;
ragge
1.26
919         }
920
mickey
1.1
921         if (t > BTMASK)
ragge
1.7
922                 t = LONG/* pointer */
mickey
1.1
923
ragge
1.40
924         if (p->n_op == COMOP) {
925                 NODE *r = p->n_right;
926                 tfree(p->n_left);
927                 nfree(p);
928                 p = r;
929         }
930
931         if (p->n_op != ICON && p->n_op != FCON) {
932 fwalk(peprint0);
mickey
1.1
933                 cerror("ninval: init node not constant");
ragge
1.40
934         }
mickey
1.1
935
ragge
1.7
936         if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != LONG)
mickey
1.1
937                 uerror("element not constant");
938
939         switch (t) {
ragge
1.6
940         case LONG:
941         case ULONG:
ragge
1.7
942                 printf("\t.quad 0x%llx"p->n_lval);
mickey
1.1
943                 if ((q = p->n_sp) != NULL) {
ragge
1.2
944                         if ((q->sclass == STATIC && q->slevel > 0)) {
mickey
1.1
945                                 printf("+" LABFMTq->soffset);
946                         } else {
ragge
1.6
947                                 char *name;
948                                 if ((name = q->soname) == NULL)
ragge
1.26
949                                         name = q->sname;
950                                 /* Never any PIC stuff in static init */
951                                 if (strchr(name'@')) {
952                                         name = tmpstrdup(name);
953                                         *strchr(name'@') = 0;
954                                 }
ragge
1.6
955                                 printf("+%s"name);
mickey
1.1
956                         }
957                 }
958                 printf("\n");
959                 break;
ragge
1.6
960         case INT:
961         case UNSIGNED:
962                 printf("\t.long 0x%x\n", (int)p->n_lval & 0xffffffff);
963                 break;
mickey
1.1
964         case SHORT:
965         case USHORT:
966                 printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff);
967                 break;
968         case BOOL:
969                 if (p->n_lval > 1)
970                         p->n_lval = p->n_lval != 0;
971                 /* FALLTHROUGH */
972         case CHAR:
973         case UCHAR:
974                 printf("\t.byte %d\n", (int)p->n_lval & 0xff);
975                 break;
976         case LDOUBLE:
977                 u.i[2] = 0;
978                 u.l = (long double)p->n_dcon;
979 #if defined(HOST_BIG_ENDIAN)
980                 /* XXX probably broken on most hosts */
ragge
1.36
981                 printf("\t.long\t0x%x,0x%x,0x%x,0\n"u.i[2], u.i[1], u.i[0]);
mickey
1.1
982 #else
ragge
1.36
983                 printf("\t.long\t0x%x,0x%x,0x%x,0\n"u.i[0], u.i[1], u.i[2]);
mickey
1.1
984 #endif
985                 break;
986         case DOUBLE:
987                 u.d = (double)p->n_dcon;
988 #if defined(HOST_BIG_ENDIAN)
989                 printf("\t.long\t0x%x,0x%x\n"u.i[1], u.i[0]);
990 #else
991                 printf("\t.long\t0x%x,0x%x\n"u.i[0], u.i[1]);
992 #endif
993                 break;
994         case FLOAT:
995                 u.f = (float)p->n_dcon;
996                 printf("\t.long\t0x%x\n"u.i[0]);
997                 break;
998         default:
999                 cerror("ninval");
1000         }
ragge
1.33
1001         if (op)
1002                 tfree(op);
mickey
1.1
1003 }
1004
1005 /* make a name look like an external name in the local machine */
1006 char *
1007 exname(char *p)
1008 {
ragge
1.31
1009 #ifdef MACHOABI
1010
1011 #define NCHNAM  256
1012         static char text[NCHNAM+1];
1013         int i;
1014
1015         if (p == NULL)
1016                 return "";
1017
1018         text[0] = '_';
1019         for (i=1; *p && i<NCHNAM; ++i)
1020                 text[i] = *p++;
1021
1022         text[i] = '\0';
1023         text[NCHNAM] = '\0';  /* truncate */
1024
1025         return (text);
1026 #else
mickey
1.1
1027         return (p == NULL ? "" : p);
ragge
1.31
1028 #endif
mickey
1.1
1029 }
1030
1031 /*
1032  * map types which are not defined on the local machine
1033  */
1034 TWORD
1035 ctype(TWORD type)
1036 {
1037         switch (BTYPE(type)) {
ragge
1.5
1038         case LONGLONG:
mickey
1.1
1039                 MODTYPE(type,LONG);
1040                 break;
1041
ragge
1.5
1042         case ULONGLONG:
mickey
1.1
1043                 MODTYPE(type,ULONG);
1044
1045         }
1046         return (type);
1047 }
1048
1049 void