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