comparison dmd2/struct.c @ 758:f04dde6e882c

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