init.c (7788B)
1 #include "c.h" 2 3 4 static int curseg; /* current segment */ 5 6 /* defpointer - initialize a pointer to p or to 0 if p==0 */ 7 void defpointer(Symbol p) { 8 if (p) { 9 (*IR->defaddress)(p); 10 p->ref++; 11 } else { 12 static Value v; 13 (*IR->defconst)(P, voidptype->size, v); 14 } 15 } 16 17 /* genconst - generate/check constant expression e; return size */ 18 static int genconst(Tree e, int def) { 19 for (;;) 20 switch (generic(e->op)) { 21 case ADDRG: 22 if (def) 23 (*IR->defaddress)(e->u.sym); 24 return e->type->size; 25 case CNST: 26 if (e->op == CNST+P && isarray(e->type)) { 27 e = cvtconst(e); 28 continue; 29 } 30 if (def) 31 (*IR->defconst)(e->type->op, e->type->size, e->u.v); 32 return e->type->size; 33 case RIGHT: 34 assert(e->kids[0] || e->kids[1]); 35 if (e->kids[1] && e->kids[0]) 36 error("initializer must be constant\n"); 37 e = e->kids[1] ? e->kids[1] : e->kids[0]; 38 continue; 39 case CVP: 40 if (isarith(e->type)) 41 error("cast from `%t' to `%t' is illegal in constant expressions\n", 42 e->kids[0]->type, e->type); 43 /* fall thru */ 44 case CVI: case CVU: case CVF: 45 e = e->kids[0]; 46 continue; 47 default: 48 error("initializer must be constant\n"); 49 if (def) 50 genconst(consttree(0, inttype), def); 51 return inttype->size; 52 } 53 } 54 55 /* initvalue - evaluate a constant expression for a value of integer type ty */ 56 static Tree initvalue(Type ty) { 57 Type aty; 58 Tree e; 59 60 needconst++; 61 e = expr1(0); 62 if ((aty = assign(ty, e)) != NULL) 63 e = cast(e, aty); 64 else { 65 error("invalid initialization type; found `%t' expected `%t'\n", 66 e->type, ty); 67 e = retype(consttree(0, inttype), ty); 68 } 69 needconst--; 70 if (generic(e->op) != CNST) { 71 error("initializer must be constant\n"); 72 e = retype(consttree(0, inttype), ty); 73 } 74 return e; 75 } 76 77 /* initarray - initialize array of ty of <= len bytes; if len == 0, go to } */ 78 static int initarray(int len, Type ty, int lev) { 79 int n = 0; 80 81 do { 82 initializer(ty, lev); 83 n += ty->size; 84 if (len > 0 && n >= len || t != ',') 85 break; 86 t = gettok(); 87 } while (t != '}'); 88 return n; 89 } 90 91 /* initchar - initialize array of <= len ty characters; if len == 0, go to } */ 92 static int initchar(int len, Type ty) { 93 int n = 0; 94 char buf[16], *s = buf; 95 96 do { 97 *s++ = initvalue(ty)->u.v.i; 98 if (++n%inttype->size == 0) { 99 (*IR->defstring)(inttype->size, buf); 100 s = buf; 101 } 102 if (len > 0 && n >= len || t != ',') 103 break; 104 t = gettok(); 105 } while (t != '}'); 106 if (s > buf) 107 (*IR->defstring)(s - buf, buf); 108 return n; 109 } 110 111 /* initend - finish off an initialization at level lev; accepts trailing comma */ 112 static void initend(int lev, char follow[]) { 113 if (lev == 0 && t == ',') 114 t = gettok(); 115 test('}', follow); 116 } 117 118 /* initfields - initialize <= an unsigned's worth of bit fields in fields p to q */ 119 static int initfields(Field p, Field q) { 120 unsigned int bits = 0; 121 int i, n = 0; 122 123 do { 124 i = initvalue(inttype)->u.v.i; 125 if (fieldsize(p) < 8*p->type->size) { 126 if (p->type == inttype && 127 (i < -(int)(fieldmask(p)>>1)-1 || i > (int)(fieldmask(p)>>1)) 128 || p->type == unsignedtype && (i&~fieldmask(p)) != 0) 129 warning("initializer exceeds bit-field width\n"); 130 i &= fieldmask(p); 131 } 132 bits |= i<<fieldright(p); 133 if (IR->little_endian) { 134 if (fieldsize(p) + fieldright(p) > n) 135 n = fieldsize(p) + fieldright(p); 136 } else { 137 if (fieldsize(p) + fieldleft(p) > n) 138 n = fieldsize(p) + fieldleft(p); 139 } 140 if (p->link == q) 141 break; 142 p = p->link; 143 } while (t == ',' && (t = gettok()) != 0); 144 n = (n + 7)/8; 145 for (i = 0; i < n; i++) { 146 Value v; 147 if (IR->little_endian) { 148 v.u = (unsigned char)bits; 149 bits >>= 8; 150 } else { /* a big endian */ 151 v.u = (unsigned char)(bits>>(8*(unsignedtype->size - 1))); 152 bits <<= 8; 153 } 154 (*IR->defconst)(U, unsignedchar->size, v); 155 } 156 return n; 157 } 158 159 /* initstruct - initialize a struct ty of <= len bytes; if len == 0, go to } */ 160 static int initstruct(int len, Type ty, int lev) { 161 int a, n = 0; 162 Field p = ty->u.sym->u.s.flist; 163 164 do { 165 if (p->offset > n) { 166 (*IR->space)(p->offset - n); 167 n += p->offset - n; 168 } 169 if (p->lsb) { 170 Field q = p; 171 while (q->link && q->link->offset == p->offset) 172 q = q->link; 173 n += initfields(p, q->link); 174 p = q; 175 } else { 176 initializer(p->type, lev); 177 n += p->type->size; 178 } 179 if (p->link) { 180 p = p->link; 181 a = p->type->align; 182 } else 183 a = ty->align; 184 if (a && n%a) { 185 (*IR->space)(a - n%a); 186 n = roundup(n, a); 187 } 188 if (len > 0 && n >= len || t != ',') 189 break; 190 t = gettok(); 191 } while (t != '}'); 192 return n; 193 } 194 195 /* initializer - constexpr | { constexpr ( , constexpr )* [ , ] } */ 196 Type initializer(Type ty, int lev) { 197 int n = 0; 198 Tree e; 199 Type aty = NULL; 200 static char follow[] = { IF, CHAR, STATIC, 0 }; 201 202 ty = unqual(ty); 203 if (isscalar(ty)) { 204 needconst++; 205 if (t == '{') { 206 t = gettok(); 207 e = expr1(0); 208 initend(lev, follow); 209 } else 210 e = expr1(0); 211 e = pointer(e); 212 if ((aty = assign(ty, e)) != NULL) 213 e = cast(e, aty); 214 else 215 error("invalid initialization type; found `%t' expected `%t'\n", 216 e->type, ty); 217 n = genconst(e, 1); 218 deallocate(STMT); 219 needconst--; 220 } 221 if ((isunion(ty) || isstruct(ty)) && ty->size == 0) { 222 static char follow[] = { CHAR, STATIC, 0 }; 223 error("cannot initialize undefined `%t'\n", ty); 224 skipto(';', follow); 225 return ty; 226 } else if (isunion(ty)) { 227 if (t == '{') { 228 t = gettok(); 229 n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1); 230 initend(lev, follow); 231 } else { 232 if (lev == 0) 233 error("missing { in initialization of `%t'\n", ty); 234 n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1); 235 } 236 } else if (isstruct(ty)) { 237 if (t == '{') { 238 t = gettok(); 239 n = initstruct(0, ty, lev + 1); 240 test('}', follow); 241 } else if (lev > 0) 242 n = initstruct(ty->size, ty, lev + 1); 243 else { 244 error("missing { in initialization of `%t'\n", ty); 245 n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1); 246 } 247 } 248 if (isarray(ty)) 249 aty = unqual(ty->type); 250 if (isarray(ty) && ischar(aty)) { 251 if (t == SCON) { 252 if (ty->size > 0 && ty->size == tsym->type->size - 1) 253 tsym->type = array(chartype, ty->size, 0); 254 n = tsym->type->size; 255 (*IR->defstring)(tsym->type->size, tsym->u.c.v.p); 256 t = gettok(); 257 } else if (t == '{') { 258 t = gettok(); 259 if (t == SCON) { 260 ty = initializer(ty, lev + 1); 261 initend(lev, follow); 262 return ty; 263 } 264 n = initchar(0, aty); 265 test('}', follow); 266 } else if (lev > 0 && ty->size > 0) 267 n = initchar(ty->size, aty); 268 else { /* eg, char c[] = 0; */ 269 error("missing { in initialization of `%t'\n", ty); 270 n = initchar(1, aty); 271 } 272 } else if (isarray(ty)) { 273 if (t == SCON && aty == widechar) { 274 int i; 275 unsigned int *s = tsym->u.c.v.p; 276 if (ty->size > 0 && ty->size == tsym->type->size - widechar->size) 277 tsym->type = array(widechar, ty->size/widechar->size, 0); 278 n = tsym->type->size; 279 for (i = 0; i < n; i += widechar->size) { 280 Value v; 281 v.u = *s++; 282 (*IR->defconst)(widechar->op, widechar->size, v); 283 } 284 t = gettok(); 285 } else if (t == '{') { 286 t = gettok(); 287 if (t == SCON && aty == widechar) { 288 ty = initializer(ty, lev + 1); 289 initend(lev, follow); 290 return ty; 291 } 292 n = initarray(0, aty, lev + 1); 293 test('}', follow); 294 } else if (lev > 0 && ty->size > 0) 295 n = initarray(ty->size, aty, lev + 1); 296 else { 297 error("missing { in initialization of `%t'\n", ty); 298 n = initarray(aty->size, aty, lev + 1); 299 } 300 } 301 if (ty->size) { 302 if (n > ty->size) 303 error("too many initializers\n"); 304 else if (n < ty->size) 305 (*IR->space)(ty->size - n); 306 } else if (isarray(ty) && ty->type->size > 0) 307 ty = array(ty->type, n/ty->type->size, 0); 308 else 309 ty->size = n; 310 return ty; 311 } 312 313 /* swtoseg - switch to segment seg, if necessary */ 314 void swtoseg(int seg) { 315 if (curseg != seg) 316 (*IR->segment)(seg); 317 curseg = seg; 318 }