scc

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

builtin.c (2522B)


      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 	return np;
     30 
     31 error:
     32 	return constnode(zero);
     33 }
     34 
     35 static Node *
     36 builtin_va_copy(Symbol *sym)
     37 {
     38 	Node *np, *src, *dst;
     39 
     40 	dst = simplify(assign());
     41 	expect(',');
     42 	src = simplify(assign());
     43 
     44 	if (!valid_va_list(dst->type) || !valid_va_list(src->type)) {
     45 		errorp("incorrect parameters for va_copy");
     46 		return constnode(zero);
     47 	}
     48 
     49 	if (dst->type != va_type)
     50 		dst = node(OPTR, dst->type->type, dst, NULL);
     51 	if (src->type != va_type)
     52 		src = node(OPTR, src->type->type, src, NULL);
     53 	np = node(OASSIGN, dst->type, dst, src);
     54 	np = node(OCAST, voidtype, np, NULL);
     55 
     56 	return np;
     57 }
     58 
     59 static Node *
     60 builtin_va_start(Symbol *sym)
     61 {
     62 	Node *np, *ap, *last;
     63 	Symbol **p;
     64 	Type *tp;
     65 
     66 	ap = simplify(assign());
     67 	expect(',');
     68 	last = assign();
     69 	if (last->op != OSYM)
     70 		goto error;
     71 
     72 	if (!valid_va_list(ap->type) || !(last->sym->flags&SDECLARED))
     73 		 goto error;
     74 
     75 	for (p = curfun->u.pars; p && *p != last->sym; ++p)
     76 		;
     77 	if (!p || *p == NULL || p[1] == NULL || p[1]->type != ellipsistype)
     78 		warn("second parameter of 'va_start' not last named argument");
     79 
     80 	tp = last->type;
     81 	if (tp == booltype ||
     82 	    tp == chartype || tp == uchartype || tp == schartype ||
     83 	    tp == shorttype || tp == ushorttype) {
     84 		warn("last parameter before '...' must not be bool, char or short");
     85 	}
     86 
     87 	np = node(OBUILTIN, voidtype, ap, last);
     88 	np->sym = sym;
     89 	return np;
     90 
     91 error:
     92 	errorp("incorrect parameters for va_start");
     93 	return constnode(zero);
     94 }
     95 
     96 static Node *
     97 builtin_va_end(Symbol *sym)
     98 {
     99 	Node *ap, *np;
    100 
    101 	ap = simplify(assign());
    102 
    103 	if (!valid_va_list(ap->type)) {
    104 		errorp("incorrect parameters for va_end");
    105 		return constnode(zero);
    106 	}
    107 
    108 	np = node(OBUILTIN, voidtype, ap, NULL);
    109 	np->sym = sym;
    110 	return np;
    111 }
    112 
    113 void
    114 ibuilts(void)
    115 {
    116 	struct builtin built[] = {
    117 		{"__builtin_va_arg", builtin_va_arg},
    118 		{"__builtin_va_copy", builtin_va_copy},
    119 		{"__builtin_va_start", builtin_va_start},
    120 		{"__builtin_va_end", builtin_va_end},
    121 		{NULL}
    122 	};
    123 	builtins(built);
    124 }