Mercurial > projects > ldc
comparison gen/typinf.cpp @ 86:fd32135dca3e trunk
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
Lots of bugfixes.
Added support for special foreach on strings.
Added std.array, std.utf, std.ctype and std.uni to phobos.
Changed all the .c files in the gen dir to .cpp (it *is* C++ after all)
author | lindquist |
---|---|
date | Sat, 03 Nov 2007 14:44:58 +0100 |
parents | gen/typinf.c@3587401b6eeb |
children | ccca1c13e13a |
comparison
equal
deleted
inserted
replaced
85:f869c636a113 | 86:fd32135dca3e |
---|---|
1 | |
2 | |
3 // Copyright (c) 1999-2004 by Digital Mars | |
4 // All Rights Reserved | |
5 // written by Walter Bright | |
6 // 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 <cstdio> | |
12 #include <cassert> | |
13 | |
14 #include "gen/llvm.h" | |
15 | |
16 #include "mars.h" | |
17 #include "module.h" | |
18 #include "mtype.h" | |
19 #include "scope.h" | |
20 #include "init.h" | |
21 #include "expression.h" | |
22 #include "attrib.h" | |
23 #include "declaration.h" | |
24 #include "template.h" | |
25 #include "id.h" | |
26 #include "enum.h" | |
27 #include "import.h" | |
28 #include "aggregate.h" | |
29 | |
30 #include "gen/irstate.h" | |
31 #include "gen/logger.h" | |
32 #include "gen/runtime.h" | |
33 #include "gen/tollvm.h" | |
34 #include "gen/arrays.h" | |
35 | |
36 /******************************************* | |
37 * Get a canonicalized form of the TypeInfo for use with the internal | |
38 * runtime library routines. Canonicalized in that static arrays are | |
39 * represented as dynamic arrays, enums are represented by their | |
40 * underlying type, etc. This reduces the number of TypeInfo's needed, | |
41 * so we can use the custom internal ones more. | |
42 */ | |
43 | |
44 Expression *Type::getInternalTypeInfo(Scope *sc) | |
45 { TypeInfoDeclaration *tid; | |
46 Expression *e; | |
47 Type *t; | |
48 static TypeInfoDeclaration *internalTI[TMAX]; | |
49 | |
50 //printf("Type::getInternalTypeInfo() %s\n", toChars()); | |
51 t = toBasetype(); | |
52 switch (t->ty) | |
53 { | |
54 case Tsarray: | |
55 t = t->next->arrayOf(); // convert to corresponding dynamic array type | |
56 break; | |
57 | |
58 case Tclass: | |
59 if (((TypeClass *)t)->sym->isInterfaceDeclaration()) | |
60 break; | |
61 goto Linternal; | |
62 | |
63 case Tarray: | |
64 if (t->next->ty != Tclass) | |
65 break; | |
66 goto Linternal; | |
67 | |
68 case Tfunction: | |
69 case Tdelegate: | |
70 case Tpointer: | |
71 Linternal: | |
72 tid = internalTI[t->ty]; | |
73 if (!tid) | |
74 { tid = new TypeInfoDeclaration(t, 1); | |
75 internalTI[t->ty] = tid; | |
76 } | |
77 e = new VarExp(0, tid); | |
78 //e = e->addressOf(sc); | |
79 e->type = tid->type; // do this so we don't get redundant dereference | |
80 return e; | |
81 | |
82 default: | |
83 break; | |
84 } | |
85 //printf("\tcalling getTypeInfo() %s\n", t->toChars()); | |
86 return t->getTypeInfo(sc); | |
87 } | |
88 | |
89 | |
90 /**************************************************** | |
91 * Get the exact TypeInfo. | |
92 */ | |
93 | |
94 Expression *Type::getTypeInfo(Scope *sc) | |
95 { | |
96 Expression *e; | |
97 Type *t; | |
98 | |
99 //printf("Type::getTypeInfo() %p, %s\n", this, toChars()); | |
100 t = merge(); // do this since not all Type's are merge'd | |
101 if (!t->vtinfo) | |
102 { t->vtinfo = t->getTypeInfoDeclaration(); | |
103 assert(t->vtinfo); | |
104 | |
105 /* If this has a custom implementation in std/typeinfo, then | |
106 * do not generate a COMDAT for it. | |
107 */ | |
108 if (!t->builtinTypeInfo()) | |
109 { // Generate COMDAT | |
110 if (sc) // if in semantic() pass | |
111 { // Find module that will go all the way to an object file | |
112 Module *m = sc->module->importedFrom; | |
113 m->members->push(t->vtinfo); | |
114 } | |
115 else // if in obj generation pass | |
116 { | |
117 t->vtinfo->toObjFile(); | |
118 } | |
119 } | |
120 } | |
121 e = new VarExp(0, t->vtinfo); | |
122 //e = e->addressOf(sc); | |
123 e->type = t->vtinfo->type; // do this so we don't get redundant dereference | |
124 return e; | |
125 } | |
126 | |
127 enum RET TypeFunction::retStyle() | |
128 { | |
129 return RETstack; | |
130 } | |
131 | |
132 TypeInfoDeclaration *Type::getTypeInfoDeclaration() | |
133 { | |
134 //printf("Type::getTypeInfoDeclaration() %s\n", toChars()); | |
135 return new TypeInfoDeclaration(this, 0); | |
136 } | |
137 | |
138 TypeInfoDeclaration *TypeTypedef::getTypeInfoDeclaration() | |
139 { | |
140 return new TypeInfoTypedefDeclaration(this); | |
141 } | |
142 | |
143 TypeInfoDeclaration *TypePointer::getTypeInfoDeclaration() | |
144 { | |
145 return new TypeInfoPointerDeclaration(this); | |
146 } | |
147 | |
148 TypeInfoDeclaration *TypeDArray::getTypeInfoDeclaration() | |
149 { | |
150 return new TypeInfoArrayDeclaration(this); | |
151 } | |
152 | |
153 TypeInfoDeclaration *TypeSArray::getTypeInfoDeclaration() | |
154 { | |
155 return new TypeInfoStaticArrayDeclaration(this); | |
156 } | |
157 | |
158 TypeInfoDeclaration *TypeAArray::getTypeInfoDeclaration() | |
159 { | |
160 return new TypeInfoAssociativeArrayDeclaration(this); | |
161 } | |
162 | |
163 TypeInfoDeclaration *TypeStruct::getTypeInfoDeclaration() | |
164 { | |
165 return new TypeInfoStructDeclaration(this); | |
166 } | |
167 | |
168 TypeInfoDeclaration *TypeClass::getTypeInfoDeclaration() | |
169 { | |
170 if (sym->isInterfaceDeclaration()) | |
171 return new TypeInfoInterfaceDeclaration(this); | |
172 else | |
173 return new TypeInfoClassDeclaration(this); | |
174 } | |
175 | |
176 TypeInfoDeclaration *TypeEnum::getTypeInfoDeclaration() | |
177 { | |
178 return new TypeInfoEnumDeclaration(this); | |
179 } | |
180 | |
181 TypeInfoDeclaration *TypeFunction::getTypeInfoDeclaration() | |
182 { | |
183 return new TypeInfoFunctionDeclaration(this); | |
184 } | |
185 | |
186 TypeInfoDeclaration *TypeDelegate::getTypeInfoDeclaration() | |
187 { | |
188 return new TypeInfoDelegateDeclaration(this); | |
189 } | |
190 | |
191 TypeInfoDeclaration *TypeTuple::getTypeInfoDeclaration() | |
192 { | |
193 return new TypeInfoTupleDeclaration(this); | |
194 } | |
195 | |
196 | |
197 /* ========================================================================= */ | |
198 | |
199 /* These decide if there's an instance for them already in std.typeinfo, | |
200 * because then the compiler doesn't need to build one. | |
201 */ | |
202 | |
203 int Type::builtinTypeInfo() | |
204 { | |
205 return 0; | |
206 } | |
207 | |
208 int TypeBasic::builtinTypeInfo() | |
209 { | |
210 return 1; | |
211 } | |
212 | |
213 int TypeDArray::builtinTypeInfo() | |
214 { | |
215 return next->isTypeBasic() != NULL; | |
216 } | |
217 | |
218 /* ========================================================================= */ | |
219 | |
220 /*************************************** | |
221 * Create a static array of TypeInfo references | |
222 * corresponding to an array of Expression's. | |
223 * Used to supply hidden _arguments[] value for variadic D functions. | |
224 */ | |
225 | |
226 Expression *createTypeInfoArray(Scope *sc, Expression *exps[], int dim) | |
227 { | |
228 assert(0); | |
229 return NULL; | |
230 } | |
231 | |
232 /* ========================================================================= */ | |
233 | |
234 ////////////////////////////////////////////////////////////////////////////// | |
235 // MAGIC PLACE | |
236 ////////////////////////////////////////////////////////////////////////////// | |
237 | |
238 void TypeInfoDeclaration::toObjFile() | |
239 { | |
240 if (llvmTouched) return; | |
241 else llvmTouched = true; | |
242 | |
243 Logger::println("TypeInfoDeclaration::toObjFile()"); | |
244 LOG_SCOPE; | |
245 | |
246 Logger::println("type = '%s'", tinfo->toChars()); | |
247 Logger::println("typeinfo mangle: %s", mangle()); | |
248 | |
249 // this is a declaration of a builtin __initZ var | |
250 if (tinfo->builtinTypeInfo()) { | |
251 llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle()); | |
252 assert(llvmValue); | |
253 Logger::cout() << "Got typeinfo var:" << '\n' << *llvmValue << '\n'; | |
254 } | |
255 // custom typedef | |
256 else { | |
257 toDt(NULL); | |
258 } | |
259 } | |
260 | |
261 /* ========================================================================= */ | |
262 | |
263 void TypeInfoDeclaration::toDt(dt_t **pdt) | |
264 { | |
265 assert(0 && "TypeInfoDeclaration"); | |
266 } | |
267 | |
268 /* ========================================================================= */ | |
269 | |
270 void TypeInfoTypedefDeclaration::toDt(dt_t **pdt) | |
271 { | |
272 Logger::println("TypeInfoTypedefDeclaration::toDt() %s", toChars()); | |
273 LOG_SCOPE; | |
274 | |
275 ClassDeclaration* base = Type::typeinfotypedef; | |
276 base->toObjFile(); | |
277 | |
278 llvm::Constant* initZ = base->llvmInitZ; | |
279 assert(initZ); | |
280 const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType()); | |
281 | |
282 std::vector<llvm::Constant*> sinits; | |
283 sinits.push_back(initZ->getOperand(0)); | |
284 | |
285 assert(tinfo->ty == Ttypedef); | |
286 TypeTypedef *tc = (TypeTypedef *)tinfo; | |
287 TypedefDeclaration *sd = tc->sym; | |
288 | |
289 // TypeInfo base | |
290 //const llvm::PointerType* basept = llvm::cast<llvm::PointerType>(initZ->getOperand(1)->getType()); | |
291 //sinits.push_back(llvm::ConstantPointerNull::get(basept)); | |
292 Logger::println("generating base typeinfo"); | |
293 //sd->basetype = sd->basetype->merge(); | |
294 sd->basetype->getTypeInfo(NULL); // generate vtinfo | |
295 assert(sd->basetype->vtinfo); | |
296 if (!sd->basetype->vtinfo->llvmValue) | |
297 sd->basetype->vtinfo->toObjFile(); | |
298 assert(llvm::isa<llvm::Constant>(sd->basetype->vtinfo->llvmValue)); | |
299 llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->basetype->vtinfo->llvmValue); | |
300 castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType()); | |
301 sinits.push_back(castbase); | |
302 | |
303 // char[] name | |
304 char *name = sd->toPrettyChars(); | |
305 sinits.push_back(DtoConstString(name)); | |
306 assert(sinits.back()->getType() == initZ->getOperand(2)->getType()); | |
307 | |
308 // void[] init | |
309 const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty); | |
310 if (tinfo->isZeroInit() || !sd->init) // 0 initializer, or the same as the base type | |
311 { | |
312 sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt))); | |
313 } | |
314 else | |
315 { | |
316 llvm::Constant* ci = DtoConstInitializer(sd->basetype, sd->init); | |
317 std::string ciname(sd->mangle()); | |
318 ciname.append("__init"); | |
319 llvm::GlobalVariable* civar = new llvm::GlobalVariable(DtoType(sd->basetype),true,llvm::GlobalValue::InternalLinkage,ci,ciname,gIR->module); | |
320 llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(civar, initpt); | |
321 size_t cisize = gTargetData->getTypeSize(DtoType(sd->basetype)); | |
322 sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast)); | |
323 } | |
324 | |
325 // create the symbol | |
326 llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits); | |
327 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module); | |
328 | |
329 llvmValue = gvar; | |
330 } | |
331 | |
332 /* ========================================================================= */ | |
333 | |
334 void TypeInfoEnumDeclaration::toDt(dt_t **pdt) | |
335 { | |
336 Logger::println("TypeInfoTypedefDeclaration::toDt() %s", toChars()); | |
337 LOG_SCOPE; | |
338 | |
339 ClassDeclaration* base = Type::typeinfoenum; | |
340 base->toObjFile(); | |
341 | |
342 llvm::Constant* initZ = base->llvmInitZ; | |
343 assert(initZ); | |
344 const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType()); | |
345 | |
346 std::vector<llvm::Constant*> sinits; | |
347 sinits.push_back(initZ->getOperand(0)); | |
348 | |
349 assert(tinfo->ty == Tenum); | |
350 TypeEnum *tc = (TypeEnum *)tinfo; | |
351 EnumDeclaration *sd = tc->sym; | |
352 | |
353 // TypeInfo base | |
354 //const llvm::PointerType* basept = llvm::cast<llvm::PointerType>(initZ->getOperand(1)->getType()); | |
355 //sinits.push_back(llvm::ConstantPointerNull::get(basept)); | |
356 Logger::println("generating base typeinfo"); | |
357 //sd->basetype = sd->basetype->merge(); | |
358 sd->memtype->getTypeInfo(NULL); // generate vtinfo | |
359 assert(sd->memtype->vtinfo); | |
360 if (!sd->memtype->vtinfo->llvmValue) | |
361 sd->memtype->vtinfo->toObjFile(); | |
362 assert(llvm::isa<llvm::Constant>(sd->memtype->vtinfo->llvmValue)); | |
363 llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->memtype->vtinfo->llvmValue); | |
364 castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType()); | |
365 sinits.push_back(castbase); | |
366 | |
367 // char[] name | |
368 char *name = sd->toPrettyChars(); | |
369 sinits.push_back(DtoConstString(name)); | |
370 assert(sinits.back()->getType() == initZ->getOperand(2)->getType()); | |
371 | |
372 // void[] init | |
373 const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty); | |
374 if (tinfo->isZeroInit() || !sd->defaultval) // 0 initializer, or the same as the base type | |
375 { | |
376 sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt))); | |
377 } | |
378 else | |
379 { | |
380 const llvm::Type* memty = DtoType(sd->memtype); | |
381 llvm::Constant* ci = llvm::ConstantInt::get(memty, sd->defaultval, !sd->memtype->isunsigned()); | |
382 std::string ciname(sd->mangle()); | |
383 ciname.append("__init"); | |
384 llvm::GlobalVariable* civar = new llvm::GlobalVariable(memty,true,llvm::GlobalValue::InternalLinkage,ci,ciname,gIR->module); | |
385 llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(civar, initpt); | |
386 size_t cisize = gTargetData->getTypeSize(memty); | |
387 sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast)); | |
388 } | |
389 | |
390 // create the symbol | |
391 llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits); | |
392 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module); | |
393 | |
394 llvmValue = gvar; | |
395 } | |
396 | |
397 /* ========================================================================= */ | |
398 | |
399 static llvm::Constant* LLVM_D_Create_TypeInfoBase(Type* basetype, TypeInfoDeclaration* tid, ClassDeclaration* cd) | |
400 { | |
401 ClassDeclaration* base = cd; | |
402 base->toObjFile(); | |
403 | |
404 llvm::Constant* initZ = base->llvmInitZ; | |
405 assert(initZ); | |
406 const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType()); | |
407 | |
408 std::vector<llvm::Constant*> sinits; | |
409 sinits.push_back(initZ->getOperand(0)); | |
410 | |
411 // TypeInfo base | |
412 Logger::println("generating base typeinfo"); | |
413 basetype->getTypeInfo(NULL); | |
414 assert(basetype->vtinfo); | |
415 if (!basetype->vtinfo->llvmValue) | |
416 basetype->vtinfo->toObjFile(); | |
417 assert(llvm::isa<llvm::Constant>(basetype->vtinfo->llvmValue)); | |
418 llvm::Constant* castbase = llvm::cast<llvm::Constant>(basetype->vtinfo->llvmValue); | |
419 castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType()); | |
420 sinits.push_back(castbase); | |
421 | |
422 // create the symbol | |
423 llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits); | |
424 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,tid->toChars(),gIR->module); | |
425 | |
426 tid->llvmValue = gvar; | |
427 } | |
428 | |
429 /* ========================================================================= */ | |
430 | |
431 void TypeInfoPointerDeclaration::toDt(dt_t **pdt) | |
432 { | |
433 Logger::println("TypeInfoPointerDeclaration::toDt() %s", toChars()); | |
434 LOG_SCOPE; | |
435 | |
436 assert(tinfo->ty == Tpointer); | |
437 TypePointer *tc = (TypePointer *)tinfo; | |
438 | |
439 LLVM_D_Create_TypeInfoBase(tc->next, this, Type::typeinfopointer); | |
440 } | |
441 | |
442 /* ========================================================================= */ | |
443 | |
444 void TypeInfoArrayDeclaration::toDt(dt_t **pdt) | |
445 { | |
446 Logger::println("TypeInfoArrayDeclaration::toDt() %s", toChars()); | |
447 LOG_SCOPE; | |
448 | |
449 assert(tinfo->ty == Tarray); | |
450 TypeDArray *tc = (TypeDArray *)tinfo; | |
451 | |
452 LLVM_D_Create_TypeInfoBase(tc->next, this, Type::typeinfoarray); | |
453 } | |
454 | |
455 /* ========================================================================= */ | |
456 | |
457 void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt) | |
458 { | |
459 assert(0 && "TypeInfoStaticArrayDeclaration"); | |
460 | |
461 /* | |
462 //printf("TypeInfoStaticArrayDeclaration::toDt()\n"); | |
463 dtxoff(pdt, Type::typeinfostaticarray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_StaticArray | |
464 dtdword(pdt, 0); // monitor | |
465 | |
466 assert(tinfo->ty == Tsarray); | |
467 | |
468 TypeSArray *tc = (TypeSArray *)tinfo; | |
469 | |
470 tc->next->getTypeInfo(NULL); | |
471 dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type | |
472 | |
473 dtdword(pdt, tc->dim->toInteger()); // length | |
474 */ | |
475 } | |
476 | |
477 /* ========================================================================= */ | |
478 | |
479 void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt) | |
480 { | |
481 assert(0 && "TypeInfoAssociativeArrayDeclaration"); | |
482 | |
483 /* | |
484 //printf("TypeInfoAssociativeArrayDeclaration::toDt()\n"); | |
485 dtxoff(pdt, Type::typeinfoassociativearray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_AssociativeArray | |
486 dtdword(pdt, 0); // monitor | |
487 | |
488 assert(tinfo->ty == Taarray); | |
489 | |
490 TypeAArray *tc = (TypeAArray *)tinfo; | |
491 | |
492 tc->next->getTypeInfo(NULL); | |
493 dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type | |
494 | |
495 tc->index->getTypeInfo(NULL); | |
496 dtxoff(pdt, tc->index->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type | |
497 */ | |
498 } | |
499 | |
500 /* ========================================================================= */ | |
501 | |
502 void TypeInfoFunctionDeclaration::toDt(dt_t **pdt) | |
503 { | |
504 Logger::println("TypeInfoFunctionDeclaration::toDt() %s", toChars()); | |
505 LOG_SCOPE; | |
506 | |
507 assert(tinfo->ty == Tfunction); | |
508 TypeFunction *tc = (TypeFunction *)tinfo; | |
509 | |
510 LLVM_D_Create_TypeInfoBase(tc->next, this, Type::typeinfofunction); | |
511 } | |
512 | |
513 /* ========================================================================= */ | |
514 | |
515 void TypeInfoDelegateDeclaration::toDt(dt_t **pdt) | |
516 { | |
517 Logger::println("TypeInfoDelegateDeclaration::toDt() %s", toChars()); | |
518 LOG_SCOPE; | |
519 | |
520 assert(tinfo->ty == Tdelegate); | |
521 TypeDelegate *tc = (TypeDelegate *)tinfo; | |
522 | |
523 LLVM_D_Create_TypeInfoBase(tc->next->next, this, Type::typeinfodelegate); | |
524 } | |
525 | |
526 /* ========================================================================= */ | |
527 | |
528 void TypeInfoStructDeclaration::toDt(dt_t **pdt) | |
529 { | |
530 Logger::println("TypeInfoStructDeclaration::toDt() %s", toChars()); | |
531 LOG_SCOPE; | |
532 | |
533 assert(tinfo->ty == Tstruct); | |
534 TypeStruct *tc = (TypeStruct *)tinfo; | |
535 StructDeclaration *sd = tc->sym; | |
536 | |
537 ClassDeclaration* base = Type::typeinfostruct; | |
538 base->toObjFile(); | |
539 | |
540 const llvm::StructType* stype = llvm::cast<llvm::StructType>(base->llvmType); | |
541 | |
542 std::vector<llvm::Constant*> sinits; | |
543 sinits.push_back(base->llvmVtbl); | |
544 | |
545 // char[] name | |
546 char *name = sd->toPrettyChars(); | |
547 sinits.push_back(DtoConstString(name)); | |
548 Logger::println("************** A"); | |
549 assert(sinits.back()->getType() == stype->getElementType(1)); | |
550 | |
551 // void[] init | |
552 const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty); | |
553 if (sd->zeroInit) // 0 initializer, or the same as the base type | |
554 { | |
555 sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt))); | |
556 } | |
557 else | |
558 { | |
559 assert(sd->llvmInitZ); | |
560 size_t cisize = gTargetData->getTypeSize(tc->llvmType); | |
561 llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(tc->llvmInit, initpt); | |
562 sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast)); | |
563 } | |
564 | |
565 // toX functions ground work | |
566 FuncDeclaration *fd; | |
567 FuncDeclaration *fdx; | |
568 TypeFunction *tf; | |
569 Type *ta; | |
570 Dsymbol *s; | |
571 | |
572 static TypeFunction *tftohash; | |
573 static TypeFunction *tftostring; | |
574 | |
575 if (!tftohash) | |
576 { | |
577 Scope sc; | |
578 | |
579 tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); | |
580 tftohash = (TypeFunction *)tftohash->semantic(0, &sc); | |
581 | |
582 tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd); | |
583 tftostring = (TypeFunction *)tftostring->semantic(0, &sc); | |
584 } | |
585 | |
586 TypeFunction *tfeqptr; | |
587 { | |
588 Scope sc; | |
589 Arguments *arguments = new Arguments; | |
590 Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL); | |
591 | |
592 arguments->push(arg); | |
593 tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); | |
594 tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc); | |
595 } | |
596 | |
597 #if 0 | |
598 TypeFunction *tfeq; | |
599 { | |
600 Scope sc; | |
601 Array *arguments = new Array; | |
602 Argument *arg = new Argument(In, tc, NULL, NULL); | |
603 | |
604 arguments->push(arg); | |
605 tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); | |
606 tfeq = (TypeFunction *)tfeq->semantic(0, &sc); | |
607 } | |
608 #endif | |
609 | |
610 Logger::println("************** B"); | |
611 const llvm::PointerType* ptty = llvm::cast<llvm::PointerType>(stype->getElementType(3)); | |
612 | |
613 s = search_function(sd, Id::tohash); | |
614 fdx = s ? s->isFuncDeclaration() : NULL; | |
615 if (fdx) | |
616 { | |
617 fd = fdx->overloadExactMatch(tftohash); | |
618 if (fd) { | |
619 assert(fd->llvmValue != 0); | |
620 llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue); | |
621 assert(c); | |
622 c = llvm::ConstantExpr::getBitCast(c, ptty); | |
623 sinits.push_back(c); | |
624 } | |
625 else { | |
626 //fdx->error("must be declared as extern (D) uint toHash()"); | |
627 sinits.push_back(llvm::ConstantPointerNull::get(ptty)); | |
628 } | |
629 } | |
630 else { | |
631 sinits.push_back(llvm::ConstantPointerNull::get(ptty)); | |
632 } | |
633 | |
634 s = search_function(sd, Id::eq); | |
635 fdx = s ? s->isFuncDeclaration() : NULL; | |
636 for (int i = 0; i < 2; i++) | |
637 { | |
638 Logger::println("************** C %d", i); | |
639 ptty = llvm::cast<llvm::PointerType>(stype->getElementType(4+i)); | |
640 if (fdx) | |
641 { | |
642 fd = fdx->overloadExactMatch(tfeqptr); | |
643 if (fd) { | |
644 assert(fd->llvmValue != 0); | |
645 llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue); | |
646 assert(c); | |
647 c = llvm::ConstantExpr::getBitCast(c, ptty); | |
648 sinits.push_back(c); | |
649 } | |
650 else { | |
651 //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars()); | |
652 sinits.push_back(llvm::ConstantPointerNull::get(ptty)); | |
653 } | |
654 } | |
655 else { | |
656 sinits.push_back(llvm::ConstantPointerNull::get(ptty)); | |
657 } | |
658 | |
659 s = search_function(sd, Id::cmp); | |
660 fdx = s ? s->isFuncDeclaration() : NULL; | |
661 } | |
662 | |
663 Logger::println("************** D"); | |
664 ptty = llvm::cast<llvm::PointerType>(stype->getElementType(6)); | |
665 s = search_function(sd, Id::tostring); | |
666 fdx = s ? s->isFuncDeclaration() : NULL; | |
667 if (fdx) | |
668 { | |
669 fd = fdx->overloadExactMatch(tftostring); | |
670 if (fd) { | |
671 assert(fd->llvmValue != 0); | |
672 llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue); | |
673 assert(c); | |
674 c = llvm::ConstantExpr::getBitCast(c, ptty); | |
675 sinits.push_back(c); | |
676 } | |
677 else { | |
678 //fdx->error("must be declared as extern (D) char[] toString()"); | |
679 sinits.push_back(llvm::ConstantPointerNull::get(ptty)); | |
680 } | |
681 } | |
682 else { | |
683 sinits.push_back(llvm::ConstantPointerNull::get(ptty)); | |
684 } | |
685 | |
686 // uint m_flags; | |
687 sinits.push_back(DtoConstUint(tc->hasPointers())); | |
688 | |
689 // create the symbol | |
690 llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits); | |
691 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module); | |
692 | |
693 llvmValue = gvar; | |
694 } | |
695 | |
696 /* ========================================================================= */ | |
697 | |
698 void TypeInfoClassDeclaration::toDt(dt_t **pdt) | |
699 { | |
700 assert(0 && "TypeInfoClassDeclaration"); | |
701 | |
702 /* | |
703 //printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars()); | |
704 dtxoff(pdt, Type::typeinfoclass->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoClass | |
705 dtdword(pdt, 0); // monitor | |
706 | |
707 assert(tinfo->ty == Tclass); | |
708 | |
709 TypeClass *tc = (TypeClass *)tinfo; | |
710 Symbol *s; | |
711 | |
712 if (!tc->sym->vclassinfo) | |
713 tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym); | |
714 s = tc->sym->vclassinfo->toSymbol(); | |
715 dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo | |
716 */ | |
717 } | |
718 | |
719 /* ========================================================================= */ | |
720 | |
721 void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt) | |
722 { | |
723 assert(0 && "TypeInfoInterfaceDeclaration"); | |
724 | |
725 /* | |
726 //printf("TypeInfoInterfaceDeclaration::toDt() %s\n", tinfo->toChars()); | |
727 dtxoff(pdt, Type::typeinfointerface->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface | |
728 dtdword(pdt, 0); // monitor | |
729 | |
730 assert(tinfo->ty == Tclass); | |
731 | |
732 TypeClass *tc = (TypeClass *)tinfo; | |
733 Symbol *s; | |
734 | |
735 if (!tc->sym->vclassinfo) | |
736 tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym); | |
737 s = tc->sym->vclassinfo->toSymbol(); | |
738 dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo | |
739 */ | |
740 } | |
741 | |
742 /* ========================================================================= */ | |
743 | |
744 void TypeInfoTupleDeclaration::toDt(dt_t **pdt) | |
745 { | |
746 assert(0 && "TypeInfoTupleDeclaration"); | |
747 | |
748 /* | |
749 //printf("TypeInfoTupleDeclaration::toDt() %s\n", tinfo->toChars()); | |
750 dtxoff(pdt, Type::typeinfotypelist->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface | |
751 dtdword(pdt, 0); // monitor | |
752 | |
753 assert(tinfo->ty == Ttuple); | |
754 | |
755 TypeTuple *tu = (TypeTuple *)tinfo; | |
756 | |
757 size_t dim = tu->arguments->dim; | |
758 dtdword(pdt, dim); // elements.length | |
759 | |
760 dt_t *d = NULL; | |
761 for (size_t i = 0; i < dim; i++) | |
762 { Argument *arg = (Argument *)tu->arguments->data[i]; | |
763 Expression *e = arg->type->getTypeInfo(NULL); | |
764 e = e->optimize(WANTvalue); | |
765 e->toDt(&d); | |
766 } | |
767 | |
768 Symbol *s; | |
769 s = static_sym(); | |
770 s->Sdt = d; | |
771 outdata(s); | |
772 | |
773 dtxoff(pdt, s, 0, TYnptr); // elements.ptr | |
774 */ | |
775 } |