00001 #include "c.h"
00002
00003
00004 static int curseg;
00005
00006
00007 void defpointer(Symbol p) {
00008 if (p) {
00009 (*IR->defaddress)(p);
00010 p->ref++;
00011 } else {
00012 static Value v;
00013 (*IR->defconst)(P, voidptype->size, v);
00014 }
00015 }
00016
00017
00018 static int genconst(Tree e, int def) {
00019 for (;;)
00020 switch (generic(e->op)) {
00021 case ADDRG:
00022 if (def)
00023 (*IR->defaddress)(e->u.sym);
00024 return e->type->size;
00025 case CNST:
00026 if (e->op == CNST+P && isarray(e->type)) {
00027 e = cvtconst(e);
00028 continue;
00029 }
00030 if (def)
00031 (*IR->defconst)(e->type->op, e->type->size, e->u.v);
00032 return e->type->size;
00033 case RIGHT:
00034 assert(e->kids[0] || e->kids[1]);
00035 if (e->kids[1] && e->kids[0])
00036 error("initializer must be constant\n");
00037 e = e->kids[1] ? e->kids[1] : e->kids[0];
00038 continue;
00039 case CVP:
00040 if (isarith(e->type))
00041 error("cast from `%t' to `%t' is illegal in constant expressions\n",
00042 e->kids[0]->type, e->type);
00043
00044 case CVI: case CVU: case CVF:
00045 e = e->kids[0];
00046 continue;
00047 default:
00048 error("initializer must be constant\n");
00049 if (def)
00050 genconst(consttree(0, inttype), def);
00051 return inttype->size;
00052 }
00053 }
00054
00055
00056 static Tree initvalue(Type ty) {
00057 Type aty;
00058 Tree e;
00059
00060 needconst++;
00061 e = expr1(0);
00062 if ((aty = assign(ty, e)) != NULL)
00063 e = cast(e, aty);
00064 else {
00065 error("invalid initialization type; found `%t' expected `%t'\n",
00066 e->type, ty);
00067 e = retype(consttree(0, inttype), ty);
00068 }
00069 needconst--;
00070 if (generic(e->op) != CNST) {
00071 error("initializer must be constant\n");
00072 e = retype(consttree(0, inttype), ty);
00073 }
00074 return e;
00075 }
00076
00077
00078 static int initarray(int len, Type ty, int lev) {
00079 int n = 0;
00080
00081 do {
00082 initializer(ty, lev);
00083 n += ty->size;
00084 if (len > 0 && n >= len || t != ',')
00085 break;
00086 t = gettok();
00087 } while (t != '}');
00088 return n;
00089 }
00090
00091
00092 static int initchar(int len, Type ty) {
00093 int n = 0;
00094 char buf[16], *s = buf;
00095
00096 do {
00097 *s++ = initvalue(ty)->u.v.i;
00098 if (++n%inttype->size == 0) {
00099 (*IR->defstring)(inttype->size, buf);
00100 s = buf;
00101 }
00102 if (len > 0 && n >= len || t != ',')
00103 break;
00104 t = gettok();
00105 } while (t != '}');
00106 if (s > buf)
00107 (*IR->defstring)(s - buf, buf);
00108 return n;
00109 }
00110
00111
00112 static void initend(int lev, char follow[]) {
00113 if (lev == 0 && t == ',')
00114 t = gettok();
00115 test('}', follow);
00116 }
00117
00118
00119 static int initfields(Field p, Field q) {
00120 unsigned int bits = 0;
00121 int i, n = 0;
00122
00123 do {
00124 i = initvalue(inttype)->u.v.i;
00125 if (fieldsize(p) < 8*p->type->size) {
00126 if (p->type == inttype &&
00127 (i < -(int)(fieldmask(p)>>1)-1 || i > (int)(fieldmask(p)>>1))
00128 || p->type == unsignedtype && (i&~fieldmask(p)) != 0)
00129 warning("initializer exceeds bit-field width\n");
00130 i &= fieldmask(p);
00131 }
00132 bits |= i<<fieldright(p);
00133 if (IR->little_endian) {
00134 if (fieldsize(p) + fieldright(p) > n)
00135 n = fieldsize(p) + fieldright(p);
00136 } else {
00137 if (fieldsize(p) + fieldleft(p) > n)
00138 n = fieldsize(p) + fieldleft(p);
00139 }
00140 if (p->link == q)
00141 break;
00142 p = p->link;
00143 } while (t == ',' && (t = gettok()) != 0);
00144 n = (n + 7)/8;
00145 for (i = 0; i < n; i++) {
00146 Value v;
00147 if (IR->little_endian) {
00148 v.u = (unsigned char)bits;
00149 bits >>= 8;
00150 } else {
00151 v.u = (unsigned char)(bits>>(8*(unsignedtype->size - 1)));
00152 bits <<= 8;
00153 }
00154 (*IR->defconst)(U, unsignedchar->size, v);
00155 }
00156 return n;
00157 }
00158
00159
00160 static int initstruct(int len, Type ty, int lev) {
00161 int a, n = 0;
00162 Field p = ty->u.sym->u.s.flist;
00163
00164 do {
00165 if (p->offset > n) {
00166 (*IR->space)(p->offset - n);
00167 n += p->offset - n;
00168 }
00169 if (p->lsb) {
00170 Field q = p;
00171 while (q->link && q->link->offset == p->offset)
00172 q = q->link;
00173 n += initfields(p, q->link);
00174 p = q;
00175 } else {
00176 initializer(p->type, lev);
00177 n += p->type->size;
00178 }
00179 if (p->link) {
00180 p = p->link;
00181 a = p->type->align;
00182 } else
00183 a = ty->align;
00184 if (a && n%a) {
00185 (*IR->space)(a - n%a);
00186 n = roundup(n, a);
00187 }
00188 if (len > 0 && n >= len || t != ',')
00189 break;
00190 t = gettok();
00191 } while (t != '}');
00192 return n;
00193 }
00194
00195
00196 Type initializer(Type ty, int lev) {
00197 int n = 0;
00198 Tree e;
00199 Type aty = NULL;
00200 static char follow[] = { IF, CHAR, STATIC, 0 };
00201
00202 ty = unqual(ty);
00203 if (isscalar(ty)) {
00204 needconst++;
00205 if (t == '{') {
00206 t = gettok();
00207 e = expr1(0);
00208 initend(lev, follow);
00209 } else
00210 e = expr1(0);
00211 e = pointer(e);
00212 if ((aty = assign(ty, e)) != NULL)
00213 e = cast(e, aty);
00214 else
00215 error("invalid initialization type; found `%t' expected `%t'\n",
00216 e->type, ty);
00217 n = genconst(e, 1);
00218 deallocate(STMT);
00219 needconst--;
00220 }
00221 if ((isunion(ty) || isstruct(ty)) && ty->size == 0) {
00222 static char follow[] = { CHAR, STATIC, 0 };
00223 error("cannot initialize undefined `%t'\n", ty);
00224 skipto(';', follow);
00225 return ty;
00226 } else if (isunion(ty)) {
00227 if (t == '{') {
00228 t = gettok();
00229 n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
00230 initend(lev, follow);
00231 } else {
00232 if (lev == 0)
00233 error("missing { in initialization of `%t'\n", ty);
00234 n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
00235 }
00236 } else if (isstruct(ty)) {
00237 if (t == '{') {
00238 t = gettok();
00239 n = initstruct(0, ty, lev + 1);
00240 test('}', follow);
00241 } else if (lev > 0)
00242 n = initstruct(ty->size, ty, lev + 1);
00243 else {
00244 error("missing { in initialization of `%t'\n", ty);
00245 n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
00246 }
00247 }
00248 if (isarray(ty))
00249 aty = unqual(ty->type);
00250 if (isarray(ty) && ischar(aty)) {
00251 if (t == SCON) {
00252 if (ty->size > 0 && ty->size == tsym->type->size - 1)
00253 tsym->type = array(chartype, ty->size, 0);
00254 n = tsym->type->size;
00255 (*IR->defstring)(tsym->type->size, tsym->u.c.v.p);
00256 t = gettok();
00257 } else if (t == '{') {
00258 t = gettok();
00259 if (t == SCON) {
00260 ty = initializer(ty, lev + 1);
00261 initend(lev, follow);
00262 return ty;
00263 }
00264 n = initchar(0, aty);
00265 test('}', follow);
00266 } else if (lev > 0 && ty->size > 0)
00267 n = initchar(ty->size, aty);
00268 else {
00269 error("missing { in initialization of `%t'\n", ty);
00270 n = initchar(1, aty);
00271 }
00272 } else if (isarray(ty)) {
00273 if (t == SCON && aty == widechar) {
00274 int i;
00275 unsigned int *s = tsym->u.c.v.p;
00276 if (ty->size > 0 && ty->size == tsym->type->size - widechar->size)
00277 tsym->type = array(widechar, ty->size/widechar->size, 0);
00278 n = tsym->type->size;
00279 for (i = 0; i < n; i += widechar->size) {
00280 Value v;
00281 v.u = *s++;
00282 (*IR->defconst)(widechar->op, widechar->size, v);
00283 }
00284 t = gettok();
00285 } else if (t == '{') {
00286 t = gettok();
00287 if (t == SCON && aty == widechar) {
00288 ty = initializer(ty, lev + 1);
00289 initend(lev, follow);
00290 return ty;
00291 }
00292 n = initarray(0, aty, lev + 1);
00293 test('}', follow);
00294 } else if (lev > 0 && ty->size > 0)
00295 n = initarray(ty->size, aty, lev + 1);
00296 else {
00297 error("missing { in initialization of `%t'\n", ty);
00298 n = initarray(aty->size, aty, lev + 1);
00299 }
00300 }
00301 if (ty->size) {
00302 if (n > ty->size)
00303 error("too many initializers\n");
00304 else if (n < ty->size)
00305 (*IR->space)(ty->size - n);
00306 } else if (isarray(ty) && ty->type->size > 0)
00307 ty = array(ty->type, n/ty->type->size, 0);
00308 else
00309 ty->size = n;
00310 return ty;
00311 }
00312
00313
00314 void swtoseg(int seg) {
00315 if (curseg != seg)
00316 (*IR->segment)(seg);
00317 curseg = seg;
00318 }