Mercurial > projects > ldc
annotate dmd/init.c @ 305:2b72433d5c8c trunk
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
Fixed problems with label collisions when using labels inside inline asm. LabelStatement is now easily reached given its
Identifier, which should be useful elsewhere too.
Enabled inline asm for building the lib/compiler/llvmdc runtime code, fixing branches out of asm makes this possible.
author | lindquist |
---|---|
date | Fri, 27 Jun 2008 22:04:35 +0200 |
parents | 5825d48b27d1 |
children | aaade6ded589 |
rev | line source |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2006 by Digital Mars | |
4 // All Rights Reserved | |
5 // written by Walter Bright | |
6 // http://www.digitalmars.com | |
7 // License for redistribution is by either the Artistic License | |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
9 // See the included readme.txt for details. | |
10 | |
11 #include <stdio.h> | |
12 #include <assert.h> | |
13 | |
14 #include "mars.h" | |
15 #include "init.h" | |
16 #include "expression.h" | |
17 #include "statement.h" | |
18 #include "identifier.h" | |
19 #include "declaration.h" | |
20 #include "aggregate.h" | |
21 #include "scope.h" | |
22 #include "mtype.h" | |
23 #include "hdrgen.h" | |
24 | |
25 /********************************** Initializer *******************************/ | |
26 | |
27 Initializer::Initializer(Loc loc) | |
28 { | |
29 this->loc = loc; | |
30 } | |
31 | |
32 Initializer *Initializer::syntaxCopy() | |
33 { | |
34 return this; | |
35 } | |
36 | |
37 Initializer *Initializer::semantic(Scope *sc, Type *t) | |
38 { | |
39 return this; | |
40 } | |
41 | |
42 Type *Initializer::inferType(Scope *sc) | |
43 { | |
44 error(loc, "cannot infer type from initializer"); | |
45 return Type::terror; | |
46 } | |
47 | |
48 Initializers *Initializer::arraySyntaxCopy(Initializers *ai) | |
49 { Initializers *a = NULL; | |
50 | |
51 if (ai) | |
52 { | |
53 a = new Initializers(); | |
54 a->setDim(ai->dim); | |
55 for (int i = 0; i < a->dim; i++) | |
56 { Initializer *e = (Initializer *)ai->data[i]; | |
57 | |
58 e = e->syntaxCopy(); | |
59 a->data[i] = e; | |
60 } | |
61 } | |
62 return a; | |
63 } | |
64 | |
65 char *Initializer::toChars() | |
66 { OutBuffer *buf; | |
67 HdrGenState hgs; | |
68 | |
69 memset(&hgs, 0, sizeof(hgs)); | |
70 buf = new OutBuffer(); | |
71 toCBuffer(buf, &hgs); | |
72 return buf->toChars(); | |
73 } | |
74 | |
75 /********************************** VoidInitializer ***************************/ | |
76 | |
77 VoidInitializer::VoidInitializer(Loc loc) | |
78 : Initializer(loc) | |
79 { | |
80 type = NULL; | |
81 } | |
82 | |
83 | |
84 Initializer *VoidInitializer::syntaxCopy() | |
85 { | |
86 return new VoidInitializer(loc); | |
87 } | |
88 | |
89 | |
90 Initializer *VoidInitializer::semantic(Scope *sc, Type *t) | |
91 { | |
92 //printf("VoidInitializer::semantic(t = %p)\n", t); | |
93 type = t; | |
94 return this; | |
95 } | |
96 | |
97 | |
98 Expression *VoidInitializer::toExpression() | |
99 { | |
100 error(loc, "void initializer has no value"); | |
101 return new IntegerExp(0); | |
102 } | |
103 | |
104 | |
105 void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
106 { | |
107 buf->writestring("void"); | |
108 } | |
109 | |
110 | |
111 /********************************** StructInitializer *************************/ | |
112 | |
113 StructInitializer::StructInitializer(Loc loc) | |
114 : Initializer(loc) | |
115 { | |
116 ad = NULL; | |
117 } | |
118 | |
119 Initializer *StructInitializer::syntaxCopy() | |
120 { | |
121 StructInitializer *ai = new StructInitializer(loc); | |
122 | |
123 assert(field.dim == value.dim); | |
124 ai->field.setDim(field.dim); | |
125 ai->value.setDim(value.dim); | |
126 for (int i = 0; i < field.dim; i++) | |
127 { | |
128 ai->field.data[i] = field.data[i]; | |
129 | |
130 Initializer *init = (Initializer *)value.data[i]; | |
131 init = init->syntaxCopy(); | |
132 ai->value.data[i] = init; | |
133 } | |
134 return ai; | |
135 } | |
136 | |
137 void StructInitializer::addInit(Identifier *field, Initializer *value) | |
138 { | |
139 //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value); | |
140 this->field.push(field); | |
141 this->value.push(value); | |
142 } | |
143 | |
144 Initializer *StructInitializer::semantic(Scope *sc, Type *t) | |
145 { | |
146 TypeStruct *ts; | |
147 int errors = 0; | |
148 | |
149 //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars()); | |
150 vars.setDim(field.dim); | |
151 t = t->toBasetype(); | |
152 if (t->ty == Tstruct) | |
153 { unsigned i; | |
154 unsigned fieldi = 0; | |
155 | |
156 ts = (TypeStruct *)t; | |
157 ad = ts->sym; | |
158 for (i = 0; i < field.dim; i++) | |
159 { | |
160 Identifier *id = (Identifier *)field.data[i]; | |
161 Initializer *val = (Initializer *)value.data[i]; | |
162 Dsymbol *s; | |
163 VarDeclaration *v; | |
164 | |
165 if (id == NULL) | |
166 { | |
167 if (fieldi >= ad->fields.dim) | |
168 { error(loc, "too many initializers for %s", ad->toChars()); | |
169 continue; | |
170 } | |
171 else | |
172 { | |
173 s = (Dsymbol *)ad->fields.data[fieldi]; | |
174 } | |
175 } | |
176 else | |
177 { | |
178 //s = ad->symtab->lookup(id); | |
179 s = ad->search(loc, id, 0); | |
180 if (!s) | |
181 { | |
131 | 182 error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); |
1 | 183 continue; |
184 } | |
185 | |
186 // Find out which field index it is | |
187 for (fieldi = 0; 1; fieldi++) | |
188 { | |
189 if (fieldi >= ad->fields.dim) | |
190 { | |
191 s->error("is not a per-instance initializable field"); | |
192 break; | |
193 } | |
194 if (s == (Dsymbol *)ad->fields.data[fieldi]) | |
195 break; | |
196 } | |
197 } | |
198 if (s && (v = s->isVarDeclaration()) != NULL) | |
199 { | |
200 val = val->semantic(sc, v->type); | |
201 value.data[i] = (void *)val; | |
202 vars.data[i] = (void *)v; | |
203 } | |
204 else | |
205 { error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars()); | |
206 errors = 1; | |
207 } | |
208 fieldi++; | |
209 } | |
210 } | |
211 else if (t->ty == Tdelegate && value.dim == 0) | |
212 { /* Rewrite as empty delegate literal { } | |
213 */ | |
214 Arguments *arguments = new Arguments; | |
215 Type *tf = new TypeFunction(arguments, NULL, 0, LINKd); | |
216 FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL); | |
217 fd->fbody = new CompoundStatement(loc, new Statements()); | |
218 fd->endloc = loc; | |
219 Expression *e = new FuncExp(loc, fd); | |
220 ExpInitializer *ie = new ExpInitializer(loc, e); | |
221 return ie->semantic(sc, t); | |
222 } | |
223 else | |
224 { | |
225 error(loc, "a struct is not a valid initializer for a %s", t->toChars()); | |
226 errors = 1; | |
227 } | |
228 if (errors) | |
229 { | |
230 field.setDim(0); | |
231 value.setDim(0); | |
232 vars.setDim(0); | |
233 } | |
234 return this; | |
235 } | |
236 | |
237 | |
19 | 238 /*************************************** |
239 * This works by transforming a struct initializer into | |
240 * a struct literal. In the future, the two should be the | |
241 * same thing. | |
242 */ | |
1 | 243 Expression *StructInitializer::toExpression() |
19 | 244 { Expression *e; |
245 | |
246 //printf("StructInitializer::toExpression() %s\n", toChars()); | |
247 if (!ad) // if fwd referenced | |
248 { | |
249 return NULL; | |
250 } | |
251 StructDeclaration *sd = ad->isStructDeclaration(); | |
252 if (!sd) | |
253 return NULL; | |
254 Expressions *elements = new Expressions(); | |
255 for (size_t i = 0; i < value.dim; i++) | |
256 { | |
257 if (field.data[i]) | |
258 goto Lno; | |
259 Initializer *iz = (Initializer *)value.data[i]; | |
260 if (!iz) | |
261 goto Lno; | |
262 Expression *ex = iz->toExpression(); | |
263 if (!ex) | |
264 goto Lno; | |
265 elements->push(ex); | |
266 } | |
267 e = new StructLiteralExp(loc, sd, elements); | |
268 e->type = sd->type; | |
269 return e; | |
270 | |
271 Lno: | |
272 delete elements; | |
273 //error(loc, "struct initializers as expressions are not allowed"); | |
274 return NULL; | |
1 | 275 } |
276 | |
277 | |
278 void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
279 { | |
280 //printf("StructInitializer::toCBuffer()\n"); | |
281 buf->writebyte('{'); | |
282 for (int i = 0; i < field.dim; i++) | |
283 { | |
284 if (i > 0) | |
285 buf->writebyte(','); | |
286 Identifier *id = (Identifier *)field.data[i]; | |
287 if (id) | |
288 { | |
289 buf->writestring(id->toChars()); | |
290 buf->writebyte(':'); | |
291 } | |
292 Initializer *iz = (Initializer *)value.data[i]; | |
293 if (iz) | |
294 iz->toCBuffer(buf, hgs); | |
295 } | |
296 buf->writebyte('}'); | |
297 } | |
298 | |
299 /********************************** ArrayInitializer ************************************/ | |
300 | |
301 ArrayInitializer::ArrayInitializer(Loc loc) | |
302 : Initializer(loc) | |
303 { | |
304 dim = 0; | |
305 type = NULL; | |
306 sem = 0; | |
307 } | |
308 | |
309 Initializer *ArrayInitializer::syntaxCopy() | |
310 { | |
311 //printf("ArrayInitializer::syntaxCopy()\n"); | |
312 | |
313 ArrayInitializer *ai = new ArrayInitializer(loc); | |
314 | |
315 assert(index.dim == value.dim); | |
316 ai->index.setDim(index.dim); | |
317 ai->value.setDim(value.dim); | |
318 for (int i = 0; i < ai->value.dim; i++) | |
319 { Expression *e = (Expression *)index.data[i]; | |
320 if (e) | |
321 e = e->syntaxCopy(); | |
322 ai->index.data[i] = e; | |
323 | |
324 Initializer *init = (Initializer *)value.data[i]; | |
325 init = init->syntaxCopy(); | |
326 ai->value.data[i] = init; | |
327 } | |
328 return ai; | |
329 } | |
330 | |
331 void ArrayInitializer::addInit(Expression *index, Initializer *value) | |
332 { | |
333 this->index.push(index); | |
334 this->value.push(value); | |
335 dim = 0; | |
336 type = NULL; | |
337 } | |
338 | |
339 Initializer *ArrayInitializer::semantic(Scope *sc, Type *t) | |
340 { unsigned i; | |
341 unsigned length; | |
342 | |
343 //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); | |
344 if (sem) // if semantic() already run | |
345 return this; | |
346 sem = 1; | |
347 type = t; | |
348 t = t->toBasetype(); | |
349 switch (t->ty) | |
350 { | |
351 case Tpointer: | |
352 case Tsarray: | |
353 case Tarray: | |
354 break; | |
355 | |
356 default: | |
357 error(loc, "cannot use array to initialize %s", type->toChars()); | |
358 return this; | |
359 } | |
360 | |
361 length = 0; | |
362 for (i = 0; i < index.dim; i++) | |
363 { Expression *idx; | |
364 Initializer *val; | |
365 | |
366 idx = (Expression *)index.data[i]; | |
367 if (idx) | |
368 { idx = idx->semantic(sc); | |
369 idx = idx->optimize(WANTvalue | WANTinterpret); | |
370 index.data[i] = (void *)idx; | |
371 length = idx->toInteger(); | |
372 } | |
373 | |
374 val = (Initializer *)value.data[i]; | |
375 val = val->semantic(sc, t->next); | |
376 value.data[i] = (void *)val; | |
377 length++; | |
378 if (length == 0) | |
379 error("array dimension overflow"); | |
380 if (length > dim) | |
381 dim = length; | |
382 } | |
383 unsigned long amax = 0x80000000; | |
384 if ((unsigned long) dim * t->next->size() >= amax) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
131
diff
changeset
|
385 error(loc, "array dimension %u exceeds max of %llu", dim, amax / t->next->size()); |
1 | 386 return this; |
387 } | |
388 | |
389 /******************************** | |
390 * If possible, convert array initializer to array literal. | |
391 */ | |
392 | |
393 Expression *ArrayInitializer::toExpression() | |
394 { Expressions *elements; | |
395 Expression *e; | |
396 | |
397 //printf("ArrayInitializer::toExpression()\n"); | |
398 //static int i; if (++i == 2) halt(); | |
399 elements = new Expressions(); | |
400 for (size_t i = 0; i < value.dim; i++) | |
401 { | |
402 if (index.data[i]) | |
403 goto Lno; | |
404 Initializer *iz = (Initializer *)value.data[i]; | |
405 if (!iz) | |
406 goto Lno; | |
407 Expression *ex = iz->toExpression(); | |
408 if (!ex) | |
409 goto Lno; | |
410 elements->push(ex); | |
411 } | |
412 e = new ArrayLiteralExp(loc, elements); | |
413 e->type = type; | |
414 return e; | |
415 | |
416 Lno: | |
417 delete elements; | |
418 error(loc, "array initializers as expressions are not allowed"); | |
419 return NULL; | |
420 } | |
421 | |
422 | |
423 /******************************** | |
424 * If possible, convert array initializer to associative array initializer. | |
425 */ | |
426 | |
427 Initializer *ArrayInitializer::toAssocArrayInitializer() | |
428 { Expressions *keys; | |
429 Expressions *values; | |
430 Expression *e; | |
431 | |
432 //printf("ArrayInitializer::toAssocArrayInitializer()\n"); | |
433 //static int i; if (++i == 2) halt(); | |
434 keys = new Expressions(); | |
435 keys->setDim(value.dim); | |
436 values = new Expressions(); | |
437 values->setDim(value.dim); | |
438 | |
439 for (size_t i = 0; i < value.dim; i++) | |
440 { | |
441 e = (Expression *)index.data[i]; | |
442 if (!e) | |
443 goto Lno; | |
444 keys->data[i] = (void *)e; | |
445 | |
446 Initializer *iz = (Initializer *)value.data[i]; | |
447 if (!iz) | |
448 goto Lno; | |
449 e = iz->toExpression(); | |
450 if (!e) | |
451 goto Lno; | |
452 values->data[i] = (void *)e; | |
453 } | |
454 e = new AssocArrayLiteralExp(loc, keys, values); | |
455 return new ExpInitializer(loc, e); | |
456 | |
457 Lno: | |
458 delete keys; | |
459 delete values; | |
460 error(loc, "not an associative array initializer"); | |
461 return this; | |
462 } | |
463 | |
464 | |
465 Type *ArrayInitializer::inferType(Scope *sc) | |
466 { | |
467 for (size_t i = 0; i < value.dim; i++) | |
468 { | |
469 if (index.data[i]) | |
470 goto Lno; | |
471 } | |
472 if (value.dim) | |
473 { | |
474 Initializer *iz = (Initializer *)value.data[0]; | |
475 if (iz) | |
476 { Type *t = iz->inferType(sc); | |
477 t = new TypeSArray(t, new IntegerExp(value.dim)); | |
478 t = t->semantic(loc, sc); | |
479 return t; | |
480 } | |
481 } | |
482 | |
483 Lno: | |
484 error(loc, "cannot infer type from this array initializer"); | |
485 return Type::terror; | |
486 } | |
487 | |
488 | |
489 void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
490 { | |
491 buf->writebyte('['); | |
492 for (int i = 0; i < index.dim; i++) | |
493 { | |
494 if (i > 0) | |
495 buf->writebyte(','); | |
496 Expression *ex = (Expression *)index.data[i]; | |
497 if (ex) | |
498 { | |
499 ex->toCBuffer(buf, hgs); | |
500 buf->writebyte(':'); | |
501 } | |
502 Initializer *iz = (Initializer *)value.data[i]; | |
503 if (iz) | |
504 iz->toCBuffer(buf, hgs); | |
505 } | |
506 buf->writebyte(']'); | |
507 } | |
508 | |
509 | |
510 /********************************** ExpInitializer ************************************/ | |
511 | |
512 ExpInitializer::ExpInitializer(Loc loc, Expression *exp) | |
513 : Initializer(loc) | |
514 { | |
515 this->exp = exp; | |
516 } | |
517 | |
518 Initializer *ExpInitializer::syntaxCopy() | |
519 { | |
520 return new ExpInitializer(loc, exp->syntaxCopy()); | |
521 } | |
522 | |
523 Initializer *ExpInitializer::semantic(Scope *sc, Type *t) | |
524 { | |
525 //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars()); | |
526 exp = exp->semantic(sc); | |
527 Type *tb = t->toBasetype(); | |
528 | |
529 /* Look for case of initializing a static array with a too-short | |
530 * string literal, such as: | |
531 * char[5] foo = "abc"; | |
532 * Allow this by doing an explicit cast, which will lengthen the string | |
533 * literal. | |
534 */ | |
535 if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray) | |
536 { StringExp *se = (StringExp *)exp; | |
537 | |
538 if (!se->committed && se->type->ty == Tsarray && | |
539 ((TypeSArray *)se->type)->dim->toInteger() < | |
540 ((TypeSArray *)t)->dim->toInteger()) | |
541 { | |
542 exp = se->castTo(sc, t); | |
543 goto L1; | |
544 } | |
545 } | |
546 | |
547 // Look for the case of statically initializing an array | |
548 // with a single member. | |
549 if (tb->ty == Tsarray && | |
550 !tb->next->equals(exp->type->toBasetype()->next) && | |
551 exp->implicitConvTo(tb->next) | |
552 ) | |
553 { | |
554 t = tb->next; | |
555 } | |
556 | |
557 exp = exp->implicitCastTo(sc, t); | |
558 L1: | |
559 exp = exp->optimize(WANTvalue | WANTinterpret); | |
560 //printf("-ExpInitializer::semantic(): "); exp->print(); | |
561 return this; | |
562 } | |
563 | |
564 Type *ExpInitializer::inferType(Scope *sc) | |
565 { | |
566 //printf("ExpInitializer::inferType() %s\n", toChars()); | |
567 exp = exp->semantic(sc); | |
568 exp = resolveProperties(sc, exp); | |
569 return exp->type; | |
570 } | |
571 | |
572 Expression *ExpInitializer::toExpression() | |
573 { | |
574 return exp; | |
575 } | |
576 | |
577 | |
578 void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
579 { | |
580 exp->toCBuffer(buf, hgs); | |
581 } | |
582 | |
583 | |
584 |