ManagedValue SILGenFunction::emitFunctionRef(SILLocation loc, SILDeclRef constant, SILConstantInfo constantInfo) { // If the function has captures, apply them. if (auto fn = constant.getAnyFunctionRef()) { if (fn->getCaptureInfo().hasLocalCaptures() || fn->getCaptureInfo().hasGenericParamCaptures()) { return emitClosureValue(loc, constant, *fn); } } // Otherwise, use a global FunctionRefInst. SILValue c = emitGlobalFunctionRef(loc, constant, constantInfo); return ManagedValue::forUnmanaged(c); }
ManagedValue SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant, CanType expectedType, ArrayRef<Substitution> subs) { auto closure = *constant.getAnyFunctionRef(); auto captureInfo = closure.getCaptureInfo(); assert(((constant.uncurryLevel == 1 && captureInfo.hasLocalCaptures()) || (constant.uncurryLevel == 0 && !captureInfo.hasLocalCaptures())) && "curried local functions not yet supported"); auto constantInfo = getConstantInfo(constant); SILValue functionRef = emitGlobalFunctionRef(loc, constant, constantInfo); SILType functionTy = functionRef->getType(); // Apply substitutions. auto pft = constantInfo.SILFnType; bool wasSpecialized = false; if (pft->isPolymorphic()) { // If the lowered function type is generic but Sema did not hand us any // substitutions, the function is a local function that appears in a // generic context but does not have a generic parameter list of its own; // just use our forwarding substitutions. if (subs.empty()) { assert(closure.getAsDeclContext()->isLocalContext() && "cannot reference generic global function without substitutions"); subs = getForwardingSubstitutions(); } auto specialized = pft->substGenericArgs(F.getModule(), F.getModule().getSwiftModule(), subs); functionTy = SILType::getPrimitiveObjectType(specialized); wasSpecialized = true; } // If we're in top-level code, we don't need to physically capture script // globals, but we still need to mark them as escaping so that DI can flag // uninitialized uses. if (this == SGM.TopLevelSGF) { SGM.emitMarkFunctionEscapeForTopLevelCodeGlobals( loc, captureInfo); } if (!captureInfo.hasLocalCaptures() && !wasSpecialized) { auto result = ManagedValue::forUnmanaged(functionRef); return emitOrigToSubstValue(loc, result, AbstractionPattern(expectedType), expectedType); } SmallVector<ManagedValue, 4> capturedArgs; emitCaptures(loc, closure, CaptureEmission::PartialApplication, capturedArgs); // The partial application takes ownership of the context parameters. SmallVector<SILValue, 4> forwardedArgs; for (auto capture : capturedArgs) forwardedArgs.push_back(capture.forward(*this)); SILType closureTy = SILGenBuilder::getPartialApplyResultType(functionRef->getType(), capturedArgs.size(), SGM.M, subs); auto toClosure = B.createPartialApply(loc, functionRef, functionTy, subs, forwardedArgs, closureTy); auto result = emitManagedRValueWithCleanup(toClosure); // Get the lowered AST types: // - the original type auto origLoweredFormalType = AbstractionPattern(constantInfo.LoweredInterfaceType); if (captureInfo.hasLocalCaptures()) { // Get the unlowered formal type of the constant, stripping off // the first level of function application, which applies captures. origLoweredFormalType = AbstractionPattern(constantInfo.FormalInterfaceType) .getFunctionResultType(); // Lower it, being careful to use the right generic signature. origLoweredFormalType = AbstractionPattern( origLoweredFormalType.getGenericSignature(), SGM.Types.getLoweredASTFunctionType( cast<FunctionType>(origLoweredFormalType.getType()), 0, constant)); } // - the substituted type auto substFormalType = cast<FunctionType>(expectedType); auto substLoweredFormalType = SGM.Types.getLoweredASTFunctionType(substFormalType, 0, constant); // Generalize if necessary. result = emitOrigToSubstValue(loc, result, origLoweredFormalType, substLoweredFormalType); return result; }
ManagedValue SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant, CanType expectedType, SubstitutionList subs) { auto closure = *constant.getAnyFunctionRef(); auto captureInfo = closure.getCaptureInfo(); auto loweredCaptureInfo = SGM.Types.getLoweredLocalCaptures(closure); auto hasCaptures = SGM.Types.hasLoweredLocalCaptures(closure); assert(((constant.uncurryLevel == 1 && hasCaptures) || (constant.uncurryLevel == 0 && !hasCaptures)) && "curried local functions not yet supported"); auto constantInfo = getConstantInfo(constant); SILValue functionRef = emitGlobalFunctionRef(loc, constant, constantInfo); SILType functionTy = functionRef->getType(); // Apply substitutions. auto pft = constantInfo.SILFnType; auto *dc = closure.getAsDeclContext()->getParent(); if (dc->isLocalContext() && !loweredCaptureInfo.hasGenericParamCaptures()) { // If the lowered function type is not polymorphic but we were given // substitutions, we have a closure in a generic context which does not // capture generic parameters. Just drop the substitutions. subs = { }; } else if (closure.getAbstractClosureExpr()) { // If we have a closure expression in generic context, Sema won't give // us substitutions, so we just use the forwarding substitutions from // context. subs = getForwardingSubstitutions(); } bool wasSpecialized = false; if (!subs.empty()) { auto specialized = pft->substGenericArgs(F.getModule(), subs); functionTy = SILType::getPrimitiveObjectType(specialized); wasSpecialized = true; } // If we're in top-level code, we don't need to physically capture script // globals, but we still need to mark them as escaping so that DI can flag // uninitialized uses. if (this == SGM.TopLevelSGF) { SGM.emitMarkFunctionEscapeForTopLevelCodeGlobals( loc, captureInfo); } if (!hasCaptures && !wasSpecialized) { auto result = ManagedValue::forUnmanaged(functionRef); return emitOrigToSubstValue(loc, result, AbstractionPattern(expectedType), expectedType); } SmallVector<ManagedValue, 4> capturedArgs; emitCaptures(loc, closure, CaptureEmission::PartialApplication, capturedArgs); // The partial application takes ownership of the context parameters. SmallVector<SILValue, 4> forwardedArgs; for (auto capture : capturedArgs) forwardedArgs.push_back(capture.forward(*this)); SILType closureTy = SILGenBuilder::getPartialApplyResultType(functionRef->getType(), capturedArgs.size(), SGM.M, subs, ParameterConvention::Direct_Owned); auto toClosure = B.createPartialApply(loc, functionRef, functionTy, subs, forwardedArgs, closureTy); auto result = emitManagedRValueWithCleanup(toClosure); // Get the lowered AST types: // - the original type auto origLoweredFormalType = AbstractionPattern(constantInfo.LoweredInterfaceType); if (hasCaptures) { // Get the unlowered formal type of the constant, stripping off // the first level of function application, which applies captures. origLoweredFormalType = AbstractionPattern(constantInfo.FormalInterfaceType) .getFunctionResultType(); // Lower it, being careful to use the right generic signature. origLoweredFormalType = AbstractionPattern( origLoweredFormalType.getGenericSignature(), SGM.Types.getLoweredASTFunctionType( cast<FunctionType>(origLoweredFormalType.getType()), 0, constant)); } // - the substituted type auto substFormalType = cast<FunctionType>(expectedType); auto substLoweredFormalType = SGM.Types.getLoweredASTFunctionType(substFormalType, 0, constant); // Generalize if necessary. result = emitOrigToSubstValue(loc, result, origLoweredFormalType, substLoweredFormalType); return result; }