Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20100501124156

Diff

Diff from 1.117 to:

Annotations

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

Annotated File View

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