Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20121028135928

Diff

Diff from 1.168 to:

Annotations

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

Annotated File View

ragge
1.168
1 /*      $Id: local.c,v 1.168 2012/10/28 13:59:28 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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27
ragge
1.48
28 #include "pass1.h"
ragge
1.1
29
ragge
1.60
30 /*      this file contains code which is dependent on the target machine */
31
ragge
1.130
32 #ifdef notyet
ragge
1.57
33 /*
34  * Check if a constant is too large for a type.
35  */
36 static int
37 toolarge(TWORD tCONSZ con)
38 {
39         U_CONSZ ucon = con;
40
41         switch (t) {
42         case ULONGLONG:
43         case LONGLONG:
44                 break/* cannot be too large */
45 #define SCHK(i) case i: if (con > MAX_##i || con < MIN_##i) return 1; break
46 #define UCHK(i) case i: if (ucon > MAX_##i) return 1; break
47         SCHK(INT);
48         SCHK(SHORT);
otto
1.58
49         case BOOL:
ragge
1.57
50         SCHK(CHAR);
51         UCHK(UNSIGNED);
52         UCHK(USHORT);
53         UCHK(UCHAR);
54         default:
55                 cerror("toolarge");
56         }
57         return 0;
58 }
ragge
1.130
59 #endif
ragge
1.57
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));
plunky
1.166
78         s->name = newstring(namestrlen(name));
gmcgarry
1.83
79         DLIST_INSERT_BEFORE(listslink);
80 }
81
82 #endif
83
ragge
1.60
84 #define IALLOC(sz)      (isinlining ? permalloc(sz) : tmpalloc(sz))
gmcgarry
1.86
85
ragge
1.60
86 /*
87  * Make a symtab entry for PIC use.
88  */
89 static struct symtab *
gmcgarry
1.83
90 picsymtab(char *pchar *schar *s2)
ragge
1.60
91 {
92         struct symtab *sp = IALLOC(sizeof(struct symtab));
gmcgarry
1.83
93         size_t len = strlen(p) + strlen(s) + strlen(s2) + 1;
ragge
1.60
94         
ragge
1.69
95         sp->sname = sp->soname = IALLOC(len);
gmcgarry
1.83
96         strlcpy(sp->sonameplen);
97         strlcat(sp->sonameslen);
ragge
1.69
98         strlcat(sp->sonames2len);
ragge
1.123
99         sp->sap = NULL;
ragge
1.60
100         sp->sclass = EXTERN;
ragge
1.64
101         sp->sflags = sp->slevel = 0;
gmcgarry
1.158
102         sp->stype = 0xdeadbeef;
ragge
1.60
103         return sp;
104 }
gmcgarry
1.103
105
106 #ifdef os_win32
107 static NODE *
108 import(NODE *p)
109 {
110         NODE *q;
111         char *name;
112         struct symtab *sp;
113
114         if ((name = p->n_sp->soname) == NULL)
115                 name = exname(p->n_sp->sname);
116
117         sp = picsymtab("__imp_"name"");
118         q = xbcon(0spPTR+VOID);
ragge
1.138
119         q = block(UMULq0PTR|VOID00);
ragge
1.136
120         q = block(UMULq0p->n_typep->n_dfp->n_ap);
gmcgarry
1.103
121         q->n_sp = p->n_sp/* for init */
122         nfree(p);
123
124         return q;
125 }
gmcgarry
1.86
126 #endif
ragge
1.60
127
128 int gotnr/* tempnum for GOT register */
gmcgarry
1.86
129 int argstacksize;
130
ragge
1.60
131 /*
132  * Create a reference for an extern variable.
133  */
134 static NODE *
135 picext(NODE *p)
136 {
gmcgarry
1.86
137
138 #if defined(ELFABI)
139
ragge
1.168
140         struct attr *ga;
ragge
1.60
141         NODE *q, *r;
stefan
1.66
142         struct symtab *sp;
ragge
1.96
143         char *name;
ragge
1.60
144
ragge
1.168
145         if ((ga = attr_find(p->n_sp->sapGCC_ATYP_VISIBILITY)) &&
146             strcmp(ga->sarg(0), "hidden") == 0)
147                 return p/* no GOT reference */
148
ragge
1.138
149         q = tempnode(gotnrPTR|VOID00);
ragge
1.96
150         if ((name = p->n_sp->soname) == NULL)
151                 name = p->n_sp->sname;
152         sp = picsymtab(""name"@GOT");
ragge
1.117
153 #ifdef GCC_COMPAT
ragge
1.123
154         if (attr_find(p->n_sp->sapGCC_ATYP_STDCALL) != NULL)
ragge
1.117
155                 p->n_sp->sflags |= SSTDCALL;
156 #endif
ragge
1.118
157         sp->sflags = p->n_sp->sflags & SSTDCALL;
stefan
1.66
158         r = xbcon(0spINT);
ragge
1.60
159         q = buildtree(PLUSqr);
ragge
1.138
160         q = block(UMULq0PTR|VOID00);
ragge
1.123
161         q = block(UMULq0p->n_typep->n_dfp->n_ap);
gmcgarry
1.86
162         q->n_sp = p->n_sp/* for init */
163         nfree(p);
164         return q;
gmcgarry
1.83
165
166 #elif defined(MACHOABI)
167
gmcgarry
1.86
168         NODE *q, *r;
169         struct symtab *sp;
gmcgarry
1.101
170         char buf2[256], *name, *pspn;
gmcgarry
1.83
171
ragge
1.96
172         if ((name = cftnsp->soname) == NULL)
173                 name = cftnsp->sname;
174         if ((pspn = p->n_sp->soname) == NULL)
pantzer
1.98
175                 pspn = exname(p->n_sp->sname);
gmcgarry
1.83
176         if (p->n_sp->sclass == EXTDEF) {
gmcgarry
1.101
177                 snprintf(buf2256"-L%s$pb"name);
pantzer
1.98
178                 sp = picsymtab(""pspnbuf2);
gmcgarry
1.83
179         } else {
gmcgarry
1.101
180                 snprintf(buf2256"$non_lazy_ptr-L%s$pb"name);
ragge
1.96
181                 sp = picsymtab("L"pspnbuf2);
182                 addstub(&nlplistpspn);
gmcgarry
1.83
183         }
gmcgarry
1.158
184
185         sp->stype = p->n_sp->stype;
186
ragge
1.138
187         q = tempnode(gotnrPTR+VOID00);
gmcgarry
1.83
188         r = xbcon(0spINT);
189         q = buildtree(PLUSqr);
190
191         if (p->n_sp->sclass != EXTDEF)
ragge
1.138
192                 q = block(UMULq0PTR+VOID00);
ragge
1.123
193         q = block(UMULq0p->n_typep->n_dfp->n_ap);
ragge
1.65
194         q->n_sp = p->n_sp/* for init */
ragge
1.60
195         nfree(p);
196         return q;
gmcgarry
1.86
197
ragge
1.137
198 #else /* defined(PECOFFABI) || defined(AOUTABI) */
gmcgarry
1.86
199
200         return p;
201
202 #endif
203
ragge
1.60
204 }
205
206 /*
207  * Create a reference for a static variable.
208  */
209 static NODE *
210 picstatic(NODE *p)
211 {
gmcgarry
1.86
212
213 #if defined(ELFABI)
214
ragge
1.60
215         NODE *q, *r;
stefan
1.66
216         struct symtab *sp;
ragge
1.60
217
ragge
1.138
218         q = tempnode(gotnrPTR|VOID00);
ragge
1.94
219         if (p->n_sp->slevel > 0) {
ragge
1.60
220                 char buf[32];
221                 snprintf(buf32LABFMT, (int)p->n_sp->soffset);
gmcgarry
1.83
222                 sp = picsymtab(""buf"@GOTOFF");
ragge
1.96
223         } else {
224                 char *name;
225                 if ((name = p->n_sp->soname) == NULL)
226                         name = p->n_sp->sname;
227                 sp = picsymtab(""name"@GOTOFF");
228         }
229         
stefan
1.66
230         sp->sclass = STATIC;
231         sp->stype = p->n_sp->stype;
232         r = xbcon(0spINT);
ragge
1.60
233         q = buildtree(PLUSqr);
ragge
1.123
234         q = block(UMULq0p->n_typep->n_dfp->n_ap);
ragge
1.65
235         q->n_sp = p->n_sp/* for init */
ragge
1.60
236         nfree(p);
gmcgarry
1.86
237         return q;
gmcgarry
1.83
238
239 #elif defined(MACHOABI)
240
gmcgarry
1.86
241         NODE *q, *r;
242         struct symtab *sp;
gmcgarry
1.101
243         char buf2[256];
gmcgarry
1.83
244
gmcgarry
1.101
245         snprintf(buf2256"-L%s$pb",
ragge
1.97
246             cftnsp->soname ? cftnsp->soname : cftnsp->sname);
gmcgarry
1.83
247
ragge
1.94
248         if (p->n_sp->slevel > 0) {
gmcgarry
1.101
249                 char buf1[32];
250                 snprintf(buf132LABFMT, (int)p->n_sp->soffset);
gmcgarry
1.83
251                 sp = picsymtab(""buf1buf2);
252         } else  {
ragge
1.96
253                 char *name;
254                 if ((name = p->n_sp->soname) == NULL)
255                         name = p->n_sp->sname;
256                 sp = picsymtab(""exname(name), buf2);
gmcgarry
1.83
257         }
258         sp->sclass = STATIC;
259         sp->stype = p->n_sp->stype;
ragge
1.138
260         q = tempnode(gotnrPTR+VOID00);
gmcgarry
1.83
261         r = xbcon(0spINT);
262         q = buildtree(PLUSqr);
ragge
1.123
263         q = block(UMULq0p->n_typep->n_dfp->n_ap);
gmcgarry
1.83
264         q->n_sp = p->n_sp;
265         nfree(p);
gmcgarry
1.86
266         return q;
267
ragge
1.137
268 #else /* defined(PECOFFABI) || defined(AOUTABI) */
gmcgarry
1.86
269
270         return p;
gmcgarry
1.83
271
272 #endif
273
ragge
1.60
274 }
ragge
1.1
275
ragge
1.73
276 #ifdef TLS
277 /*
278  * Create a reference for a TLS variable.
279  */
280 static NODE *
281 tlspic(NODE *p)
282 {
283         NODE *q, *r;
ragge
1.85
284         struct symtab *sp, *sp2;
ragge
1.96
285         char *name;
ragge
1.73
286
287         /*
288          * creates:
289          *   leal var@TLSGD(%ebx),%eax
290          *   call ___tls_get_addr@PLT
291          */
292
293         /* calc address of var@TLSGD */
ragge
1.138
294         q = tempnode(gotnrPTR|VOID00);
ragge
1.96
295         if ((name = p->n_sp->soname) == NULL)
296                 name = p->n_sp->sname;
297         sp = picsymtab(""name"@TLSGD");
ragge
1.73
298         r = xbcon(0spINT);
299         q = buildtree(PLUSqr);
300
301         /* assign to %eax */
ragge
1.138
302         r = block(REGNILNILPTR|VOID00);
ragge
1.73
303         r->n_rval = EAX;
304         q = buildtree(ASSIGNrq);
305
306         /* call ___tls_get_addr */
ragge
1.85
307         sp2 = lookup("___tls_get_addr@PLT"0);
308         sp2->stype = EXTERN|INT|FTN;
309         r = nametree(sp2);
ragge
1.73
310         r = buildtree(ADDROFrNIL);
ragge
1.138
311         r = block(UCALLrNILINT00);
ragge
1.73
312
313         /* fusion both parts together */
314         q = buildtree(COMOPqr);
ragge
1.123
315         q = block(UMULq0p->n_typep->n_dfp->n_ap);
ragge
1.73
316         q->n_sp = p->n_sp/* for init */
317
318         nfree(p);
319         return q;
320 }
321
322 static NODE *
323 tlsnonpic(NODE *p)
324 {
325         NODE *q, *r;
ragge
1.85
326         struct symtab *sp, *sp2;
ragge
1.73
327         int ext = p->n_sp->sclass;
ragge
1.96
328         char *name;
ragge
1.73
329
ragge
1.96
330         if ((name = p->n_sp->soname) == NULL)
331                 name = p->n_sp->sname;
332         sp = picsymtab(""name,
gmcgarry
1.83
333             ext == EXTERN ? "@INDNTPOFF" : "@NTPOFF");
ragge
1.73
334         q = xbcon(0spINT);
335         if (ext == EXTERN)
ragge
1.138
336                 q = block(UMULqNILPTR|VOID00);
ragge
1.73
337
ragge
1.85
338         sp2 = lookup("%gs:0"0);
339         sp2->stype = EXTERN|INT;
340         r = nametree(sp2);
ragge
1.73
341
342         q = buildtree(PLUSqr);
ragge
1.123
343         q = block(UMULq0p->n_typep->n_dfp->n_ap);
ragge
1.73
344         q->n_sp = p->n_sp/* for init */
345
346         nfree(p);
347         return q;
348 }
349
350 static NODE *
351 tlsref(NODE *p)
352 {
353         if (kflag)
354                 return (tlspic(p));
355         else
356                 return (tlsnonpic(p));
357 }
358 #endif
359
ragge
1.48
360 /* clocal() is called to do local transformations on
361  * an expression tree preparitory to its being
362  * written out in intermediate code.
363  *
364  * the major essential job is rewriting the
365  * automatic variables and arguments in terms of
366  * REG and OREG nodes
367  * conversion ops which are not necessary are also clobbered here
368  * in addition, any special features (such as rewriting
369  * exclusive or) are easily handled here as well
370  */
ragge
1.1
371 NODE *
372 clocal(NODE *p)
373 {
374
375         register struct symtab *q;
gmcgarry
1.113
376         register NODE *r, *l;
377 #if defined(os_openbsd)
378         register NODE *s, *n;
379 #endif
ragge
1.1
380         register int o;
ragge
1.40
381         register int m;
ragge
1.1
382
ragge
1.54
383 #ifdef PCC_DEBUG
384         if (xdebug) {
385                 printf("clocal: %p\n"p);
386                 fwalk(peprint0);
387         }
388 #endif
ragge
1.1
389         switcho = p->n_op ){
390
391         case NAME:
392                 if ((q = p->n_sp) == NULL)
393                         return p/* Nothing to care about */
394
395                 switch (q->sclass) {
396
397                 case PARAM:
398                 case AUTO:
399                         /* fake up a structure reference */
400                         r = block(REGNILNILPTR+STRTY00);
401                         r->n_lval = 0;
402                         r->n_rval = FPREG;
403                         p = stref(block(STREFrp000));
404                         break;
405
ragge
1.65
406                 case USTATIC:
407                         if (kflag == 0)
408                                 break;
409                         /* FALLTHROUGH */
ragge
1.1
410                 case STATIC:
ragge
1.73
411 #ifdef TLS
412                         if (q->sflags & STLS) {
413                                 p = tlsref(p);
414                                 break;
415                         }
416 #endif
ragge
1.60
417                         if (kflag == 0) {
418                                 if (q->slevel == 0)
419                                         break;
ragge
1.147
420                         } else if (blevel > 0 && !statinit)
ragge
1.60
421                                 p = picstatic(p);
ragge
1.1
422                         break;
423
424                 case REGISTER:
425                         p->n_op = REG;
426                         p->n_lval = 0;
427                         p->n_rval = q->soffset;
428                         break;
429
ragge
1.60
430                 case EXTERN:
431                 case EXTDEF:
ragge
1.73
432 #ifdef TLS
433                         if (q->sflags & STLS) {
434                                 p = tlsref(p);
435                                 break;
436                         }
437 #endif
gmcgarry
1.103
438
439 #ifdef os_win32
440                         if (q->sflags & SDLLINDIRECT)
441                                 p = import(p);
442 #endif
ragge
1.60
443                         if (kflag == 0)
444                                 break;
ragge
1.147
445                         if (blevel > 0 && !statinit)
ragge
1.60
446                                 p = picext(p);
447                         break;
448                 }
ragge
1.1
449                 break;
450
ragge
1.65
451         case ADDROF:
452                 if (kflag == 0 || blevel == 0)
453                         break;
454                 /* char arrays may end up here */
455                 l = p->n_left;
456                 if (l->n_op != NAME ||
457                     (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE))
458                         break;
459                 l = p;
460                 p = picstatic(p->n_left);
461                 nfree(l);
462                 if (p->n_op != UMUL)
463                         cerror("ADDROF error");
464                 l = p;
465                 p = p->n_left;
466                 nfree(l);
467                 break;
468
ragge
1.62
469         case UCALL:
470         case USTCALL:
ragge
1.60
471                 if (kflag == 0)
472                         break;
gmcgarry
1.86
473 #if defined(ELFABI)
ragge
1.62
474                 /* Change to CALL node with ebx as argument */
ragge
1.138
475                 l = block(REGNILNILINT00);
ragge
1.62
476                 l->n_rval = EBX;
477                 p->n_right = buildtree(ASSIGNl,
ragge
1.138
478                     tempnode(gotnrINT00));
ragge
1.62
479                 p->n_op -= (UCALL-CALL);
gmcgarry
1.86
480 #endif
pantzer
1.89
481         
482         /* FALLTHROUGH */
483 #if defined(MACHOABI)
484         case CALL:
485         case STCALL:
486                 if (p->n_type == VOID)
487                         break;
488
ragge
1.123
489                 r = tempnode(0p->n_typep->n_dfp->n_ap);
pantzer
1.89
490                 l = tcopy(r);
491                 p = buildtree(COMOPbuildtree(ASSIGNrp), l);
492 #endif
493                         
ragge
1.10
494                 break;
ragge
1.64
495
ragge
1.159
496 #if defined(os_openbsd)
497 /*
498  * The called function returns structures according to their aligned size:
499  *  Structures 1, 2 or 4 bytes in size are placed in EAX.
500  *  Structures 8 bytes in size are placed in: EAX and EDX.
501  */
502         case UMUL:
503                 o = 0;
504                 l = p->n_left;
505                 if (l->n_op == PLUS)
506                         l = l->n_lefto++;
507                 if (l->n_op != PCONV)
508                         break;
509                 l = l->n_left;
510                 if (l->n_op != STCALL && l->n_op != USTCALL)
511                         break;
512                 m = tsize(DECREF(l->n_type), l->n_dfl->n_ap);
513                 if (m != SZCHAR && m != SZSHORT &&
514                     m != SZINT && m != SZLONGLONG)
515                         break;
516                 /* This is a direct reference to a small struct return */
517                 l->n_op -= (STCALL-CALL);
518                 if (o == 0) {
519                         /* first element in struct */
520                         p->n_left = nfree(p->n_left); /* free PCONV */
521                         l->n_ap = p->n_ap;
522                         l->n_df = p->n_df;
523                         l->n_type = p->n_type;
524                         if (p->n_type < INT) {
525                                 /* Need to add SCONV */
526                                 p->n_op = SCONV;
527                         } else
528                                 p = nfree(p); /* no casts needed */
529                 } else {
530                         /* convert PLUS to RS */
531                         o = p->n_left->n_right->n_lval;
532                         l->n_type = (o > 3 ? ULONGLONG : UNSIGNED);
533                         nfree(p->n_left->n_right);
534                         p->n_left = nfree(p->n_left);
535                         p->n_left = nfree(p->n_left);
536                         p->n_left = buildtree(RSp->n_leftbcon(o*8));
537                         p->n_left = makety(p->n_leftp->n_typep->n_qual,
538                             p->n_dfp->n_ap);
539                         p = nfree(p);
540                 }
541                 break;
542 #endif
543
ragge
1.129
544 #ifdef notyet
545         /* XXX breaks sometimes */
ragge
1.8
546         case CBRANCH:
547                 l = p->n_left;
548
549                 /*
ragge
1.77
550                  * Remove unnecessary conversion ops.
ragge
1.8
551                  */
ragge
1.128
552                 if (!clogop(l->n_op) || l->n_left->n_op != SCONV)
553                         break;
554                 if (coptype(l->n_op) != BITYPE)
555                         break;
556                 if (l->n_right->n_op != ICON)
557                         break;
558                 r = l->n_left->n_left;
559                 if (r->n_type >= FLOAT)
560                         break;
561                 if (toolarge(r->n_typel->n_right->n_lval))
562                         break;
563                 l->n_right->n_type = r->n_type;
564                 if (l->n_op >= ULE && l->n_op <= UGT)
565                         l->n_op -= (UGT-ULE);
566                 p->n_left = buildtree(l->n_oprl->n_right);
567                 nfree(l->n_left);
568                 nfree(l);
ragge
1.8
569                 break;
ragge
1.129
570 #endif
ragge
1.8
571
ragge
1.1
572         case PCONV:
573                 l = p->n_left;
ragge
1.162
574
575                 /* Make int type before pointer */
ragge
1.40
576                 if (l->n_type < INT || l->n_type == LONGLONG || 
ragge
1.134
577                     l->n_type == ULONGLONG || l->n_type == BOOL) {
ragge
1.40
578                         /* float etc? */
ragge
1.162
579                         p->n_left = block(SCONVlNILUNSIGNED00);
ragge
1.40
580                 }
581                 break;
582
ragge
1.1
583         case SCONV:
ragge
1.109
584                 if (p->n_left->n_op == COMOP)
585                         break;  /* may propagate wrong type later */
ragge
1.1
586                 l = p->n_left;
ragge
1.4
587
ragge
1.25
588                 if (p->n_type == l->n_type) {
589                         nfree(p);
590                         return l;
591                 }
592
ragge
1.4
593                 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
ragge
1.139
594                     tsize(p->n_typep->n_dfp->n_ap) ==
595                     tsize(l->n_typel->n_dfl->n_ap)) {
ragge
1.4
596                         if (p->n_type != FLOAT && p->n_type != DOUBLE &&
ragge
1.15
597                             l->n_type != FLOAT && l->n_type != DOUBLE &&
598                             l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
ragge
1.41
599                                 if (l->n_op == NAME || l->n_op == UMUL ||
600                                     l->n_op == TEMP) {
ragge
1.15
601                                         l->n_type = p->n_type;
602                                         nfree(p);
603                                         return l;
604                                 }
ragge
1.4
605                         }
ragge
1.6
606                 }
607
ragge
1.42
608                 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
ragge
1.131
609                     coptype(l->n_op) == BITYPE && l->n_op != COMOP &&
610                     l->n_op != QUEST) {
ragge
1.42
611                         l->n_type = p->n_type;
612                         nfree(p);
613                         return l;
614                 }
615
ragge
1.3
616                 o = l->n_op;
ragge
1.4
617                 m = p->n_type;
ragge
1.1
618
619                 if (o == ICON) {
ragge
1.147
620                         /*
621                          * Can only end up here if o is an address,
622                          * and in that case the only compile-time conversion
623                          * possible is to int.
624                          */
ragge
1.156
625                         if ((TMASK & l->n_type) == 0 && l->n_sp == NULL)
ragge
1.147
626                                 cerror("SCONV ICON");
627                         if (l->n_sp == 0) {
628                                 p->n_type = UNSIGNED;
629                                 concast(lm);
630                         } else if (m != INT && m != UNSIGNED)
ragge
1.1
631                                 break;
632                         l->n_type = m;
ragge
1.138
633                         l->n_ap = 0;
ragge
1.1
634                         nfree(p);
635                         return l;
ragge
1.147
636                 } else if (l->n_op == FCON)
637                         cerror("SCONV FCON");
ragge
1.36
638                 if ((p->n_type == CHAR || p->n_type == UCHAR ||
639                     p->n_type == SHORT || p->n_type == USHORT) &&
640                     (l->n_type == FLOAT || l->n_type == DOUBLE ||
641                     l->n_type == LDOUBLE)) {
ragge
1.123
642                         p = block(SCONVpNILp->n_typep->n_dfp->n_ap);
ragge
1.36
643                         p->n_left->n_type = INT;
644                         return p;
645                 }
ragge
1.1
646                 break;
647
ragge
1.15
648         case MOD:
649         case DIV:
650                 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
651                         break;
ragge
1.16
652                 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
ragge
1.15
653                         break;
654                 /* make it an int division by inserting conversions */
ragge
1.147
655                 p->n_left = makety(p->n_leftINT000);
656                 p->n_right = makety(p->n_rightINT000);
657                 o = p->n_type;
658                 p->n_type = INT;
659                 p = makety(po000);
ragge
1.15
660                 break;
661
ragge
1.31
662         case FORCE:
ragge
1.32
663                 /* put return value in return reg */
664                 p->n_op = ASSIGN;
665                 p->n_right = p->n_left;
ragge
1.138
666                 p->n_left = block(REGNILNILp->n_type00);
ragge
1.53
667                 p->n_left->n_rval = p->n_left->n_type == BOOL ? 
668                     RETREG(CHAR) : RETREG(p->n_type);
ragge
1.31
669                 break;
ragge
1.39
670
671         case LS:
672         case RS:
ragge
1.127
673                 /* shift count must be in a char */
ragge
1.39
674                 if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR)
675                         break;
ragge
1.138
676                 p->n_right = block(SCONVp->n_rightNILCHAR00);
ragge
1.39
677                 break;
ragge
1.108
678 #if defined(os_openbsd)
679                 /* If not using pcc struct return */
680         case STASG:
681                 r = p->n_right;
682                 if (r->n_op != STCALL && r->n_op != USTCALL)
683                         break;
ragge
1.123
684                 m = tsize(BTYPE(r->n_type), r->n_dfr->n_ap);
ragge
1.108
685                 if (m == SZCHAR)
686                         m = CHAR;
687                 else if (m == SZSHORT)
688                         m = SHORT;
689                 else if (m == SZINT)
690                         m = INT;
691                 else if (m == SZLONGLONG)
692                         m = LONGLONG;
693                 else
694                         break;
695
696                 l = buildtree(ADDROFp->n_leftNIL);
697                 nfree(p);
698
699                 r->n_op -= (STCALL-CALL);
700                 r->n_type = m;
701
702                 /* r = long, l = &struct */
703
ragge
1.123
704                 n = tempnode(0mr->n_dfr->n_ap);
ragge
1.108
705                 r = buildtree(ASSIGNccopy(n), r);
706
ragge
1.123
707                 s = tempnode(0l->n_typel->n_dfl->n_ap);
ragge
1.108
708                 l = buildtree(ASSIGNccopy(s), l);
709
710                 p = buildtree(COMOPrl);
711
712                 l = buildtree(CAST,
ragge
1.138
713                     block(NAMENILNILm|PTR00), ccopy(s));
ragge
1.108
714                 r = l->n_right;
715                 nfree(l->n_left);
716                 nfree(l);
717
718                 r = buildtree(ASSIGNbuildtree(UMULrNIL), n);
719                 p = buildtree(COMOPpr);
720                 p = buildtree(COMOPps);
721                 break;
722 #endif
ragge
1.1
723         }
ragge
1.54
724 #ifdef PCC_DEBUG
725         if (xdebug) {
726                 printf("clocal end: %p\n"p);
727                 fwalk(peprint0);
728         }
729 #endif
ragge
1.1
730         return(p);
731 }
732
ragge
1.64
733 /*
734  * Change CALL references to either direct (static) or PLT.
735  */
736 static void
ragge
1.88
737 fixnames(NODE *pvoid *arg)
ragge
1.64
738 {
ragge
1.137
739 #if defined(ELFABI) || defined(MACHOABI)
gmcgarry
1.86
740
ragge
1.64
741         struct symtab *sp;
ragge
1.123
742         struct attr *ap;
ragge
1.64
743         NODE *q;
744         char *c;
745         int isu;
746
747         if ((cdope(p->n_op) & CALLFLG) == 0)
748                 return;
749         isu = 0;
750         q = p->n_left;
ragge
1.123
751         ap = q->n_ap;
ragge
1.64
752         if (q->n_op == UMUL)
753                 q = q->n_leftisu = 1;
gmcgarry
1.83
754
ragge
1.64
755         if (q->n_op == PLUS && q->n_left->n_op == TEMP &&
756             q->n_right->n_op == ICON) {
757                 sp = q->n_right->n_sp;
758
ragge
1.65
759                 if (sp == NULL)
760                         return/* nothing to do */
ragge
1.64
761                 if (sp->sclass == STATIC && !ISFTN(sp->stype))
762                         return/* function pointer */
763
764                 if (sp->sclass != STATIC && sp->sclass != EXTERN &&
765                     sp->sclass != EXTDEF)
766                         cerror("fixnames");
ragge
1.96
767                 c = NULL;
gmcgarry
1.83
768 #if defined(ELFABI)
769
ragge
1.96
770                 if (sp->soname == NULL ||
771                     (c = strstr(sp->soname"@GOT")) == NULL)
ragge
1.64
772                         cerror("fixnames2");
773                 if (isu) {
774                         memcpy(c"@PLT"sizeof("@PLT"));
775                 } else
776                         *c = 0;
gmcgarry
1.83
777
778 #elif defined(MACHOABI)
779
ragge
1.96
780                 if (sp->soname == NULL ||
781                     ((c = strstr(sp->soname"$non_lazy_ptr")) == NULL &&
782                     (c = strstr(sp->soname"-L")) == NULL))
gmcgarry
1.83
783                                 cerror("fixnames2");
gmcgarry
1.158
784
785                 if (!ISFTN(sp->stype))
786                         return/* function pointer */
787
gmcgarry
1.83
788                 if (isu) {
789                         addstub(&stublistsp->soname+1);
plunky
1.166
790                         memcpy(c"$stub"sizeof("$stub"));
gmcgarry
1.83
791                 } else 
792                         *c = 0;
793
794 #endif
795
ragge
1.64
796                 nfree(q->n_left);
797                 q = q->n_right;
798                 if (isu)
799                         nfree(p->n_left->n_left);
800                 nfree(p->n_left);
801                 p->n_left = q;
ragge
1.123
802                 q->n_ap = ap;
ragge
1.64
803         }
gmcgarry
1.86
804 #endif
ragge
1.64
805 }
806
ragge
1.117
807 static void mangle(NODE *p);
808
ragge
1.1
809 void
810 myp2tree(NODE *p)
811 {
ragge
1.67
812         struct symtab *sp;
813
ragge
1.64
814         if (kflag)
ragge
1.117
815                 fixnames(p0);
816
817         mangle(p);
818
ragge
1.67
819         if (p->n_op != FCON)
820                 return;
821
822         sp = IALLOC(sizeof(struct symtab));
823         sp->sclass = STATIC;
ragge
1.138
824         sp->sap = 0;
ragge
1.67
825         sp->slevel = 1/* fake numeric label */
ragge
1.70
826         sp->soffset = getlab();
ragge
1.67
827         sp->sflags = 0;
ragge
1.70
828         sp->stype = p->n_type;
829         sp->squal = (CON >> TSHIFT);
gmcgarry
1.144
830         sp->sname = sp->soname = NULL;
ragge
1.70
831
ragge
1.154
832         locctr(DATAsp);
ragge
1.70
833         defloc(sp);
ragge
1.139
834         ninval(0tsize(sp->stypesp->sdfsp->sap), p);
ragge
1.67
835
836         p->n_op = NAME;
837         p->n_lval = 0;
838         p->n_sp = sp;
ragge
1.161
839
840         if (kflag) {
841                 NODE *q = optim(picstatic(tcopy(p)));
842                 *p = *q;
843                 nfree(q);
844         }
ragge
1.1
845 }
846
847 /*ARGSUSED*/
848 int
849 andable(NODE *p)
850 {
ragge
1.64
851         return(1);      /* all names can have & taken on them */
ragge
1.1
852 }
853
854 /*
ragge
1.36
855  * Return 1 if a variable of type type is OK to put in register.
856  */
857 int
858 cisreg(TWORD t)
859 {
860         if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
861                 return 0/* not yet */
862         return 1;
863 }
864
865 /*
ragge
1.1
866  * Allocate off bits on the stack.  p is a tree that when evaluated
ragge
1.45
867  * is the multiply count for off, t is a storeable node where to write
ragge
1.1
868  * the allocated address.
869  */
870 void
871 spalloc(NODE *tNODE *pOFFSZ off)
872 {
873         NODE *sp;
874
ragge
1.45
875         p = buildtree(MULpbcon(off/SZCHAR)); /* XXX word alignment? */
876
877         /* sub the size from sp */
ragge
1.138
878         sp = block(REGNILNILp->n_type00);
ragge
1.45
879         sp->n_lval = 0;
880         sp->n_rval = STKREG;
881         ecomp(buildtree(MINUSEQspp));
ragge
1.1
882
pantzer
1.100
883 #ifdef MACHOABI 
884         /* align to 16 bytes */
ragge
1.138
885         sp = block(REGNILNILp->n_type00);
pantzer
1.100
886         sp->n_lval = 0;
887         sp->n_rval = STKREG;
888         ecomp(buildtree(PLUSEQspbcon(15)));
889         
ragge
1.138
890         sp = block(REGNILNILp->n_type00);
pantzer
1.100
891         sp->n_lval = 0;
892         sp->n_rval = STKREG;
893         ecomp(buildtree(RSEQspbcon(4)));
894         
ragge
1.138
895         sp = block(REGNILNILp->n_type00);
pantzer
1.100
896         sp->n_lval = 0;
897         sp->n_rval = STKREG;
898         ecomp(buildtree(LSEQspbcon(4)));
899 #endif
900         
901
ragge
1.1
902         /* save the address of sp */
ragge
1.123
903         sp = block(REGNILNILPTR+INTt->n_dft->n_ap);
ragge
1.1
904         sp->n_lval = 0;
905         sp->n_rval = STKREG;
906         t->n_type = sp->n_type;
907         ecomp(buildtree(ASSIGNtsp)); /* Emit! */
908
909 }
910
911 /*
ragge
1.46
912  * print out a constant node, may be associated with a label.
913  * Do not free the node after use.
ragge
1.49
914  * off is bit offset from the beginning of the aggregate
915  * fsz is the number of bits this is referring to
ragge
1.21
916  */
ragge
1.150
917 int
ragge
1.49
918 ninval(CONSZ offint fszNODE *p)
ragge
1.21
919 {
ragge
1.46
920         union { float fdouble dlong double lint i[3]; } u;
921         int i;
ragge
1.23
922
ragge
1.151
923         switch (p->n_type) {
ragge
1.21
924         case LONGLONG:
925         case ULONGLONG:
gmcgarry
1.107
926                 i = (int)(p->n_lval >> 32);
ragge
1.46
927                 p->n_lval &= 0xffffffff;
ragge
1.51
928                 p->n_type = INT;
ragge
1.151
929                 inval(off32p);
ragge