Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

root/gen/classes.cpp

Revision 1587:def7a1d494fd, 24.2 kB (checked in by Christian Kamm <kamm incasoftware de>, 3 years ago)

Merge DMD 1.051

Line 
1 #include "gen/llvm.h"
2
3 #include "mtype.h"
4 #include "aggregate.h"
5 #include "init.h"
6 #include "declaration.h"
7
8 #include "gen/dvalue.h"
9 #include "gen/irstate.h"
10
11 #include "gen/arrays.h"
12 #include "gen/classes.h"
13 #include "gen/functions.h"
14 #include "gen/llvmhelpers.h"
15 #include "gen/logger.h"
16 #include "gen/nested.h"
17 #include "gen/rttibuilder.h"
18 #include "gen/runtime.h"
19 #include "gen/structs.h"
20 #include "gen/tollvm.h"
21 #include "gen/utils.h"
22
23 #include "ir/irstruct.h"
24 #include "ir/irtypeclass.h"
25
26 //////////////////////////////////////////////////////////////////////////////////////////
27
28 // FIXME: this needs to be cleaned up
29
30 void DtoResolveClass(ClassDeclaration* cd)
31 {
32     // make sure the base classes are processed first
33     ArrayIter<BaseClass> base_iter(cd->baseclasses);
34     while (base_iter.more())
35     {
36         BaseClass* bc = base_iter.get();
37         if (bc)
38         {
39             bc->base->codegen(Type::sir);
40         }
41         base_iter.next();
42     }
43
44     if (cd->ir.resolved) return;
45     cd->ir.resolved = true;
46
47     Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
48     LOG_SCOPE;
49
50     // make sure type exists
51     DtoType(cd->type);
52
53     // create IrStruct
54     assert(cd->ir.irStruct == NULL);
55     IrStruct* irstruct = new IrStruct(cd);
56     cd->ir.irStruct = irstruct;
57
58     // make sure all fields really get their ir field
59     ArrayIter<VarDeclaration> it(cd->fields);
60     for (; !it.done(); it.next())
61     {
62         VarDeclaration* vd = it.get();
63         if (vd->ir.irField == NULL) {
64             new IrField(vd);
65         } else {
66             IF_LOG Logger::println("class field already exists!!!");
67         }
68     }
69
70     bool needs_def = mustDefineSymbol(cd);
71
72     // emit the ClassZ symbol
73     LLGlobalVariable* ClassZ = irstruct->getClassInfoSymbol();
74
75     // emit the interfaceInfosZ symbol if necessary
76     if (cd->vtblInterfaces && cd->vtblInterfaces->dim > 0)
77         irstruct->getInterfaceArraySymbol(); // initializer is applied when it's built
78
79     // interface only emit typeinfo and classinfo
80     if (cd->isInterfaceDeclaration())
81     {
82         irstruct->initializeInterface();
83     }
84     else
85     {
86         // emit the initZ symbol
87         LLGlobalVariable* initZ = irstruct->getInitSymbol();
88         // emit the vtblZ symbol
89         LLGlobalVariable* vtblZ = irstruct->getVtblSymbol();
90
91         // perform definition
92         if (needs_def)
93         {
94             // set symbol initializers
95             initZ->setInitializer(irstruct->getDefaultInit());
96             vtblZ->setInitializer(irstruct->getVtblInit());
97         }
98     }
99
100     // emit members
101     if (cd->members)
102     {
103         ArrayIter<Dsymbol> it(*cd->members);
104         while (!it.done())
105         {
106             Dsymbol* member = it.get();
107             if (member)
108                 member->codegen(Type::sir);
109             it.next();
110         }
111     }
112
113     if (needs_def)
114     {
115         // emit typeinfo
116         DtoTypeInfoOf(cd->type);
117
118         // define classinfo
119         ClassZ->setInitializer(irstruct->getClassInfoInit());
120     }
121 }
122
123 //////////////////////////////////////////////////////////////////////////////////////////
124
125 DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
126 {
127     // resolve type
128     tc->sym->codegen(Type::sir);
129
130     // allocate
131     LLValue* mem;
132     if (newexp->onstack)
133     {
134         // FIXME align scope class to its largest member
135         mem = DtoRawAlloca(DtoType(tc)->getContainedType(0), 0, ".newclass_alloca");
136     }
137     // custom allocator
138     else if (newexp->allocator)
139     {
140         newexp->allocator->codegen(Type::sir);
141         DFuncValue dfn(newexp->allocator, newexp->allocator->ir.irFunc->func);
142         DValue* res = DtoCallFunction(newexp->loc, NULL, &dfn, newexp->newargs);
143         mem = DtoBitCast(res->getRVal(), DtoType(tc), ".newclass_custom");
144     }
145     // default allocator
146     else
147     {
148         llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_allocclass");
149         LLConstant* ci = DtoBitCast(tc->sym->ir.irStruct->getClassInfoSymbol(), DtoType(ClassDeclaration::classinfo->type));
150         mem = gIR->CreateCallOrInvoke(fn, ci, ".newclass_gc_alloc").getInstruction();
151         mem = DtoBitCast(mem, DtoType(tc), ".newclass_gc");
152     }
153
154     // init
155     DtoInitClass(tc, mem);
156
157     // init inner-class outer reference
158     if (newexp->thisexp)
159     {
160         Logger::println("Resolving outer class");
161         LOG_SCOPE;
162         DValue* thisval = newexp->thisexp->toElem(gIR);
163         size_t idx = tc->sym->vthis->ir.irField->index;
164         LLValue* src = thisval->getRVal();
165         LLValue* dst = DtoGEPi(mem,0,idx,"tmp");
166         if (Logger::enabled())
167             Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n';
168         DtoStore(src, dst);
169     }
170     // set the context for nested classes
171     else if (tc->sym->isNested() && tc->sym->vthis)
172     {
173         Logger::println("Resolving nested context");
174         LOG_SCOPE;
175
176         // get context
177         LLValue* nest = DtoNestedContext(loc, tc->sym);
178
179         // store into right location
180         size_t idx = tc->sym->vthis->ir.irField->index;
181         LLValue* gep = DtoGEPi(mem,0,idx,"tmp");
182         DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep);
183     }
184
185     // call constructor
186     if (newexp->member)
187     {
188         Logger::println("Calling constructor");
189         assert(newexp->arguments != NULL);
190         newexp->member->codegen(Type::sir);
191         DFuncValue dfn(newexp->member, newexp->member->ir.irFunc->func, mem);
192         return DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments);
193     }
194
195     // return default constructed class
196     return new DImValue(tc, mem);
197 }
198
199 //////////////////////////////////////////////////////////////////////////////////////////
200
201 void DtoInitClass(TypeClass* tc, LLValue* dst)
202 {
203     tc->sym->codegen(Type::sir);
204
205     uint64_t n = tc->sym->structsize - PTRSIZE * 2;
206
207     // set vtable field seperately, this might give better optimization
208     LLValue* tmp = DtoGEPi(dst,0,0,"vtbl");
209     LLValue* val = DtoBitCast(tc->sym->ir.irStruct->getVtblSymbol(), tmp->getType()->getContainedType(0));
210     DtoStore(val, tmp);
211
212     // monitor always defaults to zero
213     tmp = DtoGEPi(dst,0,1,"monitor");
214     val = LLConstant::getNullValue(tmp->getType()->getContainedType(0));
215     DtoStore(val, tmp);
216
217     // done?
218     if (n == 0)
219         return;
220
221     // copy the rest from the static initializer
222     LLValue* dstarr = DtoGEPi(dst,0,2,"tmp");
223
224     // init symbols might not have valid types
225     LLValue* initsym = tc->sym->ir.irStruct->getInitSymbol();
226     initsym = DtoBitCast(initsym, DtoType(tc));
227     LLValue* srcarr = DtoGEPi(initsym,0,2,"tmp");
228
229     DtoMemCpy(dstarr, srcarr, DtoConstSize_t(n));
230 }
231
232 //////////////////////////////////////////////////////////////////////////////////////////
233
234 void DtoFinalizeClass(LLValue* inst)
235 {
236     // get runtime function
237     llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_callfinalizer");
238     // build args
239     LLSmallVector<LLValue*,1> arg;
240     arg.push_back(DtoBitCast(inst, fn->getFunctionType()->getParamType(0), ".tmp"));
241     // call
242     gIR->CreateCallOrInvoke(fn, arg.begin(), arg.end(), "");
243 }
244
245 //////////////////////////////////////////////////////////////////////////////////////////
246
247 DValue* DtoCastClass(DValue* val, Type* _to)
248 {
249     Logger::println("DtoCastClass(%s, %s)", val->getType()->toChars(), _to->toChars());
250     LOG_SCOPE;
251
252     Type* to = _to->toBasetype();
253
254     // class -> pointer
255     if (to->ty == Tpointer) {
256         IF_LOG Logger::println("to pointer");
257         const LLType* tolltype = DtoType(_to);
258         LLValue* rval = DtoBitCast(val->getRVal(), tolltype);
259         return new DImValue(_to, rval);
260     }
261     // class -> bool
262     else if (to->ty == Tbool) {
263         IF_LOG Logger::println("to bool");
264         LLValue* llval = val->getRVal();
265         LLValue* zero = LLConstant::getNullValue(llval->getType());
266         return new DImValue(_to, gIR->ir->CreateICmpNE(llval, zero, "tmp"));
267     }
268     // class -> integer
269     else if (to->isintegral()) {
270         IF_LOG Logger::println("to %s", to->toChars());
271
272         // get class ptr
273         LLValue* v = val->getRVal();
274         // cast to size_t
275         v = gIR->ir->CreatePtrToInt(v, DtoSize_t(), "");
276         // cast to the final int type
277         DImValue im(Type::tsize_t, v);
278         Loc loc;
279         return DtoCastInt(loc, &im, _to);
280     }
281
282     // must be class/interface
283     assert(to->ty == Tclass);
284     TypeClass* tc = (TypeClass*)to;
285
286     // from type
287     Type* from = val->getType()->toBasetype();
288     TypeClass* fc = (TypeClass*)from;
289
290     // x -> interface
291     if (InterfaceDeclaration* it = tc->sym->isInterfaceDeclaration()) {
292         Logger::println("to interface");
293         // interface -> interface
294         if (fc->sym->isInterfaceDeclaration()) {
295             Logger::println("from interface");
296             return DtoDynamicCastInterface(val, _to);
297         }
298         // class -> interface - static cast
299         else if (it->isBaseOf(fc->sym,NULL)) {
300             Logger::println("static down cast");
301
302             // get the from class
303             ClassDeclaration* cd = fc->sym->isClassDeclaration();
304             DtoResolveClass(cd); // add this
305             IrStruct* irstruct = cd->ir.irStruct;
306             IrTypeClass* typeclass = fc->irtype->isClass();
307
308             // find interface impl
309            
310             size_t i_index = typeclass->getInterfaceIndex(it);
311             assert(i_index != ~0 && "requesting interface that is not implemented by this class");
312
313             // offset pointer
314             LLValue* v = val->getRVal();
315             LLValue* orig = v;
316             v = DtoGEPi(v, 0, i_index);
317             const LLType* ifType = DtoType(_to);
318             if (Logger::enabled())
319             {
320                 Logger::cout() << "V = " << *v << std::endl;
321                 Logger::cout() << "T = " << *ifType << std::endl;
322             }
323             v = DtoBitCast(v, ifType);
324
325             // Check whether the original value was null, and return null if so.
326             // Sure we could have jumped over the code above in this case, but
327             // it's just a GEP and (maybe) a pointer-to-pointer BitCast, so it
328             // should be pretty cheap and perfectly safe even if the original was null.
329             LLValue* isNull = gIR->ir->CreateICmpEQ(orig, LLConstant::getNullValue(orig->getType()), ".nullcheck");
330             v = gIR->ir->CreateSelect(isNull, LLConstant::getNullValue(ifType), v, ".interface");
331
332             // return r-value
333             return new DImValue(_to, v);
334         }
335         // class -> interface
336         else {
337             Logger::println("from object");
338             return DtoDynamicCastObject(val, _to);
339         }
340     }
341     // x -> class
342     else {
343         Logger::println("to class");
344         int poffset;
345         // interface -> class
346         if (fc->sym->isInterfaceDeclaration()) {
347             Logger::println("interface cast");
348             return DtoDynamicCastInterface(val, _to);
349         }
350         // class -> class - static down cast
351         else if (tc->sym->isBaseOf(fc->sym,NULL)) {
352             Logger::println("static down cast");
353             const LLType* tolltype = DtoType(_to);
354             LLValue* rval = DtoBitCast(val->getRVal(), tolltype);
355             return new DImValue(_to, rval);
356         }
357         // class -> class - dynamic up cast
358         else {
359             Logger::println("dynamic up cast");
360             return DtoDynamicCastObject(val, _to);
361         }
362     }
363 }
364
365 //////////////////////////////////////////////////////////////////////////////////////////
366
367 DValue* DtoDynamicCastObject(DValue* val, Type* _to)
368 {
369     // call:
370     // Object _d_dynamic_cast(Object o, ClassInfo c)
371
372     ClassDeclaration::object->codegen(Type::sir);
373     ClassDeclaration::classinfo->codegen(Type::sir);
374
375     llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast");
376     const llvm::FunctionType* funcTy = func->getFunctionType();
377
378     std::vector<LLValue*> args;
379
380     // Object o
381     LLValue* obj = val->getRVal();
382     obj = DtoBitCast(obj, funcTy->getParamType(0));
383     assert(funcTy->getParamType(0) == obj->getType());
384
385     // ClassInfo c
386     TypeClass* to = (TypeClass*)_to->toBasetype();
387     to->sym->codegen(Type::sir);
388
389     LLValue* cinfo = to->sym->ir.irStruct->getClassInfoSymbol();
390     // unfortunately this is needed as the implementation of object differs somehow from the declaration
391     // this could happen in user code as well :/
392     cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
393     assert(funcTy->getParamType(1) == cinfo->getType());
394
395     // call it
396     LLValue* ret = gIR->CreateCallOrInvoke2(func, obj, cinfo, "tmp").getInstruction();
397
398     // cast return value
399     ret = DtoBitCast(ret, DtoType(_to));
400
401     return new DImValue(_to, ret);
402 }
403
404 //////////////////////////////////////////////////////////////////////////////////////////
405
406 DValue* DtoCastInterfaceToObject(DValue* val, Type* to)
407 {
408     // call:
409     // Object _d_toObject(void* p)
410
411     llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_toObject");
412     const llvm::FunctionType* funcTy = func->getFunctionType();
413
414     // void* p
415     LLValue* tmp = val->getRVal();
416     tmp = DtoBitCast(tmp, funcTy->getParamType(0));
417
418     // call it
419     LLValue* ret = gIR->CreateCallOrInvoke(func, tmp, "tmp").getInstruction();
420
421     // cast return value
422     if (to != NULL)
423         ret = DtoBitCast(ret, DtoType(to));
424     else
425         to = ClassDeclaration::object->type;
426
427     return new DImValue(to, ret);
428 }
429
430 //////////////////////////////////////////////////////////////////////////////////////////
431
432 DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
433 {
434     // call:
435     // Object _d_interface_cast(void* p, ClassInfo c)
436
437     ClassDeclaration::object->codegen(Type::sir);
438     ClassDeclaration::classinfo->codegen(Type::sir);
439
440     llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_interface_cast");
441     const llvm::FunctionType* funcTy = func->getFunctionType();
442
443     std::vector<LLValue*> args;
444
445     // void* p
446     LLValue* ptr = val->getRVal();
447     ptr = DtoBitCast(ptr, funcTy->getParamType(0));
448
449     // ClassInfo c
450     TypeClass* to = (TypeClass*)_to->toBasetype();
451     to->sym->codegen(Type::sir);
452     LLValue* cinfo = to->sym->ir.irStruct->getClassInfoSymbol();
453     // unfortunately this is needed as the implementation of object differs somehow from the declaration
454     // this could happen in user code as well :/
455     cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
456
457     // call it
458     LLValue* ret = gIR->CreateCallOrInvoke2(func, ptr, cinfo, "tmp").getInstruction();
459
460     // cast return value
461     ret = DtoBitCast(ret, DtoType(_to));
462
463     return new DImValue(_to, ret);
464 }
465
466 //////////////////////////////////////////////////////////////////////////////////////////
467
468 LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd)
469 {
470     Logger::println("indexing class field %s:", vd->toPrettyChars());
471     LOG_SCOPE;
472
473     if (Logger::enabled())
474         Logger::cout() << "src: " << *src << '\n';
475
476     // make sure class is resolved
477     DtoResolveClass(cd);
478
479     // vd must be a field
480     IrField* field = vd->ir.irField;
481     assert(field);
482
483     // get the start pointer
484     const LLType* st = DtoType(cd->type);
485     // cast to the struct type
486     src = DtoBitCast(src, st);
487
488     // gep to the index
489 #if 0
490     if (Logger::enabled())
491     {
492         Logger::cout() << "src2: " << *src << '\n';
493         Logger::cout() << "index: " << field->index << '\n';
494         Logger::cout() << "srctype: " << *src->getType() << '\n';
495     }
496 #endif
497     LLValue* val = DtoGEPi(src, 0, field->index);
498
499     // do we need to offset further? (union area)
500     if (field->unionOffset)
501     {
502         // cast to void*
503         val = DtoBitCast(val, getVoidPtrType());
504         // offset
505         val = DtoGEPi1(val, field->unionOffset);
506     }
507
508     // cast it to the right type
509     val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
510
511     if (Logger::enabled())
512         Logger::cout() << "value: " << *val << '\n';
513
514     return val;
515 }
516
517 //////////////////////////////////////////////////////////////////////////////////////////
518
519 LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl, char* name)
520 {
521     // sanity checks
522     assert(fdecl->isVirtual());
523     assert(!fdecl->isFinal());
524     assert(fdecl->vtblIndex > 0); // 0 is always ClassInfo/Interface*
525     assert(inst->getType()->toBasetype()->ty == Tclass);
526
527     // get instance
528     LLValue* vthis = inst->getRVal();
529     if (Logger::enabled())
530         Logger::cout() << "vthis: " << *vthis << '\n';
531
532     LLValue* funcval = vthis;
533     // get the vtbl for objects
534     funcval = DtoGEPi(funcval, 0, 0, "tmp");
535     // load vtbl ptr
536     funcval = DtoLoad(funcval);
537     // index vtbl
538     std::string vtblname = name;
539     vtblname.append("@vtbl");
540     funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, vtblname.c_str());
541     // load funcptr
542     funcval = DtoAlignedLoad(funcval);
543
544     if (Logger::enabled())
545         Logger::cout() << "funcval: " << *funcval << '\n';
546
547     // cast to final funcptr type
548     funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type)));
549
550     // postpone naming until after casting to get the name in call instructions
551     funcval->setName(name);
552
553     if (Logger::enabled())
554         Logger::cout() << "funcval casted: " << *funcval << '\n';
555
556     return funcval;
557 }
558
559 //////////////////////////////////////////////////////////////////////////////////////////
560
561 #if GENERATE_OFFTI
562
563 // build a single element for the OffsetInfo[] of ClassInfo
564 static LLConstant* build_offti_entry(ClassDeclaration* cd, VarDeclaration* vd)
565 {
566     std::vector<LLConstant*> inits(2);
567
568     // size_t offset;
569     //
570     assert(vd->ir.irField);
571     // grab the offset from llvm and the formal class type
572     size_t offset = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(vd->ir.irField->index);
573     // offset nested struct/union fields
574     offset += vd->ir.irField->unionOffset;
575
576     // assert that it matches DMD
577     Logger::println("offsets: %lu vs %u", offset, vd->offset);
578     assert(offset == vd->offset);
579
580     inits[0] = DtoConstSize_t(offset);
581
582     // TypeInfo ti;
583     inits[1] = DtoTypeInfoOf(vd->type, true);
584
585     // done
586     return llvm::ConstantStruct::get(inits);
587 }
588
589 static LLConstant* build_offti_array(ClassDeclaration* cd, const LLType* arrayT)
590 {
591     IrStruct* irstruct = cd->ir.irStruct;
592
593     size_t nvars = irstruct->varDecls.size();
594     std::vector<LLConstant*> arrayInits(nvars);
595
596     for (size_t i=0; i<nvars; i++)
597     {
598         arrayInits[i] = build_offti_entry(cd, irstruct->varDecls[i]);
599     }
600
601     LLConstant* size = DtoConstSize_t(nvars);
602     LLConstant* ptr;
603
604     if (nvars == 0)
605         return LLConstant::getNullValue( arrayT );
606
607     // array type
608     const llvm::ArrayType* arrTy = llvm::ArrayType::get(arrayInits[0]->getType(), nvars);
609     LLConstant* arrInit = LLConstantArray::get(arrTy, arrayInits);
610
611     // mangle
612     std::string name(cd->type->vtinfo->toChars());
613     name.append("__OffsetTypeInfos");
614
615     // create symbol
616     llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,DtoInternalLinkage(cd),arrInit,name,gIR->module);
617     ptr = DtoBitCast(gvar, getPtrToType(arrTy->getElementType()));
618
619     return DtoConstSlice(size, ptr);
620 }
621
622 #endif // GENERATE_OFFTI
623
624 static LLConstant* build_class_dtor(ClassDeclaration* cd)
625 {
626     FuncDeclaration* dtor = cd->dtor;
627
628     // if no destructor emit a null
629     if (!dtor)
630         return getNullPtr(getVoidPtrType());
631
632     dtor->codegen(Type::sir);
633     return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::getInt8Ty(gIR->context())));
634 }
635
636 static unsigned build_classinfo_flags(ClassDeclaration* cd)
637 {
638     // adapted from original dmd code
639     unsigned flags = 0;
640     //flags |= isCOMclass(); // IUnknown
641     bool hasOffTi = false;
642     if (cd->ctor) flags |= 8;
643     for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass)
644     {
645     if (cd2->members)
646     {
647         for (size_t i = 0; i < cd2->members->dim; i++)
648         {
649         Dsymbol *sm = (Dsymbol *)cd2->members->data[i];
650         if (sm->isVarDeclaration() && !sm->isVarDeclaration()->isDataseg()) // is this enough?
651             hasOffTi = true;
652         //printf("sm = %s %s\n", sm->kind(), sm->toChars());
653         if (sm->hasPointers())
654             goto L2;
655         }
656     }
657     }
658     flags |= 2;         // no pointers
659 L2:
660     if (hasOffTi)
661         flags |= 4;
662
663     // always define the typeinfo field.
664     // why would ever not do this?
665     flags |= 32;
666
667     return flags;
668 }
669
670 LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
671 {
672 //     The layout is:
673 //        {
674 //         void **vptr;
675 //         monitor_t monitor;
676 //         byte[] initializer;     // static initialization data
677 //         char[] name;        // class name
678 //         void *[] vtbl;
679 //         Interface[] interfaces;
680 //         ClassInfo *base;        // base class
681 //         void *destructor;
682 //         void *invariant;        // class invariant
683 //         uint flags;
684 //         void *deallocator;
685 //         OffsetTypeInfo[] offTi;
686 //         void *defaultConstructor;
687 //         version(D_Version2)
688 //              const(MemberInfo[]) function(string) xgetMembers;
689 //         TypeInfo typeinfo; // since dmd 1.045
690 //        }
691
692     Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
693     LOG_SCOPE;
694
695     assert(cd->type->ty == Tclass);
696     TypeClass* cdty = (TypeClass*)cd->type;
697
698     IrStruct* ir = cd->ir.irStruct;
699     assert(ir);
700
701     ClassDeclaration* cinfo = ClassDeclaration::classinfo;
702
703 #if DMDV2
704     if (cinfo->fields.dim != 13)
705 #else
706     if (cinfo->fields.dim != 12)
707 #endif
708     {
709         error("object.d ClassInfo class is incorrect");
710         fatal();
711     }
712
713     // use the rtti builder
714     RTTIBuilder b(ClassDeclaration::classinfo);
715
716     LLConstant* c;
717
718     const LLType* voidPtr = getVoidPtrType();
719     const LLType* voidPtrPtr = getPtrToType(voidPtr);
720
721     // byte[] init
722     if (cd->isInterfaceDeclaration())
723     {
724         b.push_null_void_array();
725     }
726     else
727     {
728         const LLType* cd_type = cdty->irtype->getPA();
729         size_t initsz = getTypePaddedSize(cd_type);
730         b.push_void_array(initsz, ir->getInitSymbol());
731     }
732
733     // class name
734     // code from dmd
735     const char *name = cd->ident->toChars();
736     size_t namelen = strlen(name);
737     if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
738     {
739         name = cd->toPrettyChars();
740         namelen = strlen(name);
741     }
742     b.push_string(name);
743
744     // vtbl array
745     if (cd->isInterfaceDeclaration())
746     {
747         b.push_array(0, getNullValue(voidPtrPtr));
748     }
749     else
750     {
751         c = DtoBitCast(ir->getVtblSymbol(), voidPtrPtr);
752         b.push_array(cd->vtbl.dim, c);
753     }
754
755     // interfaces array
756     b.push(ir->getClassInfoInterfaces());
757
758     // base classinfo
759     // interfaces never get a base , just the interfaces[]
760     if (cd->baseClass && !cd->isInterfaceDeclaration())
761         b.push_classinfo(cd->baseClass);
762     else
763         b.push_null(cinfo->type);
764
765     // destructor
766     if (cd->isInterfaceDeclaration())
767         b.push_null_vp();
768     else
769         b.push(build_class_dtor(cd));
770
771     // invariant
772     VarDeclaration* invVar = (VarDeclaration*)cinfo->fields.data[6];
773     b.push_funcptr(cd->inv, invVar->type);
774
775     // uint flags
776     if (cd->isInterfaceDeclaration())
777         b.push_uint(0);
778     else
779         b.push_uint(build_classinfo_flags(cd));
780
781     // deallocator
782     b.push_funcptr(cd->aggDelete, Type::tvoid->pointerTo());
783
784     // offset typeinfo
785     VarDeclaration* offTiVar = (VarDeclaration*)cinfo->fields.data[9];
786
787 #if GENERATE_OFFTI
788
789     if (cd->isInterfaceDeclaration())
790         b.push_null(offTiVar->type);
791     else
792         b.push(build_offti_array(cd, DtoType(offTiVar->type)));
793
794 #else // GENERATE_OFFTI
795
796     b.push_null(offTiVar->type);
797
798 #endif // GENERATE_OFFTI
799
800     // default constructor
801     b.push_funcptr(cd->defaultCtor, Type::tvoid->pointerTo());
802
803 #if DMDV2
804
805     // xgetMembers
806     VarDeclaration* xgetVar = (VarDeclaration*)cinfo->fields.data[11];
807
808     // FIXME: fill it out!
809     b.push_null(xgetVar->type);
810
811 #endif
812
813     // typeinfo - since 1.045
814     b.push_typeinfo(cd->type);
815
816     /*size_t n = inits.size();
817     for (size_t i=0; i<n; ++i)
818     {
819         Logger::cout() << "inits[" << i << "]: " << *inits[i] << '\n';
820     }*/
821
822     // build the initializer
823     LLConstant* finalinit = b.get_constant();
824
825     //Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
826     ir->constClassInfo = finalinit;
827
828     // sanity check
829     assert(finalinit->getType() == ir->classInfo->getType()->getContainedType(0) &&
830         "__ClassZ initializer does not match the ClassInfo type");
831
832     // return initializer
833     return finalinit;
834 }
Note: See TracBrowser for help on using the browser.
Copyright © 2008, LDC Development Team.