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 }