Mercurial > projects > ldc
diff gen/classes.cpp @ 136:0e28624814e8 trunk
[svn r140] did a lot of the work towards being able to pass multiple modules on the command line. not complete yet though
author | lindquist |
---|---|
date | Thu, 17 Jan 2008 03:15:12 +0100 |
parents | 44a95ac7368a |
children | ce7b81fb957f |
line wrap: on
line diff
--- a/gen/classes.cpp Mon Jan 14 23:09:55 2008 +0100 +++ b/gen/classes.cpp Thu Jan 17 03:15:12 2008 +0100 @@ -16,6 +16,8 @@ #include "gen/runtime.h" #include "gen/dvalue.h" +#include "ir/irstruct.h" + ////////////////////////////////////////////////////////////////////////////////////////// static void LLVM_AddBaseClassData(BaseClasses* bcs) @@ -24,9 +26,8 @@ for (int j=0; j<bcs->dim; j++) { BaseClass* bc = (BaseClass*)(bcs->data[j]); - assert(bc); if (bc->base->isInterfaceDeclaration()) - continue; // interfaces only has methods + continue; // interfaces only have methods LLVM_AddBaseClassData(&bc->base->baseclasses); @@ -38,14 +39,6 @@ VarDeclaration* v = (VarDeclaration*)(arr->data[k]); v->toObjFile(); } - - /*for (int k=0; k < bc->base->members->dim; k++) { - Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); - if (dsym->isVarDeclaration()) - { - dsym->toObjFile(); - } - }*/ } } @@ -63,11 +56,11 @@ assert(cd->type->ty == Tclass); TypeClass* ts = (TypeClass*)cd->type; - // make sure the IRStruct is created - IRStruct* irstruct = cd->llvmIRStruct; + // make sure the IrStruct is created + IrStruct* irstruct = cd->llvmIrStruct; if (!irstruct) { - irstruct = new IRStruct(ts); - cd->llvmIRStruct = irstruct; + irstruct = new IrStruct(ts); + cd->llvmIrStruct = irstruct; } // resolve the base class @@ -75,7 +68,7 @@ DtoResolveClass(cd->baseClass); } - // resolve interfaces + // resolve interface vtables if (cd->vtblInterfaces) { for (int i=0; i < cd->vtblInterfaces->dim; i++) { BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i]; @@ -111,7 +104,7 @@ fieldtypes.push_back(ivtblTy); // add this interface to the map - IRInterface* iri = new IRInterface(b, isaStruct(itc->llvmVtblType->get())); + IrInterface* iri = new IrInterface(b, isaStruct(itc->llvmVtblType->get())); irstruct->interfaces.insert(std::make_pair(id, iri)); } @@ -140,14 +133,14 @@ VarDeclaration* fieldinit = NULL; size_t fieldpad = 0; int idx = 0; - for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { + for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { // first iteration if (lastoffset == (unsigned)-1) { lastoffset = i->first; fieldtype = i->second.type; fieldinit = i->second.var; prevsize = getABITypeSize(fieldtype); - i->second.var->llvmFieldIndex = idx; + i->second.var->irField->index = idx; } // colliding offset? else if (lastoffset == i->first) { @@ -157,15 +150,15 @@ prevsize = s; } cd->llvmHasUnions = true; - i->second.var->llvmFieldIndex = idx; + i->second.var->irField->index = idx; } // intersecting offset? else if (i->first < (lastoffset + prevsize)) { size_t s = getABITypeSize(i->second.type); assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size cd->llvmHasUnions = true; - i->second.var->llvmFieldIndex = idx; - i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s; + i->second.var->irField->index = idx; + i->second.var->irField->indexOffset = (i->first - lastoffset) / s; } // fresh offset else { @@ -185,7 +178,7 @@ fieldtype = i->second.type; fieldinit = i->second.var; prevsize = getABITypeSize(fieldtype); - i->second.var->llvmFieldIndex = idx; + i->second.var->irField->index = idx; fieldpad = 0; } } @@ -199,7 +192,7 @@ /* // add field types - for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { + for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { fieldtypes.push_back(i->second.type); } */ @@ -307,8 +300,8 @@ assert(cd->type->ty == Tclass); TypeClass* ts = (TypeClass*)cd->type; - assert(cd->llvmIRStruct); - IRStruct* irstruct = cd->llvmIRStruct; + assert(cd->llvmIrStruct); + IrStruct* irstruct = cd->llvmIrStruct; gIR->structs.push_back(irstruct); gIR->classes.push_back(cd); @@ -318,56 +311,45 @@ needs_definition = true; } - // interface vtables are emitted by the class implementing them - // also, interfaces have no static initializer - // also, abstract classes have no vtable + llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; + + // interfaces have no static initializer + // same goes for abstract classes if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { // vtable std::string varname("_D"); varname.append(cd->mangle()); varname.append("6__vtblZ"); - llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; - const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); + } - // build interface info type - std::vector<const llvm::Type*> types; - // ClassInfo classinfo - ClassDeclaration* cd2 = ClassDeclaration::classinfo; - DtoResolveClass(cd2); - types.push_back(getPtrToType(cd2->type->llvmType->get())); - // void*[] vtbl - std::vector<const llvm::Type*> vtbltypes; - vtbltypes.push_back(DtoSize_t()); - const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); - vtbltypes.push_back(byteptrptrty); - types.push_back(llvm::StructType::get(vtbltypes)); - // int offset - types.push_back(llvm::Type::Int32Ty); - // create type - const llvm::StructType* infoTy = llvm::StructType::get(types); + // get interface info type + const llvm::StructType* infoTy = DtoInterfaceInfoType(); - // interface info array - if (cd->vtblInterfaces->dim > 0) { - // symbol name - std::string nam = "_D"; - nam.append(cd->mangle()); - nam.append("16__interfaceInfosZ"); - // resolve array type - const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->vtblInterfaces->dim); - // declare global - irstruct->interfaceInfosTy = arrTy; - irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module); - } + // interface info array + if (cd->vtblInterfaces->dim > 0) { + // symbol name + std::string nam = "_D"; + nam.append(cd->mangle()); + nam.append("16__interfaceInfosZ"); + // resolve array type + const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->vtblInterfaces->dim); + // declare global + irstruct->interfaceInfosTy = arrTy; + irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module); + } + // interfaces have no static initializer + // same goes for abstract classes + if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { // interface vtables unsigned idx = 0; - for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) + for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) { ClassDeclaration* id = i->first; - IRInterface* iri = i->second; + IrInterface* iri = i->second; std::string nam("_D"); nam.append(cd->mangle()); @@ -377,7 +359,6 @@ assert(iri->vtblTy); iri->vtbl = new llvm::GlobalVariable(iri->vtblTy, true, _linkage, 0, nam, gIR->module); - iri->infoTy = infoTy; llvm::Constant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)}; iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2); idx++; @@ -420,7 +401,7 @@ Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); LOG_SCOPE; - IRStruct* irstruct = cd->llvmIRStruct; + IrStruct* irstruct = cd->llvmIrStruct; gIR->structs.push_back(irstruct); gIR->classes.push_back(cd); @@ -431,12 +412,12 @@ const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get()); // make sure each offset knows its default initializer - for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) + for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { - IRStruct::Offset* so = &i->second; + IrStruct::Offset* so = &i->second; llvm::Constant* finit = DtoConstFieldInitializer(so->var->type, so->var->init); so->init = finit; - so->var->llvmConstInit = finit; + so->var->irField->constInit = finit; } // fill out fieldtypes/inits @@ -465,9 +446,11 @@ size_t dataoffset = 2; // next comes interface vtables - for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) + const llvm::StructType* infoTy = DtoInterfaceInfoType(); + for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) { - IRInterface* iri = i->second; + IrInterface* iri = i->second; + iri->infoTy = infoTy; if (cd->isAbstract()) { fieldinits.push_back(llvm::Constant::getNullValue(iri->vtblTy)); @@ -482,7 +465,7 @@ /* // rest - for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { + for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { Logger::println("adding fieldinit for: %s", i->second.var->toChars()); fieldinits.push_back(i->second.init); } @@ -493,7 +476,7 @@ for (size_t i=0; i<nfi; ++i) { llvm::Constant* c; if (irstruct->defaultFields[i] != NULL) { - c = irstruct->defaultFields[i]->llvmConstInit; + c = irstruct->defaultFields[i]->irField->constInit; assert(c); } else { @@ -535,8 +518,8 @@ if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { DtoForceDeclareDsymbol(fd); - assert(fd->llvmValue); - llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); + assert(fd->irFunc->func); + llvm::Constant* c = llvm::cast<llvm::Constant>(fd->irFunc->func); // cast if necessary (overridden method) if (c->getType() != vtbltype->getElementType(k)) c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k)); @@ -568,30 +551,34 @@ // create interface vtable const initalizers int idx = 2; int idxScale = PTRSIZE; - for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) + for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) { ClassDeclaration* id = i->first; assert(id->type->ty == Tclass); TypeClass* its = (TypeClass*)id->type; - IRInterface* iri = i->second; + IrInterface* iri = i->second; BaseClass* b = iri->base; const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get()); // generate interface info initializer std::vector<llvm::Constant*> infoInits; + // classinfo assert(id->llvmClass); llvm::Constant* c = id->llvmClass; infoInits.push_back(c); + // vtbl const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty); c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c); infoInits.push_back(c); + // offset infoInits.push_back(DtoConstInt(idx*idxScale)); + // create interface info initializer constant iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); @@ -608,8 +595,9 @@ FuncDeclaration* fd = dsym->isFuncDeclaration(); assert(fd); DtoForceDeclareDsymbol(fd); - assert(fd->llvmValue); - llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); + assert(fd->irFunc->func); + llvm::Constant* c = llvm::cast<llvm::Constant>(fd->irFunc->func); + // we have to bitcast, as the type created in ResolveClass expects a different this type c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k)); iinits.push_back(c); @@ -629,7 +617,39 @@ idx++; } - } // !abstract + } + // we always generate interfaceinfos as best we can + else + { + for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) + { + ClassDeclaration* id = i->first; + assert(id->type->ty == Tclass); + TypeClass* its = (TypeClass*)id->type; + + IrInterface* iri = i->second; + BaseClass* b = iri->base; + + // generate interface info initializer + std::vector<llvm::Constant*> infoInits; + + // classinfo + assert(id->llvmClass); + llvm::Constant* c = id->llvmClass; + infoInits.push_back(c); + + // vtbl + const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); + c = DtoConstSlice(DtoConstSize_t(0), getNullPtr(byteptrptrty)); + infoInits.push_back(c); + + // offset + infoInits.push_back(DtoConstInt(0)); + + // create interface info initializer constant + iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); + } + } gIR->classes.pop_back(); gIR->structs.pop_back(); @@ -658,11 +678,11 @@ cd->llvmVtbl->setInitializer(cd->llvmConstVtbl); // initialize interface vtables - IRStruct* irstruct = cd->llvmIRStruct; + IrStruct* irstruct = cd->llvmIrStruct; std::vector<llvm::Constant*> infoInits; - for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) + for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) { - IRInterface* iri = i->second; + IrInterface* iri = i->second; iri->vtbl->setInitializer(iri->vtblInit); infoInits.push_back(iri->infoInit); } @@ -711,7 +731,7 @@ LOG_SCOPE; DValue* thisval = newexp->thisexp->toElem(gIR); size_t idx = 2; - idx += tc->sym->llvmIRStruct->interfaces.size(); + idx += tc->sym->llvmIrStruct->interfaces.size(); llvm::Value* dst = thisval->getRVal(); llvm::Value* src = DtoGEPi(mem,0,idx,"tmp"); Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; @@ -723,10 +743,10 @@ Logger::println("Resolving nested context"); LOG_SCOPE; size_t idx = 2; - idx += tc->sym->llvmIRStruct->interfaces.size(); - llvm::Value* nest = gIR->func()->decl->llvmNested; + idx += tc->sym->llvmIrStruct->interfaces.size(); + llvm::Value* nest = gIR->func()->decl->irFunc->nestedVar; if (!nest) - nest = gIR->func()->decl->llvmThisVar; + nest = gIR->func()->decl->irFunc->thisVar; assert(nest); llvm::Value* gep = DtoGEPi(mem,0,idx,"tmp"); nest = DtoBitCast(nest, gep->getType()->getContainedType(0)); @@ -792,7 +812,7 @@ assert(ctor); DtoForceDeclareDsymbol(ctor); - llvm::Function* fn = llvm::cast<llvm::Function>(ctor->llvmValue); + llvm::Function* fn = ctor->irFunc->func; TypeFunction* tf = (TypeFunction*)DtoDType(ctor->type); std::vector<llvm::Value*> ctorargs; @@ -822,8 +842,8 @@ for (size_t i=0; i<arr->dim; i++) { FuncDeclaration* fd = (FuncDeclaration*)arr->data[i]; - assert(fd->llvmValue); - new llvm::CallInst(fd->llvmValue, instance, "", gIR->scopebb()); + assert(fd->irFunc->func); + new llvm::CallInst(fd->irFunc->func, instance, "", gIR->scopebb()); } } @@ -1031,37 +1051,37 @@ unsigned dataoffset = 2 + cd->vtblInterfaces->dim; - IRStruct* irstruct = cd->llvmIRStruct; - for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { + IrStruct* irstruct = cd->llvmIrStruct; + for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { //for (unsigned i=0; i<cd->fields.dim; ++i) { //VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i]; VarDeclaration* vd = i->second.var; assert(vd); Type* vdtype = DtoDType(vd->type); Logger::println("found %u type %s", vd->offset, vdtype->toChars()); - assert(vd->llvmFieldIndex >= 0); + assert(vd->irField->index >= 0); if (os == vd->offset && vdtype == t) { - idxs.push_back(vd->llvmFieldIndex + dataoffset); + idxs.push_back(vd->irField->index + dataoffset); Logger::cout() << "indexing: " << *ptr << '\n'; ptr = DtoGEP(ptr, idxs, "tmp"); if (ptr->getType() != llt) ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); Logger::cout() << "indexing: " << *ptr << '\n'; - if (vd->llvmFieldIndexOffset) - ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); + if (vd->irField->indexOffset) + ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->irField->indexOffset), "tmp", gIR->scopebb()); Logger::cout() << "indexing: " << *ptr << '\n'; return ptr; } else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) { TypeStruct* ts = (TypeStruct*)vdtype; StructDeclaration* ssd = ts->sym; - idxs.push_back(vd->llvmFieldIndex + dataoffset); - if (vd->llvmFieldIndexOffset) { + idxs.push_back(vd->irField->index + dataoffset); + if (vd->irField->indexOffset) { Logger::println("has union field offset"); ptr = DtoGEP(ptr, idxs, "tmp"); if (ptr->getType() != llt) ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); - ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); + ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->irField->indexOffset), "tmp", gIR->scopebb()); std::vector<unsigned> tmp; return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); } @@ -1153,7 +1173,7 @@ vd->type->getTypeInfo(NULL); assert(vd->type->vtinfo); DtoForceDeclareDsymbol(vd->type->vtinfo); - llvm::Constant* c = isaConstant(vd->type->vtinfo->llvmValue); + llvm::Constant* c = isaConstant(vd->type->vtinfo->getIrValue()); const llvm::Type* tiTy = getPtrToType(Type::typeinfo->type->llvmType->get()); //Logger::cout() << "tiTy = " << *tiTy << '\n'; @@ -1230,8 +1250,8 @@ else if (cd->dtors.dim == 1) { DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[0]; DtoForceDeclareDsymbol(d); - assert(d->llvmValue); - return llvm::ConstantExpr::getBitCast(isaConstant(d->llvmValue), getPtrToType(llvm::Type::Int8Ty)); + assert(d->irFunc->func); + return llvm::ConstantExpr::getBitCast(isaConstant(d->irFunc->func), getPtrToType(llvm::Type::Int8Ty)); } std::string gname("_D"); @@ -1249,8 +1269,8 @@ { DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[i]; DtoForceDeclareDsymbol(d); - assert(d->llvmValue); - builder.CreateCall(d->llvmValue, thisptr); + assert(d->irFunc->func); + builder.CreateCall(d->irFunc->func, thisptr); } builder.CreateRetVoid(); @@ -1380,7 +1400,7 @@ inits.push_back(c); // interfaces array - IRStruct* irstruct = cd->llvmIRStruct; + IrStruct* irstruct = cd->llvmIrStruct; if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos || cd->isAbstract()) { c = cinfo->llvmConstInit->getOperand(5); } @@ -1446,7 +1466,7 @@ // default constructor if (cd->defaultCtor && !cd->isInterfaceDeclaration() && !cd->isAbstract()) { DtoForceDeclareDsymbol(cd->defaultCtor); - c = isaConstant(cd->defaultCtor->llvmValue); + c = isaConstant(cd->defaultCtor->irFunc->func); const llvm::Type* toTy = cinfo->llvmConstInit->getOperand(12)->getType(); c = llvm::ConstantExpr::getBitCast(c, toTy); }