Mercurial > projects > ddmd
annotate dmd/InterfaceDeclaration.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | fa9a71a9f5a8 |
children | b0d41ff5e0df |
rev | line source |
---|---|
0 | 1 module dmd.InterfaceDeclaration; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.ClassDeclaration; |
5 import dmd.Loc; | |
6 import dmd.DsymbolTable; | |
7 import dmd.STC; | |
8 import dmd.Type; | |
9 import dmd.TY; | |
10 import dmd.LINK; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
125
diff
changeset
|
11 import dmd.Parameter; |
0 | 12 import dmd.Util; |
13 import dmd.TypeTuple; | |
14 import dmd.PROT; | |
15 import dmd.TypeClass; | |
16 import dmd.Identifier; | |
17 import dmd.ArrayTypes; | |
18 import dmd.Dsymbol; | |
19 import dmd.Scope; | |
20 import dmd.Global; | |
22
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
21 import dmd.Module; |
0 | 22 import dmd.BaseClass; |
23 import dmd.Id; | |
24 | |
25 import dmd.backend.Symbol; | |
26 import dmd.backend.TYM; | |
27 import dmd.backend.dt_t; | |
28 import dmd.backend.Util; | |
29 import dmd.codegen.Util; | |
30 import dmd.backend.SC; | |
31 import dmd.backend.FL; | |
32 import dmd.backend.LIST; | |
33 import dmd.backend.SFL; | |
34 | |
35 class InterfaceDeclaration : ClassDeclaration | |
36 { | |
37 version (DMDV2) { | |
38 bool cpp; // true if this is a C++ interface | |
39 } | |
40 this(Loc loc, Identifier id, BaseClasses baseclasses) | |
41 { | |
178 | 42 register(); |
0 | 43 super(loc, id, baseclasses); |
176 | 44 |
0 | 45 if (id is Id.IUnknown) // IUnknown is the root of all COM interfaces |
46 { | |
47 com = true; | |
48 cpp = true; // IUnknown is also a C++ interface | |
49 } | |
50 } | |
176 | 51 |
72 | 52 override Dsymbol syntaxCopy(Dsymbol s) |
0 | 53 { |
123 | 54 InterfaceDeclaration id; |
55 | |
56 if (s) | |
57 id = cast(InterfaceDeclaration)s; | |
58 else | |
59 id = new InterfaceDeclaration(loc, ident, null); | |
60 | |
61 ClassDeclaration.syntaxCopy(id); | |
62 return id; | |
0 | 63 } |
176 | 64 |
72 | 65 override void semantic(Scope sc) |
0 | 66 { |
67 //printf("InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type); | |
68 if (inuse) | |
69 return; | |
70 | |
71 if (!sc) | |
72 sc = scope_; | |
73 if (!parent && sc.parent && !sc.parent.isModule()) | |
74 parent = sc.parent; | |
75 | |
76 type = type.semantic(loc, sc); | |
77 handle = type; | |
78 | |
79 if (!members) // if forward reference | |
176 | 80 { |
0 | 81 //printf("\tinterface '%s' is forward referenced\n", toChars()); |
82 return; | |
83 } | |
84 if (symtab) // if already done | |
176 | 85 { |
0 | 86 if (!scope_) |
87 return; | |
88 } | |
89 else | |
90 symtab = new DsymbolTable(); | |
91 | |
92 Scope scx = null; | |
93 if (scope_) | |
176 | 94 { |
0 | 95 sc = scope_; |
96 scx = scope_; // save so we don't make redundant copies | |
97 scope_ = null; | |
98 } | |
99 | |
100 if (sc.stc & STC.STCdeprecated) | |
101 { | |
102 isdeprecated = true; | |
103 } | |
104 | |
105 // Expand any tuples in baseclasses[] | |
89 | 106 for (size_t i = 0; i < baseclasses.dim; ) |
176 | 107 { |
125
767a01c2a272
BaseClasses -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
108 auto b = baseclasses[0]; |
0 | 109 b.type = b.type.semantic(loc, sc); |
110 Type tb = b.type.toBasetype(); | |
111 | |
112 if (tb.ty == TY.Ttuple) | |
113 { TypeTuple tup = cast(TypeTuple)tb; | |
114 PROT protection = b.protection; | |
115 baseclasses.remove(i); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
125
diff
changeset
|
116 size_t dim = Parameter.dim(tup.arguments); |
0 | 117 for (size_t j = 0; j < dim; j++) |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
125
diff
changeset
|
118 { auto arg = Parameter.getNth(tup.arguments, j); |
0 | 119 b = new BaseClass(arg.type, protection); |
125
767a01c2a272
BaseClasses -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
120 baseclasses.insert(i + j, b); |
0 | 121 } |
122 } | |
123 else | |
124 i++; | |
125 } | |
126 | |
127 if (!baseclasses.dim && sc.linkage == LINK.LINKcpp) | |
128 cpp = 1; | |
129 | |
130 // Check for errors, handle forward references | |
89 | 131 for (size_t i = 0; i < baseclasses.dim; ) |
176 | 132 { |
0 | 133 TypeClass tc; |
134 BaseClass b; | |
135 Type tb; | |
136 | |
125
767a01c2a272
BaseClasses -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
137 b = baseclasses[i]; |
0 | 138 b.type = b.type.semantic(loc, sc); |
139 tb = b.type.toBasetype(); | |
140 if (tb.ty == TY.Tclass) | |
141 tc = cast(TypeClass)tb; | |
142 else | |
143 tc = null; | |
144 if (!tc || !tc.sym.isInterfaceDeclaration()) | |
145 { | |
146 error("base type must be interface, not %s", b.type.toChars()); | |
147 baseclasses.remove(i); | |
148 continue; | |
149 } | |
150 else | |
151 { | |
152 // Check for duplicate interfaces | |
153 for (size_t j = 0; j < i; j++) | |
154 { | |
125
767a01c2a272
BaseClasses -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
155 auto b2 = baseclasses[j]; |
0 | 156 if (b2.base is tc.sym) |
157 error("inherits from duplicate interface %s", b2.base.toChars()); | |
158 } | |
159 | |
160 b.base = tc.sym; | |
161 if (b.base == this || isBaseOf2(b.base)) | |
162 { | |
163 error("circular inheritance of interface"); | |
164 baseclasses.remove(i); | |
165 continue; | |
166 } | |
167 if (!b.base.symtab) | |
176 | 168 { |
0 | 169 // Try to resolve forward reference |
170 if (sc.mustsemantic && b.base.scope_) | |
171 b.base.semantic(null); | |
172 } | |
173 if (!b.base.symtab || b.base.scope_ || b.base.inuse) | |
174 { | |
175 //error("forward reference of base class %s", baseClass.toChars()); | |
176 // Forward reference of base, try again later | |
177 //printf("\ttry later, forward reference of base %s\n", b.base.toChars()); | |
87
b17640f0e4e8
Fixed a bug with a Scope.this(Scope enclosing) being called instead of Scope.clone() method (as a copy ctor replacement)
korDen
parents:
77
diff
changeset
|
178 scope_ = scx ? scx : sc.clone(); |
0 | 179 scope_.setNoFree(); |
180 scope_.module_.addDeferredSemantic(this); | |
181 return; | |
182 } | |
183 } | |
184 static if (false) { | |
185 // Inherit const/invariant from base class | |
186 storage_class |= b.base.storage_class & STC.STC_TYPECTOR; | |
187 } | |
188 i++; | |
189 } | |
190 | |
191 interfaces_dim = baseclasses.dim; | |
125
767a01c2a272
BaseClasses -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
192 interfaces = baseclasses.ptr; |
0 | 193 |
194 interfaceSemantic(sc); | |
195 | |
196 if (vtblOffset()) | |
197 vtbl.push(cast(void*)this); // leave room at vtbl[0] for classinfo | |
198 | |
199 // Cat together the vtbl[]'s from base interfaces | |
89 | 200 for (size_t i = 0; i < interfaces_dim; i++) |
176 | 201 { |
0 | 202 BaseClass b = interfaces[i]; |
203 | |
204 // Skip if b has already appeared | |
205 for (int k = 0; k < i; k++) | |
206 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
125
diff
changeset
|
207 if (b == interfaces[k]) |
0 | 208 goto Lcontinue; |
209 } | |
210 | |
211 // Copy vtbl[] from base class | |
212 if (b.base.vtblOffset()) | |
213 { int d = b.base.vtbl.dim; | |
214 if (d > 1) | |
215 { | |
216 vtbl.reserve(d - 1); | |
217 for (int j = 1; j < d; j++) | |
218 vtbl.push(b.base.vtbl.data[j]); | |
219 } | |
220 } | |
221 else | |
222 { | |
223 vtbl.append(b.base.vtbl); | |
224 } | |
225 | |
226 Lcontinue: | |
227 ; | |
228 } | |
229 | |
230 protection = sc.protection; | |
231 storage_class |= sc.stc & STC.STC_TYPECTOR; | |
232 | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
233 foreach(Dsymbol s; members) |
13 | 234 s.addMember(sc, this, true); |
0 | 235 |
236 sc = sc.push(this); | |
237 sc.stc &= ~(STC.STCfinal | STC.STCauto | STC.STCscope | STC.STCstatic | | |
238 STC.STCabstract | STC.STCdeprecated | STC.STC_TYPECTOR | STC.STCtls | STC.STCgshared); | |
239 sc.stc |= storage_class & STC.STC_TYPECTOR; | |
240 sc.parent = this; | |
241 if (isCOMinterface()) | |
242 sc.linkage = LINK.LINKwindows; | |
243 else if (isCPPinterface()) | |
244 sc.linkage = LINK.LINKcpp; | |
245 sc.structalign = 8; | |
246 structalign = sc.structalign; | |
247 sc.offset = PTRSIZE * 2; | |
248 inuse++; | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
249 foreach(Dsymbol s; members) |
0 | 250 s.semantic(sc); |
251 inuse--; | |
252 //members.print(); | |
253 sc.pop(); | |
254 //printf("-InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type); | |
255 } | |
176 | 256 |
72 | 257 override bool isBaseOf(ClassDeclaration cd, int* poffset) |
0 | 258 { |
259 uint j; | |
260 | |
261 //printf("%s.InterfaceDeclaration.isBaseOf(cd = '%s')\n", toChars(), cd.toChars()); | |
262 assert(!baseClass); | |
263 for (j = 0; j < cd.interfaces_dim; j++) | |
264 { | |
265 BaseClass b = cd.interfaces[j]; | |
266 | |
267 //printf("\tbase %s\n", b.base.toChars()); | |
268 if (this == b.base) | |
269 { | |
270 //printf("\tfound at offset %d\n", b.offset); | |
271 if (poffset) | |
176 | 272 { |
0 | 273 *poffset = b.offset; |
274 if (j && cd.isInterfaceDeclaration()) | |
275 *poffset = OFFSET_RUNTIME; | |
276 } | |
277 return true; | |
278 } | |
279 if (isBaseOf(b, poffset)) | |
176 | 280 { |
0 | 281 if (j && poffset && cd.isInterfaceDeclaration()) |
282 *poffset = OFFSET_RUNTIME; | |
283 return true; | |
284 } | |
285 } | |
286 | |
287 if (cd.baseClass && isBaseOf(cd.baseClass, poffset)) | |
288 return true; | |
289 | |
290 if (poffset) | |
291 *poffset = 0; | |
292 return false; | |
293 } | |
176 | 294 |
0 | 295 bool isBaseOf(BaseClass bc, int* poffset) |
296 { | |
64 | 297 //printf("%s.InterfaceDeclaration.isBaseOf(bc = '%s')\n", toChars(), bc.base.toChars()); |
298 for (uint j = 0; j < bc.baseInterfaces.length; j++) | |
299 { | |
300 BaseClass b = bc.baseInterfaces[j]; | |
301 | |
302 if (this == b.base) | |
303 { | |
304 if (poffset) | |
176 | 305 { |
64 | 306 *poffset = b.offset; |
307 if (j && bc.base.isInterfaceDeclaration()) | |
308 *poffset = OFFSET_RUNTIME; | |
309 } | |
166
d8565fbd755c
Moved object and classinfo from ClassDeclaration to Global (as part of getting rid of the global state)
korDen
parents:
130
diff
changeset
|
310 return true; |
64 | 311 } |
312 if (isBaseOf(b, poffset)) | |
176 | 313 { |
64 | 314 if (j && poffset && bc.base.isInterfaceDeclaration()) |
315 *poffset = OFFSET_RUNTIME; | |
166
d8565fbd755c
Moved object and classinfo from ClassDeclaration to Global (as part of getting rid of the global state)
korDen
parents:
130
diff
changeset
|
316 return true; |
64 | 317 } |
318 } | |
319 if (poffset) | |
320 *poffset = 0; | |
166
d8565fbd755c
Moved object and classinfo from ClassDeclaration to Global (as part of getting rid of the global state)
korDen
parents:
130
diff
changeset
|
321 return false; |
0 | 322 } |
176 | 323 |
72 | 324 override string kind() |
0 | 325 { |
326 assert(false); | |
327 } | |
176 | 328 |
0 | 329 /**************************************** |
330 * Determine if slot 0 of the vtbl[] is reserved for something else. | |
331 * For class objects, yes, this is where the ClassInfo ptr goes. | |
332 * For COM interfaces, no. | |
333 * For non-COM interfaces, yes, this is where the Interface ptr goes. | |
334 */ | |
72 | 335 override int vtblOffset() |
0 | 336 { |
337 if (isCOMinterface() || isCPPinterface()) | |
338 return 0; | |
339 return 1; | |
340 } | |
176 | 341 |
0 | 342 version (DMDV2) { |
72 | 343 override bool isCPPinterface() |
0 | 344 { |
345 return cpp; | |
346 } | |
347 } | |
72 | 348 override bool isCOMinterface() |
0 | 349 { |
350 return com; | |
351 } | |
352 | |
72 | 353 override void toObjFile(int multiobj) // compile to .obj file |
0 | 354 { |
355 uint offset; | |
356 Symbol* sinit; | |
357 SC scclass; | |
358 | |
359 //printf("InterfaceDeclaration.toObjFile('%s')\n", toChars()); | |
360 | |
361 if (!members) | |
362 return; | |
363 | |
364 if (global.params.symdebug) | |
365 toDebug(); | |
366 | |
367 scclass = SCglobal; | |
368 if (inTemplateInstance()) | |
369 scclass = SCcomdat; | |
370 | |
371 // Put out the members | |
77
ad4792a1cfd6
more D-ification container accessing
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
372 foreach(Dsymbol member; members) |
0 | 373 { |
374 if (!member.isFuncDeclaration()) | |
375 member.toObjFile(0); | |
376 } | |
377 | |
378 // Generate C symbols | |
379 toSymbol(); | |
380 | |
381 ////////////////////////////////////////////// | |
382 | |
383 // Put out the TypeInfo | |
384 type.getTypeInfo(null); | |
385 type.vtinfo.toObjFile(multiobj); | |
386 | |
387 ////////////////////////////////////////////// | |
388 | |
389 // Put out the ClassInfo | |
390 csym.Sclass = scclass; | |
391 csym.Sfl = FLdata; | |
392 | |
393 /* The layout is: | |
394 { | |
395 void **vptr; | |
396 monitor_t monitor; | |
397 byte[] initializer; // static initialization data | |
398 char[] name; // class name | |
399 void *[] vtbl; | |
400 Interface[] interfaces; | |
401 Object *base; // base class | |
402 void *destructor; | |
403 void *invariant; // class invariant | |
404 uint flags; | |
405 void *deallocator; | |
406 OffsetTypeInfo[] offTi; | |
407 void *defaultConstructor; | |
408 #if DMDV2 | |
409 const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function | |
410 #endif | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
125
diff
changeset
|
411 //TypeInfo typeinfo; |
0 | 412 } |
413 */ | |
414 dt_t *dt = null; | |
415 | |
166
d8565fbd755c
Moved object and classinfo from ClassDeclaration to Global (as part of getting rid of the global state)
korDen
parents:
130
diff
changeset
|
416 if (global.classinfo) |
d8565fbd755c
Moved object and classinfo from ClassDeclaration to Global (as part of getting rid of the global state)
korDen
parents:
130
diff
changeset
|
417 dtxoff(&dt, global.classinfo.toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo |
0 | 418 else |
419 dtdword(&dt, 0); // BUG: should be an assert() | |
420 dtdword(&dt, 0); // monitor | |
421 | |
422 // initializer[] | |
423 dtdword(&dt, 0); // size | |
424 dtdword(&dt, 0); // initializer | |
425 | |
426 // name[] | |
427 string name = toPrettyChars(); | |
428 size_t namelen = name.length; | |
429 dtdword(&dt, namelen); | |
430 dtabytes(&dt, TYnptr, 0, namelen + 1, toStringz(name)); | |
431 | |
432 // vtbl[] | |
433 dtdword(&dt, 0); | |
434 dtdword(&dt, 0); | |
435 | |
436 // vtblInterfaces.data[] | |
437 dtdword(&dt, vtblInterfaces.dim); | |
438 if (vtblInterfaces.dim) | |
439 { | |
166
d8565fbd755c
Moved object and classinfo from ClassDeclaration to Global (as part of getting rid of the global state)
korDen
parents:
130
diff
changeset
|
440 if (global.classinfo) |
d8565fbd755c
Moved object and classinfo from ClassDeclaration to Global (as part of getting rid of the global state)
korDen
parents:
130
diff
changeset
|
441 assert(global.classinfo.structsize == CLASSINFO_SIZE); |
0 | 442 offset = CLASSINFO_SIZE; |
443 dtxoff(&dt, csym, offset, TYnptr); // (*) | |
444 } | |
445 else | |
446 dtdword(&dt, 0); | |
447 | |
448 // base | |
449 assert(!baseClass); | |
450 dtdword(&dt, 0); | |
451 | |
452 // dtor | |
453 dtdword(&dt, 0); | |
454 | |
455 // invariant | |
456 dtdword(&dt, 0); | |
457 | |
458 // flags | |
459 dtdword(&dt, 4 | isCOMinterface() | 32); | |
460 | |
461 // deallocator | |
462 dtdword(&dt, 0); | |
463 | |
464 // offTi[] | |
465 dtdword(&dt, 0); | |
466 dtdword(&dt, 0); // null for now, fix later | |
467 | |
468 // defaultConstructor | |
469 dtdword(&dt, 0); | |
470 | |
471 version (DMDV2) { | |
472 // xgetMembers | |
473 dtdword(&dt, 0); | |
474 } | |
475 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
125
diff
changeset
|
476 //dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr); // typeinfo |
0 | 477 |
478 ////////////////////////////////////////////// | |
479 | |
480 // Put out vtblInterfaces.data[]. Must immediately follow csym, because | |
481 // of the fixup (*) | |
482 | |
483 offset += vtblInterfaces.dim * (4 * PTRSIZE); | |
125
767a01c2a272
BaseClasses -> Vector
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
484 foreach (b; vtblInterfaces) |
176 | 485 { |
0 | 486 ClassDeclaration id = b.base; |
487 | |
488 // ClassInfo | |
489 dtxoff(&dt, id.toSymbol(), 0, TYnptr); | |
490 | |
491 // vtbl[] | |
492 dtdword(&dt, 0); | |
493 dtdword(&dt, 0); | |
494 | |
495 // this offset | |
496 dtdword(&dt, b.offset); | |
497 } | |
498 | |
499 csym.Sdt = dt; | |
500 version (ELFOBJ) { | |
22
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
501 csym.Sseg = Segment.CDATA; |
0 | 502 } |
503 version (MACHOBJ) { | |
22
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
504 csym.Sseg = Segment.DATA; |
0 | 505 } |
506 outdata(csym); | |
507 if (isExport()) | |
508 obj_export(csym,0); | |
509 } | |
510 | |
511 /************************************* | |
512 * Create the "InterfaceInfo" symbol | |
513 */ | |
72 | 514 override Symbol* toSymbol() |
0 | 515 { |
516 if (!csym) | |
517 { | |
518 Symbol *s; | |
519 | |
176 | 520 s = toSymbolX("__Interface", SCextern, global.scc.Stype, "Z"); |
0 | 521 s.Sfl = FLextern; |
522 s.Sflags |= SFLnodebug; | |
523 csym = s; | |
524 slist_add(s); | |
525 } | |
526 return csym; | |
527 } | |
528 | |
72 | 529 override InterfaceDeclaration isInterfaceDeclaration() { return this; } |
22
fd4acc376c45
Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
530 } |