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