mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 16:41:06 +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) {
|
||||
// resolve type
|
||||
DtoResolveClass(tc->sym);
|
||||
const auto irClass = getIrAggr(tc->sym);
|
||||
|
||||
// allocate
|
||||
LLValue *mem;
|
||||
bool doInit = true;
|
||||
if (newexp->onstack) {
|
||||
mem = DtoRawAlloca(getIrAggr(tc->sym)->getLLStructType(), tc->sym->alignsize,
|
||||
mem = DtoRawAlloca(irClass->getLLStructType(), tc->sym->alignsize,
|
||||
".newclass_alloca");
|
||||
} else {
|
||||
const bool useEHAlloc = global.params.ehnogc && newexp->thrownew;
|
||||
llvm::Function *fn = getRuntimeFunction(
|
||||
loc, gIR->module, useEHAlloc ? "_d_newThrowable" : "_d_allocclass");
|
||||
LLConstant *ci = DtoBitCast(getIrAggr(tc->sym)->getClassInfoSymbol(),
|
||||
DtoType(getClassInfoType()));
|
||||
LLConstant *ci =
|
||||
DtoBitCast(irClass->getClassInfoSymbol(), DtoType(getClassInfoType()));
|
||||
mem = gIR->CreateCallOrInvoke(
|
||||
fn, ci, useEHAlloc ? ".newthrowable_alloc" : ".newclass_gc_alloc");
|
||||
mem = DtoBitCast(mem, DtoType(tc),
|
||||
|
@ -105,7 +106,7 @@ DValue *DtoNewClass(const Loc &loc, TypeClass *tc, NewExp *newexp) {
|
|||
LOG_SCOPE;
|
||||
unsigned idx = getFieldGEPIndex(tc->sym, tc->sym->vthis);
|
||||
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';
|
||||
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;
|
||||
if (!isCPPclass) {
|
||||
tmp = DtoGEP(st, dst, 0, 1, "monitor");
|
||||
val = LLConstant::getNullValue(getVoidPtrType());
|
||||
val = LLConstant::getNullValue(st->getElementType(1));
|
||||
DtoStore(val, tmp);
|
||||
}
|
||||
|
||||
|
@ -197,9 +198,9 @@ void DtoFinalizeScopeClass(const Loc &loc, DValue *dval,
|
|||
}
|
||||
|
||||
bool hasDtor = false;
|
||||
auto cd = dval->type->toBasetype()->isTypeClass()->sym;
|
||||
for (; cd; cd = cd->baseClass) {
|
||||
if (cd->dtor) {
|
||||
const auto cd = dval->type->toBasetype()->isTypeClass()->sym;
|
||||
for (auto cd2 = cd; cd2; cd2 = cd2->baseClass) {
|
||||
if (cd2->dtor) {
|
||||
hasDtor = true;
|
||||
break;
|
||||
}
|
||||
|
@ -216,7 +217,7 @@ void DtoFinalizeScopeClass(const Loc &loc, DValue *dval,
|
|||
llvm::BasicBlock *endbb = gIR->insertBBAfter(ifbb, "endif");
|
||||
|
||||
llvm::StructType *st =
|
||||
getIrAggr(static_cast<TypeClass *>(dval->type)->sym)->getLLStructType();
|
||||
isaStruct(getIrType(cd->type, true)->isClass()->getMemoryLLType());
|
||||
const auto monitor =
|
||||
DtoLoad(st->getElementType(1), DtoGEP(st, inst, 0, 1), ".monitor");
|
||||
const auto hasMonitor =
|
||||
|
@ -425,7 +426,7 @@ LLValue *DtoVirtualFunctionPointer(DValue *inst, FuncDeclaration *fdecl) {
|
|||
// sanity checks
|
||||
assert(fdecl->isVirtual());
|
||||
assert(!fdecl->isFinalFunc());
|
||||
TypeClass * tc = inst->type->toBasetype()->isTypeClass();
|
||||
TypeClass *tc = inst->type->toBasetype()->isTypeClass();
|
||||
assert(tc);
|
||||
// slot 0 is always ClassInfo/Interface* unless it is a CPP class
|
||||
assert(fdecl->vtblIndex > 0 ||
|
||||
|
@ -436,20 +437,20 @@ LLValue *DtoVirtualFunctionPointer(DValue *inst, FuncDeclaration *fdecl) {
|
|||
LLValue *vthis = DtoRVal(inst);
|
||||
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;
|
||||
// get the vtbl for objects
|
||||
llvm::GlobalVariable* vtblsym = irc->getVtblSymbol();
|
||||
funcval = DtoGEP(irc->getLLStructType(), funcval, 0u, 0);
|
||||
funcval = DtoGEP(irtc->getMemoryLLType(), funcval, 0u, 0);
|
||||
// load vtbl ptr
|
||||
funcval = DtoLoad(vtblsym->getType(), funcval);
|
||||
funcval = DtoLoad(vtblType->getPointerTo(), funcval);
|
||||
// index vtbl
|
||||
const std::string name = fdecl->toChars();
|
||||
const auto vtblname = name + "@vtbl";
|
||||
funcval = DtoGEP(vtblsym->getValueType(),
|
||||
funcval, 0, fdecl->vtblIndex, vtblname.c_str());
|
||||
funcval = DtoGEP(vtblType, funcval, 0, fdecl->vtblIndex, vtblname.c_str());
|
||||
// load opaque pointer
|
||||
funcval = DtoAlignedLoad(getVoidPtrType(), funcval);
|
||||
funcval = DtoAlignedLoad(vtblType->getElementType(), funcval);
|
||||
|
||||
IF_LOG Logger::cout() << "funcval: " << *funcval << '\n';
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "ir/irfunction.h"
|
||||
#include "ir/irmodule.h"
|
||||
#include "ir/irtypeaggr.h"
|
||||
#include "ir/irtypeclass.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/Support/CommandLine.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
|
||||
// based on.
|
||||
LLType *st = nullptr;
|
||||
LLType *pst = nullptr;
|
||||
if (ad->isClassDeclaration()) {
|
||||
st = getIrAggr(ad)->getLLStructType();
|
||||
pst = DtoType(ad->type);
|
||||
if (auto irtc = irTypeAggr->isClass()) {
|
||||
st = irtc->getMemoryLLType();
|
||||
} else {
|
||||
st = irTypeAggr->getLLType();
|
||||
}
|
||||
else {
|
||||
st = DtoType(ad->type);
|
||||
pst = getPtrToType(st);
|
||||
}
|
||||
ptr = DtoBitCast(ptr, pst);
|
||||
ptr = DtoBitCast(ptr, st->getPointerTo());
|
||||
ptr = DtoGEP(st, ptr, 0, off);
|
||||
ty = isaStruct(st)->getElementType(off);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,8 @@ LLValue *loadThisPtr(AggregateDeclaration *ad, IrFunction &irfunc) {
|
|||
}
|
||||
|
||||
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);
|
||||
return DtoLoad(st->getElementType(idx),
|
||||
DtoGEP(st, val, 0, idx, ".vthis"));
|
||||
|
@ -226,7 +227,7 @@ void DtoResolveNestedContext(const Loc &loc, AggregateDeclaration *decl,
|
|||
DtoResolveDsymbol(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");
|
||||
DtoStore(DtoBitCast(nest, st->getElementType(idx)), gep);
|
||||
}
|
||||
|
|
16
gen/toir.cpp
16
gen/toir.cpp
|
@ -2757,22 +2757,22 @@ public:
|
|||
return;
|
||||
}
|
||||
if (Expression *ex = isExpression(e->obj)) {
|
||||
Type *t = ex->type->toBasetype();
|
||||
assert(t->ty == TY::Tclass);
|
||||
const auto tc = ex->type->toBasetype()->isTypeClass();
|
||||
assert(tc);
|
||||
|
||||
ClassDeclaration *sym = static_cast<TypeClass *>(t)->sym;
|
||||
IrClass *irc = getIrAggr(sym, true);
|
||||
const auto irtc = getIrType(tc->sym->type, true)->isClass();
|
||||
const auto vtblType = irtc->getVtblType();
|
||||
LLValue *val = DtoRVal(ex);
|
||||
|
||||
// Get and load vtbl pointer.
|
||||
llvm::GlobalVariable* vtblsym = irc->getVtblSymbol();
|
||||
llvm::Value *vtbl = DtoLoad(vtblsym->getType(), DtoGEP(irc->getLLStructType(), val, 0u, 0));
|
||||
llvm::Value *vtbl = DtoLoad(vtblType->getPointerTo(),
|
||||
DtoGEP(irtc->getMemoryLLType(), val, 0u, 0));
|
||||
|
||||
// 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;
|
||||
if (sym->isInterfaceDeclaration()) {
|
||||
if (tc->sym->isInterfaceDeclaration()) {
|
||||
// For interfaces, the first entry in the vtbl is actually a pointer
|
||||
// to an Interface instance, which has the type info as its first
|
||||
// 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 "
|
||||
"built-in TypeInfo");
|
||||
} else {
|
||||
DtoType(decl->type);
|
||||
TypeClass *tclass = decl->type->isTypeClass();
|
||||
LLType *type = getIrType(tclass)->isClass()->getMemoryLLType();
|
||||
TypeClass *tc = decl->type->isTypeClass();
|
||||
LLType *type = getIrType(tc->sym->type, true)->isClass()->getMemoryLLType();
|
||||
// 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
|
||||
// implicit monitor.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue