scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

builtin.c (2658B)


      1 #include <stdio.h>
      2 
      3 #include <scc/scc.h>
      4 #include "cc1.h"
      5 
      6 static Node *
      7 builtin_va_arg(Symbol *sym)
      8 {
      9 	Node *np, *ap;
     10 	Type *tp;
     11 
     12 	ap = simplify(assign());
     13 	expect(',');
     14 	tp = typename();
     15 
     16 	if (!valid_va_list(ap->type)) {
     17 		errorp("incorrect parameters for va_arg");
     18 		goto error;
     19 	}
     20 	if (tp == booltype ||
     21 	    tp == chartype || tp == uchartype || tp == schartype ||
     22 	    tp == shorttype || tp == ushorttype) {
     23 		warn("bool, char and short are promoted to int when passed through '...'");
     24 		tp = (tp->prop & TSIGNED) ? inttype : uinttype;
     25 	}
     26 
     27 	np = node(OBUILTIN, tp, ap, NULL);
     28 	np->sym = sym;
     29 	np->flags |= NEFFECT;
     30 	return np;
     31 
     32 error:
     33 	return constnode(zero);
     34 }
     35 
     36 static Node *
     37 builtin_va_copy(Symbol *sym)
     38 {
     39 	Node *np, *src, *dst;
     40 
     41 	dst = simplify(assign());
     42 	expect(',');
     43 	src = simplify(assign());
     44 
     45 	if (!valid_va_list(dst->type) || !valid_va_list(src->type)) {
     46 		errorp("incorrect parameters for va_copy");
     47 		return constnode(zero);
     48 	}
     49 
     50 	if (dst->type != va_type)
     51 		dst = node(OPTR, dst->type->type, dst, NULL);
     52 	if (src->type != va_type)
     53 		src = node(OPTR, src->type->type, src, NULL);
     54 	np = node(OASSIGN, dst->type, dst, src);
     55 	np = node(OCAST, voidtype, np, NULL);
     56 	np->flags |= NEFFECT;
     57 
     58 	return np;
     59 }
     60 
     61 static Node *
     62 builtin_va_start(Symbol *sym)
     63 {
     64 	Node *np, *ap, *last;
     65 	Symbol **p;
     66 	Type *tp;
     67 
     68 	ap = simplify(assign());
     69 	expect(',');
     70 	last = assign();
     71 	if (last->op != OSYM)
     72 		goto error;
     73 
     74 	if (!valid_va_list(ap->type) || !(last->sym->flags&SDECLARED))
     75 		 goto error;
     76 
     77 	tp = curfun->type;
     78 	for (p = curfun->u.pars; p && *p != last->sym; ++p)
     79 		;
     80 	if (!p || *p == NULL || p[1] != NULL ||
     81 	    tp->p.pars[tp->n.elem-1] != ellipsistype) {
     82 		warn("second parameter of 'va_start' not last named argument");
     83 	}
     84 
     85 	tp = last->type;
     86 	if (tp == booltype ||
     87 	    tp == chartype || tp == uchartype || tp == schartype ||
     88 	    tp == shorttype || tp == ushorttype) {
     89 		warn("last parameter before '...' must not be bool, char or short");
     90 	}
     91 
     92 	np = node(OBUILTIN, voidtype, ap, last);
     93 	np->sym = sym;
     94 	np->flags |= NEFFECT;
     95 	return np;
     96 
     97 error:
     98 	errorp("incorrect parameters for va_start");
     99 	return constnode(zero);
    100 }
    101 
    102 static Node *
    103 builtin_va_end(Symbol *sym)
    104 {
    105 	Node *ap, *np;
    106 
    107 	ap = simplify(assign());
    108 
    109 	if (!valid_va_list(ap->type)) {
    110 		errorp("incorrect parameters for va_end");
    111 		return constnode(zero);
    112 	}
    113 
    114 	np = node(OBUILTIN, voidtype, ap, NULL);
    115 	np->sym = sym;
    116 	np->flags |= NEFFECT;
    117 	return np;
    118 }
    119 
    120 void
    121 ibuilts(void)
    122 {
    123 	struct builtin built[] = {
    124 		{"__builtin_va_arg", builtin_va_arg},
    125 		{"__builtin_va_copy", builtin_va_copy},
    126 		{"__builtin_va_start", builtin_va_start},
    127 		{"__builtin_va_end", builtin_va_end},
    128 		{NULL}
    129 	};
    130 	builtins(built);
    131 }