mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-04 09:00:33 +03:00
Fix v1.31 regression wrt. unresolved IrAggr (#4312)
And use `IrTypeClass::getVtblType()` to get the vtable LLVM array type, instead of deriving it from the `IrClass::getVtblSymbol()` global (invoking that function may define the vtable!). I've hit some compiler crashes for the Symmetry code base, on Windows only. I guess the problem surfaced due to `-link-defaultlib-shared`, which on Windows causes some vtables of instantiated classes to be defined whenever accessing the vtable symbol. I don't have a reduced test case unfortunately.
This commit is contained in:
parent
58c4b8bdae
commit
5f46c65ab5
5 changed files with 37 additions and 39 deletions
|
@ -75,19 +75,20 @@ void DtoResolveClass(ClassDeclaration *cd) {
|
||||||
DValue *DtoNewClass(const Loc &loc, TypeClass *tc, NewExp *newexp) {
|
DValue *DtoNewClass(const Loc &loc, TypeClass *tc, NewExp *newexp) {
|
||||||
// resolve type
|
// resolve type
|
||||||
DtoResolveClass(tc->sym);
|
DtoResolveClass(tc->sym);
|
||||||
|
const auto irClass = getIrAggr(tc->sym);
|
||||||
|
|
||||||
// allocate
|
// allocate
|
||||||
LLValue *mem;
|
LLValue *mem;
|
||||||
bool doInit = true;
|
bool doInit = true;
|
||||||
if (newexp->onstack) {
|
if (newexp->onstack) {
|
||||||
mem = DtoRawAlloca(getIrAggr(tc->sym)->getLLStructType(), tc->sym->alignsize,
|
mem = DtoRawAlloca(irClass->getLLStructType(), tc->sym->alignsize,
|
||||||
".newclass_alloca");
|
".newclass_alloca");
|
||||||
} else {
|
} else {
|
||||||
const bool useEHAlloc = global.params.ehnogc && newexp->thrownew;
|
const bool useEHAlloc = global.params.ehnogc && newexp->thrownew;
|
||||||
llvm::Function *fn = getRuntimeFunction(
|
llvm::Function *fn = getRuntimeFunction(
|
||||||
loc, gIR->module, useEHAlloc ? "_d_newThrowable" : "_d_allocclass");
|
loc, gIR->module, useEHAlloc ? "_d_newThrowable" : "_d_allocclass");
|
||||||
LLConstant *ci = DtoBitCast(getIrAggr(tc->sym)->getClassInfoSymbol(),
|
LLConstant *ci =
|
||||||
DtoType(getClassInfoType()));
|
DtoBitCast(irClass->getClassInfoSymbol(), DtoType(getClassInfoType()));
|
||||||
mem = gIR->CreateCallOrInvoke(
|
mem = gIR->CreateCallOrInvoke(
|
||||||
fn, ci, useEHAlloc ? ".newthrowable_alloc" : ".newclass_gc_alloc");
|
fn, ci, useEHAlloc ? ".newthrowable_alloc" : ".newclass_gc_alloc");
|
||||||
mem = DtoBitCast(mem, DtoType(tc),
|
mem = DtoBitCast(mem, DtoType(tc),
|
||||||
|
@ -105,7 +106,7 @@ DValue *DtoNewClass(const Loc &loc, TypeClass *tc, NewExp *newexp) {
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
unsigned idx = getFieldGEPIndex(tc->sym, tc->sym->vthis);
|
unsigned idx = getFieldGEPIndex(tc->sym, tc->sym->vthis);
|
||||||
LLValue *src = DtoRVal(newexp->thisexp);
|
LLValue *src = DtoRVal(newexp->thisexp);
|
||||||
LLValue *dst = DtoGEP(getIrAggr(tc->sym)->getLLStructType(), mem, 0, idx);
|
LLValue *dst = DtoGEP(irClass->getLLStructType(), mem, 0, idx);
|
||||||
IF_LOG Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n';
|
IF_LOG Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n';
|
||||||
DtoStore(src, DtoBitCast(dst, getPtrToType(src->getType())));
|
DtoStore(src, DtoBitCast(dst, getPtrToType(src->getType())));
|
||||||
}
|
}
|
||||||
|
@ -152,7 +153,7 @@ void DtoInitClass(TypeClass *tc, LLValue *dst) {
|
||||||
const bool isCPPclass = tc->sym->isCPPclass() ? true : false;
|
const bool isCPPclass = tc->sym->isCPPclass() ? true : false;
|
||||||
if (!isCPPclass) {
|
if (!isCPPclass) {
|
||||||
tmp = DtoGEP(st, dst, 0, 1, "monitor");
|
tmp = DtoGEP(st, dst, 0, 1, "monitor");
|
||||||
val = LLConstant::getNullValue(getVoidPtrType());
|
val = LLConstant::getNullValue(st->getElementType(1));
|
||||||
DtoStore(val, tmp);
|
DtoStore(val, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,9 +198,9 @@ void DtoFinalizeScopeClass(const Loc &loc, DValue *dval,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasDtor = false;
|
bool hasDtor = false;
|
||||||
auto cd = dval->type->toBasetype()->isTypeClass()->sym;
|
const auto cd = dval->type->toBasetype()->isTypeClass()->sym;
|
||||||
for (; cd; cd = cd->baseClass) {
|
for (auto cd2 = cd; cd2; cd2 = cd2->baseClass) {
|
||||||
if (cd->dtor) {
|
if (cd2->dtor) {
|
||||||
hasDtor = true;
|
hasDtor = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -216,7 +217,7 @@ void DtoFinalizeScopeClass(const Loc &loc, DValue *dval,
|
||||||
llvm::BasicBlock *endbb = gIR->insertBBAfter(ifbb, "endif");
|
llvm::BasicBlock *endbb = gIR->insertBBAfter(ifbb, "endif");
|
||||||
|
|
||||||
llvm::StructType *st =
|
llvm::StructType *st =
|
||||||
getIrAggr(static_cast<TypeClass *>(dval->type)->sym)->getLLStructType();
|
isaStruct(getIrType(cd->type, true)->isClass()->getMemoryLLType());
|
||||||
const auto monitor =
|
const auto monitor =
|
||||||
DtoLoad(st->getElementType(1), DtoGEP(st, inst, 0, 1), ".monitor");
|
DtoLoad(st->getElementType(1), DtoGEP(st, inst, 0, 1), ".monitor");
|
||||||
const auto hasMonitor =
|
const auto hasMonitor =
|
||||||
|
@ -425,7 +426,7 @@ LLValue *DtoVirtualFunctionPointer(DValue *inst, FuncDeclaration *fdecl) {
|
||||||
// sanity checks
|
// sanity checks
|
||||||
assert(fdecl->isVirtual());
|
assert(fdecl->isVirtual());
|
||||||
assert(!fdecl->isFinalFunc());
|
assert(!fdecl->isFinalFunc());
|
||||||
TypeClass * tc = inst->type->toBasetype()->isTypeClass();
|
TypeClass *tc = inst->type->toBasetype()->isTypeClass();
|
||||||
assert(tc);
|
assert(tc);
|
||||||
// slot 0 is always ClassInfo/Interface* unless it is a CPP class
|
// slot 0 is always ClassInfo/Interface* unless it is a CPP class
|
||||||
assert(fdecl->vtblIndex > 0 ||
|
assert(fdecl->vtblIndex > 0 ||
|
||||||
|
@ -436,20 +437,20 @@ LLValue *DtoVirtualFunctionPointer(DValue *inst, FuncDeclaration *fdecl) {
|
||||||
LLValue *vthis = DtoRVal(inst);
|
LLValue *vthis = DtoRVal(inst);
|
||||||
IF_LOG Logger::cout() << "vthis: " << *vthis << '\n';
|
IF_LOG Logger::cout() << "vthis: " << *vthis << '\n';
|
||||||
|
|
||||||
IrClass * irc = getIrAggr(tc->sym, true);
|
const auto irtc = getIrType(tc->sym->type, true)->isClass();
|
||||||
|
const auto vtblType = irtc->getVtblType();
|
||||||
|
|
||||||
LLValue *funcval = vthis;
|
LLValue *funcval = vthis;
|
||||||
// get the vtbl for objects
|
// get the vtbl for objects
|
||||||
llvm::GlobalVariable* vtblsym = irc->getVtblSymbol();
|
funcval = DtoGEP(irtc->getMemoryLLType(), funcval, 0u, 0);
|
||||||
funcval = DtoGEP(irc->getLLStructType(), funcval, 0u, 0);
|
|
||||||
// load vtbl ptr
|
// load vtbl ptr
|
||||||
funcval = DtoLoad(vtblsym->getType(), funcval);
|
funcval = DtoLoad(vtblType->getPointerTo(), funcval);
|
||||||
// index vtbl
|
// index vtbl
|
||||||
const std::string name = fdecl->toChars();
|
const std::string name = fdecl->toChars();
|
||||||
const auto vtblname = name + "@vtbl";
|
const auto vtblname = name + "@vtbl";
|
||||||
funcval = DtoGEP(vtblsym->getValueType(),
|
funcval = DtoGEP(vtblType, funcval, 0, fdecl->vtblIndex, vtblname.c_str());
|
||||||
funcval, 0, fdecl->vtblIndex, vtblname.c_str());
|
|
||||||
// load opaque pointer
|
// load opaque pointer
|
||||||
funcval = DtoAlignedLoad(getVoidPtrType(), funcval);
|
funcval = DtoAlignedLoad(vtblType->getElementType(), funcval);
|
||||||
|
|
||||||
IF_LOG Logger::cout() << "funcval: " << *funcval << '\n';
|
IF_LOG Logger::cout() << "funcval: " << *funcval << '\n';
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "ir/irfunction.h"
|
#include "ir/irfunction.h"
|
||||||
#include "ir/irmodule.h"
|
#include "ir/irmodule.h"
|
||||||
#include "ir/irtypeaggr.h"
|
#include "ir/irtypeaggr.h"
|
||||||
|
#include "ir/irtypeclass.h"
|
||||||
#include "llvm/MC/MCAsmInfo.h"
|
#include "llvm/MC/MCAsmInfo.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/ManagedStatic.h"
|
#include "llvm/Support/ManagedStatic.h"
|
||||||
|
@ -1895,16 +1896,12 @@ DLValue *DtoIndexAggregate(LLValue *src, AggregateDeclaration *ad,
|
||||||
// Cast the pointer we got to the canonical struct type the indices are
|
// Cast the pointer we got to the canonical struct type the indices are
|
||||||
// based on.
|
// based on.
|
||||||
LLType *st = nullptr;
|
LLType *st = nullptr;
|
||||||
LLType *pst = nullptr;
|
if (auto irtc = irTypeAggr->isClass()) {
|
||||||
if (ad->isClassDeclaration()) {
|
st = irtc->getMemoryLLType();
|
||||||
st = getIrAggr(ad)->getLLStructType();
|
} else {
|
||||||
pst = DtoType(ad->type);
|
st = irTypeAggr->getLLType();
|
||||||
}
|
}
|
||||||
else {
|
ptr = DtoBitCast(ptr, st->getPointerTo());
|
||||||
st = DtoType(ad->type);
|
|
||||||
pst = getPtrToType(st);
|
|
||||||
}
|
|
||||||
ptr = DtoBitCast(ptr, pst);
|
|
||||||
ptr = DtoGEP(st, ptr, 0, off);
|
ptr = DtoGEP(st, ptr, 0, off);
|
||||||
ty = isaStruct(st)->getElementType(off);
|
ty = isaStruct(st)->getElementType(off);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,8 @@ LLValue *loadThisPtr(AggregateDeclaration *ad, IrFunction &irfunc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
LLValue *indexVThis(AggregateDeclaration *ad, LLValue* val) {
|
LLValue *indexVThis(AggregateDeclaration *ad, LLValue* val) {
|
||||||
llvm::StructType *st = getIrAggr(ad, true)->getLLStructType();
|
DtoResolveDsymbol(ad);
|
||||||
|
llvm::StructType *st = getIrAggr(ad)->getLLStructType();
|
||||||
unsigned idx = getVthisIdx(ad);
|
unsigned idx = getVthisIdx(ad);
|
||||||
return DtoLoad(st->getElementType(idx),
|
return DtoLoad(st->getElementType(idx),
|
||||||
DtoGEP(st, val, 0, idx, ".vthis"));
|
DtoGEP(st, val, 0, idx, ".vthis"));
|
||||||
|
@ -226,7 +227,7 @@ void DtoResolveNestedContext(const Loc &loc, AggregateDeclaration *decl,
|
||||||
DtoResolveDsymbol(decl);
|
DtoResolveDsymbol(decl);
|
||||||
|
|
||||||
unsigned idx = getVthisIdx(decl);
|
unsigned idx = getVthisIdx(decl);
|
||||||
llvm::StructType *st = getIrAggr(decl, true)->getLLStructType();
|
llvm::StructType *st = getIrAggr(decl)->getLLStructType();
|
||||||
LLValue *gep = DtoGEP(st, value, 0, idx, ".vthis");
|
LLValue *gep = DtoGEP(st, value, 0, idx, ".vthis");
|
||||||
DtoStore(DtoBitCast(nest, st->getElementType(idx)), gep);
|
DtoStore(DtoBitCast(nest, st->getElementType(idx)), gep);
|
||||||
}
|
}
|
||||||
|
|
16
gen/toir.cpp
16
gen/toir.cpp
|
@ -2757,22 +2757,22 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Expression *ex = isExpression(e->obj)) {
|
if (Expression *ex = isExpression(e->obj)) {
|
||||||
Type *t = ex->type->toBasetype();
|
const auto tc = ex->type->toBasetype()->isTypeClass();
|
||||||
assert(t->ty == TY::Tclass);
|
assert(tc);
|
||||||
|
|
||||||
ClassDeclaration *sym = static_cast<TypeClass *>(t)->sym;
|
const auto irtc = getIrType(tc->sym->type, true)->isClass();
|
||||||
IrClass *irc = getIrAggr(sym, true);
|
const auto vtblType = irtc->getVtblType();
|
||||||
LLValue *val = DtoRVal(ex);
|
LLValue *val = DtoRVal(ex);
|
||||||
|
|
||||||
// Get and load vtbl pointer.
|
// Get and load vtbl pointer.
|
||||||
llvm::GlobalVariable* vtblsym = irc->getVtblSymbol();
|
llvm::Value *vtbl = DtoLoad(vtblType->getPointerTo(),
|
||||||
llvm::Value *vtbl = DtoLoad(vtblsym->getType(), DtoGEP(irc->getLLStructType(), val, 0u, 0));
|
DtoGEP(irtc->getMemoryLLType(), val, 0u, 0));
|
||||||
|
|
||||||
// TypeInfo ptr is first vtbl entry.
|
// TypeInfo ptr is first vtbl entry.
|
||||||
llvm::Value *typinf = DtoGEP(vtblsym->getValueType(), vtbl, 0u, 0);
|
llvm::Value *typinf = DtoGEP(vtblType, vtbl, 0u, 0);
|
||||||
|
|
||||||
Type *resultType;
|
Type *resultType;
|
||||||
if (sym->isInterfaceDeclaration()) {
|
if (tc->sym->isInterfaceDeclaration()) {
|
||||||
// For interfaces, the first entry in the vtbl is actually a pointer
|
// For interfaces, the first entry in the vtbl is actually a pointer
|
||||||
// to an Interface instance, which has the type info as its first
|
// to an Interface instance, which has the type info as its first
|
||||||
// member, so we have to add an extra layer of indirection.
|
// member, so we have to add an extra layer of indirection.
|
||||||
|
|
|
@ -441,9 +441,8 @@ void buildTypeInfo(TypeInfoDeclaration *decl) {
|
||||||
assert(isBuiltin && "existing global expected to be the init symbol of a "
|
assert(isBuiltin && "existing global expected to be the init symbol of a "
|
||||||
"built-in TypeInfo");
|
"built-in TypeInfo");
|
||||||
} else {
|
} else {
|
||||||
DtoType(decl->type);
|
TypeClass *tc = decl->type->isTypeClass();
|
||||||
TypeClass *tclass = decl->type->isTypeClass();
|
LLType *type = getIrType(tc->sym->type, true)->isClass()->getMemoryLLType();
|
||||||
LLType *type = getIrType(tclass)->isClass()->getMemoryLLType();
|
|
||||||
// We need to keep the symbol mutable as the type is not declared as
|
// We need to keep the symbol mutable as the type is not declared as
|
||||||
// immutable on the D side, and e.g. synchronized() can be used on the
|
// immutable on the D side, and e.g. synchronized() can be used on the
|
||||||
// implicit monitor.
|
// implicit monitor.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue