Mercurial > projects > ldc
view ir/irtypeclass.cpp @ 1228:79758fd2f48a
Added Doxygen file.
Completely seperated type and symbol generation. Should fix a lot of bugs, but is not yet 100% complete.
author | Tomas Lindquist Olsen <tomas.l.olsen gmail.com> |
---|---|
date | Wed, 15 Apr 2009 20:06:25 +0200 |
parents | |
children | e67c85d6e680 |
line wrap: on
line source
#include "llvm/DerivedTypes.h" #include "aggregate.h" #include "declaration.h" #include "dsymbol.h" #include "mtype.h" #include "gen/irstate.h" #include "gen/logger.h" #include "gen/tollvm.h" #include "gen/utils.h" #include "ir/irtypeclass.h" ////////////////////////////////////////////////////////////////////////////// extern size_t add_zeros(std::vector<const llvm::Type*>& defaultTypes, size_t diff); ////////////////////////////////////////////////////////////////////////////// IrTypeClass::IrTypeClass(ClassDeclaration* cd) : IrTypeAggr(cd), cd(cd), tc((TypeClass*)cd->type), vtbl_pa(llvm::OpaqueType::get()) { vtbl_size = cd->vtbl.dim; } ////////////////////////////////////////////////////////////////////////////// void IrTypeClass::addBaseClassData( std::vector< const llvm::Type * > & defaultTypes, ClassDeclaration * base, size_t & offset, size_t & field_index) { if (base->baseClass) { addBaseClassData(defaultTypes, base->baseClass, offset, field_index); } ArrayIter<VarDeclaration> it(base->fields); for (; !it.done(); it.next()) { VarDeclaration* vd = it.get(); // skip if offset moved backwards if (vd->offset < offset) { IF_LOG Logger::println("Skipping field %s %s (+%u) for default", vd->type->toChars(), vd->toChars(), vd->offset); if (vd->ir.irField == NULL) { new IrField(vd, 2, vd->offset - PTRSIZE * 2); } continue; } IF_LOG Logger::println("Adding default field %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset); // get next aligned offset for this type size_t alignsize = vd->type->alignsize(); size_t alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1); // do we need to insert explicit padding before the field? if (alignedoffset < vd->offset) { field_index += add_zeros(defaultTypes, vd->offset - alignedoffset); } // add default type defaultTypes.push_back(DtoType(vd->type)); // advance offset to right past this field offset = vd->offset + vd->type->size(); // give field index // the IrField creation doesn't really belong here, but it's a trivial operation // and it save yet another of these loops. IF_LOG Logger::println("Field index: %zu", field_index); if (vd->ir.irField == NULL) { new IrField(vd, field_index); } field_index++; } // any interface implementations? if (base->vtblInterfaces) { bool new_instances = (base == cd); ArrayIter<BaseClass> it2(*base->vtblInterfaces); for (; !it2.done(); it2.next()) { BaseClass* b = it2.get(); IF_LOG Logger::println("Adding interface vtbl for %s", b->base->toPrettyChars()); Array arr; b->fillVtbl(cd, &arr, new_instances); const llvm::Type* ivtbl_type = buildVtblType(Type::tvoid->pointerTo(), &arr); defaultTypes.push_back(llvm::PointerType::get(ivtbl_type, 0)); offset += PTRSIZE; // add to the interface map if (interfaceMap.find(b->base) == interfaceMap.end()) interfaceMap.insert(std::make_pair(b->base, field_index)); field_index++; } } // tail padding? if (offset < base->structsize) { field_index += add_zeros(defaultTypes, base->structsize - offset); offset = base->structsize; } } ////////////////////////////////////////////////////////////////////////////// const llvm::Type* IrTypeClass::buildType() { IF_LOG Logger::println("Building class type %s @ %s", cd->toPrettyChars(), cd->locToChars()); LOG_SCOPE; IF_LOG Logger::println("Instance size: %u", cd->structsize); // find the fields that contribute to the default initializer. // these will define the default type. std::vector<const llvm::Type*> defaultTypes; defaultTypes.reserve(32); // add vtbl defaultTypes.push_back(llvm::PointerType::get(vtbl_pa.get(), 0)); // interface are just a vtable if (!cd->isInterfaceDeclaration()) { // add monitor defaultTypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty, 0)); // we start right after the vtbl and monitor size_t offset = PTRSIZE * 2; size_t field_index = 2; // add data members recursively addBaseClassData(defaultTypes, cd, offset, field_index); } // errors are fatal during codegen if (global.errors) fatal(); // build the llvm type const llvm::Type* st = llvm::StructType::get(defaultTypes, false); // refine type llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(st); // name type Type::sir->getState()->module->addTypeName(cd->toPrettyChars(), pa.get()); // VTBL // build vtbl type const llvm::Type* vtblty = buildVtblType( ClassDeclaration::classinfo->type, &cd->vtbl); // refine vtbl pa llvm::cast<llvm::OpaqueType>(vtbl_pa.get())->refineAbstractTypeTo(vtblty); // name vtbl type std::string name(cd->toPrettyChars()); name.append(".__vtbl"); Type::sir->getState()->module->addTypeName(name, vtbl_pa.get()); #if 0 IF_LOG Logger::cout() << "class type: " << *pa.get() << std::endl; #endif return get(); } ////////////////////////////////////////////////////////////////////////////// const llvm::Type* IrTypeClass::buildVtblType(Type* first, Array* vtbl_array) { IF_LOG Logger::println("Building vtbl type for class %s", cd->toPrettyChars()); LOG_SCOPE; std::vector<const llvm::Type*> types; types.reserve(vtbl_array->dim); // first comes the classinfo types.push_back(DtoType(first)); // then come the functions ArrayIter<Dsymbol> it(*vtbl_array); it.index = 1; for (; !it.done(); it.next()) { FuncDeclaration* fd = it.get()->isFuncDeclaration(); assert(fd && "invalid vtbl entry"); IF_LOG Logger::println("Adding type of %s", fd->toPrettyChars()); types.push_back(DtoType(fd->type->pointerTo())); } // build the vtbl llvm type return llvm::StructType::get(types, false); } ////////////////////////////////////////////////////////////////////////////// const llvm::Type * IrTypeClass::get() { return llvm::PointerType::get(pa.get(), 0); } ////////////////////////////////////////////////////////////////////////////// size_t IrTypeClass::getInterfaceIndex(ClassDeclaration * inter) { ClassIndexMap::iterator it = interfaceMap.find(inter); if (it == interfaceMap.end()) return ~0; return it->second; } //////////////////////////////////////////////////////////////////////////////