comparison ir/irclass.cpp @ 1228:79758fd2f48a

Added Doxygen file. Completely seperated type and symbol generation. Should fix a lot of bugs, but is not yet 100% complete.
author Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
date Wed, 15 Apr 2009 20:06:25 +0200
parents
children fafe7c8d6734
comparison
equal deleted inserted replaced
1215:08f87d8cd101 1228:79758fd2f48a
1 #include "llvm/Constants.h"
2 #include "llvm/DerivedTypes.h"
3
4 #include "aggregate.h"
5 #include "declaration.h"
6 #include "mtype.h"
7
8 #include "gen/irstate.h"
9 #include "gen/logger.h"
10 #include "gen/tollvm.h"
11 #include "gen/llvmhelpers.h"
12 #include "gen/utils.h"
13 #include "gen/arrays.h"
14
15 #include "ir/irstruct.h"
16 #include "ir/irtypeclass.h"
17
18 //////////////////////////////////////////////////////////////////////////////
19
20 extern LLConstant* get_default_initializer(VarDeclaration* vd, Initializer* init);
21 extern size_t add_zeros(std::vector<llvm::Constant*>& constants, size_t diff);
22
23 extern LLConstant* DtoDefineClassInfo(ClassDeclaration* cd);
24
25 //////////////////////////////////////////////////////////////////////////////
26
27 LLGlobalVariable * IrStruct::getVtblSymbol()
28 {
29 if (vtbl)
30 return vtbl;
31
32 // create the initZ symbol
33 std::string initname("_D");
34 initname.append(aggrdecl->mangle());
35 initname.append("6__vtblZ");
36
37 llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
38
39 const LLType* vtblTy = type->irtype->isClass()->getVtbl();
40
41 vtbl = new llvm::GlobalVariable(
42 vtblTy, true, _linkage, NULL, initname, gIR->module);
43
44 return vtbl;
45 }
46
47 //////////////////////////////////////////////////////////////////////////////
48
49 LLGlobalVariable * IrStruct::getClassInfoSymbol()
50 {
51 if (classInfo)
52 return classInfo;
53
54 // create the initZ symbol
55 std::string initname("_D");
56 initname.append(aggrdecl->mangle());
57 if (aggrdecl->isInterfaceDeclaration())
58 initname.append("11__InterfaceZ");
59 else
60 initname.append("7__ClassZ");
61
62 llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
63
64 ClassDeclaration* cinfo = ClassDeclaration::classinfo;
65 DtoType(cinfo->type);
66 IrTypeClass* tc = cinfo->type->irtype->isClass();
67 assert(tc && "invalid ClassInfo type");
68
69 classInfo = new llvm::GlobalVariable(
70 tc->getPA().get(), true, _linkage, NULL, initname, gIR->module);
71
72 return classInfo;
73 }
74
75 //////////////////////////////////////////////////////////////////////////////
76
77 LLGlobalVariable * IrStruct::getInterfaceArraySymbol()
78 {
79 if (classInterfacesArray)
80 return classInterfacesArray;
81
82 ClassDeclaration* cd = aggrdecl->isClassDeclaration();
83
84 assert(cd->vtblInterfaces && cd->vtblInterfaces->dim > 0 &&
85 "should not create interface info array for class with no explicit "
86 "interface implementations")
87
88 VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3);
89 const llvm::Type* InterfaceTy = DtoType(idx->type);
90
91 // create Interface[N]
92 const llvm::ArrayType* array_type = llvm::ArrayType::get(
93 InterfaceTy,
94 cd->vtblInterfaces->dim);
95
96 // put it in a global
97 std::string name("_D");
98 name.append(cd->mangle());
99 name.append("16__interfaceInfosZ");
100 classInterfacesArray = new llvm::GlobalVariable(array_type, true, DtoLinkage(cd), NULL, name, classInfo);
101
102 return classInterfacesArray;
103 }
104
105 //////////////////////////////////////////////////////////////////////////////
106
107 LLConstant * IrStruct::getVtblInit()
108 {
109 if (constVtbl)
110 return constVtbl;
111
112 IF_LOG Logger::println("Building vtbl initializer");
113 LOG_SCOPE;
114
115 ClassDeclaration* cd = aggrdecl->isClassDeclaration();
116 assert(cd && "not class");
117
118 std::vector<llvm::Constant*> constants;
119 constants.reserve(cd->vtbl.dim);
120
121 // start with the classinfo
122 llvm::Constant* c = getClassInfoSymbol();
123 c = DtoBitCast(c, DtoType(ClassDeclaration::classinfo->type));
124 constants.push_back(c);
125
126 // add virtual function pointers
127 size_t n = cd->vtbl.dim;
128 for (size_t i = 1; i < n; i++)
129 {
130 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[i];
131 assert(dsym && "null vtbl member");
132
133 FuncDeclaration* fd = dsym->isFuncDeclaration();
134 assert(fd && "vtbl entry not a function");
135
136 if (fd->isAbstract() && !fd->fbody)
137 {
138 c = getNullValue(DtoType(fd->type->pointerTo()));
139 }
140 else
141 {
142 fd->codegen(Type::sir);
143 assert(fd->ir.irFunc && "invalid vtbl function");
144 c = fd->ir.irFunc->func;
145 }
146 constants.push_back(c);
147 }
148
149 // build the constant struct
150 constVtbl = llvm::ConstantStruct::get(constants, false);
151
152 // sanity check
153 #if 0
154 IF_LOG Logger::cout() << "constVtbl type: " << *constVtbl->getType() << std::endl;
155 IF_LOG Logger::cout() << "vtbl type: " << *type->irtype->isClass()->getVtbl() << std::endl;
156 #endif
157
158 assert(constVtbl->getType() == type->irtype->isClass()->getVtbl() &&
159 "vtbl initializer type mismatch");
160
161 return constVtbl;
162 }
163
164 //////////////////////////////////////////////////////////////////////////////
165
166 LLConstant * IrStruct::getClassInfoInit()
167 {
168 if (constClassInfo)
169 return constClassInfo;
170 constClassInfo = DtoDefineClassInfo(aggrdecl->isClassDeclaration());
171 return constClassInfo;
172 }
173
174 //////////////////////////////////////////////////////////////////////////////
175
176 void IrStruct::addBaseClassInits(
177 std::vector<llvm::Constant*>& constants,
178 ClassDeclaration* base,
179 size_t& offset,
180 size_t& field_index)
181 {
182 if (base->baseClass)
183 {
184 addBaseClassInits(constants, base->baseClass, offset, field_index);
185 }
186
187 ArrayIter<VarDeclaration> it(base->fields);
188 for (; !it.done(); it.next())
189 {
190 VarDeclaration* vd = it.get();
191
192 // skip if offset moved backwards
193 if (vd->offset < offset)
194 {
195 IF_LOG Logger::println("Skipping field %s %s (+%u) for default", vd->type->toChars(), vd->toChars(), vd->offset);
196 continue;
197 }
198
199 IF_LOG Logger::println("Adding default field %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
200 LOG_SCOPE;
201
202 // get next aligned offset for this type
203 size_t alignsize = vd->type->alignsize();
204 size_t alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
205
206 // insert explicit padding?
207 if (alignedoffset < vd->offset)
208 {
209 add_zeros(constants, vd->offset - alignedoffset);
210 }
211
212 // add default type
213 constants.push_back(get_default_initializer(vd, vd->init));
214
215 // advance offset to right past this field
216 offset = vd->offset + vd->type->size();
217 }
218
219 // has interface vtbls?
220 if (base->vtblInterfaces)
221 {
222 // false when it's not okay to use functions from super classes
223 bool newinsts = (base == aggrdecl->isClassDeclaration());
224
225 ArrayIter<BaseClass> it2(*base->vtblInterfaces);
226 for (; !it2.done(); it2.next())
227 {
228 BaseClass* b = it2.get();
229 constants.push_back(getInterfaceVtbl(b, newinsts));
230 offset += PTRSIZE;
231 }
232 }
233
234 // tail padding?
235 if (offset < base->structsize)
236 {
237 add_zeros(constants, base->structsize - offset);
238 offset = base->structsize;
239 }
240 }
241
242 //////////////////////////////////////////////////////////////////////////////
243
244 LLConstant * IrStruct::createClassDefaultInitializer()
245 {
246 ClassDeclaration* cd = aggrdecl->isClassDeclaration();
247 assert(cd && "invalid class aggregate");
248
249 IF_LOG Logger::println("Building class default initializer %s @ %s", cd->toPrettyChars(), cd->locToChars());
250 LOG_SCOPE;
251 IF_LOG Logger::println("Instance size: %u", cd->structsize);
252
253 // find the fields that contribute to the default initializer.
254 // these will define the default type.
255
256 std::vector<llvm::Constant*> constants;
257 constants.reserve(32);
258
259 // add vtbl
260 constants.push_back(getVtblSymbol());
261 // add monitor
262 constants.push_back(getNullValue(DtoType(Type::tvoid->pointerTo())));
263
264 // we start right after the vtbl and monitor
265 size_t offset = PTRSIZE * 2;
266 size_t field_index = 2;
267
268 // add data members recursively
269 addBaseClassInits(constants, cd, offset, field_index);
270
271 // build the constant
272 llvm::Constant* definit = llvm::ConstantStruct::get(constants, false);
273
274 // sanity check
275 assert(definit->getType() == type->irtype->getPA().get() && "class initializer type mismatch");
276
277 return definit;
278 }
279
280 //////////////////////////////////////////////////////////////////////////////
281
282 llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instance)
283 {
284 ClassDeclaration* cd = aggrdecl->isClassDeclaration();
285 assert(cd && "not a class aggregate");
286
287 ClassGlobalMap::iterator it = interfaceVtblMap.find(cd);
288 if (it != interfaceVtblMap.end())
289 return it->second;
290
291 IF_LOG Logger::println("Building vtbl for implementation of interface %s in class %s",
292 b->base->toPrettyChars(), aggrdecl->toPrettyChars());
293 LOG_SCOPE;
294
295 Array vtbl_array;
296 b->fillVtbl(cd, &vtbl_array, new_instance);
297
298 std::vector<llvm::Constant*> constants;
299 constants.reserve(vtbl_array.dim);
300
301 // start with the interface info
302 llvm::Constant* c = getNullValue(DtoType(Type::tvoid->pointerTo()));
303 constants.push_back(c);
304
305 // add virtual function pointers
306 size_t n = vtbl_array.dim;
307 for (size_t i = 1; i < n; i++)
308 {
309 Dsymbol* dsym = (Dsymbol*)vtbl_array.data[i];
310 assert(dsym && "null vtbl member");
311
312 FuncDeclaration* fd = dsym->isFuncDeclaration();
313 assert(fd && "vtbl entry not a function");
314
315 assert(!(fd->isAbstract() && !fd->fbody) &&
316 "null symbol in interface implementation vtable");
317
318 fd->codegen(Type::sir);
319 assert(fd->ir.irFunc && "invalid vtbl function");
320
321 constants.push_back(fd->ir.irFunc->func);
322 }
323
324 // build the vtbl constant
325 llvm::Constant* vtbl_constant = llvm::ConstantStruct::get(constants, false);
326
327 // create the global variable to hold it
328 llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
329
330 std::string mangle("_D");
331 mangle.append(cd->mangle());
332 mangle.append("11__interface");
333 mangle.append(b->base->mangle());
334 mangle.append("6__vtblZ");
335
336 llvm::GlobalVariable* GV = new llvm::GlobalVariable(
337 vtbl_constant->getType(),
338 true,
339 _linkage,
340 vtbl_constant,
341 mangle,
342 gIR->module
343 );
344
345 interfaceVtblMap.insert(std::make_pair(b->base, GV));
346
347 return GV;
348 }
349
350 //////////////////////////////////////////////////////////////////////////////
351
352 LLConstant * IrStruct::getClassInfoInterfaces()
353 {
354 IF_LOG Logger::println("Building ClassInfo.interfaces");
355 LOG_SCOPE;
356
357 ClassDeclaration* cd = aggrdecl->isClassDeclaration();
358 assert(cd);
359
360 if (!cd->vtblInterfaces || cd->vtblInterfaces->dim == 0)
361 {
362 VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3);
363 return getNullValue(DtoType(idx->type));
364 }
365
366 // Build array of:
367 //
368 // struct Interface
369 // {
370 // ClassInfo classinfo;
371 // void*[] vtbl;
372 // ptrdiff_t offset;
373 // }
374
375 LLSmallVector<LLConstant*, 6> constants;
376 constants.reserve(cd->vtblInterfaces->dim);
377
378 const LLType* classinfo_type = DtoType(ClassDeclaration::classinfo->type);
379 const LLType* voidptrptr_type = DtoType(
380 Type::tvoid->pointerTo()->pointerTo());
381
382 const LLType* our_type = type->irtype->isClass()->getPA().get();
383
384 ArrayIter<BaseClass> it(*cd->vtblInterfaces);
385 while (it.more())
386 {
387 IF_LOG Logger::println("Adding interface %s", it->base->toPrettyChars());
388
389 IrStruct* irinter = it->base->ir.irStruct;
390 assert(irinter && "interface has null IrStruct");
391 IrTypeClass* itc = irinter->type->irtype->isClass();
392 assert(itc && "null interface IrTypeClass");
393
394 // classinfo
395 LLConstant* ci = irinter->getClassInfoSymbol();
396 ci = DtoBitCast(ci, classinfo_type);
397
398 // vtbl
399 ClassGlobalMap::iterator itv = interfaceVtblMap.find(it->base);
400 assert(itv != interfaceVtblMap.end() && "interface vtbl not found");
401 LLConstant* vtb = itv->second;
402 vtb = DtoBitCast(vtb, voidptrptr_type);
403 vtb = DtoConstSlice(DtoConstSize_t(itc->getVtblSize()), vtb);
404
405 // offset
406 LLConstant* off = DtoConstSize_t(it->offset);
407
408 // create Interface struct
409 LLConstant* inits[3] = { ci, vtb, off };
410 LLConstant* entry = llvm::ConstantStruct::get(inits, 3);
411 constants.push_back(entry);
412
413 // next
414 it.next();
415 }
416
417 // create Interface[N]
418 const llvm::ArrayType* array_type = llvm::ArrayType::get(
419 constants[0]->getType(),
420 cd->vtblInterfaces->dim);
421
422 LLConstant* arr = llvm::ConstantArray::get(
423 array_type,
424 &constants[0],
425 constants.size());
426
427 // apply the initializer
428 classInterfacesArray->setInitializer(arr);
429
430 LLConstant* idxs[2] = {
431 DtoConstSize_t(0),
432 DtoConstSize_t(0)
433 };
434
435 // return as a slice
436 return DtoConstSlice(
437 DtoConstSize_t(cd->vtblInterfaces->dim),
438 llvm::ConstantExpr::getGetElementPtr(classInterfacesArray, idxs, 2));
439 }
440
441 //////////////////////////////////////////////////////////////////////////////