Mercurial > projects > ldc
diff ir/irtypestruct.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 | 212ec2d9d176 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ir/irtypestruct.cpp Wed Apr 15 20:06:25 2009 +0200 @@ -0,0 +1,148 @@ +#include "llvm/DerivedTypes.h" + +#include "aggregate.h" +#include "declaration.h" +#include "mtype.h" + +#include "gen/irstate.h" +#include "gen/tollvm.h" +#include "gen/logger.h" +#include "gen/utils.h" +#include "ir/irtypestruct.h" + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +IrTypeAggr::IrTypeAggr(AggregateDeclaration * ad) +: IrType(ad->type, llvm::OpaqueType::get()), + aggr(ad) +{ +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +IrTypeStruct::IrTypeStruct(StructDeclaration * sd) +: IrTypeAggr(sd), + sd(sd), + ts((TypeStruct*)sd->type) +{ +} + +////////////////////////////////////////////////////////////////////////////// + +size_t add_zeros(std::vector<const llvm::Type*>& defaultTypes, size_t diff) +{ + size_t n = defaultTypes.size(); + while (diff) + { + if (global.params.is64bit && diff % 8 == 0) + { + defaultTypes.push_back(llvm::Type::Int64Ty); + diff -= 8; + } + else if (diff % 4 == 0) + { + defaultTypes.push_back(llvm::Type::Int32Ty); + diff -= 4; + } + else if (diff % 2 == 0) + { + defaultTypes.push_back(llvm::Type::Int16Ty); + diff -= 2; + } + else + { + defaultTypes.push_back(llvm::Type::Int8Ty); + diff -= 1; + } + } + return defaultTypes.size() - n; +} + +const llvm::Type* IrTypeStruct::buildType() +{ + IF_LOG Logger::println("Building struct type %s @ %s", sd->toPrettyChars(), sd->locToChars()); + LOG_SCOPE; + + // find the fields that contribute to the default initializer. + // these will define the default type. + + std::vector<const llvm::Type*> defaultTypes; + defaultTypes.reserve(16); + + size_t offset = 0; + size_t field_index = 0; + + bool packed = (sd->type->alignsize() == 1); + + ArrayIter<VarDeclaration> it(sd->fields); + for (; !it.done(); it.next()) + { + VarDeclaration* vd = it.get(); + + assert(vd->ir.irField == NULL && "struct inheritance is not allowed, how can this happen?"); + + // 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); + new IrField(vd, 0, vd->offset); + 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 alignedoffset = offset; + if (!packed) + { + size_t alignsize = vd->type->alignsize(); + alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1); + } + + // insert explicit padding? + 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); + new IrField(vd, field_index); + field_index++; + } + + // tail padding? + if (offset < sd->structsize) + { + add_zeros(defaultTypes, sd->structsize - offset); + } + + // build the llvm type + const llvm::Type* st = llvm::StructType::get(defaultTypes, packed); + + // refine type + llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(st); + + // name types + Type::sir->getState()->module->addTypeName(sd->toPrettyChars(), pa.get()); + +#if 0 + IF_LOG Logger::cout() << "struct type: " << *pa.get() << std::endl; +#endif + + return pa.get(); +} + +//////////////////////////////////////////////////////////////////////////////