Exemple #1
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;
}
Exemple #2
0
static void DtoCreateNestedContextType(FuncDeclaration* fd) {
    Logger::println("DtoCreateNestedContextType for %s", fd->toChars());
    LOG_SCOPE

#if DMDV2
    DtoDeclareFunction(fd);
#endif

    if (fd->ir.irFunc->nestedContextCreated)
        return;
    fd->ir.irFunc->nestedContextCreated = true;

#if DMDV2
    if (fd->nestedVars.empty()) {
        // fill nestedVars
        size_t nnest = fd->closureVars.dim;
        for (size_t i = 0; i < nnest; ++i)
        {
            VarDeclaration* vd = (VarDeclaration*)fd->closureVars.data[i];
            fd->nestedVars.insert(vd);
        }
    }
#endif

    if (nestedCtx == NCHybrid) {
        // construct nested variables array
        if (!fd->nestedVars.empty())
        {
            Logger::println("has nested frame");
            // start with adding all enclosing parent frames until a static parent is reached

            LLStructType* innerFrameType = NULL;
            unsigned depth = -1;
            if (!fd->isStatic()) {
                if (FuncDeclaration* parfd = getParentFunc(fd, true)) {
                    // Make sure parfd->ir.irFunc has already been set.
                    DtoDeclareFunction(parfd);

                    innerFrameType = parfd->ir.irFunc->frameType;
                    if (innerFrameType)
                        depth = parfd->ir.irFunc->depth;
                }
            }
            fd->ir.irFunc->depth = ++depth;

            Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n';

            typedef std::vector<LLType*> TypeVec;
            TypeVec types;
            if (depth != 0) {
                assert(innerFrameType);
                // Add frame pointer types for all but last frame
                if (depth > 1) {
                    for (unsigned i = 0; i < (depth - 1); ++i) {
                        types.push_back(innerFrameType->getElementType(i));
                    }
                }
                // Add frame pointer type for last frame
                types.push_back(LLPointerType::getUnqual(innerFrameType));
            }

            if (Logger::enabled()) {
                Logger::println("Frame types: ");
                LOG_SCOPE;
                for (TypeVec::iterator i = types.begin(); i != types.end(); ++i)
                    Logger::cout() << **i << '\n';
            }

            // Add the direct nested variables of this function, and update their indices to match.
            // TODO: optimize ordering for minimal space usage?
            for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
            {
                VarDeclaration* vd = *i;
                if (!vd->ir.irLocal)
                    vd->ir.irLocal = new IrLocal(vd);

                vd->ir.irLocal->nestedIndex = types.size();
                vd->ir.irLocal->nestedDepth = depth;
                if (vd->isParameter()) {
                    // Parameters will have storage associated with them (to handle byref etc.),
                    // so handle those cases specially by storing a pointer instead of a value.
                    IrParameter * irparam = vd->ir.irParam;
                    LLValue* value = irparam->value;
                    assert(value);
                    LLType* type = value->getType();
                    bool refout = vd->storage_class & (STCref | STCout);
                    bool lazy = vd->storage_class & STClazy;
                    bool byref = irparam->arg->byref;
                #if STRUCTTHISREF
                    bool isVthisPtr = irparam->isVthis && !byref;
                #else
                    bool isVthisPtr = irparam->isVthis;
                #endif
                    if ((!refout && (!byref || lazy)) || isVthisPtr) {
                        // This will be copied to the nesting frame.
                        if (lazy)
                            type = type->getContainedType(0);
                        else
                            type = DtoType(vd->type);
                        vd->ir.irParam->byref = false;
                    } else {
                        vd->ir.irParam->byref = true;
                    }
                    types.push_back(type);
                } else if (vd->isRef() || vd->isOut()) {
                    // Foreach variables can also be by reference, for instance.
                    types.push_back(DtoType(vd->type->pointerTo()));
                    vd->ir.irLocal->byref = true;
                } else {
                    types.push_back(DtoType(vd->type));
                    vd->ir.irLocal->byref = false;
                }
                if (Logger::enabled()) {
                    Logger::println("Nested var: %s", vd->toChars());
                    Logger::cout() << "of type: " << *types.back() << '\n';
                }
            }

            LLStructType* frameType = LLStructType::create(gIR->context(), types,
                                                           std::string("nest.") + fd->toChars());

            Logger::cout() << "frameType = " << *frameType << '\n';

            // Store type in IrFunction
            fd->ir.irFunc->frameType = frameType;
        } else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) {
            // Propagate context arg properties if the context arg is passed on unmodified.
            DtoCreateNestedContextType(parFunc);
            fd->ir.irFunc->frameType = parFunc->ir.irFunc->frameType;
            fd->ir.irFunc->depth = parFunc->ir.irFunc->depth;
        }
    }
    else {
        assert(0 && "Not implemented yet");
    }
}