Mercurial > projects > ldc
diff ir/irstruct.cpp @ 797:340acf1535d0
Removed KDevelop3 project files, CMake can generate them just fine!
Fixed function literals in static initializers.
Changed alignment of delegates from 2*PTRSIZE to just PTRSIZE.
Changed errors to go to stderr instead of stdout.
Fairly major rewriting of struct/union/class handling, STILL A BIT BUGGY !!!
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sat, 29 Nov 2008 21:25:43 +0100 |
parents | 041c1596d217 |
children | d14e4594c7d7 |
line wrap: on
line diff
--- a/ir/irstruct.cpp Sat Nov 29 12:28:10 2008 +0100 +++ b/ir/irstruct.cpp Sat Nov 29 21:25:43 2008 +0100 @@ -3,54 +3,57 @@ #include "mtype.h" #include "aggregate.h" #include "declaration.h" +#include "init.h" #include "ir/irstruct.h" #include "gen/irstate.h" #include "gen/tollvm.h" +#include "gen/logger.h" IrInterface::IrInterface(BaseClass* b) +: vtblInitTy(llvm::OpaqueType::get()) { base = b; decl = b->base; - vtblTy = NULL; vtblInit = NULL; vtbl = NULL; infoTy = NULL; infoInit = NULL; info = NULL; - index = -1; -} - -IrInterface::~IrInterface() -{ - delete vtblTy; + index = 0; } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -IrStruct::IrStruct(Type* t) - : recty((t->ir.type) ? *t->ir.type : llvm::OpaqueType::get()) +IrStruct::IrStruct(AggregateDeclaration* aggr) +: initOpaque(llvm::OpaqueType::get()), + classInfoOpaque(llvm::OpaqueType::get()), + vtblTy(llvm::OpaqueType::get()), + vtblInitTy(llvm::OpaqueType::get()) { - type = t; + aggrdecl = aggr; + defaultFound = false; + anon = NULL; + index = 0; + + type = aggr->type; defined = false; constinited = false; - interfaceInfosTy = NULL; + interfaceInfos = NULL; - vtbl = NULL; constVtbl = NULL; + init = NULL; constInit = NULL; + classInfo = NULL; constClassInfo = NULL; - hasUnions = false; - dunion = NULL; - - classDeclared = false; - classDefined = false; + classInfoDeclared = false; + classInfoDefined = false; packed = false; @@ -61,14 +64,294 @@ { } -void IrStruct::addField(VarDeclaration* v) +////////////////////////////////////////// + +void IrStruct::pushAnon(bool isunion) +{ + anon = new Anon(isunion, anon); +} + +////////////////////////////////////////// + +void IrStruct::popAnon() +{ + assert(anon); + + const LLType* BT; + + // get the anon type + if (anon->isunion) + { + // get biggest type in block + const LLType* biggest = getBiggestType(&anon->types[0], anon->types.size()); + std::vector<const LLType*> vec(1, biggest); + BT = LLStructType::get(vec, aggrdecl->ir.irStruct->packed); + } + else + { + // build a struct from the types + BT = LLStructType::get(anon->types, aggrdecl->ir.irStruct->packed); + } + + // pop anon + Anon* tmp = anon; + anon = anon->parent; + delete tmp; + + // is there a parent anon? + if (anon) + { + // make sure type gets pushed in the anon, not the main + anon->types.push_back(BT); + // index is only manipulated at the top level, anons use raw offsets + } + // no parent anon, finally add to aggrdecl + else + { + types.push_back(BT); + // only advance to next position if main is not a union + if (!aggrdecl->isUnionDeclaration()) + { + index++; + } + } +} + +////////////////////////////////////////// + +void addZeros(std::vector<const llvm::Type*>& inits, size_t pos, size_t offset); + +void IrStruct::addVar(VarDeclaration * var) { - // might already have its irField, as classes derive each other without getting copies of the VarDeclaration - if (!v->ir.irField) + TypeVector* tvec = &types; + if (anon) + { + // make sure type gets pushed in the anon, not the main + tvec = &anon->types; + + // set but don't advance index + var->ir.irField->index = index; + + // set offset in bytes from start of anon block + var->ir.irField->unionOffset = var->offset - var->offset2; + } + else if (aggrdecl->isUnionDeclaration()) + { + // set but don't advance index + var->ir.irField->index = index; + } + else + { + // set and advance index + var->ir.irField->index = index++; + } + + // add type + tvec->push_back(DtoType(var->type)); + + // add var + varDecls.push_back(var); +} + +////////////////////////////////////////// + +const LLType* IrStruct::build() +{ + // if types is empty, add a byte + if (types.empty()) + { + types.push_back(LLType::Int8Ty); + } + + // union type + if (aggrdecl->isUnionDeclaration()) + { + const LLType* biggest = getBiggestType(&types[0], types.size()); + std::vector<const LLType*> vec(1, biggest); + return LLStructType::get(vec, aggrdecl->ir.irStruct->packed); + } + // struct/class type + else + { + return LLStructType::get(types, aggrdecl->ir.irStruct->packed); + } +} + +void addZeros(std::vector<const llvm::Type*>& inits, size_t pos, size_t offset) +{ + assert(offset > pos); + size_t diff = offset - pos; + + size_t sz; + + do { - assert(!v->ir.isSet()); - v->ir.irField = new IrField(v); + if (pos%8 == 0 && diff >= 8) + sz = 8; + else if (pos%4 == 0 && diff >= 4) + sz = 4; + else if (pos%2 == 0 && diff >= 2) + sz = 2; + else // if (pos % 1 == 0) + sz = 1; + inits.push_back(LLIntegerType::get(sz*8)); + pos += sz; + diff -= sz; + } while (pos < offset); + + assert(pos == offset); +} + +void addZeros(std::vector<llvm::Constant*>& inits, size_t pos, size_t offset) +{ + assert(offset > pos); + size_t diff = offset - pos; + + size_t sz; + + do + { + if (pos%8 == 0 && diff >= 8) + sz = 8; + else if (pos%4 == 0 && diff >= 4) + sz = 4; + else if (pos%2 == 0 && diff >= 2) + sz = 2; + else // if (pos % 1 == 0) + sz = 1; + inits.push_back(LLConstant::getNullValue(LLIntegerType::get(sz*8))); + pos += sz; + diff -= sz; + } while (pos < offset); + + assert(pos == offset); +} + +// FIXME: body is exact copy of above +void addZeros(std::vector<llvm::Value*>& inits, size_t pos, size_t offset) +{ + assert(offset > pos); + size_t diff = offset - pos; + + size_t sz; + + do + { + if (pos%8 == 0 && diff >= 8) + sz = 8; + else if (pos%4 == 0 && diff >= 4) + sz = 4; + else if (pos%2 == 0 && diff >= 2) + sz = 2; + else // if (pos % 1 == 0) + sz = 1; + inits.push_back(LLConstant::getNullValue(LLIntegerType::get(sz*8))); + pos += sz; + diff -= sz; + } while (pos < offset); + + assert(pos == offset); +} + +void IrStruct::buildDefaultConstInit(std::vector<llvm::Constant*>& inits) +{ + assert(!defaultFound); + defaultFound = true; + + const llvm::StructType* structtype = isaStruct(aggrdecl->type->ir.type->get()); + Logger::cout() << "struct type: " << *structtype << '\n'; + + size_t lastoffset = 0; + size_t lastsize = 0; + + { + Logger::println("Find the default fields"); + LOG_SCOPE; + + // go through all vars and find the ones that contribute to the default + size_t nvars = varDecls.size(); + for (size_t i=0; i<nvars; i++) + { + VarDeclaration* var = varDecls[i]; + + Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset); + + // only add vars that don't overlap + size_t offset = var->offset; + size_t size = var->type->size(); + if (offset >= lastoffset+lastsize) + { + Logger::println(" added"); + lastoffset = offset; + lastsize = size; + defVars.push_back(var); + } + } } - const LLType* _type = DtoType(v->type); - offsets.insert(std::make_pair(v->offset, IrStruct::Offset(v, _type))); + + { + Logger::println("Build the default initializer"); + LOG_SCOPE; + + lastoffset = 0; + lastsize = 0; + + // go through the default vars and build the default constant initializer + // adding zeros along the way to live up to alignment expectations + size_t nvars = defVars.size(); + for (size_t i=0; i<nvars; i++) + { + VarDeclaration* var = defVars[i]; + + Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset); + + // get offset and size + size_t offset = var->offset; + size_t size = var->type->size(); + + // is there space in between last last offset and this one? + // if so, fill it with zeros + if (offset > lastoffset+lastsize) + { + size_t pos = lastoffset + lastsize; + addZeros(inits, pos, offset); + } + + // add the field + assert(var->ir.irField->constInit); + inits.push_back(var->ir.irField->constInit); + + lastoffset = offset; + lastsize = var->type->size(); + } + + // there might still be padding after the last one, make sure that is zeroed as well + // is there space in between last last offset and this one? + size_t structsize = getABITypeSize(structtype); + + if (structsize > lastoffset+lastsize) + { + size_t pos = lastoffset + lastsize; + addZeros(inits, pos, structsize); + } + } } + +LLConstant* IrStruct::buildDefaultConstInit() +{ + // doesn't work for classes, they add stuff before and maybe after data fields + assert(!aggrdecl->isClassDeclaration()); + + // initializer llvm constant list + std::vector<LLConstant*> inits; + + // just start with an empty list + buildDefaultConstInit(inits); + + // build the constant + // note that the type matches the initializer, not the aggregate in cases with unions + LLConstant* c = LLConstantStruct::get(inits, aggrdecl->ir.irStruct->packed); + Logger::cout() << "llvm constant: " << *c << '\n'; +// assert(0); + return c; +}