ldc/ir/irtypeclass.cpp
2017-01-20 22:21:39 +01:00

142 lines
4.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//===-- irtypeclass.cpp ---------------------------------------------------===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/DerivedTypes.h"
#include "aggregate.h"
#include "declaration.h"
#include "dsymbol.h"
#include "mtype.h"
#include "target.h"
#include "template.h"
#include "gen/irstate.h"
#include "gen/logger.h"
#include "gen/tollvm.h"
#include "gen/llvmhelpers.h"
#include "gen/functions.h"
#include "ir/irtypeclass.h"
IrTypeClass::IrTypeClass(ClassDeclaration *cd)
: IrTypeAggr(cd), cd(cd), tc(static_cast<TypeClass *>(cd->type)) {
vtbl_type = LLArrayType::get(getVoidPtrType(), cd->vtbl.dim);
}
void IrTypeClass::addClassData(AggrTypeBuilder &builder,
ClassDeclaration *currCd) {
// First, recursively add the fields for our base class and interfaces, if
// any.
if (currCd->baseClass) {
addClassData(builder, currCd->baseClass);
}
if (currCd->vtblInterfaces && currCd->vtblInterfaces->dim > 0) {
// KLUDGE: The first pointer in the vtbl will be of type object.Interface;
// extract that from the "well-known" object.TypeInfo_Class definition.
// For C++ interfaces, this vtbl entry has to be omitted
builder.alignCurrentOffset(Target::ptrsize);
for (auto b : *currCd->vtblInterfaces) {
IF_LOG Logger::println("Adding interface vtbl for %s",
b->sym->toPrettyChars());
// add to the interface map
addInterfaceToMap(b->sym, builder.currentFieldIndex());
auto vtblTy = LLArrayType::get(getVoidPtrType(), b->sym->vtbl.dim);
builder.addType(llvm::PointerType::get(vtblTy, 0), Target::ptrsize);
++num_interface_vtbls;
}
}
// Finally, the data members for this class.
builder.addAggregate(currCd);
}
IrTypeClass *IrTypeClass::get(ClassDeclaration *cd) {
const auto t = new IrTypeClass(cd);
cd->type->ctype = t;
IF_LOG Logger::println("Building class type %s @ %s", cd->toPrettyChars(),
cd->loc.toChars());
LOG_SCOPE;
IF_LOG Logger::println("Instance size: %u", cd->structsize);
// This class may contain an align declaration. See GitHub #726.
t->packed = false;
for (auto base = cd; base != nullptr && !t->packed; base = base->baseClass) {
t->packed = isPacked(base);
}
AggrTypeBuilder builder(t->packed);
// add vtbl
builder.addType(llvm::PointerType::get(t->vtbl_type, 0), Target::ptrsize);
if (cd->isInterfaceDeclaration()) {
// interfaces are just a vtable
t->num_interface_vtbls = cd->vtblInterfaces ? cd->vtblInterfaces->dim : 0;
} else {
// classes have monitor and fields
if (!cd->isCPPclass() && !cd->isCPPinterface()) {
// add monitor
builder.addType(
llvm::PointerType::get(llvm::Type::getInt8Ty(gIR->context()), 0),
Target::ptrsize);
}
// add data members recursively
t->addClassData(builder, cd);
// add tail padding
builder.addTailPadding(cd->structsize);
}
if (global.errors) {
fatal();
}
// set struct body and copy GEP indices
isaStruct(t->type)->setBody(builder.defaultTypes(), t->packed);
t->varGEPIndices = builder.varGEPIndices();
IF_LOG Logger::cout() << "class type: " << *t->type << std::endl;
return t;
}
llvm::Type *IrTypeClass::getLLType() { return llvm::PointerType::get(type, 0); }
llvm::Type *IrTypeClass::getMemoryLLType() { return type; }
size_t IrTypeClass::getInterfaceIndex(ClassDeclaration *inter) {
auto it = interfaceMap.find(inter);
if (it == interfaceMap.end()) {
return ~0UL;
}
return it->second;
}
void IrTypeClass::addInterfaceToMap(ClassDeclaration *inter, size_t index) {
// don't duplicate work or overwrite indices
if (interfaceMap.find(inter) != interfaceMap.end()) {
return;
}
// add this interface
interfaceMap.insert(std::make_pair(inter, index));
// add the direct base interfaces recursively - they
// are accessed through the same index
if (inter->interfaces.length > 0) {
BaseClass *b = inter->interfaces.ptr[0];
addInterfaceToMap(b->sym, index);
}
}