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