Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20090208160126

Diff

Diff from 1.96 to:

Annotations

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

Annotated File View

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