Skip to content

Commit

Permalink
Skip TypeInfo definitions for -betterC
Browse files Browse the repository at this point in the history
And improve robustness for TypeInfos of speculative types by only
eliding their TypeInfo definition, not the declaration of the LL global
altogether.
Handle `-betterC` exactly the same way; don't touch ClassInfos as
-betterC doesn't support classes [yet].

`DtoTypeInfoOf()` expects the LL global to be created and otherwise
fails with an assertion or segfault (e.g., issue ldc-developers#2357). So now only
linker errors should result in case the TypeInfo definition is missing.

Also normalize the calls to `DtoTypeInfoOf()` and revise the following
pointer bitcasts, as the LL type of forward-declared TypeInfo globals
may be opaque.
  • Loading branch information
kinke committed Oct 15, 2017
1 parent b95c5cc commit c0b9ba4
Show file tree
Hide file tree
Showing 8 changed files with 29 additions and 35 deletions.
15 changes: 7 additions & 8 deletions gen/aa.cpp
Expand Up @@ -24,11 +24,12 @@
#include "ir/irmodule.h"

// returns the keytype typeinfo
static LLValue *to_keyti(DValue *aa) {
static LLConstant *to_keyti(DValue *aa, LLType *targetType) {
// keyti param
assert(aa->type->toBasetype()->ty == Taarray);
TypeAArray *aatype = static_cast<TypeAArray *>(aa->type->toBasetype());
return DtoTypeInfoOf(aatype->index, false);
LLConstant *ti = DtoTypeInfoOf(aatype->index, /*base=*/false);
return DtoBitCast(ti, targetType);
}

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -59,14 +60,14 @@ DLValue *DtoAAIndex(Loc &loc, Type *type, DValue *aa, DValue *key,
LLValue *ret;
if (lvalue) {
LLValue *rawAATI =
DtoTypeInfoOf(aa->type->unSharedOf()->mutableOf(), false);
DtoTypeInfoOf(aa->type->unSharedOf()->mutableOf(), /*base=*/false);
LLValue *castedAATI = DtoBitCast(rawAATI, funcTy->getParamType(1));
LLValue *valsize = DtoConstSize_t(getTypeAllocSize(DtoType(type)));
ret = gIR->CreateCallOrInvoke(func, aaval, castedAATI, valsize, pkey,
"aa.index")
.getInstruction();
} else {
LLValue *keyti = DtoBitCast(to_keyti(aa), funcTy->getParamType(1));
LLValue *keyti = to_keyti(aa, funcTy->getParamType(1));
ret = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey, "aa.index")
.getInstruction();
}
Expand Down Expand Up @@ -125,8 +126,7 @@ DValue *DtoAAIn(Loc &loc, Type *type, DValue *aa, DValue *key) {
aaval = DtoBitCast(aaval, funcTy->getParamType(0));

// keyti param
LLValue *keyti = to_keyti(aa);
keyti = DtoBitCast(keyti, funcTy->getParamType(1));
LLValue *keyti = to_keyti(aa, funcTy->getParamType(1));

// pkey param
LLValue *pkey = makeLValue(loc, key);
Expand Down Expand Up @@ -171,8 +171,7 @@ DValue *DtoAARemove(Loc &loc, DValue *aa, DValue *key) {
aaval = DtoBitCast(aaval, funcTy->getParamType(0));

// keyti param
LLValue *keyti = to_keyti(aa);
keyti = DtoBitCast(keyti, funcTy->getParamType(1));
LLValue *keyti = to_keyti(aa, funcTy->getParamType(1));

// pkey param
LLValue *pkey = makeLValue(loc, key);
Expand Down
2 changes: 1 addition & 1 deletion gen/classes.cpp
Expand Up @@ -438,7 +438,7 @@ static LLConstant *build_offti_entry(ClassDeclaration *cd, VarDeclaration *vd) {
inits[0] = DtoConstSize_t(offset);

// TypeInfo ti;
inits[1] = DtoTypeInfoOf(vd->type, true);
inits[1] = DtoTypeInfoOf(vd->type);

// done
return llvm::ConstantStruct::get(inits);
Expand Down
24 changes: 10 additions & 14 deletions gen/declarations.cpp
Expand Up @@ -89,12 +89,13 @@ class CodegenVisitor : public Visitor {
}

// Emit TypeInfo.
DtoTypeInfoOf(decl->type);
DtoTypeInfoOf(decl->type, /*base=*/false);

// Define __InterfaceZ.
IrAggr *ir = getIrAggr(decl);
llvm::GlobalVariable *interfaceZ = ir->getClassInfoSymbol();
interfaceZ->setInitializer(ir->getClassInfoInit());
if (!isSpeculativeType(decl->type))
interfaceZ->setInitializer(ir->getClassInfoInit());
setLinkage(decl, interfaceZ);
}
}
Expand Down Expand Up @@ -139,7 +140,7 @@ class CodegenVisitor : public Visitor {
initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit());

// emit typeinfo
DtoTypeInfoOf(decl->type);
DtoTypeInfoOf(decl->type, /*base=*/false);
}

// Emit __xopEquals/__xopCmp/__xtoHash.
Expand Down Expand Up @@ -195,10 +196,9 @@ class CodegenVisitor : public Visitor {
setLinkage(lwc, vtbl);

llvm::GlobalVariable *classZ = ir->getClassInfoSymbol();
classZ->setInitializer(ir->getClassInfoInit());
if (!isSpeculativeType(decl->type))
classZ->setInitializer(ir->getClassInfoInit());
setLinkage(lwc, classZ);

// No need to do TypeInfo here, it is <name>__classZ for classes in D2.
}
}

Expand Down Expand Up @@ -468,19 +468,15 @@ class CodegenVisitor : public Visitor {
//////////////////////////////////////////////////////////////////////////

void visit(TypeInfoDeclaration *decl) LLVM_OVERRIDE {
if (irs->dcomputetarget || isSpeculativeType(decl->tinfo)) {
return;
}
TypeInfoDeclaration_codegen(decl, irs);
if (!irs->dcomputetarget)
TypeInfoDeclaration_codegen(decl, irs);
}

//////////////////////////////////////////////////////////////////////////

void visit(TypeInfoClassDeclaration *decl) LLVM_OVERRIDE {
if (irs->dcomputetarget || isSpeculativeType(decl->tinfo)) {
return;
}
TypeInfoClassDeclaration_codegen(decl, irs);
if (!irs->dcomputetarget)
TypeInfoClassDeclaration_codegen(decl, irs);
}
};

Expand Down
2 changes: 1 addition & 1 deletion gen/rttibuilder.cpp
Expand Up @@ -64,7 +64,7 @@ void RTTIBuilder::push_null(Type *T) { push(getNullValue(DtoType(T))); }

void RTTIBuilder::push_null_vp() { push(getNullValue(getVoidPtrType())); }

void RTTIBuilder::push_typeinfo(Type *t) { push(DtoTypeInfoOf(t, true)); }
void RTTIBuilder::push_typeinfo(Type *t) { push(DtoTypeInfoOf(t)); }

void RTTIBuilder::push_classinfo(ClassDeclaration *cd) {
push(getIrAggr(cd)->getClassInfoSymbol());
Expand Down
6 changes: 2 additions & 4 deletions gen/toconstelem.cpp
Expand Up @@ -68,11 +68,8 @@ class ToConstElemVisitor : public Visitor {
}

if (TypeInfoDeclaration *ti = e->var->isTypeInfoDeclaration()) {
LLType *vartype = DtoType(e->type);
result = DtoTypeInfoOf(ti->tinfo, false);
if (result->getType() != getPtrToType(vartype)) {
result = llvm::ConstantExpr::getBitCast(result, vartype);
}
result = DtoBitCast(result, DtoType(e->type));
return;
}

Expand Down Expand Up @@ -699,6 +696,7 @@ class ToConstElemVisitor : public Visitor {
}

result = DtoTypeInfoOf(t, false);
result = DtoBitCast(result, DtoType(e->type));
}

//////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion gen/toir.cpp
Expand Up @@ -2454,7 +2454,7 @@ class ToElemVisitor : public Visitor {
getRuntimeFunction(e->loc, gIR->module, "_d_assocarrayliteralTX");
LLFunctionType *funcTy = func->getFunctionType();
LLValue *aaTypeInfo =
DtoBitCast(DtoTypeInfoOf(stripModifiers(aatype)),
DtoBitCast(DtoTypeInfoOf(stripModifiers(aatype), false),
DtoType(Type::typeinfoassociativearray->type));

LLConstant *idxs[2] = {DtoConstUint(0), DtoConstUint(0)};
Expand Down
9 changes: 5 additions & 4 deletions gen/typinf.cpp
Expand Up @@ -481,7 +481,7 @@ class LLVMDefineVisitor : public Visitor {
LLType *tiTy = DtoType(Type::dtypeinfo->type);

for (auto arg : *tu->arguments) {
arrInits.push_back(DtoTypeInfoOf(arg->type, true));
arrInits.push_back(DtoTypeInfoOf(arg->type));
}

// build array
Expand Down Expand Up @@ -617,12 +617,13 @@ void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState *p) {

emitTypeMetadata(decl);

// this is a declaration of a builtin __initZ var
if (builtinTypeInfo(decl->tinfo)) {
// check if the definition can be elided
if (global.params.betterC || isSpeculativeType(decl->tinfo) ||
builtinTypeInfo(decl->tinfo)) {
return;
}

// define custom typedef
// define the TypeInfo global
LLVMDefineVisitor v;
decl->accept(&v);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/codegen/static_typeid_gh1540.d
Expand Up @@ -18,8 +18,8 @@ struct S
// CHECK: @{{.*}}classvarC14TypeInfo_Class = thread_local global %object.TypeInfo_Class* @{{.*}}1C7__ClassZ
auto classvar = typeid(C);

// CHECK: @{{.*}}interfacevarC18TypeInfo_Interface = thread_local global %"typeid({{.*}}.I)"* @_D{{[0-9]+}}TypeInfo_C{{.*}}1I6__initZ
// CHECK: @{{.*}}interfacevarC18TypeInfo_Interface = thread_local global %object.TypeInfo_Interface* {{.*}}@_D{{[0-9]+}}TypeInfo_C{{.*}}1I6__initZ
auto interfacevar = typeid(I);

// CHECK: @{{.*}}structvarC15TypeInfo_Struct = thread_local global %"typeid({{.*}}S)"* @_D{{[0-9]+}}TypeInfo_S{{.*}}1S6__initZ
// CHECK: @{{.*}}structvarC15TypeInfo_Struct = thread_local global %object.TypeInfo_Struct* {{.*}}@_D{{[0-9]+}}TypeInfo_S{{.*}}1S6__initZ
auto structvar = typeid(S);

0 comments on commit c0b9ba4

Please sign in to comment.