Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20080729132558

Diff

Diff from 1.85 to:

Annotations

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

Annotated File View

ragge
1.85
1 /*      $Id: local.c,v 1.85 2008/07/29 13:25:58 ragge Exp $     */
ragge
1.1
2 /*
3  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29
ragge
1.48
30 #include "pass1.h"
ragge
1.1
31
ragge
1.60
32 /*      this file contains code which is dependent on the target machine */
33
ragge
1.57
34 /*
35  * Check if a constant is too large for a type.
36  */
37 static int
38 toolarge(TWORD tCONSZ con)
39 {
40         U_CONSZ ucon = con;
41
42         switch (t) {
43         case ULONGLONG:
44         case LONGLONG:
45                 break/* cannot be too large */
46 #define SCHK(i) case i: if (con > MAX_##i || con < MIN_##i) return 1; break
47 #define UCHK(i) case i: if (ucon > MAX_##i) return 1; break
48         SCHK(INT);
49         SCHK(SHORT);
otto
1.58
50         case BOOL:
ragge
1.57
51         SCHK(CHAR);
52         UCHK(UNSIGNED);
53         UCHK(USHORT);
54         UCHK(UCHAR);
55         default:
56                 cerror("toolarge");
57         }
58         return 0;
59 }
60
gmcgarry
1.83
61 #if defined(MACHOABI)
62
63 /*
64  *  Keep track of PIC stubs.
65  */
66
67 void
68 addstub(struct stub *listchar *name)
69 {
70         struct stub *s;
71
72         DLIST_FOREACH(slistlink) {
73                 if (strcmp(s->namename) == 0)
74                         return;
75         }
76
77         s = permalloc(sizeof(struct stub));
78         s->name = newstring(namestrlen(name));
79         DLIST_INSERT_BEFORE(listslink);
80 }
81
82 #endif
83
ragge
1.60
84 #define IALLOC(sz)      (isinlining ? permalloc(sz) : tmpalloc(sz))
85 /*
86  * Make a symtab entry for PIC use.
87  */
88 static struct symtab *
gmcgarry
1.83
89 picsymtab(char *pchar *schar *s2)
ragge
1.60
90 {
91         struct symtab *sp = IALLOC(sizeof(struct symtab));
gmcgarry
1.83
92         size_t len = strlen(p) + strlen(s) + strlen(s2) + 1;
ragge
1.60
93         
ragge
1.69
94         sp->sname = sp->soname = IALLOC(len);
gmcgarry
1.83
95         strlcpy(sp->sonameplen);
96         strlcat(sp->sonameslen);
ragge
1.69
97         strlcat(sp->sonames2len);
ragge
1.60
98         sp->sclass = EXTERN;
ragge
1.64
99         sp->sflags = sp->slevel = 0;
ragge
1.60
100         return sp;
101 }
102
103 int gotnr/* tempnum for GOT register */
104 /*
105  * Create a reference for an extern variable.
106  */
107 static NODE *
108 picext(NODE *p)
109 {
110         NODE *q, *r;
stefan
1.66
111         struct symtab *sp;
ragge
1.60
112
gmcgarry
1.83
113 #if defined(ELFABI)
114
ragge
1.60
115         q = tempnode(gotnrPTR|VOID0MKSUE(VOID));
gmcgarry
1.83
116         sp = picsymtab(""p->n_sp->soname"@GOT");
stefan
1.66
117         r = xbcon(0spINT);
ragge
1.60
118         q = buildtree(PLUSqr);
119         q = block(UMULq0PTR|VOID0MKSUE(VOID));
gmcgarry
1.83
120
121 #elif defined(MACHOABI)
122
123         char buf2[64];
124
125         if (p->n_sp->sclass == EXTDEF) {
126                 snprintf(buf264"-L%s$pb"cftnsp->soname);
127                 sp = picsymtab(""exname(p->n_sp->soname), buf2);
128         } else {
129                 snprintf(buf264"$non_lazy_ptr-L%s$pb"cftnsp->soname);
130                 sp = picsymtab("L"p->n_sp->sonamebuf2);
131                 addstub(&nlplistp->n_sp->soname);
132         }
133         q = tempnode(gotnrPTR+VOID0MKSUE(VOID));
134         r = xbcon(0spINT);
135         q = buildtree(PLUSqr);
136
137         if (p->n_sp->sclass != EXTDEF)
138                 q = block(UMULq0PTR+VOID0MKSUE(VOID));
139
140 #endif
141
ragge
1.60
142         q = block(UMULq0p->n_typep->n_dfp->n_sue);
ragge
1.65
143         q->n_sp = p->n_sp/* for init */
ragge
1.60
144         nfree(p);
145         return q;
146 }
147
148 /*
149  * Create a reference for a static variable.
150  */
151 static NODE *
152 picstatic(NODE *p)
153 {
154         NODE *q, *r;
stefan
1.66
155         struct symtab *sp;
ragge
1.60
156
gmcgarry
1.83
157 #if defined(ELFABI)
158
ragge
1.60
159         q = tempnode(gotnrPTR|VOID0MKSUE(VOID));
ragge
1.65
160         if (p->n_sp->slevel > 0 || p->n_sp->sclass == ILABEL) {
ragge
1.60
161                 char buf[32];
162                 snprintf(buf32LABFMT, (int)p->n_sp->soffset);
gmcgarry
1.83
163                 sp = picsymtab(""buf"@GOTOFF");
ragge
1.60
164         } else
gmcgarry
1.83
165                 sp = picsymtab(""p->n_sp->soname"@GOTOFF");
stefan
1.66
166         sp->sclass = STATIC;
167         sp->stype = p->n_sp->stype;
168         r = xbcon(0spINT);
ragge
1.60
169         q = buildtree(PLUSqr);
170         q = block(UMULq0p->n_typep->n_dfp->n_sue);
ragge
1.65
171         q->n_sp = p->n_sp/* for init */
ragge
1.60
172         nfree(p);
gmcgarry
1.83
173
174 #elif defined(MACHOABI)
175
176         char buf2[64];
177
178         snprintf(buf264"-L%s$pb"cftnsp->soname);
179
180         if (p->n_sp->slevel > 0 || p->n_sp->sclass == ILABEL) {
181                 char buf1[64];
182                 snprintf(buf164LABFMT, (int)p->n_sp->soffset);
183                 sp = picsymtab(""buf1buf2);
184                 sp->sflags |= SNOUNDERSCORE;
185         } else  {
186                 sp = picsymtab(""exname(p->n_sp->soname), buf2);
187         }
188         sp->sclass = STATIC;
189         sp->stype = p->n_sp->stype;
190         q = tempnode(gotnrPTR+VOID0MKSUE(VOID));
191         r = xbcon(0spINT);
192         q = buildtree(PLUSqr);
193         q = block(UMULq0p->n_typep->n_dfp->n_sue);
194         q->n_sp = p->n_sp;
195         nfree(p);
196
197 #endif
198
ragge
1.60
199         return q;
200 }
ragge
1.1
201
ragge
1.73
202 #ifdef TLS
203 /*
204  * Create a reference for a TLS variable.
205  */
206 static NODE *
207 tlspic(NODE *p)
208 {
209         NODE *q, *r;
ragge
1.85
210         struct symtab *sp, *sp2;
ragge
1.73
211
212         /*
213          * creates:
214          *   leal var@TLSGD(%ebx),%eax
215          *   call ___tls_get_addr@PLT
216          */
217
218         /* calc address of var@TLSGD */
219         q = tempnode(gotnrPTR|VOID0MKSUE(VOID));
gmcgarry
1.83
220         sp = picsymtab(""p->n_sp->soname"@TLSGD");
ragge
1.73
221         r = xbcon(0spINT);
222         q = buildtree(PLUSqr);
223
224         /* assign to %eax */
225         r = block(REGNILNILPTR|VOID0MKSUE(VOID));
226         r->n_rval = EAX;
227         q = buildtree(ASSIGNrq);
228
229         /* call ___tls_get_addr */
ragge
1.85
230         sp2 = lookup("___tls_get_addr@PLT"0);
231         sp2->stype = EXTERN|INT|FTN;
232         r = nametree(sp2);
ragge
1.73
233         r = buildtree(ADDROFrNIL);
234         r = block(UCALLrNILINT0MKSUE(INT));
235
236         /* fusion both parts together */
237         q = buildtree(COMOPqr);
238         q = block(UMULq0p->n_typep->n_dfp->n_sue);
239         q->n_sp = p->n_sp/* for init */
240
241         nfree(p);
242         return q;
243 }
244
245 static NODE *
246 tlsnonpic(NODE *p)
247 {
248         NODE *q, *r;
ragge
1.85
249         struct symtab *sp, *sp2;
ragge
1.73
250         int ext = p->n_sp->sclass;
251
gmcgarry
1.83
252         sp = picsymtab(""p->n_sp->soname,
253             ext == EXTERN ? "@INDNTPOFF" : "@NTPOFF");
ragge
1.73
254         q = xbcon(0spINT);
255         if (ext == EXTERN)
256                 q = block(UMULqNILPTR|VOID0MKSUE(VOID));
257
ragge
1.85
258         sp2 = lookup("%gs:0"0);
259         sp2->stype = EXTERN|INT;
260         r = nametree(sp2);
ragge
1.73
261
262         q = buildtree(PLUSqr);
263         q = block(UMULq0p->n_typep->n_dfp->n_sue);
264         q->n_sp = p->n_sp/* for init */
265
266         nfree(p);
267         return q;
268 }
269
270 static NODE *
271 tlsref(NODE *p)
272 {
273         if (kflag)
274                 return (tlspic(p));
275         else
276                 return (tlsnonpic(p));
277 }
278 #endif
279
ragge
1.48
280 /* clocal() is called to do local transformations on
281  * an expression tree preparitory to its being
282  * written out in intermediate code.
283  *
284  * the major essential job is rewriting the
285  * automatic variables and arguments in terms of
286  * REG and OREG nodes
287  * conversion ops which are not necessary are also clobbered here
288  * in addition, any special features (such as rewriting
289  * exclusive or) are easily handled here as well
290  */
ragge
1.1
291 NODE *
292 clocal(NODE *p)
293 {
294
295         register struct symtab *q;
ragge
1.2
296         register NODE *r, *l;
ragge
1.1
297         register int o;
ragge
1.40
298         register int m;
ragge
1.19
299         TWORD t;
ragge
1.1
300
ragge
1.54
301 #ifdef PCC_DEBUG
302         if (xdebug) {
303                 printf("clocal: %p\n"p);
304                 fwalk(peprint0);
305         }
306 #endif
ragge
1.1
307         switcho = p->n_op ){
308
309         case NAME:
310                 if ((q = p->n_sp) == NULL)
311                         return p/* Nothing to care about */
312
313                 switch (q->sclass) {
314
315                 case PARAM:
316                 case AUTO:
317                         /* fake up a structure reference */
318                         r = block(REGNILNILPTR+STRTY00);
319                         r->n_lval = 0;
320                         r->n_rval = FPREG;
321                         p = stref(block(STREFrp000));
322                         break;
323
ragge
1.65
324                 case USTATIC:
325                         if (kflag == 0)
326                                 break;
327                         /* FALLTHROUGH */
ragge
1.1
328                 case STATIC:
ragge
1.73
329 #ifdef TLS
330                         if (q->sflags & STLS) {
331                                 p = tlsref(p);
332                                 break;
333                         }
334 #endif
ragge
1.60
335                         if (kflag == 0) {
336                                 if (q->slevel == 0)
337                                         break;
338                                 p->n_lval = 0;
ragge
1.64
339                         } else if (blevel > 0)
ragge
1.60
340                                 p = picstatic(p);
ragge
1.1
341                         break;
342
343                 case REGISTER:
344                         p->n_op = REG;
345                         p->n_lval = 0;
346                         p->n_rval = q->soffset;
347                         break;
348
ragge
1.60
349                 case EXTERN:
350                 case EXTDEF:
ragge
1.73
351 #ifdef TLS
352                         if (q->sflags & STLS) {
353                                 p = tlsref(p);
354                                 break;
355                         }
356 #endif
ragge
1.60
357                         if (kflag == 0)
358                                 break;
ragge
1.64
359                         if (blevel > 0)
ragge
1.60
360                                 p = picext(p);
361                         break;
ragge
1.65
362
363                 case ILABEL:
364                         if (kflag && blevel)
365                                 p = picstatic(p);
366                         break;
ragge
1.60
367                 }
ragge
1.1
368                 break;
369
ragge
1.65
370         case ADDROF:
371                 if (kflag == 0 || blevel == 0)
372                         break;
373                 /* char arrays may end up here */
374                 l = p->n_left;
375                 if (l->n_op != NAME ||
376                     (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE))
377                         break;
378                 l = p;
379                 p = picstatic(p->n_left);
380                 nfree(l);
381                 if (p->n_op != UMUL)
382                         cerror("ADDROF error");
383                 l = p;
384                 p = p->n_left;
385                 nfree(l);
386                 break;
387
ragge
1.62
388         case UCALL:
389         case USTCALL:
ragge
1.60
390                 if (kflag == 0)
391                         break;
ragge
1.62
392                 /* Change to CALL node with ebx as argument */
393                 l = block(REGNILNILINT0MKSUE(INT));
394                 l->n_rval = EBX;
395                 p->n_right = buildtree(ASSIGNl,
396                     tempnode(gotnrINT0MKSUE(INT)));
397                 p->n_op -= (UCALL-CALL);
ragge
1.10
398                 break;
ragge
1.64
399
ragge
1.8
400         case CBRANCH:
401                 l = p->n_left;
402
403                 /*
ragge
1.77
404                  * Remove unnecessary conversion ops.
ragge
1.8
405                  */
ragge
1.10
406                 if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
ragge
1.12
407                         if (coptype(l->n_op) != BITYPE)
408                                 break;
ragge
1.8
409                         if (l->n_right->n_op == ICON) {
410                                 r = l->n_left->n_left;
ragge
1.24
411                                 if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
412                                         break;
ragge
1.59
413                                 if (ISPTR(r->n_type))
414                                         break/* no opt for pointers */
ragge
1.57
415                                 if (toolarge(r->n_typel->n_right->n_lval))
416                                         break;
ragge
1.18
417                                 /* Type must be correct */
ragge
1.19
418                                 t = r->n_type;
ragge
1.8
419                                 nfree(l->n_left);
420                                 l->n_left = r;
ragge
1.19
421                                 l->n_type = t;
422                                 l->n_right->n_type = t;
ragge
1.17
423                         }
ragge
1.8
424                 }
425                 break;
426
ragge
1.1
427         case PCONV:
ragge
1.40
428                 /* Remove redundant PCONV's. Be careful */
ragge
1.1
429                 l = p->n_left;
ragge
1.40
430                 if (l->n_op == ICON) {
431                         l->n_lval = (unsigned)l->n_lval;
432                         goto delp;
433                 }
434                 if (l->n_type < INT || l->n_type == LONGLONG || 
435                     l->n_type == ULONGLONG) {
436                         /* float etc? */
437                         p->n_left = block(SCONVlNIL,
438                             UNSIGNED0MKSUE(UNSIGNED));
439                         break;
440                 }
441                 /* if left is SCONV, cannot remove */
442                 if (l->n_op == SCONV)
ragge
1.1
443                         break;
ragge
1.54
444
445                 /* avoid ADDROF TEMP */
446                 if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
447                         break;
448
ragge
1.40
449                 /* if conversion to another pointer type, just remove */
450                 if (p->n_type > BTMASK && l->n_type > BTMASK)
451                         goto delp;
452                 break;
453
454         delp:   l->n_type = p->n_type;
ragge
1.1
455                 l->n_qual = p->n_qual;
456                 l->n_df = p->n_df;
457                 l->n_sue = p->n_sue;
458                 nfree(p);
459                 p = l;
460                 break;
ragge
1.40
461                 
ragge
1.1
462         case SCONV:
463                 l = p->n_left;
ragge
1.4
464
ragge
1.25
465                 if (p->n_type == l->n_type) {
466                         nfree(p);
467                         return l;
468                 }
469
ragge
1.4
470                 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
pj
1.30
471                     btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
ragge
1.4
472                         if (p->n_type != FLOAT && p->n_type != DOUBLE &&
ragge
1.15
473                             l->n_type != FLOAT && l->n_type != DOUBLE &&
474                             l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
ragge
1.41
475                                 if (l->n_op == NAME || l->n_op == UMUL ||
476                                     l->n_op == TEMP) {
ragge
1.15
477                                         l->n_type = p->n_type;
478                                         nfree(p);
479                                         return l;
480                                 }
ragge
1.4
481                         }
ragge
1.6
482                 }
483
ragge
1.42
484                 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
485                     coptype(l->n_op) == BITYPE) {
486                         l->n_type = p->n_type;
487                         nfree(p);
488                         return l;
489                 }
490
ragge
1.3
491                 o = l->n_op;
ragge
1.4
492                 m = p->n_type;
ragge
1.1
493
494                 if (o == ICON) {
495                         CONSZ val = l->n_lval;
496
ragge
1.29
497                         if (!ISPTR(m)) /* Pointers don't need to be conv'd */
498                             switch (m) {
ragge
1.52
499                         case BOOL:
500                                 l->n_lval = l->n_lval != 0;
501                                 break;
ragge
1.1
502                         case CHAR:
503                                 l->n_lval = (char)val;
504                                 break;
505                         case UCHAR:
506                                 l->n_lval = val & 0377;
507                                 break;
ragge
1.15
508                         case SHORT:
ragge
1.1
509                                 l->n_lval = (short)val;
510                                 break;
ragge
1.15
511                         case USHORT:
ragge
1.1
512                                 l->n_lval = val & 0177777;
513                                 break;
ragge
1.15
514                         case ULONG:
ragge
1.1
515                         case UNSIGNED:
516                                 l->n_lval = val & 0xffffffff;
517                                 break;
ragge
1.15
518                         case LONG:
ragge
1.1
519                         case INT:
520                                 l->n_lval = (int)val;
521                                 break;
522                         case LONGLONG:
523                                 l->n_lval = (long long)val;
ragge
1.15
524                                 break;
ragge
1.1
525                         case ULONGLONG:
526                                 l->n_lval = val;
527                                 break;
528                         case VOID:
529                                 break;
ragge
1.14
530                         case LDOUBLE:
ragge
1.1
531                         case DOUBLE:
532                         case FLOAT:
533                                 l->n_op = FCON;
534                                 l->n_dcon = val;
535                                 break;
536                         default:
537                                 cerror("unknown type %d"m);
538                         }
539                         l->n_type = m;
ragge
1.44
540                         l->n_sue = MKSUE(m);
ragge
1.1
541                         nfree(p);
542                         return l;
ragge
1.72
543                 } else if (l->n_op == FCON) {
544                         l->n_lval = l->n_dcon;
545                         l->n_sp = NULL;
546                         l->n_op = ICON;
547                         l->n_type = m;
548                         l->n_sue = MKSUE(m);
549                         nfree(p);
550                         return clocal(l);
ragge
1.1
551                 }
ragge
1.17
552                 if (DEUNSIGN(p->n_type) == SHORT &&
553                     DEUNSIGN(l->n_type) == SHORT) {
554                         nfree(p);
555                         p = l;
556                 }
ragge
1.36
557                 if ((p->n_type == CHAR || p->n_type == UCHAR ||
558                     p->n_type == SHORT || p->n_type == USHORT) &&
559                     (l->n_type == FLOAT || l->n_type == DOUBLE ||
560                     l->n_type == LDOUBLE)) {
561                         p = block(SCONVpNILp->n_typep->n_dfp->n_sue);
562                         p->n_left->n_type = INT;
563                         return p;
564                 }
ragge
1.1
565                 break;
566
ragge
1.15
567         case MOD:
568         case DIV:
569                 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
570                         break;
ragge
1.16
571                 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
ragge
1.15
572                         break;
573                 /* make it an int division by inserting conversions */
574                 p->n_left = block(SCONVp->n_leftNILINT0MKSUE(INT));
575                 p->n_right = block(SCONVp->n_rightNILINT0MKSUE(INT));
576                 p = block(SCONVpNILp->n_type0MKSUE(p->n_type));
577                 p->n_left->n_type = INT;
578                 break;
579
ragge
1.1
580         case PMCONV:
581         case PVCONV:
ragge
1.74
582                 r = p;
583                 p = buildtree(o == PMCONV ? MUL : DIVp->n_leftp->n_right);
584                 nfree(r);
585                 break;
ragge
1.1
586
ragge
1.31
587         case FORCE:
ragge
1.32
588                 /* put return value in return reg */
589                 p->n_op = ASSIGN;
590                 p->n_right = p->n_left;
591                 p->n_left = block(REGNILNILp->n_type0MKSUE(INT));
ragge
1.53
592                 p->n_left->n_rval = p->n_left->n_type == BOOL ? 
593                     RETREG(CHAR) : RETREG(p->n_type);
ragge
1.31
594                 break;
ragge
1.39
595
596         case LS:
597         case RS:
598                 /* shift count must be in a char
599                  * unless longlong, where it must be int */
600                 if (p->n_type == LONGLONG || p->n_type == ULONGLONG) {
601                         if (p->n_right->n_type != INT)
602                                 p->n_right = block(SCONVp->n_rightNIL,
603                                     INT0MKSUE(INT));
604                         break;
605                 }
606                 if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR)
607                         break;
608                 p->n_right = block(SCONVp->n_rightNIL,
609                     CHAR0MKSUE(CHAR));
610                 break;
ragge
1.1
611         }
ragge
1.54
612 #ifdef PCC_DEBUG
613         if (xdebug) {
614                 printf("clocal end: %p\n"p);
615                 fwalk(peprint0);
616         }
617 #endif
ragge
1.1
618         return(p);
619 }
620
ragge
1.64
621 /*
622  * Change CALL references to either direct (static) or PLT.
623  */
624 static void
625 fixnames(NODE *p)
626 {
627         struct symtab *sp;
ragge
1.65
628         struct suedef *sue;
ragge
1.64
629         NODE *q;
630         char *c;
631         int isu;
632
633         if ((cdope(p->n_op) & CALLFLG) == 0)
634                 return;
635         isu = 0;
636         q = p->n_left;
ragge
1.65
637         sue = q->n_sue;
ragge
1.64
638         if (q->n_op == UMUL)
639                 q = q->n_leftisu = 1;
gmcgarry
1.83
640
ragge
1.64
641         if (q->n_op == PLUS && q->n_left->n_op == TEMP &&
642             q->n_right->n_op == ICON) {
643                 sp = q->n_right->n_sp;
644
ragge
1.65
645                 if (sp == NULL)
646                         return/* nothing to do */
ragge
1.64
647                 if (sp->sclass == STATIC && !ISFTN(sp->stype))
648                         return/* function pointer */
649
650                 if (sp->sclass != STATIC && sp->sclass != EXTERN &&
651                     sp->sclass != EXTDEF)
652                         cerror("fixnames");
653
gmcgarry
1.83
654 #if defined(ELFABI)
655
ragge
1.69
656                 if ((c = strstr(sp->soname"@GOT")) == NULL)
ragge
1.64
657                         cerror("fixnames2");
658                 if (isu) {
659                         memcpy(c"@PLT"sizeof("@PLT"));
660                 } else
661                         *c = 0;
gmcgarry
1.83
662
663 #elif defined(MACHOABI)
664
665                 if ((c = strstr(sp->soname"$non_lazy_ptr")) == NULL &&
666                     (c = strstr(sp->soname"-L")) == NULL)
667                                 cerror("fixnames2");
668                 if (isu) {
669                         *c = 0;
670                         addstub(&stublistsp->soname+1);
671                         strcpy(c"$stub");
672                 } else 
673                         *c = 0;
674
675 #endif
676
ragge
1.64
677                 nfree(q->n_left);
678                 q = q->n_right;
679                 if (isu)
680                         nfree(p->n_left->n_left);
681                 nfree(p->n_left);
682                 p->n_left = q;
ragge
1.65
683                 q->n_sue = sue;
ragge
1.64
684         }
685 }
686
ragge
1.1
687 void
688 myp2tree(NODE *p)
689 {
ragge
1.67
690         struct symtab *sp;
691
ragge
1.64
692         if (kflag)
ragge
1.67
693                 walkf(pfixnames); /* XXX walkf not needed */
694         if (p->n_op != FCON)
695                 return;
696
ragge
1.70
697 #if 0
ragge
1.67
698         /* put floating constants in memory */
699         setloc1(RDATA);
700         defalign(ALLDOUBLE);
701         deflab1(i = getlab());
702         ninval(0btdims[p->n_type].suesizep);
ragge
1.70
703 #endif
ragge
1.67
704
705         sp = IALLOC(sizeof(struct symtab));
706         sp->sclass = STATIC;
gmcgarry
1.75
707         sp->ssue = MKSUE(p->n_type);
ragge
1.67
708         sp->slevel = 1/* fake numeric label */
ragge
1.70
709         sp->soffset = getlab();
ragge
1.67
710         sp->sflags = 0;
ragge
1.70
711         sp->stype = p->n_type;
712         sp->squal = (CON >> TSHIFT);
713
714         defloc(sp);
gmcgarry
1.75
715         ninval(0sp->ssue->suesizep);
ragge
1.67
716
717         p->n_op = NAME;
718         p->n_lval = 0;
719         p->n_sp = sp;
ragge
1.1
720 }
721
722 /*ARGSUSED*/
723 int
724 andable(NODE *p)
725 {
ragge
1.64
726         return(1);      /* all names can have & taken on them */
ragge
1.1
727 }
728
729 /*
730  * at the end of the arguments of a ftn, set the automatic offset
731  */
732 void
733 cendarg()
734 {
735         autooff = AUTOINIT;
736 }
737
738 /*
ragge
1.36
739  * Return 1 if a variable of type type is OK to put in register.
740  */
741 int
742 cisreg(TWORD t)
743 {
744         if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
745                 return 0/* not yet */
746         return 1;
747 }
748
749 /*
ragge
1.1
750  * return a node, for structure references, which is suitable for
751  * being added to a pointer of type t, in order to be off bits offset
752  * into a structure
753  * t, d, and s are the type, dimension offset, and sizeoffset
754  * For pdp10, return the type-specific index number which calculation
755  * is based on its size. For example, short a[3] would return 3.
756  * Be careful about only handling first-level pointers, the following
757  * indirections must be fullword.
758  */
759 NODE *
760 offcon(OFFSZ offTWORD tunion dimfun *dstruct suedef *sue)
761 {
762         register NODE *p;
763
764         if (xdebug)
765                 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
766                     offtdsue->suesize);
767
768         p = bcon(0);
769         p->n_lval = off/SZCHAR/* Default */
770         return(p);
771 }
772
773 /*
774  * Allocate off bits on the stack.  p is a tree that when evaluated
ragge
1.45
775  * is the multiply count for off, t is a storeable node where to write
ragge
1.1
776  * the allocated address.
777  */
778 void
779 spalloc(NODE *tNODE *pOFFSZ off)
780 {
781         NODE *sp;
782
ragge
1.45
783         p = buildtree(MULpbcon(off/SZCHAR)); /* XXX word alignment? */
784
785         /* sub the size from sp */
ragge
1.55
786         sp = block(REGNILNILp->n_type0MKSUE(INT));
ragge
1.45
787         sp->n_lval = 0;
788         sp->n_rval = STKREG;
789         ecomp(buildtree(MINUSEQspp));
ragge
1.1
790
791         /* save the address of sp */
792         sp = block(REGNILNILPTR+INTt->n_dft->n_sue);
793         sp->n_lval = 0;
794         sp->n_rval = STKREG;
795         t->n_type = sp->n_type;
796         ecomp(buildtree(ASSIGNtsp)); /* Emit! */
797
798 }
799
800 /*
ragge
1.48
801  * Print out a string of characters.
802  * Assume that the assembler understands C-style escape
ragge
1.70
803  * sequences.
ragge
1.48
804  */
805 void
ragge
1.70
806 instring(struct symtab *sp)
ragge
1.48
807 {
gmcgarry
1.83
808         char *s, *str = sp->sname;
809
810 #if defined(ELFABI)
ragge
1.70
811
812         defloc(sp);
gmcgarry
1.83
813
814 #elif defined(MACHOABI)
815
816         extern int lastloc;
817         if (lastloc != STRNG)
818                 printf("        .cstring\n");
819         lastloc = STRNG;
820         printf("\t.p2align 2\n");
821         printf(LABFMT ":\n"sp->soffset);
822
823 #endif
ragge
1.48
824
mickey
1.61
825         /* be kind to assemblers and avoid long strings */
ragge
1.48
826         printf("\t.ascii \"");
ragge
1.51
827         for (s = str; *s != 0; ) {
828                 if (*s++ == '\\') {
ragge
1.48
829                         (void)esccon(&s);
ragge
1.51
830                 }
ragge
1.70
831                 if (s - str > 60) {
ragge
1.48
832                         fwrite(str1s - strstdout);
833                         printf("\"\n\t.ascii \"");
834                         str = s;
835                 }
836         }
837         fwrite(str1s - strstdout);
838         printf("\\0\"\n");
839 }
840
ragge
1.70
841 /*
842  * Print out a wide string by calling ninval().
843  */
844 void
845 inwstring(struct symtab *sp)
846 {
847         char *s = sp->sname;
848         NODE *p;
849
850         defloc(sp);
gmcgarry
1.84
851         p = xbcon(0NULLWCHAR_TYPE);
ragge
1.70
852         do {
853                 if (*s++ == '\\')
854                         p->n_lval = esccon(&s);
855                 else
856                         p->n_lval = (unsigned char)s[-1];
857                 ninval(0, (MKSUE(WCHAR_TYPE))->suesizep);
858         } while (s[-1] != 0);
859         nfree(p);
860 }
861
862
ragge
1.49
863 static int inbitsinval;
864
865 /*
866  * set fsz bits in sequence to zero.
867  */
868 void
869 zbits(OFFSZ offint fsz)
870 {
871         int m;
872
873         if (idebug)
ragge
1.51
874                 printf("zbits off %lld, fsz %d inbits %d\n"offfszinbits);
ragge
1.49
875         if ((m = (inbits % SZCHAR))) {
876                 m = SZCHAR - m;
877                 if (fsz < m) {
ragge
1.51
878                         inbits += fsz;
ragge
1.49
879                         return;
880                 } else {
881                         fsz -= m;
882                         printf("\t.byte %d\n"inval);
883                         inval = inbits = 0;
884                 }
885         }
886         if (fsz >= SZCHAR) {
887                 printf("\t.zero %d\n"fsz/SZCHAR);
ragge
1.51
888                 fsz -= (fsz/SZCHAR) * SZCHAR;
ragge
1.49
889         }
890         if (fsz) {
891                 inval = 0;
892                 inbits = fsz;
893         }
894 }
895
896 /*
897  * Initialize a bitfield.
898  */
899 void
900 infld(CONSZ offint fszCONSZ val)
901 {
902         if (idebug)
ragge
1.51
903                 printf("infld off %lld, fsz %d, val %lld inbits %d\n",
904                     offfszvalinbits);
ragge
1.56
905         val &= ((CONSZ)1 << fsz)-1;
ragge
1.49
906         while (fsz + inbits >= SZCHAR) {
907                 inval |= (val << inbits);
908                 printf("\t.byte %d\n"inval & 255);
909                 fsz -= (SZCHAR - inbits);
910                 val >>= (SZCHAR - inbits);
911                 inval = inbits = 0;
912         }
ragge
1.51
913         if (fsz) {
914                 inval |= (val << inbits);
915                 inbits += fsz;
916         }
ragge
1.49
917 }
918
ragge
1.48
919 /*
ragge
1.46
920  * print out a constant node, may be associated with a label.
921  * Do not free the node after use.
ragge
1.49
922  * off is bit offset from the beginning of the aggregate
923  * fsz is the number of bits this is referring to
ragge
1.21
924  */
925 void
ragge
1.49
926 ninval(CONSZ offint fszNODE *p)
ragge
1.21
927 {
ragge
1.46
928         union { float fdouble dlong double lint i[3]; } u;
ragge
1.24
929         struct symtab *q;
ragge
1.64
930         char *c;
ragge
1.23
931         TWORD t;
ragge
1.46
932         int i;
ragge
1.23
933
934         t = p->n_type;
935         if (t > BTMASK)
936                 t = INT/* pointer */
937
ragge
1.65
938         while (p->n_op == SCONV || p->n_op == PCONV) {
939                 NODE *l = p->n_left;
940                 l->n_type = p->n_type;
941                 p = l;
942         }
943
ragge
1.64
944         if (kflag && (p->n_op == PLUS || p->n_op == UMUL)) {
945                 if (p->n_op == UMUL)
946                         p = p->n_left;
947                 p = p->n_right;
948                 q = p->n_sp;
gmcgarry
1.83
949
950 #if defined(ELFABI)
951
ragge
1.69
952                 if ((c = strstr(q->soname"@GOT")) != NULL)
ragge
1.64
953                         *c = 0/* ignore GOT ref here */
gmcgarry
1.83
954
955 #else
956
957                 if  ((c = strstr(q->soname"$non_lazy_ptr")) != NULL) {
958                         q->soname++;    /* skip "L" */
959                         *c = 0/* ignore GOT ref here */
960                 }
961                 else if ((c = strstr(q->soname"-L")) != NULL)
962                         *c = 0/* ignore GOT ref here */
963
964 #endif
ragge
1.64
965         }
ragge
1.46
966         if (p->n_op != ICON && p->n_op != FCON)
ragge
1.40
967                 cerror("ninval: init node not constant");
968
ragge
1.49
969         if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
ragge
1.46
970                 uerror("element not constant");
971
ragge
1.23
972         switch (t) {
ragge
1.21
973         case LONGLONG:
974         case ULONGLONG:
ragge
1.46
975                 i = (p->n_lval >> 32);
976                 p->n_lval &= 0xffffffff;
ragge
1.51
977                 p->n_type = INT;
ragge
1.49
978                 ninval(off32p);
ragge
1.46
979                 p->n_lval = i;
ragge
1.49
980                 ninval(off+3232p);
ragge
1.21
981                 break;
982         case INT:
983         case UNSIGNED:
984                 printf("\t.long 0x%x", (int)p->n_lval);
ragge
1.24
985                 if ((q = p->n_sp) != NULL) {
986                         if ((q->sclass == STATIC && q->slevel > 0) ||
987                             q->sclass == ILABEL) {
988