void Ir::emitFunctionBodies() { while (!functionbodies.empty()) { IrFunction* irf = functionbodies.front(); functionbodies.pop_front(); DtoDefineFunction(irf->decl); } }
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; }