comparison gen/classes.cpp @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents 7f9a0a58394b
children 44a95ac7368a
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
9 #include "gen/irstate.h" 9 #include "gen/irstate.h"
10 #include "gen/tollvm.h" 10 #include "gen/tollvm.h"
11 #include "gen/arrays.h" 11 #include "gen/arrays.h"
12 #include "gen/logger.h" 12 #include "gen/logger.h"
13 #include "gen/classes.h" 13 #include "gen/classes.h"
14 #include "gen/structs.h"
14 #include "gen/functions.h" 15 #include "gen/functions.h"
15 #include "gen/runtime.h" 16 #include "gen/runtime.h"
16 #include "gen/dvalue.h" 17 #include "gen/dvalue.h"
17 18
18 ////////////////////////////////////////////////////////////////////////////////////////// 19 //////////////////////////////////////////////////////////////////////////////////////////
30 LLVM_AddBaseClassData(&bc->base->baseclasses); 31 LLVM_AddBaseClassData(&bc->base->baseclasses);
31 32
32 Logger::println("Adding base class members of %s", bc->base->toChars()); 33 Logger::println("Adding base class members of %s", bc->base->toChars());
33 LOG_SCOPE; 34 LOG_SCOPE;
34 35
35 for (int k=0; k < bc->base->members->dim; k++) { 36 Array* arr = &bc->base->fields;
37 for (int k=0; k < arr->dim; k++) {
38 VarDeclaration* v = (VarDeclaration*)(arr->data[k]);
39 v->toObjFile();
40 }
41
42 /*for (int k=0; k < bc->base->members->dim; k++) {
36 Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); 43 Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
37 if (dsym->isVarDeclaration()) 44 if (dsym->isVarDeclaration())
38 { 45 {
39 dsym->toObjFile(); 46 dsym->toObjFile();
40 } 47 }
41 } 48 }*/
42 } 49 }
43 } 50 }
44 51
45 ////////////////////////////////////////////////////////////////////////////////////////// 52 //////////////////////////////////////////////////////////////////////////////////////////
46 53
63 // Fill in vtbl[] 70 // Fill in vtbl[]
64 b->fillVtbl(cd, &b->vtbl, 1); 71 b->fillVtbl(cd, &b->vtbl, 1);
65 } 72 }
66 } 73 }
67 74
68 Logger::println("DtoResolveClass(%s)", cd->toPrettyChars()); 75 Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
69 LOG_SCOPE; 76 LOG_SCOPE;
70 77
71 assert(cd->type->ty == Tclass); 78 assert(cd->type->ty == Tclass);
72 TypeClass* ts = (TypeClass*)cd->type; 79 TypeClass* ts = (TypeClass*)cd->type;
73 80
111 for (int k=0; k < cd->members->dim; k++) { 118 for (int k=0; k < cd->members->dim; k++) {
112 Dsymbol* dsym = (Dsymbol*)(cd->members->data[k]); 119 Dsymbol* dsym = (Dsymbol*)(cd->members->data[k]);
113 dsym->toObjFile(); 120 dsym->toObjFile();
114 } 121 }
115 122
123 // resolve class data fields (possibly unions)
124 Logger::println("doing class fields");
125
126 if (irstruct->offsets.empty())
127 {
128 Logger::println("has no fields");
129 }
130 else
131 {
132 Logger::println("has fields");
133 unsigned prevsize = (unsigned)-1;
134 unsigned lastoffset = (unsigned)-1;
135 const llvm::Type* fieldtype = NULL;
136 VarDeclaration* fieldinit = NULL;
137 size_t fieldpad = 0;
138 int idx = 0;
139 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
140 // first iteration
141 if (lastoffset == (unsigned)-1) {
142 lastoffset = i->first;
143 fieldtype = i->second.type;
144 fieldinit = i->second.var;
145 prevsize = gTargetData->getTypeSize(fieldtype);
146 i->second.var->llvmFieldIndex = idx;
147 }
148 // colliding offset?
149 else if (lastoffset == i->first) {
150 size_t s = gTargetData->getTypeSize(i->second.type);
151 if (s > prevsize) {
152 fieldpad += s - prevsize;
153 prevsize = s;
154 }
155 cd->llvmHasUnions = true;
156 i->second.var->llvmFieldIndex = idx;
157 }
158 // intersecting offset?
159 else if (i->first < (lastoffset + prevsize)) {
160 size_t s = gTargetData->getTypeSize(i->second.type);
161 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
162 cd->llvmHasUnions = true;
163 i->second.var->llvmFieldIndex = idx;
164 i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s;
165 }
166 // fresh offset
167 else {
168 // commit the field
169 fieldtypes.push_back(fieldtype);
170 irstruct->defaultFields.push_back(fieldinit);
171 if (fieldpad) {
172 fieldtypes.push_back(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad));
173 irstruct->defaultFields.push_back(NULL);
174 idx++;
175 }
176
177 idx++;
178
179 // start new
180 lastoffset = i->first;
181 fieldtype = i->second.type;
182 fieldinit = i->second.var;
183 prevsize = gTargetData->getTypeSize(fieldtype);
184 i->second.var->llvmFieldIndex = idx;
185 fieldpad = 0;
186 }
187 }
188 fieldtypes.push_back(fieldtype);
189 irstruct->defaultFields.push_back(fieldinit);
190 if (fieldpad) {
191 fieldtypes.push_back(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad));
192 irstruct->defaultFields.push_back(NULL);
193 }
194 }
195
196 /*
116 // add field types 197 // add field types
117 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { 198 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
118 fieldtypes.push_back(i->second.type); 199 fieldtypes.push_back(i->second.type);
119 } 200 }
201 */
120 202
121 const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); 203 const llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
122 // refine abstract types for stuff like: class C {C next;} 204 // refine abstract types for stuff like: class C {C next;}
123 assert(irstruct->recty != 0); 205 assert(irstruct->recty != 0);
124 206
212 void DtoDeclareClass(ClassDeclaration* cd) 294 void DtoDeclareClass(ClassDeclaration* cd)
213 { 295 {
214 if (cd->llvmDeclared) return; 296 if (cd->llvmDeclared) return;
215 cd->llvmDeclared = true; 297 cd->llvmDeclared = true;
216 298
217 Logger::println("DtoDeclareClass(%s)", cd->toPrettyChars()); 299 Logger::println("DtoDeclareClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
218 LOG_SCOPE; 300 LOG_SCOPE;
219 301
220 assert(cd->type->ty == Tclass); 302 assert(cd->type->ty == Tclass);
221 TypeClass* ts = (TypeClass*)cd->type; 303 TypeClass* ts = (TypeClass*)cd->type;
222 304
260 types.push_back(llvm::Type::Int32Ty); 342 types.push_back(llvm::Type::Int32Ty);
261 // create type 343 // create type
262 const llvm::StructType* infoTy = llvm::StructType::get(types); 344 const llvm::StructType* infoTy = llvm::StructType::get(types);
263 345
264 // interface info array 346 // interface info array
265 if (needs_definition && cd->vtblInterfaces->dim > 0) { 347 if (cd->vtblInterfaces->dim > 0) {
266 // symbol name 348 // symbol name
267 std::string nam = "_D"; 349 std::string nam = "_D";
268 nam.append(cd->mangle()); 350 nam.append(cd->mangle());
269 nam.append("16__interfaceInfosZ"); 351 nam.append("16__interfaceInfosZ");
270 // resolve array type 352 // resolve array type
271 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->vtblInterfaces->dim); 353 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->vtblInterfaces->dim);
272 // declare global 354 // declare global
273 irstruct->interfaceInfosTy = arrTy; 355 irstruct->interfaceInfosTy = arrTy;
274 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, llvm::GlobalValue::InternalLinkage, 0, nam, gIR->module); 356 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module);
275 } 357 }
276 358
277 // interface vtables 359 // interface vtables
278 unsigned idx = 0; 360 unsigned idx = 0;
279 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) 361 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
327 cd->llvmInitialized = true; 409 cd->llvmInitialized = true;
328 410
329 if (cd->isInterfaceDeclaration()) 411 if (cd->isInterfaceDeclaration())
330 return; // nothing to do 412 return; // nothing to do
331 413
332 Logger::println("DtoConstInitClass(%s)", cd->toPrettyChars()); 414 Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
333 LOG_SCOPE; 415 LOG_SCOPE;
334 416
335 IRStruct* irstruct = cd->llvmIRStruct; 417 IRStruct* irstruct = cd->llvmIRStruct;
336 gIR->structs.push_back(irstruct); 418 gIR->structs.push_back(irstruct);
337 gIR->classes.push_back(cd); 419 gIR->classes.push_back(cd);
353 fieldinits.push_back(cd->llvmVtbl); 435 fieldinits.push_back(cd->llvmVtbl);
354 436
355 // then comes monitor 437 // then comes monitor
356 fieldinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); 438 fieldinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)));
357 439
440 size_t dataoffset = 2;
441
358 // next comes interface vtables 442 // next comes interface vtables
359 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) 443 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
360 { 444 {
361 IRInterface* iri = i->second; 445 IRInterface* iri = i->second;
362 assert(iri->vtbl); 446 assert(iri->vtbl);
363 fieldinits.push_back(iri->vtbl); 447 fieldinits.push_back(iri->vtbl);
364 } 448 ++dataoffset;
365 449 }
450
451 /*
366 // rest 452 // rest
367 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { 453 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
368 Logger::println("adding fieldinit for: %s", i->second.var->toChars()); 454 Logger::println("adding fieldinit for: %s", i->second.var->toChars());
369 fieldinits.push_back(i->second.init); 455 fieldinits.push_back(i->second.init);
370 } 456 }
457 */
371 458
372 // get the struct (class) type 459 // get the struct (class) type
373 assert(cd->type->ty == Tclass); 460 assert(cd->type->ty == Tclass);
374 TypeClass* ts = (TypeClass*)cd->type; 461 TypeClass* ts = (TypeClass*)cd->type;
375 const llvm::StructType* structtype = isaStruct(ts->llvmType->get()); 462 const llvm::StructType* structtype = isaStruct(ts->llvmType->get());
376 const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get()); 463 const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get());
464
465 // go through the field inits and build the default initializer
466 size_t nfi = irstruct->defaultFields.size();
467 for (size_t i=0; i<nfi; ++i) {
468 llvm::Constant* c;
469 if (irstruct->defaultFields[i] != NULL) {
470 c = irstruct->defaultFields[i]->llvmConstInit;
471 assert(c);
472 }
473 else {
474 const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i+dataoffset));
475 std::vector<llvm::Constant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
476 c = llvm::ConstantArray::get(arrty, vals);
477 }
478 fieldinits.push_back(c);
479 }
377 480
378 // generate initializer 481 // generate initializer
379 #if 0 482 #if 0
380 Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n'; 483 Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n';
381 484
507 void DtoDefineClass(ClassDeclaration* cd) 610 void DtoDefineClass(ClassDeclaration* cd)
508 { 611 {
509 if (cd->llvmDefined) return; 612 if (cd->llvmDefined) return;
510 cd->llvmDefined = true; 613 cd->llvmDefined = true;
511 614
512 Logger::println("DtoDefineClass(%s)", cd->toPrettyChars()); 615 Logger::println("DtoDefineClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
513 LOG_SCOPE; 616 LOG_SCOPE;
514 617
515 // get the struct (class) type 618 // get the struct (class) type
516 assert(cd->type->ty == Tclass); 619 assert(cd->type->ty == Tclass);
517 TypeClass* ts = (TypeClass*)cd->type; 620 TypeClass* ts = (TypeClass*)cd->type;
696 ret = DtoBitCast(ret, DtoType(to)); 799 ret = DtoBitCast(ret, DtoType(to));
697 else 800 else
698 to = ClassDeclaration::object->type; 801 to = ClassDeclaration::object->type;
699 802
700 return new DImValue(to, ret); 803 return new DImValue(to, ret);
804 }
805
806 //////////////////////////////////////////////////////////////////////////////////////////
807
808 static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
809 {
810 // start at the bottom of the inheritance chain
811 if (cd->baseClass != 0) {
812 unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx);
813 if (o != (unsigned)-1)
814 return o;
815 }
816
817 // check this class
818 unsigned i;
819 for (i=0; i<cd->fields.dim; ++i) {
820 VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i];
821 if (os == vd->offset)
822 return i+idx;
823 }
824 idx += i;
825
826 return (unsigned)-1;
827 }
828
829 //////////////////////////////////////////////////////////////////////////////////////////
830
831 void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
832 {
833 unsigned idx = 0;
834 unsigned r = LLVM_ClassOffsetToIndex(this, os, idx);
835 assert(r != (unsigned)-1 && "Offset not found in any aggregate field");
836 // vtable is 0, monitor is 1
837 r += 2;
838 // interface offset further
839 r += vtblInterfaces->dim;
840 // the final index was not pushed
841 result.push_back(r);
842 }
843
844 //////////////////////////////////////////////////////////////////////////////////////////
845
846 llvm::Value* DtoIndexClass(llvm::Value* ptr, ClassDeclaration* cd, Type* t, unsigned os, std::vector<unsigned>& idxs)
847 {
848 Logger::println("checking for offset %u type %s:", os, t->toChars());
849 LOG_SCOPE;
850
851 if (idxs.empty())
852 idxs.push_back(0);
853
854 const llvm::Type* llt = llvm::PointerType::get(DtoType(t));
855 const llvm::Type* st = DtoType(cd->type);
856 if (ptr->getType() != st) {
857 assert(cd->llvmHasUnions);
858 ptr = gIR->ir->CreateBitCast(ptr, st, "tmp");
859 }
860
861 unsigned dataoffset = 2 + cd->vtblInterfaces->dim;
862
863 IRStruct* irstruct = cd->llvmIRStruct;
864 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
865 //for (unsigned i=0; i<cd->fields.dim; ++i) {
866 //VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i];
867 VarDeclaration* vd = i->second.var;
868 assert(vd);
869 Type* vdtype = DtoDType(vd->type);
870 Logger::println("found %u type %s", vd->offset, vdtype->toChars());
871 assert(vd->llvmFieldIndex >= 0);
872 if (os == vd->offset && vdtype == t) {
873 idxs.push_back(vd->llvmFieldIndex + dataoffset);
874 Logger::cout() << "indexing: " << *ptr << '\n';
875 ptr = DtoGEP(ptr, idxs, "tmp");
876 if (ptr->getType() != llt)
877 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
878 Logger::cout() << "indexing: " << *ptr << '\n';
879 if (vd->llvmFieldIndexOffset)
880 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
881 Logger::cout() << "indexing: " << *ptr << '\n';
882 return ptr;
883 }
884 else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
885 TypeStruct* ts = (TypeStruct*)vdtype;
886 StructDeclaration* ssd = ts->sym;
887 idxs.push_back(vd->llvmFieldIndex + dataoffset);
888 if (vd->llvmFieldIndexOffset) {
889 Logger::println("has union field offset");
890 ptr = DtoGEP(ptr, idxs, "tmp");
891 if (ptr->getType() != llt)
892 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
893 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
894 std::vector<unsigned> tmp;
895 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
896 }
897 else {
898 const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type));
899 if (ptr->getType() != sty) {
900 ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
901 std::vector<unsigned> tmp;
902 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
903 }
904 else {
905 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs);
906 }
907 }
908 }
909 }
910
911 assert(0);
912
913 size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
914 assert(os % llt_sz == 0);
915 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
916 return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
701 } 917 }
702 918
703 ////////////////////////////////////////////////////////////////////////////////////////// 919 //////////////////////////////////////////////////////////////////////////////////////////
704 920
705 void DtoDeclareClassInfo(ClassDeclaration* cd) 921 void DtoDeclareClassInfo(ClassDeclaration* cd)