Esempio n. 1
0
llvm::Constant *
IrAggr::createInitializerConstant(const VarInitMap &explicitInitializers) {
  IF_LOG Logger::println("Creating initializer constant for %s",
                         aggrdecl->toChars());
  LOG_SCOPE;

  llvm::SmallVector<llvm::Constant *, 16> constants;

  unsigned offset = 0;
  if (type->ty == Tclass) {
    // add vtbl
    constants.push_back(getVtblSymbol());
    offset += Target::ptrsize;

    // add monitor (except for C++ classes)
    if (!aggrdecl->isClassDeclaration()->isCPPclass()) {
      constants.push_back(getNullValue(getVoidPtrType()));
      offset += Target::ptrsize;
    }
  }

  // Add the initializers for the member fields. While we are traversing the
  // class hierarchy, use the opportunity to populate interfacesWithVtbls if
  // we haven't done so previously (due to e.g. ClassReferenceExp, we can
  // have multiple initializer constants for a single class).
  addFieldInitializers(constants, explicitInitializers, aggrdecl, offset,
                       interfacesWithVtbls.empty());

  // tail padding?
  const size_t structsize = aggrdecl->size(Loc());
  if (offset < structsize)
    add_zeros(constants, offset, structsize);

  assert(!constants.empty());

  // get LL field types
  llvm::SmallVector<llvm::Type *, 16> types;
  types.reserve(constants.size());
  for (auto c : constants)
    types.push_back(c->getType());

  auto llStructType = getLLStructType();
  bool isCompatible = (types.size() == llStructType->getNumElements());
  if (isCompatible) {
    for (size_t i = 0; i < types.size(); i++) {
      if (types[i] != llStructType->getElementType(i)) {
        isCompatible = false;
        break;
      }
    }
  }

  // build constant
  LLStructType *llType =
      isCompatible ? llStructType
                   : LLStructType::get(gIR->context(), types, isPacked());
  llvm::Constant *c = LLConstantStruct::get(llType, constants);
  IF_LOG Logger::cout() << "final initializer: " << *c << std::endl;
  return c;
}
Esempio n. 2
0
std::vector<llvm::Constant*> IrStruct::createClassDefaultInitializer()
{
    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
    assert(cd && "invalid class aggregate");

    IF_LOG Logger::println("Building class default initializer %s @ %s", cd->toPrettyChars(), cd->loc.toChars());
    LOG_SCOPE;
    IF_LOG Logger::println("Instance size: %u", cd->structsize);

    // find the fields that contribute to the default initializer.
    // these will define the default type.

    std::vector<llvm::Constant*> constants;
    constants.reserve(32);

    // add vtbl
    constants.push_back(getVtblSymbol());
    // add monitor
    constants.push_back(getNullValue(DtoType(Type::tvoid->pointerTo())));

    // we start right after the vtbl and monitor
    size_t offset = PTRSIZE * 2;
    size_t field_index = 2;

    // add data members recursively
    addBaseClassInits(constants, cd, offset, field_index);

    // tail padding?
    if (offset < cd->structsize)
        add_zeros(constants, cd->structsize - offset);

    return constants;
}
Esempio n. 3
0
llvm::Constant* IrAggr::createInitializerConstant(
    const VarInitMap& explicitInitializers,
    llvm::StructType* initializerType)
{
    IF_LOG Logger::println("Creating initializer constant for %s", aggrdecl->toChars());
    LOG_SCOPE;

    llvm::SmallVector<llvm::Constant*, 16> constants;

    unsigned offset = 0;
    if (type->ty == Tclass)
    {
        // add vtbl
        constants.push_back(getVtblSymbol());
        // add monitor
        constants.push_back(getNullValue(DtoType(Type::tvoid->pointerTo())));

        // we start right after the vtbl and monitor
        offset = Target::ptrsize * 2;
    }

    // Add the initializers for the member fields. While we are traversing the
    // class hierarchy, use the opportunity to populate interfacesWithVtbls if
    // we haven't done so previously (due to e.g. ClassReferenceExp, we can
    // have multiple initializer constants for a single class).
    addFieldInitializers(constants, explicitInitializers, aggrdecl, offset,
        interfacesWithVtbls.empty());

    // tail padding?
    const size_t structsize = aggrdecl->size(Loc());
    if (offset < structsize)
    {
        add_zeros(constants, offset, structsize);
    }

    // get initializer type
    if (!initializerType || initializerType->isOpaque())
    {
        llvm::SmallVector<llvm::Constant*, 16>::iterator itr, end = constants.end();
        llvm::SmallVector<llvm::Type*, 16> types;
        types.reserve(constants.size());
        for (itr = constants.begin(); itr != end; ++itr)
            types.push_back((*itr)->getType());
        if (!initializerType)
            initializerType = LLStructType::get(gIR->context(), types, isPacked());
        else
            initializerType->setBody(types, isPacked());
    }

    // build constant
    assert(!constants.empty());
    llvm::Constant* c = LLConstantStruct::get(initializerType, constants);
    IF_LOG Logger::cout() << "final initializer: " << *c << std::endl;
    return c;
}
Esempio n. 4
0
void DtoFinalizeScopeClass(Loc &loc, LLValue *inst, bool hasDtor) {
  if (!isOptimizationEnabled() || hasDtor) {
    DtoFinalizeClass(loc, inst);
    return;
  }

  // no dtors => only finalize (via druntime call) if monitor is set,
  // see https://github.com/ldc-developers/ldc/issues/2515
  llvm::BasicBlock *ifbb = gIR->insertBB("if");
  llvm::BasicBlock *endbb = gIR->insertBBAfter(ifbb, "endif");

  const auto monitor = DtoLoad(DtoGEPi(inst, 0, 1), ".monitor");
  const auto hasMonitor =
      gIR->ir->CreateICmp(llvm::CmpInst::ICMP_NE, monitor,
                          getNullValue(monitor->getType()), ".hasMonitor");
  llvm::BranchInst::Create(ifbb, endbb, hasMonitor, gIR->scopebb());

  gIR->scope() = IRScope(ifbb);
  DtoFinalizeClass(loc, inst);
  gIR->ir->CreateBr(endbb);

  gIR->scope() = IRScope(endbb);
}
Esempio n. 5
0
LLConstant * IrStruct::getClassInfoInterfaces()
{
    IF_LOG Logger::println("Building ClassInfo.interfaces");
    LOG_SCOPE;

    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
    assert(cd);

    size_t n = interfacesWithVtbls.size();
    assert(stripModifiers(type)->irtype->isClass()->getNumInterfaceVtbls() == n &&
        "inconsistent number of interface vtables in this class");

    VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);

    if (n == 0)
        return getNullValue(DtoType(interfaces_idx->type));

// Build array of:
//
//     struct Interface
//     {
//         ClassInfo   classinfo;
//         void*[]     vtbl;
//         ptrdiff_t   offset;
//     }

    LLSmallVector<LLConstant*, 6> constants;
    constants.reserve(cd->vtblInterfaces->dim);

    LLType* classinfo_type = DtoType(ClassDeclaration::classinfo->type);
    LLType* voidptrptr_type = DtoType(
        Type::tvoid->pointerTo()->pointerTo());
    VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3);
    LLStructType* interface_type = isaStruct(DtoType(idx->type->nextOf()));
    assert(interface_type);

    for (size_t i = 0; i < n; ++i)
    {
        BaseClass* it = interfacesWithVtbls[i];

        IF_LOG Logger::println("Adding interface %s", it->base->toPrettyChars());

        IrStruct* irinter = it->base->ir.irStruct;
        assert(irinter && "interface has null IrStruct");
        IrTypeClass* itc = stripModifiers(irinter->type)->irtype->isClass();
        assert(itc && "null interface IrTypeClass");

        // classinfo
        LLConstant* ci = irinter->getClassInfoSymbol();
        ci = DtoBitCast(ci, classinfo_type);

        // vtbl
        LLConstant* vtb;
        // interface get a null
        if (cd->isInterfaceDeclaration())
        {
            vtb = DtoConstSlice(DtoConstSize_t(0), getNullValue(voidptrptr_type));
        }
        else
        {
            ClassGlobalMap::iterator itv = interfaceVtblMap.find(it->base);
            assert(itv != interfaceVtblMap.end() && "interface vtbl not found");
            vtb = itv->second;
            vtb = DtoBitCast(vtb, voidptrptr_type);
            vtb = DtoConstSlice(DtoConstSize_t(itc->getVtblSize()), vtb);
        }

        // offset
        LLConstant* off = DtoConstSize_t(it->offset);

        // create Interface struct
        LLConstant* inits[3] = { ci, vtb, off };
        LLConstant* entry = LLConstantStruct::get(interface_type, llvm::makeArrayRef(inits, 3));
        constants.push_back(entry);
    }

    // create Interface[N]
    LLArrayType* array_type = llvm::ArrayType::get(interface_type, n);

    // create and apply initializer
    LLConstant* arr = LLConstantArray::get(array_type, constants);
    classInterfacesArray->setInitializer(arr);

    // return null, only baseclass provide interfaces
    if (cd->vtblInterfaces->dim == 0)
    {
        return getNullValue(DtoType(interfaces_idx->type));
    }

    // only the interface explicitly implemented by this class
    // (not super classes) should show in ClassInfo
    LLConstant* idxs[2] = {
        DtoConstSize_t(0),
        DtoConstSize_t(n - cd->vtblInterfaces->dim)
    };

    LLConstant* ptr = llvm::ConstantExpr::getGetElementPtr(
        classInterfacesArray, idxs, true);

    // return as a slice
    return DtoConstSlice( DtoConstSize_t(cd->vtblInterfaces->dim), ptr );
}
Esempio n. 6
0
llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instance, size_t interfaces_index)
{
    ClassGlobalMap::iterator it = interfaceVtblMap.find(b->base);
    if (it != interfaceVtblMap.end())
        return it->second;

    IF_LOG Logger::println("Building vtbl for implementation of interface %s in class %s",
        b->base->toPrettyChars(), aggrdecl->toPrettyChars());
    LOG_SCOPE;

    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
    assert(cd && "not a class aggregate");

    FuncDeclarations vtbl_array;
    b->fillVtbl(cd, &vtbl_array, new_instance);

    std::vector<llvm::Constant*> constants;
    constants.reserve(vtbl_array.dim);

    // start with the interface info
    VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);

    // index into the interfaces array
    llvm::Constant* idxs[2] = {
        DtoConstSize_t(0),
        DtoConstSize_t(interfaces_index)
    };

    llvm::Constant* c = llvm::ConstantExpr::getGetElementPtr(
        getInterfaceArraySymbol(), idxs, true);

    constants.push_back(c);

    // add virtual function pointers
    size_t n = vtbl_array.dim;
    for (size_t i = 1; i < n; i++)
    {
        Dsymbol* dsym = static_cast<Dsymbol*>(vtbl_array.data[i]);
        if (dsym == NULL)
        {
            // FIXME
            // why is this null?
            // happens for mini/s.d
            constants.push_back(getNullValue(getVoidPtrType()));
            continue;
        }

        FuncDeclaration* fd = dsym->isFuncDeclaration();
        assert(fd && "vtbl entry not a function");

        assert((!fd->isAbstract() || fd->fbody) &&
            "null symbol in interface implementation vtable");

        fd->codegen(Type::sir);
        assert(fd->ir.irFunc && "invalid vtbl function");

        constants.push_back(fd->ir.irFunc->func);
    }

    // build the vtbl constant
    llvm::Constant* vtbl_constant = LLConstantStruct::getAnon(gIR->context(), constants, false);

    // create the global variable to hold it
    llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);

    std::string mangle("_D");
    mangle.append(cd->mangle());
    mangle.append("11__interface");
    mangle.append(b->base->mangle());
    mangle.append("6__vtblZ");

    llvm::GlobalVariable* GV = new llvm::GlobalVariable(
        *gIR->module,
        vtbl_constant->getType(),
        true,
        _linkage,
        vtbl_constant,
        mangle
    );

    // insert into the vtbl map
    interfaceVtblMap.insert(std::make_pair(b->base, GV));

    return GV;
}
Esempio n. 7
0
LLConstant * IrStruct::getVtblInit()
{
    if (constVtbl)
        return constVtbl;

    IF_LOG Logger::println("Building vtbl initializer");
    LOG_SCOPE;

    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
    assert(cd && "not class");

    std::vector<llvm::Constant*> constants;
    constants.reserve(cd->vtbl.dim);

    // start with the classinfo
    llvm::Constant* c = getClassInfoSymbol();
    c = DtoBitCast(c, DtoType(ClassDeclaration::classinfo->type));
    constants.push_back(c);

    // add virtual function pointers
    size_t n = cd->vtbl.dim;
    for (size_t i = 1; i < n; i++)
    {
        Dsymbol* dsym = static_cast<Dsymbol*>(cd->vtbl.data[i]);
        assert(dsym && "null vtbl member");

        FuncDeclaration* fd = dsym->isFuncDeclaration();
        assert(fd && "vtbl entry not a function");

        if (cd->isAbstract() || (fd->isAbstract() && !fd->fbody))
        {
            c = getNullValue(DtoType(fd->type->pointerTo()));
        }
        else
        {
            fd->codegen(Type::sir);
            assert(fd->ir.irFunc && "invalid vtbl function");
            c = fd->ir.irFunc->func;
#if DMDV2
            if (cd->isFuncHidden(fd))
            {   /* fd is hidden from the view of this class.
                 * If fd overlaps with any function in the vtbl[], then
                 * issue 'hidden' error.
                 */
                for (size_t j = 1; j < n; j++)
                {   if (j == i)
                        continue;
                    FuncDeclaration *fd2 = static_cast<Dsymbol *>(cd->vtbl.data[j])->isFuncDeclaration();
                    if (!fd2->ident->equals(fd->ident))
                        continue;
                    if (fd->leastAsSpecialized(fd2) || fd2->leastAsSpecialized(fd))
                    {
                        if (global.params.warnings)
                        {
                            TypeFunction *tf = static_cast<TypeFunction *>(fd->type);
                            if (tf->ty == Tfunction)
                                error("%s%s is hidden by %s\n", fd->toPrettyChars(), Parameter::argsTypesToChars(tf->parameters, tf->varargs), toChars());
                            else
                                error("%s is hidden by %s\n", fd->toPrettyChars(), toChars());
                        }
                        c = DtoBitCast(LLVM_D_GetRuntimeFunction(gIR->module, "_d_hidden_func"), c->getType());
                        break;
                    }
                }
            }
#endif
        }
        constants.push_back(c);
    }

    // build the constant struct
    LLType* vtblTy = stripModifiers(type)->irtype->isClass()->getVtbl();
    constVtbl = LLConstantStruct::get(isaStruct(vtblTy), constants);

#if 0
   IF_LOG Logger::cout() << "constVtbl type: " << *constVtbl->getType() << std::endl;
   IF_LOG Logger::cout() << "vtbl type: " << *stripModifiers(type)->irtype->isClass()->getVtbl() << std::endl;
#endif

#if 0

    size_t nc = constants.size();

    for (size_t i = 0; i < nc; ++i)
    {
        if (constVtbl->getOperand(i)->getType() != vtblTy->getContainedType(i))
        {
            Logger::cout() << "type mismatch for entry # " << i << " in vtbl initializer" << std::endl;

            constVtbl->getOperand(i)->dump();
            vtblTy->getContainedType(i)->dump();
        }
    }

#endif

    assert(constVtbl->getType() == stripModifiers(type)->irtype->isClass()->getVtbl() &&
        "vtbl initializer type mismatch");

    return constVtbl;
}
Esempio n. 8
0
LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
{
//     The layout is:
//        {
//         void **vptr;
//         monitor_t monitor;
//         byte[] initializer;     // static initialization data
//         char[] name;        // class name
//         void *[] vtbl;
//         Interface[] interfaces;
//         ClassInfo *base;        // base class
//         void *destructor;
//         void *invariant;        // class invariant
//         uint flags;
//         void *deallocator;
//         OffsetTypeInfo[] offTi;
//         void *defaultConstructor;
//         version(D_Version2)
//              immutable(void)* m_RTInfo;
//         else
//              TypeInfo typeinfo; // since dmd 1.045
//        }

    Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
    LOG_SCOPE;

    assert(cd->type->ty == Tclass);
    TypeClass* cdty = static_cast<TypeClass*>(cd->type);

    IrStruct* ir = cd->ir.irStruct;
    assert(ir);

    ClassDeclaration* cinfo = ClassDeclaration::classinfo;

    if (cinfo->fields.dim != 12)
    {
        error("object.d ClassInfo class is incorrect");
        fatal();
    }

    // use the rtti builder
    RTTIBuilder b(ClassDeclaration::classinfo);

    LLConstant* c;

    LLType* voidPtr = getVoidPtrType();
    LLType* voidPtrPtr = getPtrToType(voidPtr);

    // byte[] init
    if (cd->isInterfaceDeclaration())
    {
        b.push_null_void_array();
    }
    else
    {
        LLType* cd_type = cdty->irtype->isClass()->getMemoryLLType();
        size_t initsz = getTypePaddedSize(cd_type);
        b.push_void_array(initsz, ir->getInitSymbol());
    }

    // class name
    // code from dmd
    const char *name = cd->ident->toChars();
    size_t namelen = strlen(name);
    if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
    {
        name = cd->toPrettyChars();
        namelen = strlen(name);
    }
    b.push_string(name);

    // vtbl array
    if (cd->isInterfaceDeclaration())
    {
        b.push_array(0, getNullValue(voidPtrPtr));
    }
    else
    {
        c = DtoBitCast(ir->getVtblSymbol(), voidPtrPtr);
        b.push_array(cd->vtbl.dim, c);
    }

    // interfaces array
    b.push(ir->getClassInfoInterfaces());

    // base classinfo
    // interfaces never get a base , just the interfaces[]
    if (cd->baseClass && !cd->isInterfaceDeclaration())
        b.push_classinfo(cd->baseClass);
    else
        b.push_null(cinfo->type);

    // destructor
    if (cd->isInterfaceDeclaration())
        b.push_null_vp();
    else
        b.push(build_class_dtor(cd));

    // invariant
    VarDeclaration* invVar = static_cast<VarDeclaration*>(cinfo->fields.data[6]);
    b.push_funcptr(cd->inv, invVar->type);

    // uint flags
    unsigned flags;
    if (cd->isInterfaceDeclaration())
        flags = 4 | cd->isCOMinterface() | 32;
    else
        flags = build_classinfo_flags(cd);
    b.push_uint(flags);

    // deallocator
    b.push_funcptr(cd->aggDelete, Type::tvoid->pointerTo());

    // offset typeinfo
    VarDeclaration* offTiVar = static_cast<VarDeclaration*>(cinfo->fields.data[9]);

#if GENERATE_OFFTI

    if (cd->isInterfaceDeclaration())
        b.push_null(offTiVar->type);
    else
        b.push(build_offti_array(cd, DtoType(offTiVar->type)));

#else // GENERATE_OFFTI

    b.push_null(offTiVar->type);

#endif // GENERATE_OFFTI

    // default constructor
    VarDeclaration* defConstructorVar = static_cast<VarDeclaration*>(cinfo->fields.data[10]);
    b.push_funcptr(cd->defaultCtor, defConstructorVar->type);

#if DMDV2
    // immutable(void)* m_RTInfo;
    // The cases where getRTInfo is null are not quite here, but the code is
    // modelled after what DMD does.
    if (cd->getRTInfo)
        b.push(cd->getRTInfo->toConstElem(gIR));
    else if (flags & 2)
        b.push_size_as_vp(0);       // no pointers
    else
        b.push_size_as_vp(1);       // has pointers
#else
    // typeinfo - since 1.045
    b.push_typeinfo(cd->type);
#endif

    /*size_t n = inits.size();
    for (size_t i=0; i<n; ++i)
    {
        Logger::cout() << "inits[" << i << "]: " << *inits[i] << '\n';
    }*/

    // build the initializer
    LLType *initType = ir->classInfo->getType()->getContainedType(0);
    LLConstant* finalinit = b.get_constant(isaStruct(initType));

    //Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
    ir->constClassInfo = finalinit;

    // sanity check
    assert(finalinit->getType() == initType &&
        "__ClassZ initializer does not match the ClassInfo type");

    // return initializer
    return finalinit;
}
Esempio n. 9
0
llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance, size_t interfaces_index)
{
    ClassGlobalMap::iterator it = interfaceVtblMap.find(b->base);
    if (it != interfaceVtblMap.end())
        return it->second;

    IF_LOG Logger::println("Building vtbl for implementation of interface %s in class %s",
        b->base->toPrettyChars(), aggrdecl->toPrettyChars());
    LOG_SCOPE;

    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
    assert(cd && "not a class aggregate");

    FuncDeclarations vtbl_array;
    b->fillVtbl(cd, &vtbl_array, new_instance);

    std::vector<llvm::Constant*> constants;
    constants.reserve(vtbl_array.dim);

    if (!b->base->isCPPinterface()) { // skip interface info for CPP interfaces
        // start with the interface info
        VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);

        // index into the interfaces array
        llvm::Constant* idxs[2] = {
            DtoConstSize_t(0),
            DtoConstSize_t(interfaces_index)
        };

        llvm::Constant* c = llvm::ConstantExpr::getGetElementPtr(
            getInterfaceArraySymbol(), idxs, true);

        constants.push_back(c);
    }

    // add virtual function pointers
    size_t n = vtbl_array.dim;
    for (size_t i = b->base->vtblOffset(); i < n; i++)
    {
        Dsymbol* dsym = static_cast<Dsymbol*>(vtbl_array.data[i]);
        if (dsym == NULL)
        {
            // FIXME
            // why is this null?
            // happens for mini/s.d
            constants.push_back(getNullValue(getVoidPtrType()));
            continue;
        }

        FuncDeclaration* fd = dsym->isFuncDeclaration();
        assert(fd && "vtbl entry not a function");

        assert((!fd->isAbstract() || fd->fbody) &&
            "null symbol in interface implementation vtable");

        fd->codegen(Type::sir);
        assert(fd->ir.irFunc && "invalid vtbl function");

        LLFunction *fn = fd->ir.irFunc->func;

        // If the base is a cpp interface, 'this' parameter is a pointer to
        // the interface not the underlying object as expected. Instead of
        // the function, we place into the vtable a small wrapper, called thunk,
        // that casts 'this' to the object and then pass it to the real function.
        if (b->base->isCPPinterface()) {
            TypeFunction *f = (TypeFunction*)fd->type->toBasetype();
            assert(f->fty.arg_this);

            // create the thunk function
            OutBuffer name;
            name.writestring("Th");
            name.printf("%i", b->offset);
            name.writestring(fd->mangle());
            LLFunction *thunk = LLFunction::Create(isaFunction(fn->getType()->getContainedType(0)),
                                                 DtoLinkage(fd), name.toChars(), gIR->module);

            // create entry and end blocks
            llvm::BasicBlock* beginbb = llvm::BasicBlock::Create(gIR->context(), "entry", thunk);
            llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "endentry", thunk);
            gIR->scopes.push_back(IRScope(beginbb, endbb));

            // copy the function parameters, so later we can pass them to the real function
            std::vector<LLValue*> args;
            llvm::Function::arg_iterator iarg = thunk->arg_begin();
            for (; iarg != thunk->arg_end(); ++iarg)
                args.push_back(iarg);

            // cast 'this' to Object
            LLValue* &thisArg = args[(f->fty.arg_sret == 0) ? 0 : 1];
            LLType* thisType = thisArg->getType();
            thisArg = DtoBitCast(thisArg, getVoidPtrType());
            thisArg = DtoGEP1(thisArg, DtoConstInt(-b->offset));
            thisArg = DtoBitCast(thisArg, thisType);

            // call the real vtbl function.
            LLValue *retVal = gIR->ir->CreateCall(fn, args);

            // return from the thunk
            if (thunk->getReturnType() == LLType::getVoidTy(gIR->context()))
                llvm::ReturnInst::Create(gIR->context(), beginbb);
            else
                llvm::ReturnInst::Create(gIR->context(), retVal, beginbb);

            // clean up
            gIR->scopes.pop_back();
            thunk->getBasicBlockList().pop_back();

            fn = thunk;
        }

        constants.push_back(fn);
    }

    // build the vtbl constant
    llvm::Constant* vtbl_constant = LLConstantStruct::getAnon(gIR->context(), constants, false);

    // create the global variable to hold it
    llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);

    std::string mangle("_D");
    mangle.append(cd->mangle());
    mangle.append("11__interface");
    mangle.append(b->base->mangle());
    mangle.append("6__vtblZ");

    llvm::GlobalVariable* GV = getOrCreateGlobal(cd->loc,
        *gIR->module,
        vtbl_constant->getType(),
        true,
        _linkage,
        vtbl_constant,
        mangle
    );

    // insert into the vtbl map
    interfaceVtblMap.insert(std::make_pair(b->base, GV));

    return GV;
}
Esempio n. 10
0
void RTTIBuilder::push_null_void_array()
{
    const llvm::Type* T = DtoType(Type::tvoid->arrayOf());
    inits.push_back(getNullValue(T));
}
Esempio n. 11
0
void RTTIBuilder::push_null_vp()
{
    inits.push_back(getNullValue(getVoidPtrType()));
}
Esempio n. 12
0
void RTTIBuilder::push_null(Type* T)
{
    inits.push_back(getNullValue(DtoType(T)));
}
Esempio n. 13
0
void RTTIBuilder::push_null_void_array() {
  LLType *T = DtoType(Type::tvoid->arrayOf());
  push(getNullValue(T));
}
Esempio n. 14
0
void RTTIBuilder::push_null_vp() { push(getNullValue(getVoidPtrType())); }
Esempio n. 15
0
void RTTIBuilder::push_null(Type *T) { push(getNullValue(DtoType(T))); }