mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-06 02:45:25 +03:00
[svn r117] Initial working implementation of interfaces.
Groundwork for all the different types of class/interface casts laid out.
This commit is contained in:
parent
0a8ff5931a
commit
b43f5729b0
18 changed files with 867 additions and 145 deletions
405
gen/classes.cpp
405
gen/classes.cpp
|
@ -1,3 +1,4 @@
|
|||
#include <sstream>
|
||||
#include "gen/llvm.h"
|
||||
|
||||
#include "mtype.h"
|
||||
|
@ -11,6 +12,8 @@
|
|||
#include "gen/logger.h"
|
||||
#include "gen/classes.h"
|
||||
#include "gen/functions.h"
|
||||
#include "gen/runtime.h"
|
||||
#include "gen/dvalue.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -21,10 +24,14 @@ static void LLVM_AddBaseClassData(BaseClasses* bcs)
|
|||
{
|
||||
BaseClass* bc = (BaseClass*)(bcs->data[j]);
|
||||
assert(bc);
|
||||
if (bc->base->isInterfaceDeclaration())
|
||||
continue; // interfaces only has methods
|
||||
|
||||
LLVM_AddBaseClassData(&bc->base->baseclasses);
|
||||
|
||||
Logger::println("Adding base class members of %s", bc->base->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
LLVM_AddBaseClassData(&bc->base->baseclasses);
|
||||
for (int k=0; k < bc->base->members->dim; k++) {
|
||||
Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
|
||||
if (dsym->isVarDeclaration())
|
||||
|
@ -46,10 +53,17 @@ void DtoResolveClass(ClassDeclaration* cd)
|
|||
if (cd->baseClass) {
|
||||
DtoResolveClass(cd->baseClass);
|
||||
}
|
||||
// resolve typeinfo
|
||||
//DtoResolveClass(ClassDeclaration::typeinfo);
|
||||
// resolve classinfo
|
||||
//DtoResolveClass(ClassDeclaration::classinfo);
|
||||
|
||||
// resolve interfaces
|
||||
if (cd->vtblInterfaces) {
|
||||
for (int i=0; i < cd->vtblInterfaces->dim; i++) {
|
||||
BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i];
|
||||
ClassDeclaration *id = b->base;
|
||||
DtoResolveClass(id);
|
||||
// Fill in vtbl[]
|
||||
b->fillVtbl(cd, &b->vtbl, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Logger::println("DtoResolveClass(%s)", cd->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
@ -71,6 +85,22 @@ void DtoResolveClass(ClassDeclaration* cd)
|
|||
std::vector<const llvm::Type*> fieldtypes;
|
||||
fieldtypes.push_back(vtabty);
|
||||
|
||||
// add interface vtables
|
||||
if (cd->vtblInterfaces)
|
||||
for (size_t i = 0; i < cd->vtblInterfaces->dim; i++)
|
||||
{
|
||||
BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i];
|
||||
ClassDeclaration *id = b->base;
|
||||
assert(id->type->ty == Tclass);
|
||||
TypeClass* itc = (TypeClass*)id->type;
|
||||
const llvm::Type* ivtblTy = llvm::PointerType::get(itc->llvmVtblType->get());
|
||||
fieldtypes.push_back(ivtblTy);
|
||||
|
||||
// add this interface to the map
|
||||
IRInterface* iri = new IRInterface(b, isaStruct(itc->llvmVtblType->get()));
|
||||
irstruct->interfaces.insert(std::make_pair(id, iri));
|
||||
}
|
||||
|
||||
// base classes first
|
||||
LLVM_AddBaseClassData(&cd->baseclasses);
|
||||
|
||||
|
@ -98,16 +128,31 @@ void DtoResolveClass(ClassDeclaration* cd)
|
|||
else
|
||||
*ts->llvmType = structtype;
|
||||
|
||||
bool needs_definition = false;
|
||||
if (cd->parent->isModule()) {
|
||||
gIR->module->addTypeName(cd->mangle(), ts->llvmType->get());
|
||||
needs_definition = (cd->getModule() == gIR->dmodule);
|
||||
}
|
||||
else {
|
||||
assert(0 && "class parent is not a module");
|
||||
}
|
||||
|
||||
// generate vtable
|
||||
// build interface info type
|
||||
std::vector<const llvm::Type*> infoTypes;
|
||||
// ClassInfo classinfo
|
||||
ClassDeclaration* cinfod = ClassDeclaration::classinfo;
|
||||
DtoResolveClass(cinfod);
|
||||
infoTypes.push_back(llvm::PointerType::get(cinfod->type->llvmType->get()));
|
||||
// void*[] vtbl
|
||||
std::vector<const llvm::Type*> infoVtbltypes;
|
||||
infoVtbltypes.push_back(DtoSize_t());
|
||||
const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
infoVtbltypes.push_back(byteptrptrty);
|
||||
infoTypes.push_back(llvm::StructType::get(infoVtbltypes));
|
||||
// int offset
|
||||
infoTypes.push_back(llvm::Type::Int32Ty);
|
||||
// create type
|
||||
const llvm::StructType* infoTy = llvm::StructType::get(infoTypes);
|
||||
|
||||
// create vtable type
|
||||
llvm::GlobalVariable* svtblVar = 0;
|
||||
std::vector<const llvm::Type*> sinits_ty;
|
||||
|
||||
|
@ -124,18 +169,21 @@ void DtoResolveClass(ClassDeclaration* cd)
|
|||
const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get());
|
||||
sinits_ty.push_back(fpty);
|
||||
}
|
||||
else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
|
||||
//Logger::println("*** ClassDeclaration in vtable: %s", cd->toChars());
|
||||
else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
|
||||
Logger::println("*** ClassDeclaration in vtable: %s", cd2->toChars());
|
||||
const llvm::Type* cinfoty;
|
||||
if (cd != ClassDeclaration::classinfo) {
|
||||
cd = ClassDeclaration::classinfo;
|
||||
DtoResolveClass(cd);
|
||||
cinfoty = cd->type->llvmType->get();
|
||||
if (cd->isInterfaceDeclaration()) {
|
||||
cinfoty = infoTy;
|
||||
}
|
||||
else if (cd != cinfod) {
|
||||
DtoResolveClass(cinfod);
|
||||
cinfoty = cinfod->type->llvmType->get();
|
||||
}
|
||||
else {
|
||||
// this is the ClassInfo class, the type is this type
|
||||
cinfoty = ts->llvmType->get();
|
||||
}
|
||||
const llvm::Type* cty = llvm::PointerType::get(cd->type->llvmType->get());
|
||||
const llvm::Type* cty = llvm::PointerType::get(cinfoty);
|
||||
sinits_ty.push_back(cty);
|
||||
}
|
||||
else
|
||||
|
@ -182,26 +230,78 @@ void DtoDeclareClass(ClassDeclaration* cd)
|
|||
needs_definition = (cd->getModule() == gIR->dmodule);
|
||||
}
|
||||
|
||||
// vtable
|
||||
std::string varname("_D");
|
||||
varname.append(cd->mangle());
|
||||
varname.append("6__vtblZ");
|
||||
// interface vtables are emitted by the class implementing them
|
||||
// also interfaces have no static initializer
|
||||
if (!cd->isInterfaceDeclaration()) {
|
||||
// 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;
|
||||
|
||||
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);
|
||||
|
||||
const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
|
||||
cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
|
||||
// build interface info type
|
||||
std::vector<const llvm::Type*> types;
|
||||
// ClassInfo classinfo
|
||||
ClassDeclaration* cd2 = ClassDeclaration::classinfo;
|
||||
DtoResolveClass(cd2);
|
||||
types.push_back(llvm::PointerType::get(cd2->type->llvmType->get()));
|
||||
// void*[] vtbl
|
||||
std::vector<const llvm::Type*> vtbltypes;
|
||||
vtbltypes.push_back(DtoSize_t());
|
||||
const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
vtbltypes.push_back(byteptrptrty);
|
||||
types.push_back(llvm::StructType::get(vtbltypes));
|
||||
// int offset
|
||||
types.push_back(llvm::Type::Int32Ty);
|
||||
// create type
|
||||
const llvm::StructType* infoTy = llvm::StructType::get(types);
|
||||
|
||||
// init
|
||||
std::string initname("_D");
|
||||
initname.append(cd->mangle());
|
||||
initname.append("6__initZ");
|
||||
// interface info array
|
||||
if (needs_definition && cd->vtblInterfaces->dim > 0) {
|
||||
// symbol name
|
||||
std::string nam = "_D";
|
||||
nam.append(cd->mangle());
|
||||
nam.append("16__interfaceInfosZ");
|
||||
// resolve array type
|
||||
const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->vtblInterfaces->dim);
|
||||
// declare global
|
||||
irstruct->interfaceInfosTy = arrTy;
|
||||
irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, llvm::GlobalValue::InternalLinkage, 0, nam, gIR->module);
|
||||
}
|
||||
|
||||
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module);
|
||||
ts->llvmInit = initvar;
|
||||
// interface vtables
|
||||
unsigned idx = 0;
|
||||
for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
|
||||
{
|
||||
ClassDeclaration* id = i->first;
|
||||
IRInterface* iri = i->second;
|
||||
|
||||
std::string nam("_D");
|
||||
nam.append(cd->mangle());
|
||||
nam.append("11__interface");
|
||||
nam.append(id->mangle());
|
||||
nam.append("6__vtblZ");
|
||||
|
||||
assert(iri->vtblTy);
|
||||
iri->vtbl = new llvm::GlobalVariable(iri->vtblTy, true, _linkage, 0, nam, gIR->module);
|
||||
iri->infoTy = infoTy;
|
||||
llvm::Constant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)};
|
||||
iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2);
|
||||
idx++;
|
||||
}
|
||||
|
||||
// init
|
||||
std::string initname("_D");
|
||||
initname.append(cd->mangle());
|
||||
initname.append("6__initZ");
|
||||
|
||||
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();
|
||||
|
@ -225,6 +325,9 @@ void DtoConstInitClass(ClassDeclaration* cd)
|
|||
if (cd->llvmInitialized) return;
|
||||
cd->llvmInitialized = true;
|
||||
|
||||
if (cd->isInterfaceDeclaration())
|
||||
return; // nothing to do
|
||||
|
||||
Logger::println("DtoConstInitClass(%s)", cd->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
|
@ -248,6 +351,14 @@ void DtoConstInitClass(ClassDeclaration* cd)
|
|||
assert(cd->llvmVtbl != 0);
|
||||
fieldinits.push_back(cd->llvmVtbl);
|
||||
|
||||
// next comes interface vtables
|
||||
for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
|
||||
{
|
||||
IRInterface* iri = i->second;
|
||||
assert(iri->vtbl);
|
||||
fieldinits.push_back(iri->vtbl);
|
||||
}
|
||||
|
||||
// rest
|
||||
for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
|
||||
Logger::println("adding fieldinit for: %s", i->second.var->toChars());
|
||||
|
@ -260,7 +371,8 @@ void DtoConstInitClass(ClassDeclaration* cd)
|
|||
const llvm::StructType* structtype = isaStruct(ts->llvmType->get());
|
||||
|
||||
// generate initializer
|
||||
/*Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n';
|
||||
#if 0
|
||||
Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n';
|
||||
|
||||
for(size_t i=0; i<structtype->getNumElements(); ++i) {
|
||||
Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n';
|
||||
|
@ -268,7 +380,8 @@ void DtoConstInitClass(ClassDeclaration* cd)
|
|||
|
||||
for(size_t i=0; i<fieldinits.size(); ++i) {
|
||||
Logger::cout() << "i#" << i << " = " << *fieldinits[i]->getType() << '\n';
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
|
||||
llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits);
|
||||
assert(_init);
|
||||
|
@ -300,16 +413,83 @@ void DtoConstInitClass(ClassDeclaration* cd)
|
|||
|
||||
const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
|
||||
|
||||
/*for (size_t i=0; i< sinits.size(); ++i)
|
||||
#if 0
|
||||
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());
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
|
||||
llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits);
|
||||
cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit);
|
||||
|
||||
// create interface vtable const initalizers
|
||||
int idx = 1;
|
||||
int idxScale = (global.params.is64bit) ? 8 : 4;
|
||||
for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
|
||||
{
|
||||
ClassDeclaration* id = i->first;
|
||||
assert(id->type->ty == Tclass);
|
||||
TypeClass* its = (TypeClass*)id->type;
|
||||
|
||||
IRInterface* iri = i->second;
|
||||
BaseClass* b = iri->base;
|
||||
|
||||
const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get());
|
||||
|
||||
// generate interface info initializer
|
||||
std::vector<llvm::Constant*> infoInits;
|
||||
// classinfo
|
||||
assert(id->llvmClass);
|
||||
llvm::Constant* c = id->llvmClass;
|
||||
infoInits.push_back(c);
|
||||
// vtbl
|
||||
const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty);
|
||||
c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c);
|
||||
infoInits.push_back(c);
|
||||
// offset
|
||||
infoInits.push_back(DtoConstInt(idx*idxScale));
|
||||
// create interface info initializer constant
|
||||
iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits));
|
||||
|
||||
// generate vtable initializer
|
||||
std::vector<llvm::Constant*> iinits;
|
||||
|
||||
// add interface info
|
||||
iinits.push_back(iri->info);
|
||||
|
||||
for (int k=1; k < b->vtbl.dim; k++)
|
||||
{
|
||||
Logger::println("interface vtbl const init nr. %d", k);
|
||||
Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k];
|
||||
FuncDeclaration* fd = dsym->isFuncDeclaration();
|
||||
assert(fd);
|
||||
DtoForceDeclareDsymbol(fd);
|
||||
assert(fd->llvmValue);
|
||||
llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
|
||||
// we have to bitcast, as the type created in ResolveClass expects a different this type
|
||||
c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k));
|
||||
iinits.push_back(c);
|
||||
}
|
||||
|
||||
#if 1
|
||||
for (size_t x=0; x< iinits.size(); ++x)
|
||||
{
|
||||
Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n";
|
||||
Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n";
|
||||
assert(ivtbl_ty->getElementType(x) == iinits[x]->getType());
|
||||
}
|
||||
#endif
|
||||
|
||||
llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits);
|
||||
iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit);
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
gIR->classes.pop_back();
|
||||
gIR->structs.pop_back();
|
||||
}
|
||||
|
@ -330,8 +510,26 @@ void DtoDefineClass(ClassDeclaration* cd)
|
|||
|
||||
bool def = false;
|
||||
if (cd->parent->isModule() && cd->getModule() == gIR->dmodule) {
|
||||
ts->llvmInit->setInitializer(cd->llvmInitZ);
|
||||
cd->llvmVtbl->setInitializer(cd->llvmConstVtbl);
|
||||
// interfaces don't have initializers
|
||||
if (!cd->isInterfaceDeclaration()) {
|
||||
ts->llvmInit->setInitializer(cd->llvmInitZ);
|
||||
cd->llvmVtbl->setInitializer(cd->llvmConstVtbl);
|
||||
|
||||
// initialize interface vtables
|
||||
IRStruct* irstruct = cd->llvmIRStruct;
|
||||
std::vector<llvm::Constant*> infoInits;
|
||||
for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
|
||||
{
|
||||
IRInterface* iri = i->second;
|
||||
iri->vtbl->setInitializer(iri->vtblInit);
|
||||
infoInits.push_back(iri->infoInit);
|
||||
}
|
||||
// initialize interface info array
|
||||
if (!infoInits.empty()) {
|
||||
llvm::Constant* arrInit = llvm::ConstantArray::get(irstruct->interfaceInfosTy, infoInits);
|
||||
irstruct->interfaceInfos->setInitializer(arrInit);
|
||||
}
|
||||
}
|
||||
def = true;
|
||||
}
|
||||
|
||||
|
@ -394,6 +592,54 @@ void DtoInitClass(TypeClass* tc, llvm::Value* dst)
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DValue* DtoCastObjectToInterface(DValue* val, Type* _to)
|
||||
{
|
||||
// call:
|
||||
// Object _d_dynamic_cast(Object o, ClassInfo c)
|
||||
|
||||
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast");
|
||||
const llvm::FunctionType* funcTy = func->getFunctionType();
|
||||
|
||||
std::vector<llvm::Value*> args;
|
||||
|
||||
// Object o
|
||||
llvm::Value* tmp = val->getRVal();
|
||||
tmp = DtoBitCast(tmp, funcTy->getParamType(0));
|
||||
args.push_back(tmp);
|
||||
|
||||
// ClassInfo c
|
||||
TypeClass* to = (TypeClass*)DtoDType(_to);
|
||||
DtoForceDeclareDsymbol(to->sym);
|
||||
assert(to->sym->llvmClass);
|
||||
args.push_back(to->sym->llvmClass);
|
||||
|
||||
// call it
|
||||
llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp");
|
||||
ret = DtoBitCast(ret, DtoType(_to));
|
||||
return new DImValue(_to, ret);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DValue* DtoCastInterfaceToObject(DValue* val)
|
||||
{
|
||||
// call:
|
||||
// Object _d_toObject(void* p)
|
||||
|
||||
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_toObject");
|
||||
const llvm::FunctionType* funcTy = func->getFunctionType();
|
||||
|
||||
// void* p
|
||||
llvm::Value* tmp = val->getRVal();
|
||||
tmp = DtoBitCast(tmp, funcTy->getParamType(0));
|
||||
|
||||
// call it
|
||||
llvm::Value* ret = gIR->ir->CreateCall(func, tmp, "tmp");
|
||||
return new DImValue(ClassDeclaration::object->type, ret);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDeclareClassInfo(ClassDeclaration* cd)
|
||||
{
|
||||
if (cd->llvmClassDeclared) return;
|
||||
|
@ -407,7 +653,10 @@ void DtoDeclareClassInfo(ClassDeclaration* cd)
|
|||
|
||||
std::string gname("_D");
|
||||
gname.append(cd->mangle());
|
||||
gname.append("7__ClassZ");
|
||||
if (!cd->isInterfaceDeclaration())
|
||||
gname.append("7__ClassZ");
|
||||
else
|
||||
gname.append("11__InterfaceZ");
|
||||
|
||||
const llvm::Type* st = cinfo->type->llvmType->get();
|
||||
|
||||
|
@ -538,6 +787,7 @@ static llvm::Constant* build_class_dtor(ClassDeclaration* cd)
|
|||
|
||||
static uint build_classinfo_flags(ClassDeclaration* cd)
|
||||
{
|
||||
// adapted from original dmd code
|
||||
uint flags = 0;
|
||||
//flags |= isCOMclass(); // IUnknown
|
||||
bool hasOffTi = false;
|
||||
|
@ -591,12 +841,14 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
|||
|
||||
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);
|
||||
if (!cd->isInterfaceDeclaration()) {
|
||||
assert(cd->llvmInitZ);
|
||||
assert(cd->llvmVtbl);
|
||||
assert(cd->llvmConstVtbl);
|
||||
assert(cdty->llvmInit);
|
||||
}
|
||||
|
||||
// holds the list of initializers for llvm
|
||||
std::vector<llvm::Constant*> inits;
|
||||
|
@ -617,10 +869,15 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
|||
|
||||
// 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);
|
||||
if (cd->isInterfaceDeclaration()) {
|
||||
c = cinfo->llvmInitZ->getOperand(1);
|
||||
}
|
||||
else {
|
||||
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
|
||||
|
@ -636,21 +893,34 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
|||
inits.push_back(c);
|
||||
|
||||
// vtbl array
|
||||
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);
|
||||
if (cd->isInterfaceDeclaration()) {
|
||||
c = cinfo->llvmInitZ->getOperand(3);
|
||||
}
|
||||
else {
|
||||
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 = cd->llvmConstVtbl->getType()->getNumElements();
|
||||
c = DtoConstSlice(DtoConstSize_t(vtblsz), c);
|
||||
}
|
||||
inits.push_back(c);
|
||||
|
||||
// interfaces array
|
||||
// TODO
|
||||
c = cinfo->llvmInitZ->getOperand(4);
|
||||
IRStruct* irstruct = cd->llvmIRStruct;
|
||||
if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos) {
|
||||
c = cinfo->llvmInitZ->getOperand(4);
|
||||
}
|
||||
else {
|
||||
const llvm::Type* t = cinfo->llvmInitZ->getOperand(4)->getType()->getContainedType(1);
|
||||
c = llvm::ConstantExpr::getBitCast(irstruct->interfaceInfos, t);
|
||||
size_t iisz = irstruct->interfaceInfosTy->getNumElements();
|
||||
c = DtoConstSlice(DtoConstSize_t(iisz), c);
|
||||
}
|
||||
inits.push_back(c);
|
||||
|
||||
// base classinfo
|
||||
if (cd->baseClass) {
|
||||
if (cd->baseClass && !cd->isInterfaceDeclaration()) {
|
||||
DtoDeclareClassInfo(cd->baseClass);
|
||||
c = cd->baseClass->llvmClass;
|
||||
assert(c);
|
||||
|
@ -663,7 +933,12 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
|||
}
|
||||
|
||||
// destructor
|
||||
c = build_class_dtor(cd);
|
||||
if (cd->isInterfaceDeclaration()) {
|
||||
c = cinfo->llvmInitZ->getOperand(6);
|
||||
}
|
||||
else {
|
||||
c = build_class_dtor(cd);
|
||||
}
|
||||
inits.push_back(c);
|
||||
|
||||
// invariant
|
||||
|
@ -671,9 +946,14 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
|||
c = cinfo->llvmInitZ->getOperand(7);
|
||||
inits.push_back(c);
|
||||
|
||||
// uint flags, adapted from original dmd code
|
||||
uint flags = build_classinfo_flags(cd);
|
||||
c = DtoConstUint(flags);
|
||||
// uint flags
|
||||
if (cd->isInterfaceDeclaration()) {
|
||||
c = cinfo->llvmInitZ->getOperand(8);
|
||||
}
|
||||
else {
|
||||
uint flags = build_classinfo_flags(cd);
|
||||
c = DtoConstUint(flags);
|
||||
}
|
||||
inits.push_back(c);
|
||||
|
||||
// allocator
|
||||
|
@ -682,11 +962,16 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
|||
inits.push_back(c);
|
||||
|
||||
// offset typeinfo
|
||||
c = build_offti_array(cd, cinfo->llvmInitZ->getOperand(10));
|
||||
if (cd->isInterfaceDeclaration()) {
|
||||
c = cinfo->llvmInitZ->getOperand(10);
|
||||
}
|
||||
else {
|
||||
c = build_offti_array(cd, cinfo->llvmInitZ->getOperand(10));
|
||||
}
|
||||
inits.push_back(c);
|
||||
|
||||
// default constructor
|
||||
if (cd->defaultCtor) {
|
||||
if (cd->defaultCtor && !cd->isInterfaceDeclaration()) {
|
||||
DtoForceDeclareDsymbol(cd->defaultCtor);
|
||||
c = isaConstant(cd->defaultCtor->llvmValue);
|
||||
//const llvm::Type* toTy = cinfo->llvmInitZ->getOperand(11)->getType();
|
||||
|
|
|
@ -27,4 +27,7 @@ void DtoDefineClassInfo(ClassDeclaration* cd);
|
|||
void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance);
|
||||
void DtoInitClass(TypeClass* tc, llvm::Value* dst);
|
||||
|
||||
DValue* DtoCastObjectToInterface(DValue* val, Type* to);
|
||||
DValue* DtoCastInterfaceToObject(DValue* val);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -192,7 +192,7 @@ const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
|
|||
if (AggregateDeclaration* ad = fdecl->isMember()) {
|
||||
Logger::print("isMember = this is: %s\n", ad->type->toChars());
|
||||
thisty = DtoType(ad->type);
|
||||
Logger::cout() << "this llvm type: " << *thisty << '\n';
|
||||
//Logger::cout() << "this llvm type: " << *thisty << '\n';
|
||||
if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->recty.get()))
|
||||
thisty = llvm::PointerType::get(thisty);
|
||||
}
|
||||
|
@ -277,7 +277,8 @@ void DtoResolveFunction(FuncDeclaration* fdecl)
|
|||
DtoFunctionType(fdecl);
|
||||
|
||||
// queue declaration
|
||||
gIR->declareList.push_back(fdecl);
|
||||
if (!fdecl->isAbstract())
|
||||
gIR->declareList.push_back(fdecl);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -290,6 +291,8 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
|||
Logger::println("DtoDeclareFunction(%s)", fdecl->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(!fdecl->isAbstract());
|
||||
|
||||
if (fdecl->llvmRunTimeHack) {
|
||||
Logger::println("runtime hack func chars: %s", fdecl->toChars());
|
||||
if (!fdecl->llvmValue)
|
||||
|
|
|
@ -107,6 +107,8 @@ IRStruct::IRStruct(Type* t)
|
|||
type = t;
|
||||
defined = false;
|
||||
constinited = false;
|
||||
interfaceInfosTy = NULL;
|
||||
interfaceInfos = NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <list>
|
||||
|
||||
#include "root.h"
|
||||
#include "aggregate.h"
|
||||
|
||||
// global ir state for current module
|
||||
struct IRState;
|
||||
|
@ -20,6 +21,7 @@ struct ClassDeclaration;
|
|||
struct FuncDeclaration;
|
||||
struct Module;
|
||||
struct TypeStruct;
|
||||
struct BaseClass;
|
||||
|
||||
/*
|
||||
struct LLVMValue
|
||||
|
@ -39,6 +41,32 @@ struct IRScope
|
|||
IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e);
|
||||
};
|
||||
|
||||
struct IRInterface : Object
|
||||
{
|
||||
BaseClass* base;
|
||||
ClassDeclaration* decl;
|
||||
|
||||
const llvm::StructType* vtblTy;
|
||||
llvm::ConstantStruct* vtblInit;
|
||||
llvm::GlobalVariable* vtbl;
|
||||
|
||||
const llvm::StructType* infoTy;
|
||||
llvm::ConstantStruct* infoInit;
|
||||
llvm::Constant* info;
|
||||
|
||||
IRInterface(BaseClass* b, const llvm::StructType* vt)
|
||||
{
|
||||
base = b;
|
||||
decl = b->base;
|
||||
vtblTy = vt;
|
||||
vtblInit = NULL;
|
||||
vtbl = NULL;
|
||||
infoTy = NULL;
|
||||
infoInit = NULL;
|
||||
info = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
// represents a struct or class
|
||||
struct IRStruct : Object
|
||||
{
|
||||
|
@ -54,6 +82,8 @@ struct IRStruct : Object
|
|||
|
||||
typedef std::multimap<unsigned, Offset> OffsetMap;
|
||||
typedef std::vector<VarDeclaration*> VarDeclVector;
|
||||
typedef std::map<ClassDeclaration*, IRInterface*> InterfaceMap;
|
||||
typedef InterfaceMap::iterator InterfaceIter;
|
||||
|
||||
public:
|
||||
IRStruct(Type*);
|
||||
|
@ -63,6 +93,10 @@ public:
|
|||
OffsetMap offsets;
|
||||
VarDeclVector defaultFields;
|
||||
|
||||
InterfaceMap interfaces;
|
||||
const llvm::ArrayType* interfaceInfosTy;
|
||||
llvm::GlobalVariable* interfaceInfos;
|
||||
|
||||
bool defined;
|
||||
bool constinited;
|
||||
};
|
||||
|
|
|
@ -445,7 +445,7 @@ DUnion::DUnion()
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
/*{
|
||||
LOG_SCOPE;
|
||||
Logger::println("******** DUnion BEGIN");
|
||||
size_t n = fields.size();
|
||||
|
@ -458,7 +458,7 @@ DUnion::DUnion()
|
|||
}
|
||||
}
|
||||
Logger::println("******** DUnion END");
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
static void push_nulls(size_t nbytes, std::vector<llvm::Constant*>& out)
|
||||
|
|
52
gen/toir.cpp
52
gen/toir.cpp
|
@ -1230,10 +1230,10 @@ DValue* PtrExp::toElem(IRState* p)
|
|||
|
||||
if (p->topexp() && p->topexp()->e1 == this) {
|
||||
Logger::println("lval PtrExp");
|
||||
//if (a->isField()) return a;
|
||||
return new DVarValue(type, a->getRVal(), true);
|
||||
}
|
||||
|
||||
// this should be deterministic but right now lvalue casts don't propagate lvalueness !?!
|
||||
llvm::Value* lv = a->getRVal();
|
||||
llvm::Value* v = lv;
|
||||
if (DtoCanLoad(v))
|
||||
|
@ -1253,7 +1253,7 @@ DValue* DotVarExp::toElem(IRState* p)
|
|||
Type* t = DtoDType(type);
|
||||
Type* e1type = DtoDType(e1->type);
|
||||
|
||||
Logger::print("e1->type=%s\n", e1type->toChars());
|
||||
Logger::print("e1type=%s\n", e1type->toChars());
|
||||
|
||||
if (VarDeclaration* vd = var->isVarDeclaration()) {
|
||||
llvm::Value* arrptr;
|
||||
|
@ -1265,7 +1265,7 @@ DValue* DotVarExp::toElem(IRState* p)
|
|||
std::vector<unsigned> vdoffsets;
|
||||
arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
|
||||
}
|
||||
else if (e1->type->ty == Tclass) {
|
||||
else if (e1type->ty == Tclass) {
|
||||
TypeClass* tc = (TypeClass*)e1type;
|
||||
Logger::println("Class member offset: %d", vd->offset);
|
||||
std::vector<unsigned> vdoffsets(1,0);
|
||||
|
@ -1282,14 +1282,19 @@ DValue* DotVarExp::toElem(IRState* p)
|
|||
}
|
||||
else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
|
||||
{
|
||||
if (fdecl->llvmValue == 0)
|
||||
{
|
||||
DtoForceDeclareDsymbol(fdecl);
|
||||
}
|
||||
DtoResolveDsymbol(fdecl);
|
||||
|
||||
llvm::Value* funcval = fdecl->llvmValue;
|
||||
llvm::Value* funcval;
|
||||
llvm::Value* vthis2 = 0;
|
||||
if (e1type->ty == Tclass) {
|
||||
TypeClass* tc = (TypeClass*)e1type;
|
||||
if (tc->sym->isInterfaceDeclaration()) {
|
||||
vthis2 = DtoCastInterfaceToObject(l)->getRVal();
|
||||
}
|
||||
}
|
||||
llvm::Value* vthis = l->getRVal();
|
||||
unsigned cc = (unsigned)-1;
|
||||
if (!vthis2) vthis2 = vthis;
|
||||
//unsigned cc = (unsigned)-1;
|
||||
|
||||
// virtual call
|
||||
if (!fdecl->isFinal() && fdecl->isVirtual()) {
|
||||
|
@ -1303,10 +1308,17 @@ DValue* DotVarExp::toElem(IRState* p)
|
|||
funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
|
||||
funcval = DtoGEP(funcval, zero, vtblidx, toChars(), p->scopebb());
|
||||
funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
|
||||
assert(funcval->getType() == fdecl->llvmValue->getType());
|
||||
cc = DtoCallingConv(fdecl->linkage);
|
||||
//assert(funcval->getType() == DtoType(fdecl->type));
|
||||
//cc = DtoCallingConv(fdecl->linkage);
|
||||
}
|
||||
return new DFuncValue(fdecl, funcval, vthis);
|
||||
// static call
|
||||
else {
|
||||
DtoForceDeclareDsymbol(fdecl);
|
||||
funcval = fdecl->llvmValue;
|
||||
assert(funcval);
|
||||
//assert(funcval->getType() == DtoType(fdecl->type));
|
||||
}
|
||||
return new DFuncValue(fdecl, funcval, vthis2);
|
||||
}
|
||||
else {
|
||||
printf("unknown: %s\n", var->toChars());
|
||||
|
@ -1829,15 +1841,14 @@ DValue* DeleteExp::toElem(IRState* p)
|
|||
//assert(e1->type->ty != Tclass);
|
||||
|
||||
DValue* v = e1->toElem(p);
|
||||
llvm::Value* val = v->getRVal();
|
||||
const llvm::Type* t = DtoType(v->getType());
|
||||
llvm::Value* ldval = 0;
|
||||
|
||||
const llvm::Type* t = val->getType();
|
||||
llvm::Constant* z = llvm::Constant::getNullValue(t);
|
||||
|
||||
Type* e1type = DtoDType(e1->type);
|
||||
|
||||
if (e1type->ty == Tpointer) {
|
||||
llvm::Value* val = v->getRVal();
|
||||
Logger::cout() << *z << '\n';
|
||||
Logger::cout() << *val << '\n';
|
||||
new llvm::FreeInst(val, p->scopebb());
|
||||
|
@ -1845,16 +1856,23 @@ DValue* DeleteExp::toElem(IRState* p)
|
|||
}
|
||||
else if (e1type->ty == Tclass) {
|
||||
TypeClass* tc = (TypeClass*)e1type;
|
||||
DtoCallClassDtors(tc, val);
|
||||
llvm::Value* val = 0;
|
||||
if (tc->sym->dtors.dim > 0) {
|
||||
val = v->getRVal();
|
||||
DtoCallClassDtors(tc, val);
|
||||
}
|
||||
|
||||
if (DVarValue* vv = v->isVar()) {
|
||||
if (vv->var && !vv->var->onstack)
|
||||
if (vv->var && !vv->var->onstack) {
|
||||
if (!val) val = v->getRVal();
|
||||
new llvm::FreeInst(val, p->scopebb());
|
||||
}
|
||||
}
|
||||
new llvm::StoreInst(z, v->getLVal(), p->scopebb());
|
||||
}
|
||||
else if (e1type->ty == Tarray) {
|
||||
// must be on the heap (correct?)
|
||||
llvm::Value* val = v->getRVal();
|
||||
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
||||
llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
|
||||
llvm::Value* ptr = DtoGEP(val,zero,one,"tmp",p->scopebb());
|
||||
|
|
|
@ -1140,11 +1140,35 @@ DValue* DtoCastComplex(DValue* val, Type* _to)
|
|||
|
||||
DValue* DtoCastClass(DValue* val, Type* _to)
|
||||
{
|
||||
const llvm::Type* tolltype = DtoType(_to);
|
||||
Type* to = DtoDType(_to);
|
||||
assert(to->ty == Tclass || to->ty == Tpointer);
|
||||
llvm::Value* rval = new llvm::BitCastInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
|
||||
return new DImValue(_to, rval);
|
||||
if (to->ty == Tpointer) {
|
||||
const llvm::Type* tolltype = DtoType(_to);
|
||||
llvm::Value* rval = DtoBitCast(val->getRVal(), tolltype);
|
||||
return new DImValue(_to, rval);
|
||||
}
|
||||
|
||||
assert(to->ty == Tclass);
|
||||
TypeClass* tc = (TypeClass*)to;
|
||||
|
||||
Type* from = DtoDType(val->getType());
|
||||
TypeClass* fc = (TypeClass*)from;
|
||||
|
||||
if (tc->sym->isInterfaceDeclaration()) {
|
||||
assert(!fc->sym->isInterfaceDeclaration());
|
||||
return DtoCastObjectToInterface(val, _to);
|
||||
}
|
||||
else {
|
||||
if (fc->sym->isInterfaceDeclaration()) {
|
||||
assert(0);
|
||||
return DtoCastInterfaceToObject(val);
|
||||
}
|
||||
else {
|
||||
const llvm::Type* tolltype = DtoType(_to);
|
||||
assert(to->ty == Tclass);
|
||||
llvm::Value* rval = DtoBitCast(val->getRVal(), tolltype);
|
||||
return new DImValue(_to, rval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DValue* DtoCast(DValue* val, Type* to)
|
||||
|
|
|
@ -389,7 +389,9 @@ void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>
|
|||
unsigned idx = 0;
|
||||
unsigned r = LLVM_ClassOffsetToIndex(this, os, idx);
|
||||
assert(r != (unsigned)-1 && "Offset not found in any aggregate field");
|
||||
result.push_back(r+1); // vtable is 0
|
||||
r++; // vtable is 0
|
||||
r += vtblInterfaces->dim;
|
||||
result.push_back(r);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
|
|
151
gen/typinf.cpp
151
gen/typinf.cpp
|
@ -1029,76 +1029,127 @@ void TypeInfoClassDeclaration::toDt(dt_t **pdt)
|
|||
|
||||
void TypeInfoInterfaceDeclaration::llvmDeclare()
|
||||
{
|
||||
assert(0 && "TypeInfoTupleDeclaration");
|
||||
Logger::println("TypeInfoInterfaceDeclaration::llvmDeclare() %s", toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
// init typeinfo class
|
||||
ClassDeclaration* base = Type::typeinfointerface;
|
||||
assert(base);
|
||||
DtoResolveClass(base);
|
||||
|
||||
// get type of typeinfo class
|
||||
const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
|
||||
|
||||
// create the symbol
|
||||
llvmValue = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
|
||||
}
|
||||
|
||||
void TypeInfoInterfaceDeclaration::llvmDefine()
|
||||
{
|
||||
assert(0 && "TypeInfoTupleDeclaration");
|
||||
Logger::println("TypeInfoInterfaceDeclaration::llvmDefine() %s", toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
// init typeinfo class
|
||||
ClassDeclaration* base = Type::typeinfointerface;
|
||||
assert(base);
|
||||
DtoForceConstInitDsymbol(base);
|
||||
|
||||
// get type of typeinfo class
|
||||
const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
|
||||
|
||||
// initializer vector
|
||||
std::vector<llvm::Constant*> sinits;
|
||||
// first is always the vtable
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
|
||||
// get classinfo
|
||||
assert(tinfo->ty == Tclass);
|
||||
TypeClass *tc = (TypeClass *)tinfo;
|
||||
assert(tc->sym->llvmClass);
|
||||
sinits.push_back(tc->sym->llvmClass);
|
||||
|
||||
// create the symbol
|
||||
llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
|
||||
isaGlobalVar(llvmValue)->setInitializer(tiInit);
|
||||
}
|
||||
|
||||
void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt)
|
||||
{
|
||||
assert(0 && "TypeInfoInterfaceDeclaration");
|
||||
|
||||
/*
|
||||
//printf("TypeInfoInterfaceDeclaration::toDt() %s\n", tinfo->toChars());
|
||||
dtxoff(pdt, Type::typeinfointerface->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface
|
||||
dtdword(pdt, 0); // monitor
|
||||
|
||||
assert(tinfo->ty == Tclass);
|
||||
|
||||
TypeClass *tc = (TypeClass *)tinfo;
|
||||
Symbol *s;
|
||||
|
||||
if (!tc->sym->vclassinfo)
|
||||
tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym);
|
||||
s = tc->sym->vclassinfo->toSymbol();
|
||||
dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo
|
||||
*/
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
void TypeInfoTupleDeclaration::llvmDeclare()
|
||||
{
|
||||
assert(0 && "TypeInfoTupleDeclaration");
|
||||
Logger::println("TypeInfoTupleDeclaration::llvmDeclare() %s", toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
// init typeinfo class
|
||||
ClassDeclaration* base = Type::typeinfotypelist;
|
||||
assert(base);
|
||||
DtoResolveClass(base);
|
||||
|
||||
// get type of typeinfo class
|
||||
const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
|
||||
|
||||
// create the symbol
|
||||
llvmValue = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
|
||||
}
|
||||
|
||||
void TypeInfoTupleDeclaration::llvmDefine()
|
||||
{
|
||||
assert(0 && "TypeInfoTupleDeclaration");
|
||||
Logger::println("TypeInfoTupleDeclaration::llvmDefine() %s", toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
// init typeinfo class
|
||||
ClassDeclaration* base = Type::typeinfotypelist;
|
||||
assert(base);
|
||||
DtoForceConstInitDsymbol(base);
|
||||
|
||||
// get type of typeinfo class
|
||||
const llvm::StructType* stype = isaStruct(base->type->llvmType->get());
|
||||
|
||||
// initializer vector
|
||||
std::vector<llvm::Constant*> sinits;
|
||||
// first is always the vtable
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
|
||||
// create elements array
|
||||
assert(tinfo->ty == Ttuple);
|
||||
TypeTuple *tu = (TypeTuple *)tinfo;
|
||||
|
||||
size_t dim = tu->arguments->dim;
|
||||
std::vector<llvm::Constant*> arrInits;
|
||||
|
||||
const llvm::Type* tiTy = Type::typeinfo->type->llvmType->get();
|
||||
tiTy = llvm::PointerType::get(tiTy);
|
||||
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{
|
||||
Argument *arg = (Argument *)tu->arguments->data[i];
|
||||
arg->type->getTypeInfo(NULL);
|
||||
DtoForceDeclareDsymbol(arg->type->vtinfo);
|
||||
assert(arg->type->vtinfo->llvmValue);
|
||||
llvm::Constant* c = isaConstant(arg->type->vtinfo->llvmValue);
|
||||
c = llvm::ConstantExpr::getBitCast(c, tiTy);
|
||||
arrInits.push_back(c);
|
||||
}
|
||||
|
||||
// build array type
|
||||
const llvm::ArrayType* arrTy = llvm::ArrayType::get(tiTy, dim);
|
||||
llvm::Constant* arrC = llvm::ConstantArray::get(arrTy, arrInits);
|
||||
|
||||
// build the slice
|
||||
llvm::Constant* slice = DtoConstSlice(DtoConstSize_t(dim), arrC);
|
||||
sinits.push_back(slice);
|
||||
|
||||
// create the symbol
|
||||
llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
|
||||
isaGlobalVar(llvmValue)->setInitializer(tiInit);
|
||||
}
|
||||
|
||||
void TypeInfoTupleDeclaration::toDt(dt_t **pdt)
|
||||
{
|
||||
assert(0 && "TypeInfoTupleDeclaration");
|
||||
|
||||
/*
|
||||
//printf("TypeInfoTupleDeclaration::toDt() %s\n", tinfo->toChars());
|
||||
dtxoff(pdt, Type::typeinfotypelist->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface
|
||||
dtdword(pdt, 0); // monitor
|
||||
|
||||
assert(tinfo->ty == Ttuple);
|
||||
|
||||
TypeTuple *tu = (TypeTuple *)tinfo;
|
||||
|
||||
size_t dim = tu->arguments->dim;
|
||||
dtdword(pdt, dim); // elements.length
|
||||
|
||||
dt_t *d = NULL;
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{ Argument *arg = (Argument *)tu->arguments->data[i];
|
||||
Expression *e = arg->type->getTypeInfo(NULL);
|
||||
e = e->optimize(WANTvalue);
|
||||
e->toDt(&d);
|
||||
}
|
||||
|
||||
Symbol *s;
|
||||
s = static_sym();
|
||||
s->Sdt = d;
|
||||
outdata(s);
|
||||
|
||||
dtxoff(pdt, s, 0, TYnptr); // elements.ptr
|
||||
*/
|
||||
assert(0);
|
||||
}
|
||||
|
|
|
@ -148,6 +148,7 @@ lphobos/internal/aApplyR.d
|
|||
lphobos/internal/aaA.d
|
||||
lphobos/internal/adi.d
|
||||
lphobos/internal/arrays.d
|
||||
lphobos/internal/cast.d
|
||||
lphobos/internal/contract.d
|
||||
lphobos/internal/mem.d
|
||||
lphobos/internal/moduleinit.d
|
||||
|
@ -338,7 +339,6 @@ test/classinfo1.d
|
|||
test/classinfo2.d
|
||||
test/classinfo3.d
|
||||
test/classinfo4.d
|
||||
test/classinfo5.d
|
||||
test/comma.d
|
||||
test/complex1.d
|
||||
test/complex2.d
|
||||
|
@ -378,6 +378,10 @@ test/imag1.d
|
|||
test/imports2.d
|
||||
test/imports_1of2.d
|
||||
test/imports_2of2.d
|
||||
test/interface1.d
|
||||
test/interface2.d
|
||||
test/interface3.d
|
||||
test/interface4.d
|
||||
test/intrinsics.d
|
||||
test/mainargs1.d
|
||||
test/memory1.d
|
||||
|
|
|
@ -27,6 +27,10 @@ echo "compiling typeinfo 2"
|
|||
rebuild typeinfos2.d -c -oqobj -dc=llvmdc-posix || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo2.*.bc` ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "compiling object/interface casting runtime support"
|
||||
llvmdc internal/cast.d -c -odobj || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc obj/cast.bc ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "compiling string foreach runtime support"
|
||||
llvmdc internal/aApply.d -c -odobj || exit 1
|
||||
llvmdc internal/aApplyR.d -c -odobj || exit 1
|
||||
|
|
182
lphobos/internal/cast.d
Normal file
182
lphobos/internal/cast.d
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
|
||||
import object;
|
||||
import std.c.stdio;
|
||||
|
||||
extern (C):
|
||||
|
||||
/******************************************
|
||||
* Given a pointer:
|
||||
* If it is an Object, return that Object.
|
||||
* If it is an interface, return the Object implementing the interface.
|
||||
* If it is null, return null.
|
||||
* Else, undefined crash
|
||||
*/
|
||||
|
||||
Object _d_toObject(void* p)
|
||||
{ Object o;
|
||||
|
||||
if (p)
|
||||
{
|
||||
o = cast(Object)p;
|
||||
//ClassInfo oc = o.classinfo;
|
||||
Interface *pi = **cast(Interface ***)p;
|
||||
|
||||
/* Interface.offset lines up with ClassInfo.name.ptr,
|
||||
* so we rely on pointers never being less than 64K,
|
||||
* and Objects never being greater.
|
||||
*/
|
||||
if (pi.offset < 0x10000)
|
||||
{
|
||||
//printf("\tpi.offset = %d\n", pi.offset);
|
||||
o = cast(Object)(p - pi.offset);
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* Attempts to cast Object o to class c.
|
||||
* Returns o if successful, null if not.
|
||||
*/
|
||||
|
||||
Object _d_interface_cast(void* p, ClassInfo c)
|
||||
{ Object o;
|
||||
|
||||
//printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name);
|
||||
if (p)
|
||||
{
|
||||
Interface *pi = **cast(Interface ***)p;
|
||||
|
||||
//printf("\tpi.offset = %d\n", pi.offset);
|
||||
o = cast(Object)(p - pi.offset);
|
||||
return _d_dynamic_cast(o, c);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
Object _d_dynamic_cast(Object o, ClassInfo c)
|
||||
{ ClassInfo oc;
|
||||
uint offset = 0;
|
||||
|
||||
//printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name);
|
||||
|
||||
if (o)
|
||||
{
|
||||
oc = o.classinfo;
|
||||
if (_d_isbaseof2(oc, c, offset))
|
||||
{
|
||||
//printf("\toffset = %d\n", offset);
|
||||
o = cast(Object)(cast(void*)o + offset);
|
||||
}
|
||||
else
|
||||
o = null;
|
||||
}
|
||||
//printf("\tresult = %p\n", o);
|
||||
return o;
|
||||
}
|
||||
|
||||
int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout uint offset)
|
||||
{ int i;
|
||||
|
||||
if (oc is c)
|
||||
return 1;
|
||||
do
|
||||
{
|
||||
if (oc.base is c)
|
||||
return 1;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (ic is c)
|
||||
{ offset = oc.interfaces[i].offset;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (_d_isbaseof2(ic, c, offset))
|
||||
{ offset = oc.interfaces[i].offset;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
oc = oc.base;
|
||||
} while (oc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _d_isbaseof(ClassInfo oc, ClassInfo c)
|
||||
{ int i;
|
||||
|
||||
if (oc is c)
|
||||
return 1;
|
||||
do
|
||||
{
|
||||
if (oc.base is c)
|
||||
return 1;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (ic is c || _d_isbaseof(ic, c))
|
||||
return 1;
|
||||
}
|
||||
oc = oc.base;
|
||||
} while (oc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* Find the vtbl[] associated with Interface ic.
|
||||
*/
|
||||
|
||||
void *_d_interface_vtbl(ClassInfo ic, Object o)
|
||||
{ int i;
|
||||
ClassInfo oc;
|
||||
|
||||
//printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic);
|
||||
|
||||
assert(o);
|
||||
|
||||
oc = o.classinfo;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo oic;
|
||||
|
||||
oic = oc.interfaces[i].classinfo;
|
||||
if (oic is ic)
|
||||
{
|
||||
return cast(void *)oc.interfaces[i].vtbl;
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
}
|
|
@ -879,8 +879,6 @@ class TypeInfo_Class : TypeInfo
|
|||
ClassInfo info;
|
||||
}
|
||||
|
||||
/+
|
||||
|
||||
class TypeInfo_Interface : TypeInfo
|
||||
{
|
||||
char[] toString() { return info.name; }
|
||||
|
@ -944,8 +942,6 @@ class TypeInfo_Interface : TypeInfo
|
|||
ClassInfo info;
|
||||
}
|
||||
|
||||
+/
|
||||
|
||||
class TypeInfo_Struct : TypeInfo
|
||||
{
|
||||
char[] toString() { return name; }
|
||||
|
@ -1038,8 +1034,6 @@ class TypeInfo_Struct : TypeInfo
|
|||
uint m_flags;
|
||||
}
|
||||
|
||||
/+
|
||||
|
||||
class TypeInfo_Tuple : TypeInfo
|
||||
{
|
||||
TypeInfo[] elements;
|
||||
|
@ -1102,8 +1096,6 @@ class TypeInfo_Tuple : TypeInfo
|
|||
}
|
||||
}
|
||||
|
||||
+/
|
||||
|
||||
class TypeInfo_Const : TypeInfo
|
||||
{
|
||||
char[] toString() { return "const " ~ base.toString(); }
|
||||
|
|
22
test/interface1.d
Normal file
22
test/interface1.d
Normal file
|
@ -0,0 +1,22 @@
|
|||
module interface1;
|
||||
|
||||
interface Inter
|
||||
{
|
||||
void func();
|
||||
}
|
||||
|
||||
class Class : Inter
|
||||
{
|
||||
override void func()
|
||||
{
|
||||
printf("hello world\n");
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
scope c = new Class;
|
||||
c.func();
|
||||
Inter i = c;
|
||||
i.func();
|
||||
}
|
35
test/interface2.d
Normal file
35
test/interface2.d
Normal file
|
@ -0,0 +1,35 @@
|
|||
module interface2;
|
||||
|
||||
interface A
|
||||
{
|
||||
void a();
|
||||
}
|
||||
|
||||
interface B
|
||||
{
|
||||
void b();
|
||||
}
|
||||
|
||||
class C : A,B
|
||||
{
|
||||
int i = 0;
|
||||
override void a()
|
||||
{
|
||||
printf("hello from C.a\n");
|
||||
}
|
||||
override void b()
|
||||
{
|
||||
printf("hello from C.b\n");
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
scope c = new C;
|
||||
{c.a();
|
||||
c.b();}
|
||||
{A a = c;
|
||||
a.a();}
|
||||
{B b = c;
|
||||
b.b();}
|
||||
}
|
28
test/interface3.d
Normal file
28
test/interface3.d
Normal file
|
@ -0,0 +1,28 @@
|
|||
module interface3;
|
||||
|
||||
interface I
|
||||
{
|
||||
void func();
|
||||
}
|
||||
|
||||
class C : I
|
||||
{
|
||||
int i = 42;
|
||||
override void func()
|
||||
{
|
||||
printf("hello %d\n", i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
scope c = new C;
|
||||
{c.func();}
|
||||
{
|
||||
I i = c;
|
||||
{i.func();}
|
||||
}
|
||||
{printf("final %d\n", c.i);}
|
||||
{assert(c.i == 44);}
|
||||
}
|
33
test/interface4.d
Normal file
33
test/interface4.d
Normal file
|
@ -0,0 +1,33 @@
|
|||
module interface4;
|
||||
|
||||
interface I
|
||||
{
|
||||
void func();
|
||||
}
|
||||
|
||||
interface I2
|
||||
{
|
||||
void func();
|
||||
}
|
||||
|
||||
class C : I,I2
|
||||
{
|
||||
int i = 42;
|
||||
override void func()
|
||||
{
|
||||
printf("hello %d\n", i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
scope c = new C;
|
||||
c.func();
|
||||
I i = c;
|
||||
i.func();
|
||||
I2 i2 = c;
|
||||
i2.func();
|
||||
printf("final %d\n", c.i);
|
||||
assert(c.i == 45);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue