1#include <stdio.h>23#include <scc/scc.h>4#include "cc1.h"56static Node *7builtin_va_arg(Symbol *sym)8{9 Node *np, *ap;10 Type *tp;1112 ap = simplify(assign());13 expect(',');14 tp = typename();1516 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 }2627 np = node(OBUILTIN, tp, ap, NULL);28 np->sym = sym;29 np->flags |= NEFFECT;30 return np;3132error:33 return constnode(zero);34}3536static Node *37builtin_va_copy(Symbol *sym)38{39 Node *np, *src, *dst;4041 dst = simplify(assign());42 expect(',');43 src = simplify(assign());4445 if (!valid_va_list(dst->type) || !valid_va_list(src->type)) {46 errorp("incorrect parameters for va_copy");47 return constnode(zero);48 }4950 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;5758 return np;59}6061static Node *62builtin_va_start(Symbol *sym)63{64 Node *np, *ap, *last;65 Symbol **p;66 Type *tp;6768 ap = simplify(assign());69 expect(',');70 last = assign();71 if (last->op != OSYM)72 goto error;7374 if (!valid_va_list(ap->type) || !(last->sym->flags&SDECLARED))75 goto error;7677 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 }8485 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 }9192 np = node(OBUILTIN, voidtype, ap, last);93 np->sym = sym;94 np->flags |= NEFFECT;95 return np;9697error:98 errorp("incorrect parameters for va_start");99 return constnode(zero);100}101102static Node *103builtin_va_end(Symbol *sym)104{105 Node *ap, *np;106107 ap = simplify(assign());108109 if (!valid_va_list(ap->type)) {110 errorp("incorrect parameters for va_end");111 return constnode(zero);112 }113114 np = node(OBUILTIN, voidtype, ap, NULL);115 np->sym = sym;116 np->flags |= NEFFECT;117 return np;118}119120void121ibuilts(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}