source: mainline/uspace/app/pcc/cc/ccom/builtins.c@ 3e896e1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3e896e1 was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

  • Property mode set to 100644
File size: 16.8 KB
Line 
1/* $Id: builtins.c,v 1.18.2.2 2011/03/29 15:56:24 ragge Exp $ */
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
29#ifndef MIN
30#define MIN(a,b) (((a)<(b))?(a):(b))
31#endif
32#ifndef MAX
33#define MAX(a,b) (((a)>(b))?(a):(b))
34#endif
35
36#ifndef NO_C_BUILTINS
37/*
38 * replace an alloca function with direct allocation on stack.
39 * return a destination temp node.
40 */
41static NODE *
42builtin_alloca(NODE *f, NODE *a, TWORD rt)
43{
44 struct symtab *sp;
45 NODE *t, *u;
46
47#ifdef notyet
48 if (xnobuiltins)
49 return NULL;
50#endif
51 sp = f->n_sp;
52
53 t = tempnode(0, VOID|PTR, 0, MKAP(INT) /* XXX */);
54 u = tempnode(regno(t), VOID|PTR, 0, MKAP(INT) /* XXX */);
55 spalloc(t, a, SZCHAR);
56 tfree(f);
57 return u;
58}
59
60/*
61 * See if there is a goto in the tree.
62 * XXX this function is a hack for a flaw in handling of
63 * compound expressions and inline functions and should not be
64 * needed.
65 */
66static int
67hasgoto(NODE *p)
68{
69 int o = coptype(p->n_op);
70
71 if (o == LTYPE)
72 return 0;
73 if (p->n_op == GOTO)
74 return 1;
75 if (o == UTYPE)
76 return hasgoto(p->n_left);
77 if (hasgoto(p->n_left))
78 return 1;
79 return hasgoto(p->n_right);
80}
81
82/*
83 * Determine if a value is known to be constant at compile-time and
84 * hence that PCC can perform constant-folding on expressions involving
85 * that value.
86 */
87static NODE *
88builtin_constant_p(NODE *f, NODE *a, TWORD rt)
89{
90 void putjops(NODE *p, void *arg);
91 int isconst;
92
93 tfree(f);
94 walkf(a, putjops, 0);
95 for (f = a; f->n_op == COMOP; f = f->n_right)
96 ;
97 isconst = nncon(f);
98 tfree(a);
99 return bcon(isconst);
100}
101
102/*
103 * Hint to the compiler whether this expression will evaluate true or false.
104 * Just ignored for now.
105 */
106static NODE *
107builtin_expect(NODE *f, NODE *a, TWORD rt)
108{
109
110 tfree(f);
111 if (a && a->n_op == CM) {
112 tfree(a->n_right);
113 f = a->n_left;
114 nfree(a);
115 a = f;
116 }
117
118 return a;
119}
120
121/*
122 * Take integer absolute value.
123 * Simply does: ((((x)>>(8*sizeof(x)-1))^(x))-((x)>>(8*sizeof(x)-1)))
124 */
125static NODE *
126builtin_abs(NODE *f, NODE *a, TWORD rt)
127{
128 NODE *p, *q, *r, *t, *t2, *t3;
129 int tmp1, tmp2, shift;
130
131 if (a->n_type != INT)
132 a = cast(a, INT, 0);
133
134 tfree(f);
135
136 if (a->n_op == ICON) {
137 if (a->n_lval < 0)
138 a->n_lval = -a->n_lval;
139 p = a;
140 } else {
141 t = tempnode(0, a->n_type, a->n_df, a->n_ap);
142 tmp1 = regno(t);
143 p = buildtree(ASSIGN, t, a);
144
145 t = tempnode(tmp1, a->n_type, a->n_df, a->n_ap);
146 shift = (int)tsize(a->n_type, a->n_df, a->n_ap) - 1;
147 q = buildtree(RS, t, bcon(shift));
148
149 t2 = tempnode(0, a->n_type, a->n_df, a->n_ap);
150 tmp2 = regno(t2);
151 q = buildtree(ASSIGN, t2, q);
152
153 t = tempnode(tmp1, a->n_type, a->n_df, a->n_ap);
154 t2 = tempnode(tmp2, a->n_type, a->n_df, a->n_ap);
155 t3 = tempnode(tmp2, a->n_type, a->n_df, a->n_ap);
156 r = buildtree(MINUS, buildtree(ER, t, t2), t3);
157
158 p = buildtree(COMOP, p, buildtree(COMOP, q, r));
159 }
160
161 return p;
162}
163
164/*
165 * Get size of object, if possible.
166 * Currently does nothing,
167 */
168static NODE *
169builtin_object_size(NODE *f, NODE *a, TWORD rt)
170{
171 int v = icons(a->n_right);
172 if (v < 0 || v > 3)
173 uerror("arg2 must be between 0 and 3");
174
175 tfree(f);
176 f = buildtree(COMOP, a->n_left, xbcon(v < 2 ? -1 : 0, NULL, rt));
177 nfree(a);
178 return f;
179}
180
181#ifndef TARGET_STDARGS
182static NODE *
183builtin_stdarg_start(NODE *f, NODE *a, TWORD rt)
184{
185 NODE *p, *q;
186 int sz;
187
188 /* must first deal with argument size; use int size */
189 p = a->n_right;
190 if (p->n_type < INT) {
191 sz = (int)(SZINT/tsize(p->n_type, p->n_df, p->n_ap));
192 } else
193 sz = 1;
194
195 /* do the real job */
196 p = buildtree(ADDROF, p, NIL); /* address of last arg */
197#ifdef BACKAUTO
198 p = optim(buildtree(PLUS, p, bcon(sz))); /* add one to it (next arg) */
199#else
200 p = optim(buildtree(MINUS, p, bcon(sz))); /* add one to it (next arg) */
201#endif
202 q = block(NAME, NIL, NIL, PTR+VOID, 0, 0); /* create cast node */
203 q = buildtree(CAST, q, p); /* cast to void * (for assignment) */
204 p = q->n_right;
205 nfree(q->n_left);
206 nfree(q);
207 p = buildtree(ASSIGN, a->n_left, p); /* assign to ap */
208 tfree(f);
209 nfree(a);
210 return p;
211}
212
213static NODE *
214builtin_va_arg(NODE *f, NODE *a, TWORD rt)
215{
216 NODE *p, *q, *r, *rv;
217 int sz, nodnum;
218
219 /* create a copy to a temp node of current ap */
220 p = ccopy(a->n_left);
221 q = tempnode(0, p->n_type, p->n_df, p->n_ap);
222 nodnum = regno(q);
223 rv = buildtree(ASSIGN, q, p);
224
225 r = a->n_right;
226 sz = (int)tsize(r->n_type, r->n_df, r->n_ap)/SZCHAR;
227 /* add one to ap */
228#ifdef BACKAUTO
229 rv = buildtree(COMOP, rv , buildtree(PLUSEQ, a->n_left, bcon(sz)));
230#else
231#error fix wrong eval order in builtin_va_arg
232 ecomp(buildtree(MINUSEQ, a->n_left, bcon(sz)));
233#endif
234
235 nfree(a->n_right);
236 nfree(a);
237 nfree(f);
238 r = tempnode(nodnum, INCREF(r->n_type), r->n_df, r->n_ap);
239 return buildtree(COMOP, rv, buildtree(UMUL, r, NIL));
240
241}
242
243static NODE *
244builtin_va_end(NODE *f, NODE *a, TWORD rt)
245{
246 tfree(f);
247 tfree(a);
248 return bcon(0); /* nothing */
249}
250
251static NODE *
252builtin_va_copy(NODE *f, NODE *a, TWORD rt)
253{
254 tfree(f);
255 f = buildtree(ASSIGN, a->n_left, a->n_right);
256 nfree(a);
257 return f;
258}
259#endif /* TARGET_STDARGS */
260
261/*
262 * For unimplemented "builtin" functions, try to invoke the
263 * non-builtin name
264 */
265static NODE *
266binhelp(NODE *f, NODE *a, TWORD rt, char *n)
267{
268 f->n_sp = lookup(addname(n), SNORMAL);
269 if (f->n_sp->sclass == SNULL) {
270 f->n_sp->sclass = EXTERN;
271 f->n_sp->stype = INCREF(rt)+(FTN-PTR);
272 }
273 f->n_type = f->n_sp->stype;
274 f = clocal(f);
275 return buildtree(CALL, f, a);
276}
277
278static NODE *
279builtin_unimp(NODE *f, NODE *a, TWORD rt)
280{
281 char *n = f->n_sp->sname;
282
283 if (strncmp("__builtin_", n, 10) == 0)
284 n += 10;
285 return binhelp(f, a, rt, n);
286}
287
288static NODE *
289builtin_unimp_f(NODE *f, NODE *a, TWORD rt)
290{
291 return binhelp(f, a, rt, f->n_sp->sname);
292}
293
294#ifndef TARGET_ISMATH
295/*
296 * Handle the builtin macros for the math functions is*
297 * To get something that is be somewhat generic assume that
298 * isnan() is a real function and that cast of a NaN type
299 * to double will still be a NaN.
300 */
301static NODE *
302mtisnan(NODE *p)
303{
304 NODE *q = block(NAME, NIL, NIL, INT, 0, MKAP(INT));
305
306 return binhelp(q, cast(ccopy(p), DOUBLE, 0), INT, "isnan");
307}
308
309static TWORD
310mtcheck(NODE *p)
311{
312 TWORD t1 = p->n_left->n_type, t2 = p->n_right->n_type;
313
314 if ((t1 >= FLOAT && t1 <= LDOUBLE) ||
315 (t2 >= FLOAT && t2 <= LDOUBLE))
316 return MAX(t1, t2);
317 return 0;
318}
319
320static NODE *
321builtin_isunordered(NODE *f, NODE *a, TWORD rt)
322{
323 NODE *p;
324
325 if (mtcheck(a) == 0)
326 return bcon(0);
327
328 p = buildtree(OROR, mtisnan(a->n_left), mtisnan(a->n_right));
329 tfree(f);
330 tfree(a);
331 return p;
332}
333static NODE *
334builtin_isany(NODE *f, NODE *a, TWORD rt, int cmpt)
335{
336 NODE *p, *q;
337 TWORD t;
338
339 if ((t = mtcheck(a)) == 0)
340 return bcon(0);
341 p = buildtree(OROR, mtisnan(a->n_left), mtisnan(a->n_right));
342 p = buildtree(NOT, p, NIL);
343 q = buildtree(cmpt, cast(ccopy(a->n_left), t, 0),
344 cast(ccopy(a->n_right), t, 0));
345 p = buildtree(ANDAND, p, q);
346 tfree(f);
347 tfree(a);
348 return p;
349}
350static NODE *
351builtin_isgreater(NODE *f, NODE *a, TWORD rt)
352{
353 return builtin_isany(f, a, rt, GT);
354}
355static NODE *
356builtin_isgreaterequal(NODE *f, NODE *a, TWORD rt)
357{
358 return builtin_isany(f, a, rt, GE);
359}
360static NODE *
361builtin_isless(NODE *f, NODE *a, TWORD rt)
362{
363 return builtin_isany(f, a, rt, LT);
364}
365static NODE *
366builtin_islessequal(NODE *f, NODE *a, TWORD rt)
367{
368 return builtin_isany(f, a, rt, LE);
369}
370static NODE *
371builtin_islessgreater(NODE *f, NODE *a, TWORD rt)
372{
373 NODE *p, *q, *r;
374 TWORD t;
375
376 if ((t = mtcheck(a)) == 0)
377 return bcon(0);
378 p = buildtree(OROR, mtisnan(a->n_left), mtisnan(a->n_right));
379 p = buildtree(NOT, p, NIL);
380 q = buildtree(GT, cast(ccopy(a->n_left), t, 0),
381 cast(ccopy(a->n_right), t, 0));
382 r = buildtree(LT, cast(ccopy(a->n_left), t, 0),
383 cast(ccopy(a->n_right), t, 0));
384 q = buildtree(OROR, q, r);
385 p = buildtree(ANDAND, p, q);
386 tfree(f);
387 tfree(a);
388 return p;
389}
390#endif
391
392/*
393 * Math-specific builtins that expands to constants.
394 * Versins here is for IEEE FP, vax needs its own versions.
395 */
396#ifdef RTOLBYTES
397static char vFLOAT[] = { 0, 0, 0x80, 0x7f };
398static char vDOUBLE[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f };
399#ifdef LDBL_128
400static char vLDOUBLE[] = { 0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0x7f };
401#else /* LDBL_80 */
402static char vLDOUBLE[] = { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0x7f };
403#endif
404static char nFLOAT[] = { 0, 0, 0xc0, 0x7f };
405static char nDOUBLE[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f };
406#ifdef LDBL_128
407static char nLDOUBLE[] = { 0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0xc0, 0xff, 0x7f };
408#else /* LDBL_80 */
409static char nLDOUBLE[] = { 0, 0, 0, 0, 0, 0, 0, 0xc0, 0xff, 0x7f, 0, 0 };
410#endif
411#else
412static char vFLOAT[] = { 0x7f, 0x80, 0, 0 };
413static char vDOUBLE[] = { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 };
414#ifdef LDBL_128
415static char vLDOUBLE[] = { 0x7f, 0xff, 0x80, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0 };
416#else /* LDBL_80 */
417static char vLDOUBLE[] = { 0x7f, 0xff, 0x80, 0, 0, 0, 0, 0, 0, 0 };
418#endif
419static char nFLOAT[] = { 0x7f, 0xc0, 0, 0 };
420static char nDOUBLE[] = { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 };
421#ifdef LDBL_128
422static char nLDOUBLE[] = { 0x7f, 0xff, 0xc0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0 };
423#else /* LDBL_80 */
424static char nLDOUBLE[] = { 0x7f, 0xff, 0xc0, 0, 0, 0, 0, 0, 0, 0 };
425#endif
426#endif
427
428#define VALX(typ,TYP) { \
429 typ d; \
430 int x; \
431 x = MIN(sizeof(n ## TYP), sizeof(d)); \
432 memcpy(&d, v ## TYP, x); \
433 nfree(f); \
434 f = block(FCON, NIL, NIL, TYP, NULL, MKAP(TYP)); \
435 f->n_dcon = d; \
436 return f; \
437}
438
439static NODE *
440builtin_huge_valf(NODE *f, NODE *a, TWORD rt) VALX(float,FLOAT)
441static NODE *
442builtin_huge_val(NODE *f, NODE *a, TWORD rt) VALX(double,DOUBLE)
443static NODE *
444builtin_huge_vall(NODE *f, NODE *a, TWORD rt) VALX(long double,LDOUBLE)
445
446#define builtin_inff builtin_huge_valf
447#define builtin_inf builtin_huge_val
448#define builtin_infl builtin_huge_vall
449
450#define NANX(typ,TYP) { \
451 typ d; \
452 int x; \
453 if ((a->n_op == ICON && a->n_sp && a->n_sp->sname[0] == '\0') ||\
454 (a->n_op == ADDROF && a->n_left->n_op == NAME && \
455 a->n_left->n_sp && a->n_left->n_sp->sname[0] == '\0')) { \
456 x = MIN(sizeof(n ## TYP), sizeof(d)); \
457 memcpy(&d, n ## TYP, x); \
458 tfree(a); tfree(f); \
459 f = block(FCON, NIL, NIL, TYP, NULL, MKAP(TYP)); \
460 f->n_dcon = d; \
461 return f; \
462 } \
463 return buildtree(CALL, f, a); \
464}
465
466/*
467 * Return NANs, if reasonable.
468 */
469static NODE *
470builtin_nanf(NODE *f, NODE *a, TWORD rt) NANX(float,FLOAT)
471static NODE *
472builtin_nan(NODE *f, NODE *a, TWORD rt) NANX(double,DOUBLE)
473static NODE *
474builtin_nanl(NODE *f, NODE *a, TWORD rt) NANX(long double,LDOUBLE)
475
476/*
477 * Target defines, to implement target versions of the generic builtins
478 */
479#ifndef TARGET_MEMCMP
480#define builtin_memcmp builtin_unimp
481#endif
482#ifndef TARGET_MEMCPY
483#define builtin_memcpy builtin_unimp
484#endif
485#ifndef TARGET_MEMSET
486#define builtin_memset builtin_unimp
487#endif
488
489/* Reasonable type of size_t */
490#ifndef SIZET
491#if SZINT == SZSHORT
492#define SIZET UNSIGNED
493#elif SZLONG > SZINT
494#define SIZET ULONG
495#else
496#define SIZET UNSIGNED
497#endif
498#endif
499
500static TWORD memcpyt[] = { VOID|PTR, VOID|PTR, SIZET, INT };
501static TWORD memsett[] = { VOID|PTR, INT, SIZET, INT };
502static TWORD allocat[] = { SIZET };
503static TWORD expectt[] = { LONG, LONG };
504static TWORD strcmpt[] = { CHAR|PTR, CHAR|PTR };
505static TWORD strcpyt[] = { CHAR|PTR, CHAR|PTR, INT };
506static TWORD strncpyt[] = { CHAR|PTR, CHAR|PTR, SIZET, INT };
507static TWORD strchrt[] = { CHAR|PTR, INT };
508static TWORD strcspnt[] = { CHAR|PTR, CHAR|PTR };
509static TWORD nant[] = { CHAR|PTR };
510static TWORD bitt[] = { UNSIGNED };
511static TWORD bitlt[] = { ULONG };
512static TWORD ffst[] = { INT };
513
514static const struct bitable {
515 char *name;
516 NODE *(*fun)(NODE *f, NODE *a, TWORD);
517 int narg;
518 TWORD *tp;
519 TWORD rt;
520} bitable[] = {
521 { "__builtin___memcpy_chk", builtin_unimp, 4, memcpyt, VOID|PTR },
522 { "__builtin___memmove_chk", builtin_unimp, 4, memcpyt, VOID|PTR },
523 { "__builtin___memset_chk", builtin_unimp, 4, memsett, VOID|PTR },
524
525 { "__builtin___strcat_chk", builtin_unimp, 3, strcpyt, CHAR|PTR },
526 { "__builtin___strcpy_chk", builtin_unimp, 3, strcpyt, CHAR|PTR },
527 { "__builtin___strncat_chk", builtin_unimp, 4, strncpyt,CHAR|PTR },
528 { "__builtin___strncpy_chk", builtin_unimp, 4, strncpyt,CHAR|PTR },
529
530 { "__builtin___printf_chk", builtin_unimp, -1, 0, INT },
531 { "__builtin___fprintf_chk", builtin_unimp, -1, 0, INT },
532 { "__builtin___sprintf_chk", builtin_unimp, -1, 0, INT },
533 { "__builtin___snprintf_chk", builtin_unimp, -1, 0, INT },
534 { "__builtin___vprintf_chk", builtin_unimp, -1, 0, INT },
535 { "__builtin___vfprintf_chk", builtin_unimp, -1, 0, INT },
536 { "__builtin___vsprintf_chk", builtin_unimp, -1, 0, INT },
537 { "__builtin___vsnprintf_chk", builtin_unimp, -1, 0, INT },
538
539 { "__builtin_alloca", builtin_alloca, 1, allocat },
540 { "__builtin_abs", builtin_abs, 1 },
541 { "__builtin_clz", builtin_unimp_f, 1, bitt, INT },
542 { "__builtin_ctz", builtin_unimp_f, 1, bitt, INT },
543 { "__builtin_clzl", builtin_unimp_f, 1, bitlt, INT },
544 { "__builtin_ctzl", builtin_unimp_f, 1, bitlt, INT },
545 { "__builtin_ffs", builtin_unimp, 1, ffst, INT },
546
547 { "__builtin_constant_p", builtin_constant_p, 1 },
548 { "__builtin_expect", builtin_expect, 2, expectt },
549 { "__builtin_memcmp", builtin_memcmp, 3, memcpyt, INT },
550 { "__builtin_memcpy", builtin_memcpy, 3, memcpyt, VOID|PTR },
551 { "__builtin_memset", builtin_memset, 3, memsett, VOID|PTR },
552 { "__builtin_huge_valf", builtin_huge_valf, 0 },
553 { "__builtin_huge_val", builtin_huge_val, 0 },
554 { "__builtin_huge_vall", builtin_huge_vall, 0 },
555 { "__builtin_inff", builtin_inff, 0 },
556 { "__builtin_inf", builtin_inf, 0 },
557 { "__builtin_infl", builtin_infl, 0 },
558 { "__builtin_isgreater", builtin_isgreater, 2, NULL, INT },
559 { "__builtin_isgreaterequal", builtin_isgreaterequal, 2, NULL, INT },
560 { "__builtin_isless", builtin_isless, 2, NULL, INT },
561 { "__builtin_islessequal", builtin_islessequal, 2, NULL, INT },
562 { "__builtin_islessgreater", builtin_islessgreater, 2, NULL, INT },
563 { "__builtin_isunordered", builtin_isunordered, 2, NULL, INT },
564 { "__builtin_nanf", builtin_nanf, 1, nant, FLOAT },
565 { "__builtin_nan", builtin_nan, 1, nant, DOUBLE },
566 { "__builtin_nanl", builtin_nanl, 1, nant, LDOUBLE },
567 { "__builtin_object_size", builtin_object_size, 2, memsett, SIZET },
568 { "__builtin_strcmp", builtin_unimp, 2, strcmpt, INT },
569 { "__builtin_strcpy", builtin_unimp, 2, strcmpt, CHAR|PTR },
570 { "__builtin_strchr", builtin_unimp, 2, strchrt, CHAR|PTR },
571 { "__builtin_strlen", builtin_unimp, 1, strcmpt, SIZET },
572 { "__builtin_strrchr", builtin_unimp, 2, strchrt, CHAR|PTR },
573 { "__builtin_strncpy", builtin_unimp, 3, strncpyt, CHAR|PTR },
574 { "__builtin_strncat", builtin_unimp, 3, strncpyt, CHAR|PTR },
575 { "__builtin_strcspn", builtin_unimp, 2, strcspnt, SIZET },
576#ifndef TARGET_STDARGS
577 { "__builtin_stdarg_start", builtin_stdarg_start, 2 },
578 { "__builtin_va_start", builtin_stdarg_start, 2 },
579 { "__builtin_va_arg", builtin_va_arg, 2 },
580 { "__builtin_va_end", builtin_va_end, 1 },
581 { "__builtin_va_copy", builtin_va_copy, 2 },
582#endif
583#ifdef TARGET_BUILTINS
584 TARGET_BUILTINS
585#endif
586};
587
588/*
589 * Check and cast arguments for builtins.
590 */
591static int
592acnt(NODE *a, int narg, TWORD *tp)
593{
594 NODE *q;
595 TWORD t;
596
597 if (a == NIL)
598 return narg;
599 for (; a->n_op == CM; a = a->n_left, narg--) {
600 if (tp == NULL)
601 continue;
602 q = a->n_right;
603 t = tp[narg-1];
604 if (q->n_type == t)
605 continue;
606 a->n_right = ccast(q, t, 0, NULL, MKAP(BTYPE(t)));
607 }
608
609 /* Last arg is ugly to deal with */
610 if (narg == 1 && tp != NULL) {
611 q = talloc();
612 *q = *a;
613 q = ccast(q, tp[0], 0, NULL, MKAP(BTYPE(tp[0])));
614 *a = *q;
615 nfree(q);
616 }
617 return narg != 1;
618}
619
620NODE *
621builtin_check(NODE *f, NODE *a)
622{
623 const struct bitable *bt;
624 int i;
625
626 for (i = 0; i < (int)(sizeof(bitable)/sizeof(bitable[0])); i++) {
627 bt = &bitable[i];
628 if (strcmp(bt->name, f->n_sp->sname))
629 continue;
630 if (bt->narg >= 0 && acnt(a, bt->narg, bt->tp)) {
631 uerror("wrong argument count to %s", bt->name);
632 return bcon(0);
633 }
634 return (*bt->fun)(f, a, bt->rt);
635 }
636 return NIL;
637}
638#endif
Note: See TracBrowser for help on using the repository browser.