Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20121022085148

Diff

Diff from 1.46 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/cc/ccom/builtins.c

Annotated File View

plunky
1.46
1 /*      $Id: builtins.c,v 1.46 2012/10/22 08:51:48 plunky 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 # include "pass1.h"
28
ragge
1.2
29 #ifndef MIN
30 #define MIN(a,b) (((a)<(b))?(a):(b))
31 #endif
ragge
1.18
32 #ifndef MAX
33 #define MAX(a,b) (((a)>(b))?(a):(b))
34 #endif
ragge
1.1
35
36 #ifndef NO_C_BUILTINS
ragge
1.36
37
ragge
1.1
38 /*
39  * replace an alloca function with direct allocation on stack.
40  * return a destination temp node.
41  */
42 static NODE *
ragge
1.36
43 builtin_alloca(const struct bitable *btNODE *a)
ragge
1.1
44 {
45         NODE *t, *u;
46
47 #ifdef notyet
48         if (xnobuiltins)
49                 return NULL;
50 #endif
51
ragge
1.22
52         t = tempnode(0VOID|PTR00);
53         u = tempnode(regno(t), VOID|PTR00);
ragge
1.1
54         spalloc(taSZCHAR);
55         return u;
56 }
57
58 /*
59  * Determine if a value is known to be constant at compile-time and
60  * hence that PCC can perform constant-folding on expressions involving
61  * that value.
62  */
63 static NODE *
ragge
1.36
64 builtin_constant_p(const struct bitable *btNODE *a)
ragge
1.1
65 {
ragge
1.17
66         void putjops(NODE *pvoid *arg);
ragge
1.36
67         NODE *f;
ragge
1.17
68         int isconst;
ragge
1.1
69
ragge
1.17
70         walkf(aputjops0);
71         for (f = af->n_op == COMOPf = f->n_right)
72                 ;
73         isconst = nncon(f);
74         tfree(a);
75         return bcon(isconst);
ragge
1.1
76 }
77
78 /*
79  * Hint to the compiler whether this expression will evaluate true or false.
80  * Just ignored for now.
81  */
82 static NODE *
ragge
1.36
83 builtin_expect(const struct bitable *btNODE *a)
ragge
1.1
84 {
ragge
1.36
85         NODE *f;
ragge
1.1
86
87         if (a && a->n_op == CM) {
88                 tfree(a->n_right);
89                 f = a->n_left;
90                 nfree(a);
91                 a = f;
92         }
93
94         return a;
95 }
96
97 /*
98  * Take integer absolute value.
99  * Simply does: ((((x)>>(8*sizeof(x)-1))^(x))-((x)>>(8*sizeof(x)-1)))
100  */
101 static NODE *
ragge
1.36
102 builtin_abs(const struct bitable *btNODE *a)
ragge
1.1
103 {
104         NODE *p, *q, *r, *t, *t2, *t3;
105         int tmp1tmp2shift;
106
107         if (a->n_type != INT)
108                 a = cast(aINT0);
109
110         if (a->n_op == ICON) {
111                 if (a->n_lval < 0)
112                         a->n_lval = -a->n_lval;
113                 p = a;
114         } else {
ragge
1.7
115                 t = tempnode(0a->n_typea->n_dfa->n_ap);
ragge
1.1
116                 tmp1 = regno(t);
117                 p = buildtree(ASSIGNta);
118
ragge
1.7
119                 t = tempnode(tmp1a->n_typea->n_dfa->n_ap);
120                 shift = (int)tsize(a->n_typea->n_dfa->n_ap) - 1;
ragge
1.1
121                 q = buildtree(RStbcon(shift));
122
ragge
1.7
123                 t2 = tempnode(0a->n_typea->n_dfa->n_ap);
ragge
1.1
124                 tmp2 = regno(t2);
125                 q = buildtree(ASSIGNt2q);
126
ragge
1.7
127                 t = tempnode(tmp1a->n_typea->n_dfa->n_ap);
128                 t2 = tempnode(tmp2a->n_typea->n_dfa->n_ap);
129                 t3 = tempnode(tmp2a->n_typea->n_dfa->n_ap);
ragge
1.1
130                 r = buildtree(MINUSbuildtree(ERtt2), t3);
131
132                 p = buildtree(COMOPpbuildtree(COMOPqr));
133         }
134
135         return p;
136 }
137
ragge
1.30
138 #define cmop(x,y) buildtree(COMOP, x, y)
ragge
1.31
139 #define lblnod(l) nlabel(l)
ragge
1.30
140
141 #ifndef TARGET_CXZ
142 /*
143  * Find number of beginning 0's in a word of type t.
144  * t should be deunsigned.
145  */
146 static NODE *
ragge
1.36
147 builtin_cxz(NODE *aTWORD tint isclz)
ragge
1.30
148 {
149         NODE *t101, *t102;
150         NODE *rn, *p;
151         int l15l16l17;
152         int sz;
153
154         t = ctype(t);
155         sz = (int)tsize(t00);
156
157         t101 = tempnode(0INT00);
158         t102 = tempnode(0t00);
159         l15 = getlab();
160         l16 = getlab();
161         l17 = getlab();
162         rn = buildtree(ASSIGNccopy(t102), a);
163         rn = cmop(rnbuildtree(ASSIGNccopy(t101), bcon(0)));
164         rn = cmop(rnlblnod(l16));
165
166         p = buildtree(CBRANCHbuildtree(GEccopy(t101), bcon(sz)), bcon(l15));
167         rn = cmop(rnp);
168         if (isclz) {
169                 p = buildtree(CBRANCH,
170                     buildtree(GEccopy(t102), bcon(0)), bcon(l17));
171         } else {
172                 p = buildtree(CBRANCH,
173                     buildtree(EQbuildtree(ANDccopy(t102), bcon(1)),
174                     bcon(0)), bcon(l17));
175         }
176         rn = cmop(rnp);
177
178         rn = cmop(rnblock(GOTObcon(l15), NILINT00));
179
180         rn = cmop(rnlblnod(l17));
181         rn = cmop(rnbuildtree(isclz ? LSEQ : RSEQ , t102bcon(1)));
182
183         rn = cmop(rnbuildtree(INCRccopy(t101), bcon(1)));
184
185         rn = cmop(rnblock(GOTObcon(l16), NILINT00));
186         rn = cmop(rnlblnod(l15));
187         return cmop(rnt101);
188 }
189
190 static NODE *
ragge
1.36
191 builtin_clz(const struct bitable *btNODE *a)
ragge
1.30
192 {
ragge
1.36
193         return builtin_cxz(aINT1);
ragge
1.30
194 }
195
196 static NODE *
ragge
1.36
197 builtin_clzl(const struct bitable *btNODE *a)
ragge
1.30
198 {
ragge
1.36
199         return builtin_cxz(aLONG1);
ragge
1.30
200 }
201
202 static NODE *
ragge
1.36
203 builtin_clzll(const struct bitable *btNODE *a)
ragge
1.30
204 {
ragge
1.36
205         return builtin_cxz(aLONGLONG1);
ragge
1.30
206 }
207
208 static NODE *
ragge
1.36
209 builtin_ctz(const struct bitable *btNODE *a)
ragge
1.30
210 {
ragge
1.36
211         return builtin_cxz(aINT0);
ragge
1.30
212 }
213
214 static NODE *
ragge
1.36
215 builtin_ctzl(const struct bitable *btNODE *a)
ragge
1.30
216 {
ragge
1.36
217         return builtin_cxz(aLONG0);
ragge
1.30
218 }
219
220 static NODE *
ragge
1.36
221 builtin_ctzll(const struct bitable *btNODE *a)
ragge
1.30
222 {
ragge
1.36
223         return builtin_cxz(aLONGLONG0);
ragge
1.30
224 }
225 #endif
226
ragge
1.43
227 #ifndef TARGET_ERA
228 static NODE *
229 builtin_era(const struct bitable *btNODE *a)
230 {
231         return a;       /* Just pass through */
232 }
233 #endif
234
ragge
1.30
235 #ifndef TARGET_FFS
236 /*
237  * Find number of beginning 0's in a word of type t.
238  * t should be deunsigned.
239  */
240 static NODE *
ragge
1.36
241 builtin_ff(NODE *aTWORD t)
ragge
1.30
242 {
243         NODE *t101, *t102;
244         NODE *rn, *p;
245         int l15l16l17;
246         int sz;
247
248         t = ctype(t);
249         sz = (int)tsize(t00)+1;
250
251         t101 = tempnode(0INT00);
252         t102 = tempnode(0t00);
253         l15 = getlab();
254         l16 = getlab();
255         l17 = getlab();
256         rn = buildtree(ASSIGNccopy(t101), bcon(0));
257         rn = cmop(rnbuildtree(ASSIGNccopy(t102), a));
258
259         p = buildtree(CBRANCHbuildtree(EQccopy(t102), bcon(0)), bcon(l15));
260         rn = cmop(rnp);
261
262         rn = cmop(rnbuildtree(INCRccopy(t101), bcon(1)));
263
264         rn = cmop(rnlblnod(l16));
265
266         p = buildtree(CBRANCHbuildtree(GEccopy(t101), bcon(sz)), bcon(l15));
267         rn = cmop(rnp);
268
269         p = buildtree(CBRANCH,
270             buildtree(EQbuildtree(ANDccopy(t102), bcon(1)),
271             bcon(0)), bcon(l17));
272         rn = cmop(rnp);
273
274         rn = cmop(rnblock(GOTObcon(l15), NILINT00));
275
276         rn = cmop(rnlblnod(l17));
277         rn = cmop(rnbuildtree(RSEQt102bcon(1)));
278
279         rn = cmop(rnbuildtree(INCRccopy(t101), bcon(1)));
280
281         rn = cmop(rnblock(GOTObcon(l16), NILINT00));
282         rn = cmop(rnlblnod(l15));
283         return cmop(rnt101);
284 }
285
286 static NODE *
ragge
1.36
287 builtin_ffs(const struct bitable *btNODE *a)
ragge
1.30
288 {
ragge
1.36
289         return builtin_ff(aINT);
ragge
1.30
290 }
291
292 static NODE *
ragge
1.36
293 builtin_ffsl(const struct bitable *btNODE *a)
ragge
1.30
294 {
ragge
1.36
295         return builtin_ff(aLONG);
ragge
1.30
296 }
297
298 static NODE *
ragge
1.36
299 builtin_ffsll(const struct bitable *btNODE *a)
ragge
1.30
300 {
ragge
1.36
301         return builtin_ff(aLONGLONG);
ragge
1.30
302 }
303 #endif
304
ragge
1.11
305 /*
306  * Get size of object, if possible.
307  * Currently does nothing,
308  */
309 static NODE *
ragge
1.36
310 builtin_object_size(const struct bitable *btNODE *a)
ragge
1.11
311 {
plunky
1.35
312         CONSZ v = icons(a->n_right);
ragge
1.36
313         NODE *f;
314
ragge
1.11
315         if (v < 0 || v > 3)
316                 uerror("arg2 must be between 0 and 3");
ragge
1.14
317
ragge
1.36
318         f = buildtree(COMOPa->n_leftxbcon(v < 2 ? -1 : 0NULLbt->rt));
ragge
1.11
319         nfree(a);
ragge
1.14
320         return f;
ragge
1.11
321 }
322
ragge
1.1
323 #ifndef TARGET_STDARGS
324 static NODE *
ragge
1.37
325 builtin_stdarg_start(const struct bitable *btNODE *a)
ragge
1.1
326 {
327         NODE *p, *q;
328         int sz;
329
330         /* must first deal with argument size; use int size */
331         p = a->n_right;
332         if (p->n_type < INT) {
ragge
1.7
333                 sz = (int)(SZINT/tsize(p->n_typep->n_dfp->n_ap));
ragge
1.1
334         } else
335                 sz = 1;
336
337         /* do the real job */
338         p = buildtree(ADDROFpNIL); /* address of last arg */
339 #ifdef BACKAUTO
340         p = optim(buildtree(PLUSpbcon(sz))); /* add one to it (next arg) */
341 #else
342         p = optim(buildtree(MINUSpbcon(sz))); /* add one to it (next arg) */
343 #endif
344         q = block(NAMENILNILPTR+VOID00); /* create cast node */
345         q = buildtree(CASTqp); /* cast to void * (for assignment) */
346         p = q->n_right;
347         nfree(q->n_left);
348         nfree(q);
349         p = buildtree(ASSIGNa->n_leftp); /* assign to ap */
350         nfree(a);
351         return p;
352 }
353
354 static NODE *
ragge
1.37
355 builtin_va_arg(const struct bitable *btNODE *a)
ragge
1.1
356 {
357         NODE *p, *q, *r, *rv;
358         int sznodnum;
359
360         /* create a copy to a temp node of current ap */
361         p = ccopy(a->n_left);
ragge
1.7
362         q = tempnode(0p->n_typep->n_dfp->n_ap);
ragge
1.1
363         nodnum = regno(q);
364         rv = buildtree(ASSIGNqp);
365
366         r = a->n_right;
ragge
1.7
367         sz = (int)tsize(r->n_typer->n_dfr->n_ap)/SZCHAR;
ragge
1.1
368         /* add one to ap */
369 #ifdef BACKAUTO
370         rv = buildtree(COMOPrv , buildtree(PLUSEQa->n_leftbcon(sz)));
371 #else
372 #error fix wrong eval order in builtin_va_arg
373         ecomp(buildtree(MINUSEQa->n_leftbcon(sz)));
374 #endif
375
376         nfree(a->n_right);
377         nfree(a);
ragge
1.7
378         r = tempnode(nodnumINCREF(r->n_type), r->n_dfr->n_ap);
ragge
1.1
379         return buildtree(COMOPrvbuildtree(UMULrNIL));
380
381 }
382
383 static NODE *
ragge
1.37
384 builtin_va_end(const struct bitable *btNODE *a)
ragge
1.1
385 {
386         tfree(a);
387         return bcon(0); /* nothing */
388 }
389
390 static NODE *
ragge
1.37
391 builtin_va_copy(const struct bitable *btNODE *a)
ragge
1.1
392 {
ragge
1.37
393         NODE *f;
394
ragge
1.1
395         f = buildtree(ASSIGNa->n_lefta->n_right);
396         nfree(a);
397         return f;
398 }
399 #endif /* TARGET_STDARGS */
400
ragge
1.2
401 /*
402  * For unimplemented "builtin" functions, try to invoke the
403  * non-builtin name
404  */
405 static NODE *
ragge
1.36
406 binhelp(NODE *aTWORD rtchar *n)
ragge
1.2
407 {
ragge
1.36
408         NODE *f = block(NAMENILNILINT00);
409
ragge
1.13
410         f->n_sp = lookup(addname(n), SNORMAL);
411         if (f->n_sp->sclass == SNULL) {
412                 f->n_sp->sclass = EXTERN;
413                 f->n_sp->stype = INCREF(rt)+(FTN-PTR);
414         }
415         f->n_type = f->n_sp->stype;
ragge
1.6
416         f = clocal(f);
ragge
1.2
417         return buildtree(CALLfa);
418 }
419
ragge
1.16
420 static NODE *
ragge
1.36
421 builtin_unimp(const struct bitable *btNODE *a)
ragge
1.16
422 {
ragge
1.36
423         return binhelp(abt->rt, &bt->name[10]);
ragge
1.16
424 }
425
ragge
1.30
426 #if 0
ragge
1.16
427 static NODE *
428 builtin_unimp_f(NODE *fNODE *aTWORD rt)
429 {
430         return binhelp(fartf->n_sp->sname);
431 }
ragge
1.30
432 #endif
ragge
1.16
433
ragge
1.29
434 #ifndef TARGET_PREFETCH
435 static NODE *
ragge
1.36
436 builtin_prefetch(const struct bitable *btNODE *a)
ragge
1.29
437 {
438         tfree(a);
439         return bcon(0);
440 }
441 #endif
442
ragge
1.18
443 #ifndef TARGET_ISMATH
444 /*
445  * Handle the builtin macros for the math functions is*
446  * To get something that is be somewhat generic assume that 
447  * isnan() is a real function and that cast of a NaN type 
448  * to double will still be a NaN.
449  */
450 static NODE *
451 mtisnan(NODE *p)
452 {
453
ragge
1.36
454         return binhelp(cast(ccopy(p), DOUBLE0), INT"isnan");
ragge
1.18
455 }
456
457 static TWORD
458 mtcheck(NODE *p)
459 {
460         TWORD t1 = p->n_left->n_typet2 = p->n_right->n_type;
461
462         if ((t1 >= FLOAT && t1 <= LDOUBLE) ||
463             (t2 >= FLOAT && t2 <= LDOUBLE))
464                 return MAX(t1t2);
465         return 0;
466 }
467
468 static NODE *
ragge
1.36
469 builtin_isunordered(const struct bitable *btNODE *a)
ragge
1.18
470 {
471         NODE *p;
472
473         if (mtcheck(a) == 0)
474                 return bcon(0);
475
476         p = buildtree(ORORmtisnan(a->n_left), mtisnan(a->n_right));
477         tfree(a);
478         return p;
479 }
480 static NODE *
ragge
1.36
481 builtin_isany(NODE *aTWORD rtint cmpt)
ragge
1.18
482 {
483         NODE *p, *q;
484         TWORD t;
485
486         if ((t = mtcheck(a)) == 0)
487                 return bcon(0);
488         p = buildtree(ORORmtisnan(a->n_left), mtisnan(a->n_right));
489         p = buildtree(NOTpNIL);
490         q = buildtree(cmptcast(ccopy(a->n_left), t0),
491             cast(ccopy(a->n_right), t0));
492         p = buildtree(ANDANDpq);
493         tfree(a);
494         return p;
495 }
496 static NODE *
ragge
1.36
497 builtin_isgreater(const struct bitable *btNODE *a)
ragge
1.18
498 {
ragge
1.36
499         return builtin_isany(abt->rtGT);
ragge
1.18
500 }
501 static NODE *
ragge
1.36
502 builtin_isgreaterequal(const struct bitable *btNODE *a)
ragge
1.18
503 {
ragge
1.36
504         return builtin_isany(abt->rtGE);
ragge
1.18
505 }
506 static NODE *
ragge
1.36
507 builtin_isless(const struct bitable *btNODE *a)
ragge
1.18
508 {
ragge
1.36
509         return builtin_isany(abt->rtLT);
ragge
1.18
510 }
511 static NODE *
ragge
1.36
512 builtin_islessequal(const struct bitable *btNODE *a)
ragge
1.18
513 {
ragge
1.36
514         return builtin_isany(abt->rtLE);
ragge
1.18
515 }
516 static NODE *
ragge
1.36
517 builtin_islessgreater(const struct bitable *btNODE *a)
ragge
1.18
518 {
519         NODE *p, *q, *r;
520         TWORD t;
521
522         if ((t = mtcheck(a)) == 0)
523                 return bcon(0);
524         p = buildtree(ORORmtisnan(a->n_left), mtisnan(a->n_right));
525         p = buildtree(NOTpNIL);
526         q = buildtree(GTcast(ccopy(a->n_left), t0),
527             cast(ccopy(a->n_right), t0));
528         r = buildtree(LTcast(ccopy(a->n_left), t0),
529             cast(ccopy(a->n_right), t0));
530         q = buildtree(ORORqr);
531         p = buildtree(ANDANDpq);
532         tfree(a);
533         return p;
534 }
535 #endif
536
ragge
1.2
537 /*
538  * Math-specific builtins that expands to constants.
539  * Versins here is for IEEE FP, vax needs its own versions.
540  */
ragge
1.26
541 #if TARGET_ENDIAN == TARGET_LE
plunky
1.46
542 static const unsigned char vFLOAT[] = { 000x800x7f };
543 static const unsigned char vDOUBLE[] = { 0000000xf00x7f };
ragge
1.2
544 #ifdef LDBL_128
plunky
1.46
545 static const unsigned char vLDOUBLE[] = { 0,0,0,0,0,0,00000000x800xff0x7f };
ragge
1.2
546 #else /* LDBL_80 */
plunky
1.46
547 static const unsigned char vLDOUBLE[] = { 00000000x800xff0x7f,0,0,0,0,0,0 };
ragge
1.2
548 #endif
plunky
1.46
549 static const unsigned char nFLOAT[] = { 000xc00x7f };
550 static const unsigned char nDOUBLE[] = { 0000000xf80x7f };
ragge
1.2
551 #ifdef LDBL_128
plunky
1.46
552 static const unsigned char nLDOUBLE[] = { 0,0,0,0,0,0,0,0000000xc00xff0x7f };
ragge
1.2
553 #else /* LDBL_80 */
plunky
1.46
554 static const unsigned char nLDOUBLE[] = { 00000000xc00xff0x7f,0,0,0,0,0,0 };
ragge
1.2
555 #endif
556 #else
plunky
1.46
557 static const unsigned char vFLOAT[] = { 0x7f0x8000 };
558 static const unsigned char vDOUBLE[] = { 0x7f0xf0000000 };
ragge
1.2
559 #ifdef LDBL_128
plunky
1.46
560 static const unsigned char vLDOUBLE[] = { 0x7f0xff0x800000000,0,0,0,0,0,0 };
ragge
1.2
561 #else /* LDBL_80 */
plunky
1.46
562 static const unsigned char vLDOUBLE[] = { 0x7f0xff0x800000000,0,0,0,0,0,0 };
ragge
1.2
563 #endif
plunky
1.46
564 static const unsigned char nFLOAT[] = { 0x7f0xc000 };
565 static const unsigned char nDOUBLE[] = { 0x7f0xf8000000 };
ragge
1.2
566 #ifdef LDBL_128
plunky
1.46
567 static const unsigned char nLDOUBLE[] = { 0x7f0xff0xc00000000,0,0,0,0,0,0 };
ragge
1.2
568 #else /* LDBL_80 */
plunky
1.46
569 static const unsigned char nLDOUBLE[] = { 0x7f0xff0xc00000000,0,0,0,0,0,0 };
ragge
1.2
570 #endif
571 #endif
572
573 #define VALX(typ,TYP) {                                         \
574         typ d;                                                  \
575         int x;                                                  \
ragge
1.36
576         NODE *f;                                                \
ragge
1.2
577         x = MIN(sizeof(n ## TYP), sizeof(d));                   \
578         memcpy(&dv ## TYPx);                                \
ragge
1.22
579         f = block(FCONNILNILTYPNULL0);        \
ragge
1.2
580         f->n_dcon = d;                                          \
581         return f;                                               \
582 }
583
584 static NODE *
ragge
1.36
585 builtin_huge_valf(const struct bitable *btNODE *aVALX(float,FLOAT)
ragge
1.2
586 static NODE *
ragge
1.36
587 builtin_huge_val(const struct bitable *btNODE *aVALX(double,DOUBLE)
ragge
1.2
588 static NODE *
ragge
1.36
589 builtin_huge_vall(const struct bitable *btNODE *aVALX(long double,LDOUBLE)
ragge
1.2
590
591 #define builtin_inff    builtin_huge_valf
592 #define builtin_inf     builtin_huge_val
593 #define builtin_infl    builtin_huge_vall
594
595 /*
596  * Return NANs, if reasonable.
597  */
598 static NODE *
ragge
1.36
599 builtin_nanx(const struct bitable *btNODE *a)
600 {
ragge
1.40
601
ragge
1.36
602         if (a == NULL || a->n_op == CM) {
603                 uerror("%s bad argument"bt->name);
604                 a = bcon(0);
605         } else if (a->n_op == STRING && *a->n_name == '\0') {
606                 a->n_op = FCON;
607                 a->n_type = bt->rt;
ragge
1.40
608                 if (sizeof(nLDOUBLE) < sizeof(a->n_dcon))
609                         cerror("nLDOUBLE too small");
ragge
1.36
610                 memcpy(&a->n_dconnLDOUBLEsizeof(a->n_dcon));
611         } else
612                 a = binhelp(eve(a), bt->rt, &bt->name[10]);
613         return a;
614 }
ragge
1.2
615
ragge
1.44
616 #ifndef NO_COMPLEX
617 static NODE *
618 builtin_cir(const struct bitable *btNODE *a)
619 {
620         char *n;
621
622         if (a == NIL || a->n_op == CM) {
623                 uerror("wrong argument count to %s"bt->name);
624                 return bcon(0);
625         }
626
627         n = addname(bt->name[1] == 'r' ? "__real" : "__imag");
628         return cast(structref(aDOTn), bt->rt0);
629 }
630
631 #endif
632
ragge
1.2
633 /*
634  * Target defines, to implement target versions of the generic builtins
635  */
ragge
1.21
636 #ifndef TARGET_MEMCMP
637 #define builtin_memcmp builtin_unimp
638 #endif
ragge
1.2
639 #ifndef TARGET_MEMCPY
640 #define builtin_memcpy builtin_unimp
641 #endif
plunky
1.34
642 #ifndef TARGET_MEMPCPY
643 #define builtin_mempcpy builtin_unimp
644 #endif
ragge
1.2
645 #ifndef TARGET_MEMSET
646 #define builtin_memset builtin_unimp
647 #endif
648
649 /* Reasonable type of size_t */
650 #ifndef SIZET
651 #if SZINT == SZSHORT
652 #define SIZET UNSIGNED
653 #elif SZLONG > SZINT
654 #define SIZET ULONG
655 #else
656 #define SIZET UNSIGNED
657 #endif
658 #endif
659
ragge
1.12
660 static TWORD memcpyt[] = { VOID|PTRVOID|PTRSIZETINT };
661 static TWORD memsett[] = { VOID|PTRINTSIZETINT };
ragge
1.2
662 static TWORD allocat[] = { SIZET };
663 static TWORD expectt[] = { LONGLONG };
ragge
1.8
664 static TWORD strcmpt[] = { CHAR|PTRCHAR|PTR };
ragge
1.12
665 static TWORD strcpyt[] = { CHAR|PTRCHAR|PTRINT };
666 static TWORD strncpyt[] = { CHAR|PTRCHAR|PTRSIZETINT };
ragge
1.9
667 static TWORD strchrt[] = { CHAR|PTRINT };
gmcgarry
1.19
668 static TWORD strcspnt[] = { CHAR|PTRCHAR|PTR };
gmcgarry
1.23
669 static TWORD strspnt[] = { CHAR|PTRCHAR|PTR };
gmcgarry
1.24
670 static TWORD strpbrkt[] = { CHAR|PTRCHAR|PTR };
ragge
1.2
671 static TWORD nant[] = { CHAR|PTR };
ragge
1.16
672 static TWORD bitt[] = { UNSIGNED };
673 static TWORD bitlt[] = { ULONG };
ragge
1.30
674 static TWORD bitllt[] = { ULONGLONG };
ragge
1.36
675 static TWORD abst[] = { INT };
ragge
1.2
676
ragge
1.36
677 static const struct bitable bitable[] = {
ragge
1.41
678         /* gnu universe only */
679         { "alloca"builtin_allocaBTGNUONLY1allocatVOID|PTR },
680
ragge
1.44
681 #ifndef NO_COMPLEX
682         /* builtins for complex operations */
683         { "crealf"builtin_cirBTNOPROTO10FLOAT },
684         { "creal"builtin_cirBTNOPROTO10DOUBLE },
685         { "creall"builtin_cirBTNOPROTO10LDOUBLE },
686         { "cimagf"builtin_cirBTNOPROTO10FLOAT },
687         { "cimag"builtin_cirBTNOPROTO10DOUBLE },
688         { "cimagl"builtin_cirBTNOPROTO10LDOUBLE },
689 #endif
ragge
1.41
690         /* always existing builtins */
ragge
1.36
691         { "__builtin___memcpy_chk"builtin_unimp04memcpytVOID|PTR },
692         { "__builtin___mempcpy_chk"builtin_unimp04memcpytVOID|PTR },
693         { "__builtin___memmove_chk"builtin_unimp04memcpytVOID|PTR },
694         { "__builtin___memset_chk"builtin_unimp04memsettVOID|PTR },
695
696         { "__builtin___strcat_chk"builtin_unimp03strcpytCHAR|PTR },
697         { "__builtin___strcpy_chk"builtin_unimp03strcpytCHAR|PTR },
698         { "__builtin___strncat_chk"builtin_unimp04strncpyt,CHAR|PTR },
699         { "__builtin___strncpy_chk"builtin_unimp04strncpyt,CHAR|PTR },
700
701         { "__builtin___printf_chk"builtin_unimpBTNOPROTO, -10INT },
702         { "__builtin___fprintf_chk"builtin_unimpBTNOPROTO, -10INT },
703         { "__builtin___sprintf_chk"builtin_unimpBTNOPROTO, -10INT },
704         { "__builtin___snprintf_chk"builtin_unimpBTNOPROTO, -10INT },
705         { "__builtin___vprintf_chk"builtin_unimpBTNOPROTO, -10INT },
706         { "__builtin___vfprintf_chk"builtin_unimpBTNOPROTO, -10INT },
707         { "__builtin___vsprintf_chk"builtin_unimpBTNOPROTO, -10INT },
708         { "__builtin___vsnprintf_chk"builtin_unimpBTNOPROTO, -10INT },
709
710         { "__builtin_alloca"builtin_alloca01allocatVOID|PTR },
711         { "__builtin_abs"builtin_abs01abstINT },
712         { "__builtin_clz"builtin_clz01bittINT },
713         { "__builtin_clzl"builtin_clzl01bitltINT },
714         { "__builtin_clzll"builtin_clzll01bitlltINT },
715         { "__builtin_ctz"builtin_ctz01bittINT },
716         { "__builtin_ctzl"builtin_ctzl01bitltINT },
717         { "__builtin_ctzll"builtin_ctzll01bitlltINT },
ragge
1.43
718         { "__builtin_extract_return_addr"builtin_era01memcpytVOID|PTR },
ragge
1.36
719         { "__builtin_ffs"builtin_ffs01bittINT },
720         { "__builtin_ffsl"builtin_ffsl01bitltINT },
721         { "__builtin_ffsll"builtin_ffsll01bitlltINT },
722         { "__builtin_popcount"builtin_unimp01bittUNSIGNED },
723         { "__builtin_popcountl"builtin_unimp01bitltULONG },
724         { "__builtin_popcountll"builtin_unimp01bitlltULONGLONG },
725
726         { "__builtin_constant_p"builtin_constant_p010INT },
727         { "__builtin_expect"builtin_expect02expecttLONG },
728         { "__builtin_memcmp"builtin_memcmp03memcpytINT },
729         { "__builtin_memcpy"builtin_memcpy03memcpytVOID|PTR },
730         { "__builtin_mempcpy"builtin_mempcpy03memcpytVOID|PTR },
731         { "__builtin_memset"builtin_memset03memsettVOID|PTR },
732         { "__builtin_huge_valf"builtin_huge_valf000FLOAT },
733         { "__builtin_huge_val"builtin_huge_val000DOUBLE },
734         { "__builtin_huge_vall"builtin_huge_vall000LDOUBLE },
735         { "__builtin_inff"builtin_inff000FLOAT },
736         { "__builtin_inf"builtin_inf000DOUBLE },
737         { "__builtin_infl"builtin_infl000LDOUBLE },
738         { "__builtin_isgreater"builtin_isgreater02NULLINT },
739         { "__builtin_isgreaterequal"builtin_isgreaterequal02NULLINT },
740         { "__builtin_isless"builtin_isless02NULLINT },
741         { "__builtin_islessequal"builtin_islessequal02NULLINT },
742         { "__builtin_islessgreater"builtin_islessgreater02NULLINT },
743         { "__builtin_isunordered"builtin_isunordered02NULLINT },
744         { "__builtin_nanf"builtin_nanxBTNOEVE1nantFLOAT },
745         { "__builtin_nan"builtin_nanxBTNOEVE1nantDOUBLE },
746         { "__builtin_nanl"builtin_nanxBTNOEVE1nantLDOUBLE },
747         { "__builtin_object_size"builtin_object_size02memsettSIZET },
748         { "__builtin_prefetch"builtin_prefetch01memsettVOID },
749         { "__builtin_strcmp"builtin_unimp02strcmptINT },
750         { "__builtin_strcpy"builtin_unimp02strcpytCHAR|PTR },
751         { "__builtin_stpcpy"builtin_unimp02strcpytCHAR|PTR },
752         { "__builtin_strchr"builtin_unimp02strchrtCHAR|PTR },
753         { "__builtin_strlen"builtin_unimp01strcmptSIZET },
754         { "__builtin_strrchr"builtin_unimp02strchrtCHAR|PTR },
755         { "__builtin_strncpy"builtin_unimp03strncpytCHAR|PTR },
756         { "__builtin_strncat"builtin_unimp03strncpytCHAR|PTR },
757         { "__builtin_strcspn"builtin_unimp02strcspntSIZET },
758         { "__builtin_strspn"builtin_unimp02strspntSIZET },
759         { "__builtin_strstr"builtin_unimp02strcmptCHAR|PTR },
760         { "__builtin_strpbrk"builtin_unimp02strpbrktCHAR|PTR },
ragge
1.1
761 #ifndef TARGET_STDARGS
ragge
1.37
762         { "__builtin_stdarg_start"builtin_stdarg_start020VOID },
763         { "__builtin_va_start"builtin_stdarg_start020VOID },
764         { "__builtin_va_arg"builtin_va_argBTNORVAL|BTNOPROTO200 },
765         { "__builtin_va_end"builtin_va_end010VOID },
766         { "__builtin_va_copy"builtin_va_copy020VOID },
ragge
1.1
767 #endif
ragge
1.43
768         { "__builtin_dwarf_cfa"builtin_cfa000VOID|PTR },
769         { "__builtin_frame_address",
770             builtin_frame_address01bittVOID|PTR },
771         { "__builtin_return_address",
772             builtin_return_address01bittVOID|PTR },
ragge
1.1
773 #ifdef TARGET_BUILTINS
774         TARGET_BUILTINS
775 #endif
776 };
777
ragge
1.2
778 /*
779  * Check and cast arguments for builtins.
780  */
ragge
1.1
781 static int
ragge
1.2
782 acnt(NODE *aint nargTWORD *tp)
ragge
1.1
783 {
ragge
1.2
784         NODE *q;
785         TWORD t;
786
ragge
1.1
787         if (a == NIL)
788                 return narg;
ragge
1.2
789         for (; a->n_op == CMa = a->n_leftnarg--) {
790                 if (tp == NULL)
791                         continue;
792                 q = a->n_right;
ragge
1.28
793                 t = ctype(tp[narg-1]);
ragge
1.2
794                 if (q->n_type == t)
795                         continue;
ragge
1.22
796                 a->n_right = ccast(qt0NULL0);
ragge
1.2
797         }
798
799         /* Last arg is ugly to deal with */
ragge
1.36
800         if (narg == 1 && tp != NULL && a->n_type != tp[0]) {
ragge
1.2
801                 q = talloc();
802                 *q = *a;
ragge
1.28
803                 q = ccast(qctype(tp[0]), 0NULL0);
ragge
1.2
804                 *a = *q;
805                 nfree(q);
806         }
ragge
1.1
807         return narg != 1;
808 }
809
810 NODE *
ragge
1.36
811 builtin_check(struct symtab *spNODE *a)
ragge
1.1
812 {
ragge
1.4
813         const struct bitable *bt;
ragge
1.36
814
815         if (sp->soffset < 0 ||
816             sp->soffset >= (int)(sizeof(bitable)/sizeof(bitable[0])))
817                 cerror("builtin_check");
818
819         bt = &bitable[sp->soffset];
ragge
1.38
820         if ((bt->flags & BTNOEVE) == 0 && a != NIL)
ragge
1.36
821                 a = eve(a);
822         if (((bt->flags & BTNOPROTO) == 0) && acnt(abt->nargbt->tp)) {
823                 uerror("wrong argument count to %s"bt->name);
824                 return bcon(0);
825         }
826         return (*bt->fun)(bta);
827 }
828
829 /*
830  * Put all builtin functions into the global symbol table.
831  */
832 void
833 builtin_init()
834 {
835         const struct bitable *bt;
836         NODE *p = block(TYPE00000);
837         struct symtab *sp;
ragge
1.39
838         int id_debug;
ragge
1.1
839
ragge
1.39
840         d_debug = ddebug;
841         ddebug = 0;
ragge
1.1
842         for (i = 0i < (int)(sizeof(bitable)/sizeof(bitable[0])); i++) {
ragge
1.2
843                 bt = &bitable[i];
ragge
1.41
844                 if ((bt->flags & BTGNUONLY) && xgnu99 == 0 && xgnu89 == 0)
845                         continue/* not in c99 universe, at least for now */
ragge
1.36
846                 sp = lookup(addname(bt->name), 0);
847                 if (bt->rt == 0 && (bt->flags & BTNORVAL) == 0)
848                         cerror("function '%s' has no return type"bt->name);
849                 p->n_type = INCREF(bt->rt) + (FTN-PTR);
ragge
1.42
850                 p->n_df = memset(permalloc(sizeof(union dimfun)), 0,
851                     sizeof(union dimfun));
ragge
1.36
852                 p->n_sp = sp;
ragge
1.45
853                 defid(pEXTERN);
ragge
1.36
854                 sp->soffset = i;
855                 sp->sflags |= SBUILTIN;
ragge
1.1
856         }
ragge
1.36
857         nfree(p);
ragge
1.39
858         ddebug = d_debug;
ragge
1.1
859 }
860 #endif
FishEye: Open Source License registered to PCC.
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-12-25 22:21 +0100