Exemplo n.º 1
0
Arquivo: ir.cpp Projeto: alexrp/ldc
void Ir::emitFunctionBodies()
{
    while (!functionbodies.empty())
    {
        IrFunction* irf = functionbodies.front();
        functionbodies.pop_front();
        DtoDefineFunction(irf->decl);
    }
}
Exemplo n.º 2
0
Arquivo: nested.cpp Projeto: torje/ldc
LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
{
    Logger::println("DtoNestedContext for %s", sym->toPrettyChars());
    LOG_SCOPE;

    IrFunction* irfunc = gIR->func();
    bool fromParent = true;

    LLValue* val;
    // if this func has its own vars that are accessed by nested funcs
    // use its own context
    if (irfunc->nestedVar) {
        val = irfunc->nestedVar;
        fromParent = false;
    }
    // otherwise, it may have gotten a context from the caller
    else if (irfunc->nestArg)
        val = DtoLoad(irfunc->nestArg);
    // or just have a this argument
    else if (irfunc->thisArg)
    {
#if DMDV2
        AggregateDeclaration* ad = irfunc->decl->isMember2();
        val = ad->isClassDeclaration() ? DtoLoad(irfunc->thisArg) : irfunc->thisArg;
#else
        ClassDeclaration* ad = irfunc->decl->isMember2()->isClassDeclaration();
        val = DtoLoad(irfunc->thisArg);
#endif
        if (!ad || !ad->vthis)
            return llvm::UndefValue::get(getVoidPtrType());
        val = DtoLoad(DtoGEPi(val, 0,ad->vthis->ir.irField->index, ".vthis"));
    }
    else
    {
        return llvm::UndefValue::get(getVoidPtrType());
    }
    if (nestedCtx == NCHybrid) {
        struct FuncDeclaration* fd = 0;
    #if DMDV2
        if (AggregateDeclaration *ad = sym->isAggregateDeclaration())
            // If sym is a nested struct or a nested class, pass the frame
            // of the function where sym is declared.
            fd = ad->toParent()->isFuncDeclaration();
        else
    #endif
        if (FuncDeclaration* symfd = sym->isFuncDeclaration()) {
            // Make sure we've had a chance to analyze nested context usage
        #if DMDV2
            DtoCreateNestedContextType(symfd);
        #else
            DtoDefineFunction(symfd);
        #endif

            // if this is for a function that doesn't access variables from
            // enclosing scopes, it doesn't matter what we pass.
            // Tell LLVM about it by passing an 'undef'.
            if (symfd && symfd->ir.irFunc->depth == -1)
                return llvm::UndefValue::get(getVoidPtrType());

            // If sym is a nested function, and it's parent context is different than the
            // one we got, adjust it.
            fd = getParentFunc(symfd, true);
        }
        if (fd) {
            Logger::println("For nested function, parent is %s", fd->toChars());
            FuncDeclaration* ctxfd = irfunc->decl;
            Logger::println("Current function is %s", ctxfd->toChars());
            if (fromParent) {
                ctxfd = getParentFunc(ctxfd, true);
                assert(ctxfd && "Context from outer function, but no outer function?");
            }
            Logger::println("Context is from %s", ctxfd->toChars());

            unsigned neededDepth = fd->ir.irFunc->depth;
            unsigned ctxDepth = ctxfd->ir.irFunc->depth;

            Logger::cout() << "Needed depth: " << neededDepth << '\n';
            Logger::cout() << "Context depth: " << ctxDepth << '\n';

            if (neededDepth >= ctxDepth) {
                // assert(neededDepth <= ctxDepth + 1 && "How are we going more than one nesting level up?");
                // fd needs the same context as we do, so all is well
                Logger::println("Calling sibling function or directly nested function");
            } else {
                val = DtoBitCast(val, LLPointerType::getUnqual(ctxfd->ir.irFunc->frameType));
                val = DtoGEPi(val, 0, neededDepth);
                val = DtoAlignedLoad(val, (std::string(".frame.") + fd->toChars()).c_str());
            }
        }
    }
    Logger::cout() << "result = " << *val << '\n';
    Logger::cout() << "of type " << *val->getType() << '\n';
    return val;
}