mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-14 07:09:50 +03:00
Changed some hardcoded offset/alignment for classes in DMD, broke offsets for 64bits.
Changed ClassInfo generation to no longer access the default initializer of ClassInfo, fixes problems with index mismatch.
This commit is contained in:
parent
81eded2ece
commit
577237e073
5 changed files with 136 additions and 149 deletions
|
@ -551,8 +551,8 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||||
// sc->offset += PTRSIZE; // room for uplevel context pointer
|
// sc->offset += PTRSIZE; // room for uplevel context pointer
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ sc->offset = 8; // allow room for vptr[] and monitor
|
{ sc->offset = 2*PTRSIZE; // allow room for vptr[] and monitor
|
||||||
alignsize = 4;
|
alignsize = PTRSIZE;
|
||||||
}
|
}
|
||||||
structsize = sc->offset;
|
structsize = sc->offset;
|
||||||
Scope scsave = *sc;
|
Scope scsave = *sc;
|
||||||
|
@ -1139,7 +1139,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||||
sc->linkage = LINKwindows;
|
sc->linkage = LINKwindows;
|
||||||
sc->structalign = 8;
|
sc->structalign = 8;
|
||||||
structalign = sc->structalign;
|
structalign = sc->structalign;
|
||||||
sc->offset = 8;
|
sc->offset = 2*PTRSIZE;
|
||||||
inuse++;
|
inuse++;
|
||||||
for (i = 0; i < members->dim; i++)
|
for (i = 0; i < members->dim; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -559,7 +559,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ sc->offset = PTRSIZE * 2; // allow room for __vptr and __monitor
|
{ sc->offset = PTRSIZE * 2; // allow room for __vptr and __monitor
|
||||||
alignsize = 4;
|
alignsize = PTRSIZE;
|
||||||
}
|
}
|
||||||
structsize = sc->offset;
|
structsize = sc->offset;
|
||||||
Scope scsave = *sc;
|
Scope scsave = *sc;
|
||||||
|
|
273
gen/classes.cpp
273
gen/classes.cpp
|
@ -75,6 +75,8 @@ static void add_interface(ClassDeclaration* target, BaseClass* b, int newinstanc
|
||||||
iri->index = irstruct->index++;
|
iri->index = irstruct->index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static void add_class_data(ClassDeclaration* target, ClassDeclaration* cd)
|
static void add_class_data(ClassDeclaration* target, ClassDeclaration* cd)
|
||||||
{
|
{
|
||||||
Logger::println("Adding data from class: %s", cd->toChars());
|
Logger::println("Adding data from class: %s", cd->toChars());
|
||||||
|
@ -443,7 +445,7 @@ static size_t init_class_initializer(std::vector<LLConstant*>& inits, ClassDecla
|
||||||
std::vector<VarDeclaration*> defVars;
|
std::vector<VarDeclaration*> defVars;
|
||||||
defVars.reserve(nfields);
|
defVars.reserve(nfields);
|
||||||
|
|
||||||
size_t lastoffset = offsetbegin; // vtbl,monitor
|
size_t lastoffset = offsetbegin;
|
||||||
size_t lastsize = 0;
|
size_t lastsize = 0;
|
||||||
|
|
||||||
// find fields that contribute to default
|
// find fields that contribute to default
|
||||||
|
@ -455,13 +457,21 @@ static size_t init_class_initializer(std::vector<LLConstant*>& inits, ClassDecla
|
||||||
size_t size = var->type->size();
|
size_t size = var->type->size();
|
||||||
if (offset >= lastoffset+lastsize)
|
if (offset >= lastoffset+lastsize)
|
||||||
{
|
{
|
||||||
Logger::println(" added");
|
Logger::println(" added %s", var->toChars());
|
||||||
lastoffset = offset;
|
lastoffset = offset;
|
||||||
lastsize = size;
|
lastsize = size;
|
||||||
defVars.push_back(var);
|
defVars.push_back(var);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger::println(" skipped %s", var->toChars());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset offsets, we're going from beginning again
|
||||||
|
lastoffset = offsetbegin;
|
||||||
|
lastsize = 0;
|
||||||
|
|
||||||
// go through the default vars and build the default constant initializer
|
// go through the default vars and build the default constant initializer
|
||||||
// adding zeros along the way to live up to alignment expectations
|
// adding zeros along the way to live up to alignment expectations
|
||||||
size_t nvars = defVars.size();
|
size_t nvars = defVars.size();
|
||||||
|
@ -760,11 +770,13 @@ static void DefineInterfaceInfos(IrStruct* irstruct)
|
||||||
{
|
{
|
||||||
// always do interface info array when possible
|
// always do interface info array when possible
|
||||||
std::vector<LLConstant*> infoInits;
|
std::vector<LLConstant*> infoInits;
|
||||||
infoInits.reserve(irstruct->interfaceVec.size());
|
|
||||||
|
|
||||||
for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i)
|
size_t n = irstruct->interfaceVec.size();
|
||||||
|
infoInits.reserve(n);
|
||||||
|
|
||||||
|
for (size_t i=0; i < n; i++)
|
||||||
{
|
{
|
||||||
IrInterface* iri = *i;
|
IrInterface* iri = irstruct->interfaceVec[i];
|
||||||
assert(iri->infoInit);
|
assert(iri->infoInit);
|
||||||
infoInits.push_back(iri->infoInit);
|
infoInits.push_back(iri->infoInit);
|
||||||
}
|
}
|
||||||
|
@ -834,13 +846,13 @@ void DtoDefineClass(ClassDeclaration* cd)
|
||||||
assert(irstruct->vtbl);
|
assert(irstruct->vtbl);
|
||||||
assert(irstruct->constVtbl);
|
assert(irstruct->constVtbl);
|
||||||
|
|
||||||
if (Logger::enabled())
|
// if (Logger::enabled())
|
||||||
{
|
// {
|
||||||
Logger::cout() << "initZ: " << *irstruct->init << std::endl;
|
// Logger::cout() << "initZ: " << *irstruct->init << std::endl;
|
||||||
Logger::cout() << "cinitZ: " << *irstruct->constInit << std::endl;
|
// Logger::cout() << "cinitZ: " << *irstruct->constInit << std::endl;
|
||||||
Logger::cout() << "vtblZ: " << *irstruct->vtbl << std::endl;
|
// Logger::cout() << "vtblZ: " << *irstruct->vtbl << std::endl;
|
||||||
Logger::cout() << "cvtblZ: " << *irstruct->constVtbl << std::endl;
|
// Logger::cout() << "cvtblZ: " << *irstruct->constVtbl << std::endl;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// set initializers
|
// set initializers
|
||||||
irstruct->init->setInitializer(irstruct->constInit);
|
irstruct->init->setInitializer(irstruct->constInit);
|
||||||
|
@ -1184,29 +1196,6 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
|
|
||||||
{
|
|
||||||
// start at the bottom of the inheritance chain
|
|
||||||
if (cd->baseClass != 0) {
|
|
||||||
unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx);
|
|
||||||
if (o != (unsigned)-1)
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check this class
|
|
||||||
unsigned i;
|
|
||||||
for (i=0; i<cd->fields.dim; ++i) {
|
|
||||||
VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i];
|
|
||||||
if (os == vd->offset)
|
|
||||||
return i+idx;
|
|
||||||
}
|
|
||||||
idx += i;
|
|
||||||
|
|
||||||
return (unsigned)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd)
|
LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd)
|
||||||
{
|
{
|
||||||
Logger::println("indexing class field %s:", vd->toPrettyChars());
|
Logger::println("indexing class field %s:", vd->toPrettyChars());
|
||||||
|
@ -1255,24 +1244,31 @@ LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd)
|
||||||
|
|
||||||
LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl)
|
LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl)
|
||||||
{
|
{
|
||||||
assert(fdecl->isVirtual());//fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual()));
|
// sanity checks
|
||||||
assert(fdecl->vtblIndex > 0);
|
assert(fdecl->isVirtual());
|
||||||
|
assert(fdecl->vtblIndex > 0); // 0 is always ClassInfo/Interface*
|
||||||
assert(inst->getType()->toBasetype()->ty == Tclass);
|
assert(inst->getType()->toBasetype()->ty == Tclass);
|
||||||
|
|
||||||
|
// get instance
|
||||||
LLValue* vthis = inst->getRVal();
|
LLValue* vthis = inst->getRVal();
|
||||||
if (Logger::enabled())
|
if (Logger::enabled())
|
||||||
Logger::cout() << "vthis: " << *vthis << '\n';
|
Logger::cout() << "vthis: " << *vthis << '\n';
|
||||||
|
|
||||||
LLValue* funcval = vthis;
|
LLValue* funcval = vthis;
|
||||||
if (!fdecl->isMember2()->isInterfaceDeclaration())
|
// get the vtbl for objects
|
||||||
|
if (!fdecl->isMember()->isInterfaceDeclaration())
|
||||||
funcval = DtoGEPi(funcval, 0, 0, "tmp");
|
funcval = DtoGEPi(funcval, 0, 0, "tmp");
|
||||||
|
// load vtbl ptr
|
||||||
funcval = DtoLoad(funcval);
|
funcval = DtoLoad(funcval);
|
||||||
|
// index vtbl
|
||||||
funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toChars());
|
funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toChars());
|
||||||
|
// load funcptr
|
||||||
funcval = DtoLoad(funcval);
|
funcval = DtoLoad(funcval);
|
||||||
|
|
||||||
if (Logger::enabled())
|
if (Logger::enabled())
|
||||||
Logger::cout() << "funcval: " << *funcval << '\n';
|
Logger::cout() << "funcval: " << *funcval << '\n';
|
||||||
|
|
||||||
|
// cast to final funcptr type
|
||||||
funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type)));
|
funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type)));
|
||||||
if (Logger::enabled())
|
if (Logger::enabled())
|
||||||
Logger::cout() << "funcval casted: " << *funcval << '\n';
|
Logger::cout() << "funcval casted: " << *funcval << '\n';
|
||||||
|
@ -1292,9 +1288,11 @@ void DtoDeclareClassInfo(ClassDeclaration* cd)
|
||||||
Logger::println("DtoDeclareClassInfo(%s)", cd->toChars());
|
Logger::println("DtoDeclareClassInfo(%s)", cd->toChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
// resovle ClassInfo
|
||||||
ClassDeclaration* cinfo = ClassDeclaration::classinfo;
|
ClassDeclaration* cinfo = ClassDeclaration::classinfo;
|
||||||
DtoResolveClass(cinfo);
|
DtoResolveClass(cinfo);
|
||||||
|
|
||||||
|
// do the mangle
|
||||||
std::string gname("_D");
|
std::string gname("_D");
|
||||||
gname.append(cd->mangle());
|
gname.append(cd->mangle());
|
||||||
if (!cd->isInterfaceDeclaration())
|
if (!cd->isInterfaceDeclaration())
|
||||||
|
@ -1302,74 +1300,67 @@ void DtoDeclareClassInfo(ClassDeclaration* cd)
|
||||||
else
|
else
|
||||||
gname.append("11__InterfaceZ");
|
gname.append("11__InterfaceZ");
|
||||||
|
|
||||||
|
// create global
|
||||||
irstruct->classInfo = new llvm::GlobalVariable(irstruct->classInfoOpaque.get(), false, DtoLinkage(cd), NULL, gname, gIR->module);
|
irstruct->classInfo = new llvm::GlobalVariable(irstruct->classInfoOpaque.get(), false, DtoLinkage(cd), NULL, gname, gIR->module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// build a single element for the OffsetInfo[] of ClassInfo
|
||||||
static LLConstant* build_offti_entry(ClassDeclaration* cd, VarDeclaration* vd)
|
static LLConstant* build_offti_entry(ClassDeclaration* cd, VarDeclaration* vd)
|
||||||
{
|
{
|
||||||
std::vector<const LLType*> types;
|
std::vector<LLConstant*> inits(2);
|
||||||
std::vector<LLConstant*> inits;
|
|
||||||
|
|
||||||
types.push_back(DtoSize_t());
|
|
||||||
|
|
||||||
|
// size_t offset;
|
||||||
|
//
|
||||||
assert(vd->ir.irField);
|
assert(vd->ir.irField);
|
||||||
|
// grab the offset from llvm and the formal class type
|
||||||
size_t offset = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(vd->ir.irField->index);
|
size_t offset = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(vd->ir.irField->index);
|
||||||
|
// offset nested struct/union fields
|
||||||
offset += vd->ir.irField->unionOffset;
|
offset += vd->ir.irField->unionOffset;
|
||||||
inits.push_back(DtoConstSize_t(offset));
|
|
||||||
|
|
||||||
LLConstant* c = DtoTypeInfoOf(vd->type, true);
|
// assert that it matches DMD
|
||||||
const LLType* tiTy = c->getType();
|
Logger::println("offsets: %lu vs %u", offset, vd->offset);
|
||||||
//Logger::cout() << "tiTy = " << *tiTy << '\n';
|
assert(offset == vd->offset);
|
||||||
|
|
||||||
types.push_back(tiTy);
|
inits[0] = DtoConstSize_t(offset);
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
const llvm::StructType* sTy = llvm::StructType::get(types);
|
// TypeInfo ti;
|
||||||
return llvm::ConstantStruct::get(sTy, inits);
|
inits[1] = DtoTypeInfoOf(vd->type, true);
|
||||||
|
|
||||||
|
// done
|
||||||
|
return llvm::ConstantStruct::get(inits);
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLConstant* build_offti_array(ClassDeclaration* cd, LLConstant* init)
|
static LLConstant* build_offti_array(ClassDeclaration* cd, const LLType* arrayT)
|
||||||
{
|
{
|
||||||
const llvm::StructType* initTy = isaStruct(init->getType());
|
IrStruct* irstruct = cd->ir.irStruct;
|
||||||
assert(initTy);
|
|
||||||
|
|
||||||
std::vector<LLConstant*> arrayInits;
|
size_t nvars = irstruct->varDecls.size();
|
||||||
|
std::vector<LLConstant*> arrayInits(nvars);
|
||||||
VarDeclaration** fields = &cd->ir.irStruct->varDecls[0];
|
|
||||||
size_t nvars = cd->ir.irStruct->varDecls.size();
|
|
||||||
|
|
||||||
for (size_t i=0; i<nvars; i++)
|
for (size_t i=0; i<nvars; i++)
|
||||||
{
|
{
|
||||||
LLConstant* c = build_offti_entry(cd, fields[i]);
|
arrayInits[i] = build_offti_entry(cd, irstruct->varDecls[i]);
|
||||||
assert(c);
|
|
||||||
arrayInits.push_back(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ninits = arrayInits.size();
|
LLConstant* size = DtoConstSize_t(nvars);
|
||||||
LLConstant* size = DtoConstSize_t(ninits);
|
|
||||||
LLConstant* ptr;
|
LLConstant* ptr;
|
||||||
|
|
||||||
if (ninits > 0) {
|
if (nvars == 0)
|
||||||
// OffsetTypeInfo type
|
return LLConstant::getNullValue( arrayT );
|
||||||
std::vector<const LLType*> elemtypes;
|
|
||||||
elemtypes.push_back(DtoSize_t());
|
|
||||||
const LLType* tiTy = getPtrToType(Type::typeinfo->type->ir.type->get());
|
|
||||||
elemtypes.push_back(tiTy);
|
|
||||||
const llvm::StructType* sTy = llvm::StructType::get(elemtypes);
|
|
||||||
|
|
||||||
// array type
|
// array type
|
||||||
const llvm::ArrayType* arrTy = llvm::ArrayType::get(sTy, ninits);
|
const llvm::ArrayType* arrTy = llvm::ArrayType::get(arrayInits[0]->getType(), nvars);
|
||||||
LLConstant* arrInit = llvm::ConstantArray::get(arrTy, arrayInits);
|
LLConstant* arrInit = llvm::ConstantArray::get(arrTy, arrayInits);
|
||||||
|
|
||||||
std::string name(cd->type->vtinfo->toChars());
|
// mangle
|
||||||
name.append("__OffsetTypeInfos");
|
std::string name(cd->type->vtinfo->toChars());
|
||||||
|
name.append("__OffsetTypeInfos");
|
||||||
|
|
||||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,DtoInternalLinkage(cd),arrInit,name,gIR->module);
|
// create symbol
|
||||||
ptr = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(sTy));
|
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,DtoInternalLinkage(cd),arrInit,name,gIR->module);
|
||||||
}
|
ptr = DtoBitCast(gvar, getPtrToType(arrTy->getElementType()));
|
||||||
else {
|
|
||||||
ptr = llvm::ConstantPointerNull::get(isaPointer(initTy->getElementType(1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return DtoConstSlice(size, ptr);
|
return DtoConstSlice(size, ptr);
|
||||||
}
|
}
|
||||||
|
@ -1446,7 +1437,8 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||||
assert(ir->classInfo);
|
assert(ir->classInfo);
|
||||||
|
|
||||||
TypeClass* cdty = (TypeClass*)cd->type;
|
TypeClass* cdty = (TypeClass*)cd->type;
|
||||||
if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) {
|
if (!cd->isInterfaceDeclaration() && !cd->isAbstract())
|
||||||
|
{
|
||||||
assert(ir->init);
|
assert(ir->init);
|
||||||
assert(ir->constInit);
|
assert(ir->constInit);
|
||||||
assert(ir->vtbl);
|
assert(ir->vtbl);
|
||||||
|
@ -1460,28 +1452,26 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||||
DtoForceConstInitDsymbol(cinfo);
|
DtoForceConstInitDsymbol(cinfo);
|
||||||
assert(cinfo->ir.irStruct->constInit);
|
assert(cinfo->ir.irStruct->constInit);
|
||||||
|
|
||||||
// def init constant
|
|
||||||
LLConstant* defc = cinfo->ir.irStruct->constInit;
|
|
||||||
assert(defc);
|
|
||||||
|
|
||||||
LLConstant* c;
|
LLConstant* c;
|
||||||
|
|
||||||
|
const LLType* voidPtr = getVoidPtrType();
|
||||||
|
const LLType* voidPtrPtr = getPtrToType(voidPtr);
|
||||||
|
|
||||||
// own vtable
|
// own vtable
|
||||||
c = defc->getOperand(0);
|
c = cinfo->ir.irStruct->vtbl;
|
||||||
assert(c);
|
assert(c);
|
||||||
inits.push_back(c);
|
inits.push_back(c);
|
||||||
|
|
||||||
// monitor
|
// monitor
|
||||||
c = defc->getOperand(1);
|
c = LLConstant::getNullValue(voidPtr);
|
||||||
inits.push_back(c);
|
inits.push_back(c);
|
||||||
|
|
||||||
// byte[] init
|
// byte[] init
|
||||||
const LLType* byteptrty = getPtrToType(LLType::Int8Ty);
|
if (cd->isInterfaceDeclaration())
|
||||||
if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
|
c = DtoConstSlice(DtoConstSize_t(0), LLConstant::getNullValue(voidPtr));
|
||||||
c = defc->getOperand(2);
|
else
|
||||||
}
|
{
|
||||||
else {
|
c = DtoBitCast(ir->init, voidPtr);
|
||||||
c = llvm::ConstantExpr::getBitCast(ir->init, byteptrty);
|
|
||||||
//Logger::cout() << *ir->constInit->getType() << std::endl;
|
//Logger::cout() << *ir->constInit->getType() << std::endl;
|
||||||
size_t initsz = getABITypeSize(ir->constInit->getType());
|
size_t initsz = getABITypeSize(ir->constInit->getType());
|
||||||
c = DtoConstSlice(DtoConstSize_t(initsz), c);
|
c = DtoConstSlice(DtoConstSize_t(initsz), c);
|
||||||
|
@ -1501,34 +1491,30 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||||
inits.push_back(c);
|
inits.push_back(c);
|
||||||
|
|
||||||
// vtbl array
|
// vtbl array
|
||||||
if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
|
if (cd->isInterfaceDeclaration())
|
||||||
c = defc->getOperand(4);
|
c = DtoConstSlice(DtoConstSize_t(0), LLConstant::getNullValue(getPtrToType(voidPtr)));
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
const LLType* byteptrptrty = getPtrToType(byteptrty);
|
c = DtoBitCast(ir->vtbl, voidPtrPtr);
|
||||||
c = llvm::ConstantExpr::getBitCast(cd->ir.irStruct->vtbl, byteptrptrty);
|
c = DtoConstSlice(DtoConstSize_t(cd->vtbl.dim), c);
|
||||||
|
|
||||||
assert(ir->constVtbl);
|
|
||||||
size_t vtblsz = ir->constVtbl->getNumOperands();
|
|
||||||
c = DtoConstSlice(DtoConstSize_t(vtblsz), c);
|
|
||||||
}
|
}
|
||||||
inits.push_back(c);
|
inits.push_back(c);
|
||||||
|
|
||||||
// interfaces array
|
// interfaces array
|
||||||
IrStruct* irstruct = cd->ir.irStruct;
|
VarDeclaration* intersVar = (VarDeclaration*)cinfo->fields.data[3];
|
||||||
if (!irstruct->interfaceInfos) {
|
const LLType* intersTy = DtoType(intersVar->type);
|
||||||
c = defc->getOperand(5);
|
if (!ir->interfaceInfos)
|
||||||
}
|
c = LLConstant::getNullValue(intersTy);
|
||||||
else {
|
else {
|
||||||
const LLType* t = defc->getOperand(5)->getType()->getContainedType(1);
|
const LLType* t = intersTy->getContainedType(1); // .ptr
|
||||||
c = llvm::ConstantExpr::getBitCast(irstruct->interfaceInfos, t);
|
c = DtoBitCast(ir->interfaceInfos, t);
|
||||||
size_t iisz = irstruct->interfaceVec.size();
|
size_t iisz = ir->interfaceVec.size();
|
||||||
c = DtoConstSlice(DtoConstSize_t(iisz), c);
|
c = DtoConstSlice(DtoConstSize_t(iisz), c);
|
||||||
}
|
}
|
||||||
inits.push_back(c);
|
inits.push_back(c);
|
||||||
|
|
||||||
// base classinfo
|
// base classinfo
|
||||||
if (cd->baseClass && !cd->isInterfaceDeclaration() && !cd->isAbstract()) {
|
// interfaces never get a base , just the interfaces[]
|
||||||
|
if (cd->baseClass && !cd->isInterfaceDeclaration()) {
|
||||||
DtoDeclareClassInfo(cd->baseClass);
|
DtoDeclareClassInfo(cd->baseClass);
|
||||||
c = cd->baseClass->ir.irStruct->classInfo;
|
c = cd->baseClass->ir.irStruct->classInfo;
|
||||||
assert(c);
|
assert(c);
|
||||||
|
@ -1536,34 +1522,33 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// null
|
// null
|
||||||
c = defc->getOperand(6);
|
c = LLConstant::getNullValue(DtoType(cinfo->type));
|
||||||
inits.push_back(c);
|
inits.push_back(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
|
if (cd->isInterfaceDeclaration())
|
||||||
c = defc->getOperand(7);
|
c = LLConstant::getNullValue(voidPtr);
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
c = build_class_dtor(cd);
|
c = build_class_dtor(cd);
|
||||||
}
|
|
||||||
inits.push_back(c);
|
inits.push_back(c);
|
||||||
|
|
||||||
// invariant
|
// invariant
|
||||||
if (cd->inv) {
|
VarDeclaration* invVar = (VarDeclaration*)cinfo->fields.data[6];
|
||||||
|
const LLType* invTy = DtoType(invVar->type);
|
||||||
|
if (cd->inv)
|
||||||
|
{
|
||||||
DtoForceDeclareDsymbol(cd->inv);
|
DtoForceDeclareDsymbol(cd->inv);
|
||||||
c = cd->inv->ir.irFunc->func;
|
c = cd->inv->ir.irFunc->func;
|
||||||
c = llvm::ConstantExpr::getBitCast(c, defc->getOperand(8)->getType());
|
c = DtoBitCast(c, invTy);
|
||||||
}
|
|
||||||
else {
|
|
||||||
c = defc->getOperand(8);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
c = LLConstant::getNullValue(invTy);
|
||||||
inits.push_back(c);
|
inits.push_back(c);
|
||||||
|
|
||||||
// uint flags
|
// uint flags
|
||||||
if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
|
if (cd->isInterfaceDeclaration())
|
||||||
c = defc->getOperand(9);
|
c = DtoConstUint(0);
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
unsigned flags = build_classinfo_flags(cd);
|
unsigned flags = build_classinfo_flags(cd);
|
||||||
c = DtoConstUint(flags);
|
c = DtoConstUint(flags);
|
||||||
|
@ -1571,42 +1556,44 @@ void DtoDefineClassInfo(ClassDeclaration* cd)
|
||||||
inits.push_back(c);
|
inits.push_back(c);
|
||||||
|
|
||||||
// deallocator
|
// deallocator
|
||||||
if (cd->aggDelete) {
|
if (cd->aggDelete)
|
||||||
|
{
|
||||||
DtoForceDeclareDsymbol(cd->aggDelete);
|
DtoForceDeclareDsymbol(cd->aggDelete);
|
||||||
c = cd->aggDelete->ir.irFunc->func;
|
c = cd->aggDelete->ir.irFunc->func;
|
||||||
c = llvm::ConstantExpr::getBitCast(c, defc->getOperand(10)->getType());
|
c = DtoBitCast(c, voidPtr);
|
||||||
}
|
|
||||||
else {
|
|
||||||
c = defc->getOperand(10);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
c = LLConstant::getNullValue(voidPtr);
|
||||||
inits.push_back(c);
|
inits.push_back(c);
|
||||||
|
|
||||||
// offset typeinfo
|
// offset typeinfo
|
||||||
if (cd->isInterfaceDeclaration() || cd->isAbstract()) {
|
VarDeclaration* offTiVar = (VarDeclaration*)cinfo->fields.data[9];
|
||||||
c = defc->getOperand(11);
|
const LLType* offTiTy = DtoType(offTiVar->type);
|
||||||
}
|
if (cd->isInterfaceDeclaration())
|
||||||
else {
|
c = LLConstant::getNullValue(offTiTy);
|
||||||
c = build_offti_array(cd, defc->getOperand(11));
|
else
|
||||||
}
|
c = build_offti_array(cd, offTiTy);
|
||||||
inits.push_back(c);
|
inits.push_back(c);
|
||||||
|
|
||||||
// default constructor
|
// default constructor
|
||||||
if (cd->defaultCtor && !cd->isInterfaceDeclaration() && !cd->isAbstract()) {
|
if (cd->defaultCtor)
|
||||||
|
{
|
||||||
DtoForceDeclareDsymbol(cd->defaultCtor);
|
DtoForceDeclareDsymbol(cd->defaultCtor);
|
||||||
c = isaConstant(cd->defaultCtor->ir.irFunc->func);
|
c = isaConstant(cd->defaultCtor->ir.irFunc->func);
|
||||||
const LLType* toTy = defc->getOperand(12)->getType();
|
c = DtoBitCast(c, voidPtr);
|
||||||
c = llvm::ConstantExpr::getBitCast(c, toTy);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
c = defc->getOperand(12);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
c = LLConstant::getNullValue(voidPtr);
|
||||||
inits.push_back(c);
|
inits.push_back(c);
|
||||||
|
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
|
|
||||||
// xgetMembers
|
// xgetMembers
|
||||||
c = defc->getOperand(13);
|
VarDeclaration* xgetVar = (VarDeclaration*)cinfo->fields.data[11];
|
||||||
inits.push_back(c);
|
const LLType* xgetTy = DtoType(xgetVar->type);
|
||||||
|
|
||||||
|
// FIXME: fill it out!
|
||||||
|
inits.push_back( LLConstant::getNullValue(xgetTy) );
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -138,7 +138,7 @@ LLConstant* DtoConstStructInitializer(StructInitializer* si)
|
||||||
qsort(&vars[0], nvars, sizeof(VarInitPair), &varinit_offset_cmp_func);
|
qsort(&vars[0], nvars, sizeof(VarInitPair), &varinit_offset_cmp_func);
|
||||||
|
|
||||||
// check integrity
|
// check integrity
|
||||||
// and do error checking, since the frontend does verify static struct initializers
|
// and do error checking, since the frontend does not verify static struct initializers
|
||||||
size_t lastoffset = 0;
|
size_t lastoffset = 0;
|
||||||
size_t lastsize = 0;
|
size_t lastsize = 0;
|
||||||
bool overlap = false;
|
bool overlap = false;
|
||||||
|
|
|
@ -2035,7 +2035,7 @@ DValue* ComExp::toElem(IRState* p)
|
||||||
DValue* u = e1->toElem(p);
|
DValue* u = e1->toElem(p);
|
||||||
|
|
||||||
LLValue* value = u->getRVal();
|
LLValue* value = u->getRVal();
|
||||||
LLValue* minusone = llvm::ConstantInt::get(value->getType(), -1, true);
|
LLValue* minusone = llvm::ConstantInt::get(value->getType(), (uint64_t)-1, true);
|
||||||
value = llvm::BinaryOperator::Create(llvm::Instruction::Xor, value, minusone, "tmp", p->scopebb());
|
value = llvm::BinaryOperator::Create(llvm::Instruction::Xor, value, minusone, "tmp", p->scopebb());
|
||||||
|
|
||||||
return new DImValue(type, value);
|
return new DImValue(type, value);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue