Mercurial > projects > ldc
diff 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 |
line wrap: on
line diff
--- a/gen/classes.cpp Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/classes.cpp Sun Nov 18 06:52:57 2007 +0100 @@ -10,6 +10,7 @@ #include "gen/arrays.h" #include "gen/logger.h" #include "gen/classes.h" +#include "gen/functions.h" ////////////////////////////////////////////////////////////////////////////////////////// @@ -23,8 +24,6 @@ Logger::println("Adding base class members of %s", bc->base->toChars()); LOG_SCOPE; - bc->base->toObjFile(); - LLVM_AddBaseClassData(&bc->base->baseclasses); for (int k=0; k < bc->base->members->dim; k++) { Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); @@ -38,12 +37,17 @@ ////////////////////////////////////////////////////////////////////////////////////////// -void DtoDeclareClass(ClassDeclaration* cd) +void DtoResolveClass(ClassDeclaration* cd) { - if (cd->llvmTouched) return; - cd->llvmTouched = true; + if (cd->llvmResolved) return; + cd->llvmResolved = true; - Logger::println("DtoDeclareClass(%s)\n", cd->toPrettyChars()); + // first resolve the base class + if (cd->baseClass) { + DtoResolveClass(cd->baseClass); + } + + Logger::println("DtoResolveClass(%s)", cd->toPrettyChars()); LOG_SCOPE; assert(cd->type->ty == Tclass); @@ -57,8 +61,8 @@ gIR->classes.push_back(cd); // add vtable - llvm::PATypeHolder pa = llvm::OpaqueType::get(); - const llvm::Type* vtabty = llvm::PointerType::get(pa); + ts->llvmVtblType = new llvm::PATypeHolder(llvm::OpaqueType::get()); + const llvm::Type* vtabty = llvm::PointerType::get(ts->llvmVtblType->get()); std::vector<const llvm::Type*> fieldtypes; fieldtypes.push_back(vtabty); @@ -80,13 +84,11 @@ const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); // refine abstract types for stuff like: class C {C next;} assert(irstruct->recty != 0); - { + llvm::PATypeHolder& spa = irstruct->recty; llvm::cast<llvm::OpaqueType>(spa.get())->refineAbstractTypeTo(structtype); structtype = isaStruct(spa.get()); - } - // create the type ts->llvmType = new llvm::PATypeHolder(structtype); bool needs_definition = false; @@ -100,10 +102,7 @@ // generate vtable llvm::GlobalVariable* svtblVar = 0; - std::vector<llvm::Constant*> sinits; std::vector<const llvm::Type*> sinits_ty; - sinits.reserve(cd->vtbl.dim); - sinits_ty.reserve(cd->vtbl.dim); for (int k=0; k < cd->vtbl.dim; k++) { @@ -112,73 +111,100 @@ //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { - fd->toObjFile(); - assert(fd->llvmValue); - llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); - sinits.push_back(c); - sinits_ty.push_back(c->getType()); + DtoResolveFunction(fd); + assert(fd->type->ty == Tfunction); + TypeFunction* tf = (TypeFunction*)fd->type; + const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get()); + sinits_ty.push_back(fpty); } else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty); - llvm::Constant* c = llvm::Constant::getNullValue(cty); - sinits.push_back(c); sinits_ty.push_back(cty); } else assert(0); } - const llvm::StructType* svtbl_ty = 0; - if (!sinits.empty()) - { - llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; + assert(!sinits_ty.empty()); + const llvm::StructType* svtbl_ty = llvm::StructType::get(sinits_ty); + + std::string styname(cd->mangle()); + styname.append("__vtblType"); + gIR->module->addTypeName(styname, svtbl_ty); - std::string varname("_D"); - varname.append(cd->mangle()); - varname.append("6__vtblZ"); + // refine for final vtable type + llvm::cast<llvm::OpaqueType>(ts->llvmVtblType->get())->refineAbstractTypeTo(svtbl_ty); + + gIR->classes.pop_back(); + gIR->structs.pop_back(); + + gIR->declareList.push_back(cd); +} + +////////////////////////////////////////////////////////////////////////////////////////// - std::string styname(cd->mangle()); - styname.append("__vtblTy"); +void DtoDeclareClass(ClassDeclaration* cd) +{ + if (cd->llvmDeclared) return; + cd->llvmDeclared = true; + + Logger::println("DtoDeclareClass(%s)", cd->toPrettyChars()); + LOG_SCOPE; - svtbl_ty = llvm::StructType::get(sinits_ty); - gIR->module->addTypeName(styname, svtbl_ty); - svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); + assert(cd->type->ty == Tclass); + TypeClass* ts = (TypeClass*)cd->type; + + assert(cd->llvmIRStruct); + IRStruct* irstruct = cd->llvmIRStruct; - cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits)); - if (needs_definition) - svtblVar->setInitializer(cd->llvmConstVtbl); - cd->llvmVtbl = svtblVar; + gIR->structs.push_back(irstruct); + gIR->classes.push_back(cd); + + bool needs_definition = false; + if (cd->parent->isModule()) { + needs_definition = (cd->getModule() == gIR->dmodule); } - // refine for final vtable type - llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty); + // vtable + std::string varname("_D"); + varname.append(cd->mangle()); + varname.append("6__vtblZ"); + std::string styname(cd->mangle()); + styname.append("__vtblTy"); + + 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); + + // init std::string initname("_D"); initname.append(cd->mangle()); initname.append("6__initZ"); - llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; + llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module); ts->llvmInit = initvar; gIR->classes.pop_back(); gIR->structs.pop_back(); - gIR->constInitQueue.push_back(cd); + gIR->constInitList.push_back(cd); if (needs_definition) - gIR->defineQueue.push_back(cd); + gIR->defineList.push_back(cd); } ////////////////////////////////////////////////////////////////////////////////////////// void DtoConstInitClass(ClassDeclaration* cd) { - IRStruct* irstruct = cd->llvmIRStruct; - if (irstruct->constinited) return; - irstruct->constinited = true; + if (cd->llvmInitialized) return; + cd->llvmInitialized = true; - Logger::println("DtoConstInitClass(%s)\n", cd->toPrettyChars()); + Logger::println("DtoConstInitClass(%s)", cd->toPrettyChars()); LOG_SCOPE; + IRStruct* irstruct = cd->llvmIRStruct; gIR->structs.push_back(irstruct); gIR->classes.push_back(cd); @@ -200,6 +226,7 @@ // rest 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); } @@ -210,24 +237,69 @@ // generate initializer Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n'; - Logger::println("%u %u fields", structtype->getNumElements(), fieldinits.size()); + + for(size_t i=0; i<structtype->getNumElements(); ++i) { + Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n'; + } + + for(size_t i=0; i<fieldinits.size(); ++i) { + Logger::cout() << "i#" << i << " = " << *fieldinits[i]->getType() << '\n'; + } + llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits); assert(_init); cd->llvmInitZ = _init; + // generate vtable initializer + std::vector<llvm::Constant*> sinits; + + for (int k=0; k < cd->vtbl.dim; k++) + { + Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; + assert(dsym); + //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; + + if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { + DtoForceDeclareDsymbol(fd); + assert(fd->llvmValue); + llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); + sinits.push_back(c); + } + else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { + const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty); + llvm::Constant* c = llvm::Constant::getNullValue(cty); + sinits.push_back(c); + } + else + assert(0); + } + + const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); + + /*for (size_t i=0; i< sinits.size(); ++i) + { + Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n'; + Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n'; + assert(svtbl_ty->getElementType(i) == sinits[i]->getType()); + }*/ + + llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); + cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); + gIR->classes.pop_back(); gIR->structs.pop_back(); + + DtoDeclareClassInfo(cd); } ////////////////////////////////////////////////////////////////////////////////////////// void DtoDefineClass(ClassDeclaration* cd) { - IRStruct* irstruct = cd->llvmIRStruct; - if (irstruct->defined) return; - irstruct->defined = true; + if (cd->llvmDefined) return; + cd->llvmDefined = true; - Logger::println("DtoDefineClass(%s)\n", cd->toPrettyChars()); + Logger::println("DtoDefineClass(%s)", cd->toPrettyChars()); LOG_SCOPE; // get the struct (class) type @@ -237,11 +309,11 @@ bool def = false; if (cd->parent->isModule() && cd->getModule() == gIR->dmodule) { ts->llvmInit->setInitializer(cd->llvmInitZ); + cd->llvmVtbl->setInitializer(cd->llvmConstVtbl); def = true; } // generate classinfo - DtoDeclareClassInfo(cd); if (def) DtoDefineClassInfo(cd); } @@ -302,21 +374,21 @@ void DtoDeclareClassInfo(ClassDeclaration* cd) { - if (cd->llvmClass) - return; + if (cd->llvmClassDeclared) return; + cd->llvmClassDeclared = true; - Logger::println("CLASS INFO DECLARATION: %s", cd->toChars()); + Logger::println("DtoDeclareClassInfo(%s)", cd->toChars()); LOG_SCOPE; ClassDeclaration* cinfo = ClassDeclaration::classinfo; - cinfo->toObjFile(); - - const llvm::Type* st = cinfo->type->llvmType->get(); + DtoResolveClass(cinfo); std::string gname("_D"); gname.append(cd->mangle()); gname.append("7__ClassZ"); + const llvm::Type* st = cinfo->type->llvmType->get(); + cd->llvmClass = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module); } @@ -339,18 +411,26 @@ // void *defaultConstructor; // } - if (cd->llvmClassZ) - return; + if (cd->llvmClassDefined) return; + cd->llvmClassDefined = true; + + Logger::println("DtoDefineClassInfo(%s)", cd->toChars()); + LOG_SCOPE; - Logger::println("CLASS INFO DEFINITION: %s", cd->toChars()); - LOG_SCOPE; + assert(cd->type->ty == Tclass); assert(cd->llvmClass); + assert(cd->llvmInitZ); + assert(cd->llvmVtbl); + assert(cd->llvmConstVtbl); + + TypeClass* cdty = (TypeClass*)cd->type; + assert(cdty->llvmInit); // holds the list of initializers for llvm std::vector<llvm::Constant*> inits; ClassDeclaration* cinfo = ClassDeclaration::classinfo; - DtoConstInitClass(cinfo); + DtoForceConstInitDsymbol(cinfo); assert(cinfo->llvmInitZ); llvm::Constant* c; @@ -363,8 +443,12 @@ // monitor // TODO no monitors yet - // initializer - c = cinfo->llvmInitZ->getOperand(1); + // byte[] init + const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty); + c = llvm::ConstantExpr::getBitCast(cdty->llvmInit, byteptrty); + assert(!cd->llvmInitZ->getType()->isAbstract()); + size_t initsz = gTargetData->getTypeSize(cd->llvmInitZ->getType()); + c = DtoConstSlice(DtoConstSize_t(initsz), c); inits.push_back(c); // class name @@ -380,38 +464,77 @@ inits.push_back(c); // vtbl array - c = cinfo->llvmInitZ->getOperand(3); + const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty); + assert(!cd->llvmVtbl->getType()->isAbstract()); + c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty); + assert(!cd->llvmConstVtbl->getType()->isAbstract()); + size_t vtblsz = gTargetData->getTypeSize(cd->llvmConstVtbl->getType()); + c = DtoConstSlice(DtoConstSize_t(vtblsz), c); inits.push_back(c); // interfaces array + // TODO c = cinfo->llvmInitZ->getOperand(4); inits.push_back(c); // base classinfo - c = cinfo->llvmInitZ->getOperand(5); - inits.push_back(c); + if (cd->baseClass) { + DtoDeclareClassInfo(cd->baseClass); + c = cd->baseClass->llvmClass; + assert(c); + inits.push_back(c); + } + else { + // null + c = cinfo->llvmInitZ->getOperand(5); + inits.push_back(c); + } // destructor + // TODO c = cinfo->llvmInitZ->getOperand(6); inits.push_back(c); // invariant + // TODO c = cinfo->llvmInitZ->getOperand(7); inits.push_back(c); - // flags - c = cinfo->llvmInitZ->getOperand(8); + // uint flags, adapted from original dmd code + uint flags = 0; + //flags |= 4; // has offTi + //flags |= isCOMclass(); // IUnknown + if (cd->ctor) flags |= 8; + for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass) + { + if (cd2->members) + { + for (size_t i = 0; i < cd2->members->dim; i++) + { + Dsymbol *sm = (Dsymbol *)cd2->members->data[i]; + //printf("sm = %s %s\n", sm->kind(), sm->toChars()); + if (sm->hasPointers()) + goto L2; + } + } + } + flags |= 2; // no pointers +L2: + c = DtoConstUint(flags); inits.push_back(c); // allocator + // TODO c = cinfo->llvmInitZ->getOperand(9); inits.push_back(c); // offset typeinfo + // TODO c = cinfo->llvmInitZ->getOperand(10); inits.push_back(c); // default constructor + // TODO c = cinfo->llvmInitZ->getOperand(11); inits.push_back(c);