Mercurial > projects > ldc
comparison gen/classes.cpp @ 102:027b8d8b71ec trunk
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
Basically it tries to do the following in order: Resolve types, Declare symbols, Create constant initializers, Apply initializers, Generate functions bodies.
ClassInfo is now has the most useful(biased?) members working.
Probably other stuf...
author | lindquist |
---|---|
date | Sun, 18 Nov 2007 06:52:57 +0100 |
parents | 5071469303d4 |
children | 855adfdb8d38 |
comparison
equal
deleted
inserted
replaced
101:169fda3a77d4 | 102:027b8d8b71ec |
---|---|
8 #include "gen/irstate.h" | 8 #include "gen/irstate.h" |
9 #include "gen/tollvm.h" | 9 #include "gen/tollvm.h" |
10 #include "gen/arrays.h" | 10 #include "gen/arrays.h" |
11 #include "gen/logger.h" | 11 #include "gen/logger.h" |
12 #include "gen/classes.h" | 12 #include "gen/classes.h" |
13 #include "gen/functions.h" | |
13 | 14 |
14 ////////////////////////////////////////////////////////////////////////////////////////// | 15 ////////////////////////////////////////////////////////////////////////////////////////// |
15 | 16 |
16 static void LLVM_AddBaseClassData(BaseClasses* bcs) | 17 static void LLVM_AddBaseClassData(BaseClasses* bcs) |
17 { | 18 { |
20 { | 21 { |
21 BaseClass* bc = (BaseClass*)(bcs->data[j]); | 22 BaseClass* bc = (BaseClass*)(bcs->data[j]); |
22 assert(bc); | 23 assert(bc); |
23 Logger::println("Adding base class members of %s", bc->base->toChars()); | 24 Logger::println("Adding base class members of %s", bc->base->toChars()); |
24 LOG_SCOPE; | 25 LOG_SCOPE; |
25 | |
26 bc->base->toObjFile(); | |
27 | 26 |
28 LLVM_AddBaseClassData(&bc->base->baseclasses); | 27 LLVM_AddBaseClassData(&bc->base->baseclasses); |
29 for (int k=0; k < bc->base->members->dim; k++) { | 28 for (int k=0; k < bc->base->members->dim; k++) { |
30 Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); | 29 Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); |
31 if (dsym->isVarDeclaration()) | 30 if (dsym->isVarDeclaration()) |
36 } | 35 } |
37 } | 36 } |
38 | 37 |
39 ////////////////////////////////////////////////////////////////////////////////////////// | 38 ////////////////////////////////////////////////////////////////////////////////////////// |
40 | 39 |
41 void DtoDeclareClass(ClassDeclaration* cd) | 40 void DtoResolveClass(ClassDeclaration* cd) |
42 { | 41 { |
43 if (cd->llvmTouched) return; | 42 if (cd->llvmResolved) return; |
44 cd->llvmTouched = true; | 43 cd->llvmResolved = true; |
45 | 44 |
46 Logger::println("DtoDeclareClass(%s)\n", cd->toPrettyChars()); | 45 // first resolve the base class |
46 if (cd->baseClass) { | |
47 DtoResolveClass(cd->baseClass); | |
48 } | |
49 | |
50 Logger::println("DtoResolveClass(%s)", cd->toPrettyChars()); | |
47 LOG_SCOPE; | 51 LOG_SCOPE; |
48 | 52 |
49 assert(cd->type->ty == Tclass); | 53 assert(cd->type->ty == Tclass); |
50 TypeClass* ts = (TypeClass*)cd->type; | 54 TypeClass* ts = (TypeClass*)cd->type; |
51 | 55 |
55 | 59 |
56 gIR->structs.push_back(irstruct); | 60 gIR->structs.push_back(irstruct); |
57 gIR->classes.push_back(cd); | 61 gIR->classes.push_back(cd); |
58 | 62 |
59 // add vtable | 63 // add vtable |
60 llvm::PATypeHolder pa = llvm::OpaqueType::get(); | 64 ts->llvmVtblType = new llvm::PATypeHolder(llvm::OpaqueType::get()); |
61 const llvm::Type* vtabty = llvm::PointerType::get(pa); | 65 const llvm::Type* vtabty = llvm::PointerType::get(ts->llvmVtblType->get()); |
62 | 66 |
63 std::vector<const llvm::Type*> fieldtypes; | 67 std::vector<const llvm::Type*> fieldtypes; |
64 fieldtypes.push_back(vtabty); | 68 fieldtypes.push_back(vtabty); |
65 | 69 |
66 // base classes first | 70 // base classes first |
78 } | 82 } |
79 | 83 |
80 const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); | 84 const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); |
81 // refine abstract types for stuff like: class C {C next;} | 85 // refine abstract types for stuff like: class C {C next;} |
82 assert(irstruct->recty != 0); | 86 assert(irstruct->recty != 0); |
83 { | 87 |
84 llvm::PATypeHolder& spa = irstruct->recty; | 88 llvm::PATypeHolder& spa = irstruct->recty; |
85 llvm::cast<llvm::OpaqueType>(spa.get())->refineAbstractTypeTo(structtype); | 89 llvm::cast<llvm::OpaqueType>(spa.get())->refineAbstractTypeTo(structtype); |
86 structtype = isaStruct(spa.get()); | 90 structtype = isaStruct(spa.get()); |
87 } | 91 |
88 | |
89 // create the type | |
90 ts->llvmType = new llvm::PATypeHolder(structtype); | 92 ts->llvmType = new llvm::PATypeHolder(structtype); |
91 | 93 |
92 bool needs_definition = false; | 94 bool needs_definition = false; |
93 if (cd->parent->isModule()) { | 95 if (cd->parent->isModule()) { |
94 gIR->module->addTypeName(cd->mangle(), ts->llvmType->get()); | 96 gIR->module->addTypeName(cd->mangle(), ts->llvmType->get()); |
98 assert(0 && "class parent is not a module"); | 100 assert(0 && "class parent is not a module"); |
99 } | 101 } |
100 | 102 |
101 // generate vtable | 103 // generate vtable |
102 llvm::GlobalVariable* svtblVar = 0; | 104 llvm::GlobalVariable* svtblVar = 0; |
103 std::vector<llvm::Constant*> sinits; | |
104 std::vector<const llvm::Type*> sinits_ty; | 105 std::vector<const llvm::Type*> sinits_ty; |
105 sinits.reserve(cd->vtbl.dim); | |
106 sinits_ty.reserve(cd->vtbl.dim); | |
107 | 106 |
108 for (int k=0; k < cd->vtbl.dim; k++) | 107 for (int k=0; k < cd->vtbl.dim; k++) |
109 { | 108 { |
110 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; | 109 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; |
111 assert(dsym); | 110 assert(dsym); |
112 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; | 111 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; |
113 | 112 |
114 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { | 113 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { |
115 fd->toObjFile(); | 114 DtoResolveFunction(fd); |
115 assert(fd->type->ty == Tfunction); | |
116 TypeFunction* tf = (TypeFunction*)fd->type; | |
117 const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get()); | |
118 sinits_ty.push_back(fpty); | |
119 } | |
120 else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { | |
121 const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
122 sinits_ty.push_back(cty); | |
123 } | |
124 else | |
125 assert(0); | |
126 } | |
127 | |
128 assert(!sinits_ty.empty()); | |
129 const llvm::StructType* svtbl_ty = llvm::StructType::get(sinits_ty); | |
130 | |
131 std::string styname(cd->mangle()); | |
132 styname.append("__vtblType"); | |
133 gIR->module->addTypeName(styname, svtbl_ty); | |
134 | |
135 // refine for final vtable type | |
136 llvm::cast<llvm::OpaqueType>(ts->llvmVtblType->get())->refineAbstractTypeTo(svtbl_ty); | |
137 | |
138 gIR->classes.pop_back(); | |
139 gIR->structs.pop_back(); | |
140 | |
141 gIR->declareList.push_back(cd); | |
142 } | |
143 | |
144 ////////////////////////////////////////////////////////////////////////////////////////// | |
145 | |
146 void DtoDeclareClass(ClassDeclaration* cd) | |
147 { | |
148 if (cd->llvmDeclared) return; | |
149 cd->llvmDeclared = true; | |
150 | |
151 Logger::println("DtoDeclareClass(%s)", cd->toPrettyChars()); | |
152 LOG_SCOPE; | |
153 | |
154 assert(cd->type->ty == Tclass); | |
155 TypeClass* ts = (TypeClass*)cd->type; | |
156 | |
157 assert(cd->llvmIRStruct); | |
158 IRStruct* irstruct = cd->llvmIRStruct; | |
159 | |
160 gIR->structs.push_back(irstruct); | |
161 gIR->classes.push_back(cd); | |
162 | |
163 bool needs_definition = false; | |
164 if (cd->parent->isModule()) { | |
165 needs_definition = (cd->getModule() == gIR->dmodule); | |
166 } | |
167 | |
168 // vtable | |
169 std::string varname("_D"); | |
170 varname.append(cd->mangle()); | |
171 varname.append("6__vtblZ"); | |
172 | |
173 std::string styname(cd->mangle()); | |
174 styname.append("__vtblTy"); | |
175 | |
176 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; | |
177 | |
178 const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); | |
179 cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); | |
180 | |
181 // init | |
182 std::string initname("_D"); | |
183 initname.append(cd->mangle()); | |
184 initname.append("6__initZ"); | |
185 | |
186 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module); | |
187 ts->llvmInit = initvar; | |
188 | |
189 gIR->classes.pop_back(); | |
190 gIR->structs.pop_back(); | |
191 | |
192 gIR->constInitList.push_back(cd); | |
193 if (needs_definition) | |
194 gIR->defineList.push_back(cd); | |
195 } | |
196 | |
197 ////////////////////////////////////////////////////////////////////////////////////////// | |
198 | |
199 void DtoConstInitClass(ClassDeclaration* cd) | |
200 { | |
201 if (cd->llvmInitialized) return; | |
202 cd->llvmInitialized = true; | |
203 | |
204 Logger::println("DtoConstInitClass(%s)", cd->toPrettyChars()); | |
205 LOG_SCOPE; | |
206 | |
207 IRStruct* irstruct = cd->llvmIRStruct; | |
208 gIR->structs.push_back(irstruct); | |
209 gIR->classes.push_back(cd); | |
210 | |
211 // make sure each offset knows its default initializer | |
212 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) | |
213 { | |
214 IRStruct::Offset* so = &i->second; | |
215 llvm::Constant* finit = DtoConstFieldInitializer(so->var->type, so->var->init); | |
216 so->init = finit; | |
217 so->var->llvmConstInit = finit; | |
218 } | |
219 | |
220 // fill out fieldtypes/inits | |
221 std::vector<llvm::Constant*> fieldinits; | |
222 | |
223 // first field is always the vtable | |
224 assert(cd->llvmVtbl != 0); | |
225 fieldinits.push_back(cd->llvmVtbl); | |
226 | |
227 // rest | |
228 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | |
229 Logger::println("adding fieldinit for: %s", i->second.var->toChars()); | |
230 fieldinits.push_back(i->second.init); | |
231 } | |
232 | |
233 // get the struct (class) type | |
234 assert(cd->type->ty == Tclass); | |
235 TypeClass* ts = (TypeClass*)cd->type; | |
236 const llvm::StructType* structtype = isaStruct(ts->llvmType->get()); | |
237 | |
238 // generate initializer | |
239 Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n'; | |
240 | |
241 for(size_t i=0; i<structtype->getNumElements(); ++i) { | |
242 Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n'; | |
243 } | |
244 | |
245 for(size_t i=0; i<fieldinits.size(); ++i) { | |
246 Logger::cout() << "i#" << i << " = " << *fieldinits[i]->getType() << '\n'; | |
247 } | |
248 | |
249 llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits); | |
250 assert(_init); | |
251 cd->llvmInitZ = _init; | |
252 | |
253 // generate vtable initializer | |
254 std::vector<llvm::Constant*> sinits; | |
255 | |
256 for (int k=0; k < cd->vtbl.dim; k++) | |
257 { | |
258 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; | |
259 assert(dsym); | |
260 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; | |
261 | |
262 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { | |
263 DtoForceDeclareDsymbol(fd); | |
116 assert(fd->llvmValue); | 264 assert(fd->llvmValue); |
117 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); | 265 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); |
118 sinits.push_back(c); | 266 sinits.push_back(c); |
119 sinits_ty.push_back(c->getType()); | |
120 } | 267 } |
121 else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { | 268 else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { |
122 const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty); | 269 const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty); |
123 llvm::Constant* c = llvm::Constant::getNullValue(cty); | 270 llvm::Constant* c = llvm::Constant::getNullValue(cty); |
124 sinits.push_back(c); | 271 sinits.push_back(c); |
125 sinits_ty.push_back(cty); | |
126 } | 272 } |
127 else | 273 else |
128 assert(0); | 274 assert(0); |
129 } | 275 } |
130 | 276 |
131 const llvm::StructType* svtbl_ty = 0; | 277 const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); |
132 if (!sinits.empty()) | 278 |
133 { | 279 /*for (size_t i=0; i< sinits.size(); ++i) |
134 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; | 280 { |
135 | 281 Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n'; |
136 std::string varname("_D"); | 282 Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n'; |
137 varname.append(cd->mangle()); | 283 assert(svtbl_ty->getElementType(i) == sinits[i]->getType()); |
138 varname.append("6__vtblZ"); | 284 }*/ |
139 | 285 |
140 std::string styname(cd->mangle()); | 286 llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); |
141 styname.append("__vtblTy"); | 287 cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); |
142 | |
143 svtbl_ty = llvm::StructType::get(sinits_ty); | |
144 gIR->module->addTypeName(styname, svtbl_ty); | |
145 svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); | |
146 | |
147 cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits)); | |
148 if (needs_definition) | |
149 svtblVar->setInitializer(cd->llvmConstVtbl); | |
150 cd->llvmVtbl = svtblVar; | |
151 } | |
152 | |
153 // refine for final vtable type | |
154 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty); | |
155 | |
156 std::string initname("_D"); | |
157 initname.append(cd->mangle()); | |
158 initname.append("6__initZ"); | |
159 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; | |
160 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module); | |
161 ts->llvmInit = initvar; | |
162 | 288 |
163 gIR->classes.pop_back(); | 289 gIR->classes.pop_back(); |
164 gIR->structs.pop_back(); | 290 gIR->structs.pop_back(); |
165 | 291 |
166 gIR->constInitQueue.push_back(cd); | 292 DtoDeclareClassInfo(cd); |
167 if (needs_definition) | 293 } |
168 gIR->defineQueue.push_back(cd); | 294 |
169 } | 295 ////////////////////////////////////////////////////////////////////////////////////////// |
170 | 296 |
171 ////////////////////////////////////////////////////////////////////////////////////////// | 297 void DtoDefineClass(ClassDeclaration* cd) |
172 | 298 { |
173 void DtoConstInitClass(ClassDeclaration* cd) | 299 if (cd->llvmDefined) return; |
174 { | 300 cd->llvmDefined = true; |
175 IRStruct* irstruct = cd->llvmIRStruct; | 301 |
176 if (irstruct->constinited) return; | 302 Logger::println("DtoDefineClass(%s)", cd->toPrettyChars()); |
177 irstruct->constinited = true; | |
178 | |
179 Logger::println("DtoConstInitClass(%s)\n", cd->toPrettyChars()); | |
180 LOG_SCOPE; | 303 LOG_SCOPE; |
181 | |
182 gIR->structs.push_back(irstruct); | |
183 gIR->classes.push_back(cd); | |
184 | |
185 // make sure each offset knows its default initializer | |
186 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) | |
187 { | |
188 IRStruct::Offset* so = &i->second; | |
189 llvm::Constant* finit = DtoConstFieldInitializer(so->var->type, so->var->init); | |
190 so->init = finit; | |
191 so->var->llvmConstInit = finit; | |
192 } | |
193 | |
194 // fill out fieldtypes/inits | |
195 std::vector<llvm::Constant*> fieldinits; | |
196 | |
197 // first field is always the vtable | |
198 assert(cd->llvmVtbl != 0); | |
199 fieldinits.push_back(cd->llvmVtbl); | |
200 | |
201 // rest | |
202 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | |
203 fieldinits.push_back(i->second.init); | |
204 } | |
205 | 304 |
206 // get the struct (class) type | 305 // get the struct (class) type |
207 assert(cd->type->ty == Tclass); | 306 assert(cd->type->ty == Tclass); |
208 TypeClass* ts = (TypeClass*)cd->type; | 307 TypeClass* ts = (TypeClass*)cd->type; |
209 const llvm::StructType* structtype = isaStruct(ts->llvmType->get()); | |
210 | |
211 // generate initializer | |
212 Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n'; | |
213 Logger::println("%u %u fields", structtype->getNumElements(), fieldinits.size()); | |
214 llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits); | |
215 assert(_init); | |
216 cd->llvmInitZ = _init; | |
217 | |
218 gIR->classes.pop_back(); | |
219 gIR->structs.pop_back(); | |
220 } | |
221 | |
222 ////////////////////////////////////////////////////////////////////////////////////////// | |
223 | |
224 void DtoDefineClass(ClassDeclaration* cd) | |
225 { | |
226 IRStruct* irstruct = cd->llvmIRStruct; | |
227 if (irstruct->defined) return; | |
228 irstruct->defined = true; | |
229 | |
230 Logger::println("DtoDefineClass(%s)\n", cd->toPrettyChars()); | |
231 LOG_SCOPE; | |
232 | |
233 // get the struct (class) type | |
234 assert(cd->type->ty == Tclass); | |
235 TypeClass* ts = (TypeClass*)cd->type; | |
236 | 308 |
237 bool def = false; | 309 bool def = false; |
238 if (cd->parent->isModule() && cd->getModule() == gIR->dmodule) { | 310 if (cd->parent->isModule() && cd->getModule() == gIR->dmodule) { |
239 ts->llvmInit->setInitializer(cd->llvmInitZ); | 311 ts->llvmInit->setInitializer(cd->llvmInitZ); |
312 cd->llvmVtbl->setInitializer(cd->llvmConstVtbl); | |
240 def = true; | 313 def = true; |
241 } | 314 } |
242 | 315 |
243 // generate classinfo | 316 // generate classinfo |
244 DtoDeclareClassInfo(cd); | |
245 if (def) DtoDefineClassInfo(cd); | 317 if (def) DtoDefineClassInfo(cd); |
246 } | 318 } |
247 | 319 |
248 ////////////////////////////////////////////////////////////////////////////////////////// | 320 ////////////////////////////////////////////////////////////////////////////////////////// |
249 | 321 |
300 | 372 |
301 ////////////////////////////////////////////////////////////////////////////////////////// | 373 ////////////////////////////////////////////////////////////////////////////////////////// |
302 | 374 |
303 void DtoDeclareClassInfo(ClassDeclaration* cd) | 375 void DtoDeclareClassInfo(ClassDeclaration* cd) |
304 { | 376 { |
305 if (cd->llvmClass) | 377 if (cd->llvmClassDeclared) return; |
306 return; | 378 cd->llvmClassDeclared = true; |
307 | 379 |
308 Logger::println("CLASS INFO DECLARATION: %s", cd->toChars()); | 380 Logger::println("DtoDeclareClassInfo(%s)", cd->toChars()); |
309 LOG_SCOPE; | 381 LOG_SCOPE; |
310 | 382 |
311 ClassDeclaration* cinfo = ClassDeclaration::classinfo; | 383 ClassDeclaration* cinfo = ClassDeclaration::classinfo; |
312 cinfo->toObjFile(); | 384 DtoResolveClass(cinfo); |
313 | |
314 const llvm::Type* st = cinfo->type->llvmType->get(); | |
315 | 385 |
316 std::string gname("_D"); | 386 std::string gname("_D"); |
317 gname.append(cd->mangle()); | 387 gname.append(cd->mangle()); |
318 gname.append("7__ClassZ"); | 388 gname.append("7__ClassZ"); |
389 | |
390 const llvm::Type* st = cinfo->type->llvmType->get(); | |
319 | 391 |
320 cd->llvmClass = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module); | 392 cd->llvmClass = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module); |
321 } | 393 } |
322 | 394 |
323 void DtoDefineClassInfo(ClassDeclaration* cd) | 395 void DtoDefineClassInfo(ClassDeclaration* cd) |
337 // void *deallocator; | 409 // void *deallocator; |
338 // OffsetTypeInfo[] offTi; | 410 // OffsetTypeInfo[] offTi; |
339 // void *defaultConstructor; | 411 // void *defaultConstructor; |
340 // } | 412 // } |
341 | 413 |
342 if (cd->llvmClassZ) | 414 if (cd->llvmClassDefined) return; |
343 return; | 415 cd->llvmClassDefined = true; |
344 | 416 |
345 Logger::println("CLASS INFO DEFINITION: %s", cd->toChars()); | 417 Logger::println("DtoDefineClassInfo(%s)", cd->toChars()); |
346 LOG_SCOPE; | 418 LOG_SCOPE; |
419 | |
420 assert(cd->type->ty == Tclass); | |
347 assert(cd->llvmClass); | 421 assert(cd->llvmClass); |
422 assert(cd->llvmInitZ); | |
423 assert(cd->llvmVtbl); | |
424 assert(cd->llvmConstVtbl); | |
425 | |
426 TypeClass* cdty = (TypeClass*)cd->type; | |
427 assert(cdty->llvmInit); | |
348 | 428 |
349 // holds the list of initializers for llvm | 429 // holds the list of initializers for llvm |
350 std::vector<llvm::Constant*> inits; | 430 std::vector<llvm::Constant*> inits; |
351 | 431 |
352 ClassDeclaration* cinfo = ClassDeclaration::classinfo; | 432 ClassDeclaration* cinfo = ClassDeclaration::classinfo; |
353 DtoConstInitClass(cinfo); | 433 DtoForceConstInitDsymbol(cinfo); |
354 assert(cinfo->llvmInitZ); | 434 assert(cinfo->llvmInitZ); |
355 | 435 |
356 llvm::Constant* c; | 436 llvm::Constant* c; |
357 | 437 |
358 // own vtable | 438 // own vtable |
361 inits.push_back(c); | 441 inits.push_back(c); |
362 | 442 |
363 // monitor | 443 // monitor |
364 // TODO no monitors yet | 444 // TODO no monitors yet |
365 | 445 |
366 // initializer | 446 // byte[] init |
367 c = cinfo->llvmInitZ->getOperand(1); | 447 const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty); |
448 c = llvm::ConstantExpr::getBitCast(cdty->llvmInit, byteptrty); | |
449 assert(!cd->llvmInitZ->getType()->isAbstract()); | |
450 size_t initsz = gTargetData->getTypeSize(cd->llvmInitZ->getType()); | |
451 c = DtoConstSlice(DtoConstSize_t(initsz), c); | |
368 inits.push_back(c); | 452 inits.push_back(c); |
369 | 453 |
370 // class name | 454 // class name |
371 // from dmd | 455 // from dmd |
372 char *name = cd->ident->toChars(); | 456 char *name = cd->ident->toChars(); |
378 } | 462 } |
379 c = DtoConstString(name); | 463 c = DtoConstString(name); |
380 inits.push_back(c); | 464 inits.push_back(c); |
381 | 465 |
382 // vtbl array | 466 // vtbl array |
383 c = cinfo->llvmInitZ->getOperand(3); | 467 const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty); |
468 assert(!cd->llvmVtbl->getType()->isAbstract()); | |
469 c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty); | |
470 assert(!cd->llvmConstVtbl->getType()->isAbstract()); | |
471 size_t vtblsz = gTargetData->getTypeSize(cd->llvmConstVtbl->getType()); | |
472 c = DtoConstSlice(DtoConstSize_t(vtblsz), c); | |
384 inits.push_back(c); | 473 inits.push_back(c); |
385 | 474 |
386 // interfaces array | 475 // interfaces array |
476 // TODO | |
387 c = cinfo->llvmInitZ->getOperand(4); | 477 c = cinfo->llvmInitZ->getOperand(4); |
388 inits.push_back(c); | 478 inits.push_back(c); |
389 | 479 |
390 // base classinfo | 480 // base classinfo |
391 c = cinfo->llvmInitZ->getOperand(5); | 481 if (cd->baseClass) { |
392 inits.push_back(c); | 482 DtoDeclareClassInfo(cd->baseClass); |
483 c = cd->baseClass->llvmClass; | |
484 assert(c); | |
485 inits.push_back(c); | |
486 } | |
487 else { | |
488 // null | |
489 c = cinfo->llvmInitZ->getOperand(5); | |
490 inits.push_back(c); | |
491 } | |
393 | 492 |
394 // destructor | 493 // destructor |
494 // TODO | |
395 c = cinfo->llvmInitZ->getOperand(6); | 495 c = cinfo->llvmInitZ->getOperand(6); |
396 inits.push_back(c); | 496 inits.push_back(c); |
397 | 497 |
398 // invariant | 498 // invariant |
499 // TODO | |
399 c = cinfo->llvmInitZ->getOperand(7); | 500 c = cinfo->llvmInitZ->getOperand(7); |
400 inits.push_back(c); | 501 inits.push_back(c); |
401 | 502 |
402 // flags | 503 // uint flags, adapted from original dmd code |
403 c = cinfo->llvmInitZ->getOperand(8); | 504 uint flags = 0; |
505 //flags |= 4; // has offTi | |
506 //flags |= isCOMclass(); // IUnknown | |
507 if (cd->ctor) flags |= 8; | |
508 for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass) | |
509 { | |
510 if (cd2->members) | |
511 { | |
512 for (size_t i = 0; i < cd2->members->dim; i++) | |
513 { | |
514 Dsymbol *sm = (Dsymbol *)cd2->members->data[i]; | |
515 //printf("sm = %s %s\n", sm->kind(), sm->toChars()); | |
516 if (sm->hasPointers()) | |
517 goto L2; | |
518 } | |
519 } | |
520 } | |
521 flags |= 2; // no pointers | |
522 L2: | |
523 c = DtoConstUint(flags); | |
404 inits.push_back(c); | 524 inits.push_back(c); |
405 | 525 |
406 // allocator | 526 // allocator |
527 // TODO | |
407 c = cinfo->llvmInitZ->getOperand(9); | 528 c = cinfo->llvmInitZ->getOperand(9); |
408 inits.push_back(c); | 529 inits.push_back(c); |
409 | 530 |
410 // offset typeinfo | 531 // offset typeinfo |
532 // TODO | |
411 c = cinfo->llvmInitZ->getOperand(10); | 533 c = cinfo->llvmInitZ->getOperand(10); |
412 inits.push_back(c); | 534 inits.push_back(c); |
413 | 535 |
414 // default constructor | 536 // default constructor |
537 // TODO | |
415 c = cinfo->llvmInitZ->getOperand(11); | 538 c = cinfo->llvmInitZ->getOperand(11); |
416 inits.push_back(c); | 539 inits.push_back(c); |
417 | 540 |
418 /*size_t n = inits.size(); | 541 /*size_t n = inits.size(); |
419 for (size_t i=0; i<n; ++i) | 542 for (size_t i=0; i<n; ++i) |