From 245e19e33a9ef0a1ec79f09c5948b219dde6f8c9 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 6 Jul 2018 21:22:35 +0200 Subject: [PATCH] Add some support for classes without TypeInfos For -betterC and/or a minimal object.d without TypeInfo: * Skip TypeInfo emission for classes and interfaces. * Emit null as first vtable member. Makes dmd-testsuite's {compilable,runnable}/minimal2.d work. --- gen/classes.cpp | 5 ----- gen/declarations.cpp | 25 ++++++++++++++----------- ir/irclass.cpp | 30 ++++++++++++++++++++---------- tests/baremetal/classes.d | 29 +++++++++++++++++++++++++++++ tests/d2/dmd-testsuite | 2 +- 5 files changed, 64 insertions(+), 27 deletions(-) create mode 100644 tests/baremetal/classes.d diff --git a/gen/classes.cpp b/gen/classes.cpp index 6efe4406dcb..649731b7d4e 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -65,11 +65,6 @@ void DtoResolveClass(ClassDeclaration *cd) { getIrField(vd, true); } - // emit the interfaceInfosZ symbol if necessary - if (cd->vtblInterfaces && cd->vtblInterfaces->dim > 0) { - irAggr->getInterfaceArraySymbol(); // initializer is applied when it's built - } - // interface only emit typeinfo and classinfo if (cd->isInterfaceDeclaration()) { irAggr->initializeInterface(); diff --git a/gen/declarations.cpp b/gen/declarations.cpp index 1ca7af491fe..1c4abb6427f 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -89,14 +89,13 @@ class CodegenVisitor : public Visitor { } // Emit TypeInfo. - DtoTypeInfoOf(decl->type, /*base=*/false); - - // Declare __InterfaceZ. - IrAggr *ir = getIrAggr(decl); - llvm::GlobalVariable *interfaceZ = ir->getClassInfoSymbol(); - // Only define if not speculative. - if (!isSpeculativeType(decl->type)) { - defineGlobal(interfaceZ, ir->getClassInfoInit(), decl); + if (global.params.useTypeInfo && Type::dtypeinfo) { + IrAggr *ir = getIrAggr(decl); + llvm::GlobalVariable *interfaceZ = ir->getClassInfoSymbol(); + // Only define if not speculative. + if (!isSpeculativeType(decl->type)) { + defineGlobal(interfaceZ, ir->getClassInfoInit(), decl); + } } } } @@ -196,9 +195,13 @@ class CodegenVisitor : public Visitor { ir->defineInterfaceVtbls(); - llvm::GlobalVariable *classZ = ir->getClassInfoSymbol(); - if (!isSpeculativeType(decl->type)) { - defineGlobal(classZ, ir->getClassInfoInit(), decl); + // Emit TypeInfo. + if (global.params.useTypeInfo && Type::dtypeinfo) { + llvm::GlobalVariable *classZ = ir->getClassInfoSymbol(); + // Only define if not speculative. + if (!isSpeculativeType(decl->type)) { + defineGlobal(classZ, ir->getClassInfoInit(), decl); + } } } } diff --git a/ir/irclass.cpp b/ir/irclass.cpp index 694a09bdd6d..75f70242748 100644 --- a/ir/irclass.cpp +++ b/ir/irclass.cpp @@ -164,8 +164,13 @@ LLConstant *IrAggr::getVtblInit() { // start with the classinfo llvm::Constant *c; if (!cd->isCPPclass()) { - c = getClassInfoSymbol(); - c = DtoBitCast(c, voidPtrType); + if (global.params.useTypeInfo && Type::dtypeinfo) { + c = getClassInfoSymbol(); + c = DtoBitCast(c, voidPtrType); + } else { + // use null if there are no TypeInfos + c = llvm::Constant::getNullValue(voidPtrType); + } constants.push_back(c); } @@ -312,16 +317,21 @@ void IrAggr::defineInterfaceVtbl(BaseClass *b, bool new_instance, const auto voidPtrTy = getVoidPtrType(); if (!b->sym->isCPPinterface()) { // skip interface info for CPP interfaces - // index into the interfaces array - llvm::Constant *idxs[2] = {DtoConstSize_t(0), - DtoConstSize_t(interfaces_index)}; + if (global.params.useTypeInfo && Type::dtypeinfo) { + // index into the interfaces array + llvm::Constant *idxs[2] = {DtoConstSize_t(0), + DtoConstSize_t(interfaces_index)}; - llvm::GlobalVariable *interfaceInfosZ = getInterfaceArraySymbol(); - llvm::Constant *c = llvm::ConstantExpr::getGetElementPtr( - isaPointer(interfaceInfosZ)->getElementType(), - interfaceInfosZ, idxs, true); + llvm::GlobalVariable *interfaceInfosZ = getInterfaceArraySymbol(); + llvm::Constant *c = llvm::ConstantExpr::getGetElementPtr( + isaPointer(interfaceInfosZ)->getElementType(), interfaceInfosZ, idxs, + true); - constants.push_back(DtoBitCast(c, voidPtrTy)); + constants.push_back(DtoBitCast(c, voidPtrTy)); + } else { + // use null if there are no TypeInfos + constants.push_back(llvm::Constant::getNullValue(voidPtrTy)); + } } // add virtual function pointers diff --git a/tests/baremetal/classes.d b/tests/baremetal/classes.d new file mode 100644 index 00000000000..bb673841b02 --- /dev/null +++ b/tests/baremetal/classes.d @@ -0,0 +1,29 @@ +// Use classes with virtual functions. + +// -betterC for C assert. +// RUN: %ldc -betterC %baremetal_args -run %s + +class A +{ + int x; + bool isB() { return false; } +} + +class B : A +{ + override bool isB() { return true; } +} + +__gshared A a = new A(); +__gshared B b = new B(); + +extern(C) int main() +{ + A obj = a; + assert(!obj.isB()); + + obj = b; + assert(obj.isB()); + + return 0; +} diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 977ef0696f7..a079cc80f4e 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 977ef0696f7941357385925c07617544c3527f4c +Subproject commit a079cc80f4ebe3574fc50792d9c83b112dd08008