Mercurial > projects > ldc
annotate dmd/struct.c @ 86:fd32135dca3e trunk
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
Lots of bugfixes.
Added support for special foreach on strings.
Added std.array, std.utf, std.ctype and std.uni to phobos.
Changed all the .c files in the gen dir to .cpp (it *is* C++ after all)
author | lindquist |
---|---|
date | Sat, 03 Nov 2007 14:44:58 +0100 |
parents | b706170e24a9 |
children | 058d3925950e |
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 "root.h" | |
15 #include "aggregate.h" | |
16 #include "scope.h" | |
17 #include "mtype.h" | |
18 #include "declaration.h" | |
19 #include "module.h" | |
20 #include "id.h" | |
21 #include "statement.h" | |
22 | |
23 /********************************* AggregateDeclaration ****************************/ | |
24 | |
25 AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) | |
26 : ScopeDsymbol(id) | |
27 { | |
28 this->loc = loc; | |
29 | |
30 storage_class = 0; | |
31 protection = PROTpublic; | |
32 type = NULL; | |
33 handle = NULL; | |
34 structsize = 0; // size of struct | |
35 alignsize = 0; // size of struct for alignment purposes | |
36 structalign = 0; // struct member alignment in effect | |
37 hasUnions = 0; | |
38 sizeok = 0; // size not determined yet | |
39 isdeprecated = 0; | |
40 inv = NULL; | |
41 aggNew = NULL; | |
42 aggDelete = NULL; | |
43 | |
44 stag = NULL; | |
45 sinit = NULL; | |
46 scope = NULL; | |
47 | |
48 llvmType = NULL; | |
49 llvmVtbl = NULL; | |
54
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
1
diff
changeset
|
50 llvmConstVtbl = NULL; |
1 | 51 llvmInitZ = NULL; |
52 llvmInProgress = false; | |
73 | 53 llvmHasUnions = false; |
1 | 54 } |
55 | |
56 enum PROT AggregateDeclaration::prot() | |
57 { | |
58 return protection; | |
59 } | |
60 | |
61 void AggregateDeclaration::semantic2(Scope *sc) | |
62 { | |
63 //printf("AggregateDeclaration::semantic2(%s)\n", toChars()); | |
64 if (scope) | |
65 { error("has forward references"); | |
66 return; | |
67 } | |
68 if (members) | |
69 { | |
70 sc = sc->push(this); | |
71 for (size_t i = 0; i < members->dim; i++) | |
72 { | |
73 Dsymbol *s = (Dsymbol *)members->data[i]; | |
74 s->semantic2(sc); | |
75 } | |
76 sc->pop(); | |
77 } | |
78 } | |
79 | |
80 void AggregateDeclaration::semantic3(Scope *sc) | |
81 { int i; | |
82 | |
83 //printf("AggregateDeclaration::semantic3(%s)\n", toChars()); | |
84 if (members) | |
85 { | |
86 sc = sc->push(this); | |
87 for (i = 0; i < members->dim; i++) | |
88 { | |
89 Dsymbol *s = (Dsymbol *)members->data[i]; | |
90 s->semantic3(sc); | |
91 } | |
92 sc->pop(); | |
93 } | |
94 } | |
95 | |
96 void AggregateDeclaration::inlineScan() | |
97 { int i; | |
98 | |
99 //printf("AggregateDeclaration::inlineScan(%s)\n", toChars()); | |
100 if (members) | |
101 { | |
102 for (i = 0; i < members->dim; i++) | |
103 { | |
104 Dsymbol *s = (Dsymbol *)members->data[i]; | |
105 //printf("inline scan aggregate symbol '%s'\n", s->toChars()); | |
106 s->inlineScan(); | |
107 } | |
108 } | |
109 } | |
110 | |
111 unsigned AggregateDeclaration::size(Loc loc) | |
112 { | |
113 //printf("AggregateDeclaration::size() = %d\n", structsize); | |
114 if (!members) | |
115 error(loc, "unknown size"); | |
116 if (sizeok != 1) | |
117 { error(loc, "no size yet for forward reference"); | |
118 //*(char*)0=0; | |
119 } | |
120 return structsize; | |
121 } | |
122 | |
123 Type *AggregateDeclaration::getType() | |
124 { | |
125 return type; | |
126 } | |
127 | |
128 int AggregateDeclaration::isDeprecated() | |
129 { | |
130 return isdeprecated; | |
131 } | |
132 | |
133 /**************************** | |
134 * Do byte or word alignment as necessary. | |
135 * Align sizes of 0, as we may not know array sizes yet. | |
136 */ | |
137 | |
138 void AggregateDeclaration::alignmember(unsigned salign, unsigned size, unsigned *poffset) | |
139 { | |
140 //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset); | |
141 if (salign > 1) | |
142 { int sa; | |
143 | |
144 switch (size) | |
145 { case 1: | |
146 break; | |
147 case 2: | |
148 case_2: | |
149 *poffset = (*poffset + 1) & ~1; // align to word | |
150 break; | |
151 case 3: | |
152 case 4: | |
153 if (salign == 2) | |
154 goto case_2; | |
155 *poffset = (*poffset + 3) & ~3; // align to dword | |
156 break; | |
157 default: | |
158 *poffset = (*poffset + salign - 1) & ~(salign - 1); | |
159 break; | |
160 } | |
161 } | |
162 //printf("result = %d\n",offset); | |
163 } | |
164 | |
165 | |
166 void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) | |
167 { | |
168 unsigned memsize; // size of member | |
169 unsigned memalignsize; // size of member for alignment purposes | |
170 unsigned xalign; // alignment boundaries | |
171 | |
172 //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars()); | |
173 | |
174 // Check for forward referenced types which will fail the size() call | |
175 Type *t = v->type->toBasetype(); | |
176 if (t->ty == Tstruct /*&& isStructDeclaration()*/) | |
177 { TypeStruct *ts = (TypeStruct *)t; | |
178 | |
179 if (ts->sym->sizeok != 1) | |
180 { | |
181 sizeok = 2; // cannot finish; flag as forward referenced | |
182 return; | |
183 } | |
184 } | |
185 if (t->ty == Tident) | |
186 { | |
187 sizeok = 2; // cannot finish; flag as forward referenced | |
188 return; | |
189 } | |
190 | |
191 memsize = v->type->size(loc); | |
192 memalignsize = v->type->alignsize(); | |
193 xalign = v->type->memalign(sc->structalign); | |
194 alignmember(xalign, memalignsize, &sc->offset); | |
195 v->offset = sc->offset; | |
196 sc->offset += memsize; | |
197 if (sc->offset > structsize) | |
198 structsize = sc->offset; | |
199 if (sc->structalign < memalignsize) | |
200 memalignsize = sc->structalign; | |
201 if (alignsize < memalignsize) | |
202 alignsize = memalignsize; | |
203 //printf("\talignsize = %d\n", alignsize); | |
204 | |
205 v->storage_class |= STCfield; | |
206 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize); | |
207 fields.push(v); | |
208 } | |
209 | |
210 | |
211 /********************************* StructDeclaration ****************************/ | |
212 | |
213 StructDeclaration::StructDeclaration(Loc loc, Identifier *id) | |
214 : AggregateDeclaration(loc, id) | |
215 { | |
216 zeroInit = 0; // assume false until we do semantic processing | |
217 | |
218 // For forward references | |
219 type = new TypeStruct(this); | |
220 } | |
221 | |
222 Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s) | |
223 { | |
224 StructDeclaration *sd; | |
225 | |
226 if (s) | |
227 sd = (StructDeclaration *)s; | |
228 else | |
229 sd = new StructDeclaration(loc, ident); | |
230 ScopeDsymbol::syntaxCopy(sd); | |
231 return sd; | |
232 } | |
233 | |
234 void StructDeclaration::semantic(Scope *sc) | |
235 { int i; | |
236 Scope *sc2; | |
237 | |
238 //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); | |
239 | |
240 //static int count; if (++count == 20) *(char*)0=0; | |
241 | |
242 assert(type); | |
243 if (!members) // if forward reference | |
244 return; | |
245 | |
246 if (symtab) | |
247 { if (!scope) | |
248 return; // semantic() already completed | |
249 } | |
250 else | |
251 symtab = new DsymbolTable(); | |
252 | |
253 Scope *scx = NULL; | |
254 if (scope) | |
255 { sc = scope; | |
256 scx = scope; // save so we don't make redundant copies | |
257 scope = NULL; | |
258 } | |
259 | |
260 parent = sc->parent; | |
261 handle = type->pointerTo(); | |
262 structalign = sc->structalign; | |
263 protection = sc->protection; | |
264 assert(!isAnonymous()); | |
265 if (sc->stc & STCabstract) | |
266 error("structs, unions cannot be abstract"); | |
267 | |
268 if (sizeok == 0) // if not already done the addMember step | |
269 { | |
270 for (i = 0; i < members->dim; i++) | |
271 { | |
272 Dsymbol *s = (Dsymbol *)members->data[i]; | |
273 //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars()); | |
274 s->addMember(sc, this, 1); | |
275 } | |
276 } | |
277 | |
278 sizeok = 0; | |
279 sc2 = sc->push(this); | |
280 sc2->stc = 0; | |
281 sc2->parent = this; | |
282 if (isUnionDeclaration()) | |
283 sc2->inunion = 1; | |
284 sc2->protection = PROTpublic; | |
285 sc2->explicitProtection = 0; | |
286 | |
287 int members_dim = members->dim; | |
288 for (i = 0; i < members_dim; i++) | |
289 { | |
290 Dsymbol *s = (Dsymbol *)members->data[i]; | |
291 s->semantic(sc2); | |
292 if (isUnionDeclaration()) | |
293 sc2->offset = 0; | |
294 #if 0 | |
295 if (sizeok == 2) | |
296 { //printf("forward reference\n"); | |
297 break; | |
298 } | |
299 #endif | |
300 } | |
301 | |
302 /* The TypeInfo_Struct is expecting an opEquals and opCmp with | |
303 * a parameter that is a pointer to the struct. But if there | |
304 * isn't one, but is an opEquals or opCmp with a value, write | |
305 * another that is a shell around the value: | |
306 * int opCmp(struct *p) { return opCmp(*p); } | |
307 */ | |
308 | |
309 TypeFunction *tfeqptr; | |
310 { | |
311 Arguments *arguments = new Arguments; | |
312 Argument *arg = new Argument(STCin, handle, Id::p, NULL); | |
313 | |
314 arguments->push(arg); | |
315 tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); | |
316 tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc); | |
317 } | |
318 | |
319 TypeFunction *tfeq; | |
320 { | |
321 Arguments *arguments = new Arguments; | |
322 Argument *arg = new Argument(STCin, type, NULL, NULL); | |
323 | |
324 arguments->push(arg); | |
325 tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); | |
326 tfeq = (TypeFunction *)tfeq->semantic(0, sc); | |
327 } | |
328 | |
329 Identifier *id = Id::eq; | |
330 for (int i = 0; i < 2; i++) | |
331 { | |
332 Dsymbol *s = search_function(this, id); | |
333 FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; | |
334 if (fdx) | |
335 { FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr); | |
336 if (!fd) | |
337 { fd = fdx->overloadExactMatch(tfeq); | |
338 if (fd) | |
339 { // Create the thunk, fdptr | |
340 FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr); | |
341 Expression *e = new IdentifierExp(loc, Id::p); | |
342 e = new PtrExp(loc, e); | |
343 Expressions *args = new Expressions(); | |
344 args->push(e); | |
345 e = new IdentifierExp(loc, id); | |
346 e = new CallExp(loc, e, args); | |
347 fdptr->fbody = new ReturnStatement(loc, e); | |
348 ScopeDsymbol *s = fdx->parent->isScopeDsymbol(); | |
349 assert(s); | |
350 s->members->push(fdptr); | |
351 fdptr->addMember(sc, s, 1); | |
352 fdptr->semantic(sc2); | |
353 } | |
354 } | |
355 } | |
356 | |
357 id = Id::cmp; | |
358 } | |
359 | |
360 | |
361 sc2->pop(); | |
362 | |
363 if (sizeok == 2) | |
364 { // semantic() failed because of forward references. | |
365 // Unwind what we did, and defer it for later | |
366 fields.setDim(0); | |
367 structsize = 0; | |
368 alignsize = 0; | |
369 structalign = 0; | |
370 | |
371 scope = scx ? scx : new Scope(*sc); | |
372 scope->setNoFree(); | |
373 scope->module->addDeferredSemantic(this); | |
374 //printf("\tdeferring %s\n", toChars()); | |
375 return; | |
376 } | |
377 | |
378 // 0 sized struct's are set to 1 byte | |
379 if (structsize == 0) | |
380 { | |
381 structsize = 1; | |
382 alignsize = 1; | |
383 } | |
384 | |
385 // Round struct size up to next alignsize boundary. | |
386 // This will ensure that arrays of structs will get their internals | |
387 // aligned properly. | |
388 structsize = (structsize + alignsize - 1) & ~(alignsize - 1); | |
389 | |
390 sizeok = 1; | |
391 Module::dprogress++; | |
392 | |
393 //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); | |
394 | |
395 // Determine if struct is all zeros or not | |
396 zeroInit = 1; | |
397 for (i = 0; i < fields.dim; i++) | |
398 { | |
399 Dsymbol *s = (Dsymbol *)fields.data[i]; | |
400 VarDeclaration *vd = s->isVarDeclaration(); | |
401 if (vd && !vd->isDataseg()) | |
402 { | |
403 if (vd->init) | |
404 { | |
405 // Should examine init to see if it is really all 0's | |
406 zeroInit = 0; | |
407 break; | |
408 } | |
409 else | |
410 { | |
411 if (!vd->type->isZeroInit()) | |
412 { | |
413 zeroInit = 0; | |
414 break; | |
415 } | |
416 } | |
417 } | |
418 } | |
419 | |
420 /* Look for special member functions. | |
421 */ | |
422 inv = (InvariantDeclaration *)search(0, Id::classInvariant, 0); | |
423 aggNew = (NewDeclaration *)search(0, Id::classNew, 0); | |
424 aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0); | |
425 | |
426 if (sc->func) | |
427 { | |
428 semantic2(sc); | |
429 semantic3(sc); | |
430 } | |
431 } | |
432 | |
433 void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
434 { int i; | |
435 | |
436 buf->printf("%s ", kind()); | |
437 if (!isAnonymous()) | |
438 buf->writestring(toChars()); | |
439 if (!members) | |
440 { | |
441 buf->writeByte(';'); | |
442 buf->writenl(); | |
443 return; | |
444 } | |
445 buf->writenl(); | |
446 buf->writeByte('{'); | |
447 buf->writenl(); | |
448 for (i = 0; i < members->dim; i++) | |
449 { | |
450 Dsymbol *s = (Dsymbol *)members->data[i]; | |
451 | |
452 buf->writestring(" "); | |
453 s->toCBuffer(buf, hgs); | |
454 } | |
455 buf->writeByte('}'); | |
456 buf->writenl(); | |
457 } | |
458 | |
459 | |
460 char *StructDeclaration::kind() | |
461 { | |
462 return "struct"; | |
463 } | |
464 | |
465 /********************************* UnionDeclaration ****************************/ | |
466 | |
467 UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id) | |
468 : StructDeclaration(loc, id) | |
469 { | |
470 } | |
471 | |
472 Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s) | |
473 { | |
474 UnionDeclaration *ud; | |
475 | |
476 if (s) | |
477 ud = (UnionDeclaration *)s; | |
478 else | |
479 ud = new UnionDeclaration(loc, ident); | |
480 StructDeclaration::syntaxCopy(ud); | |
481 return ud; | |
482 } | |
483 | |
484 | |
485 char *UnionDeclaration::kind() | |
486 { | |
487 return "union"; | |
488 } | |
489 | |
490 |