void SILGenFunction::emitCurryThunk(SILDeclRef thunk) { assert(thunk.isCurried); auto *vd = thunk.getDecl(); if (auto *fd = dyn_cast<AbstractFunctionDecl>(vd)) { assert(!SGM.M.Types.hasLoweredLocalCaptures(fd) && "methods cannot have captures"); (void) fd; } auto selfTy = vd->getInterfaceType()->castTo<AnyFunctionType>() ->getInput(); selfTy = vd->getInnermostDeclContext()->mapTypeIntoContext(selfTy); ManagedValue selfArg = B.createFunctionArgument(getLoweredType(selfTy), nullptr); // Forward substitutions. auto subs = F.getForwardingSubstitutions(); ManagedValue toFn = getNextUncurryLevelRef(*this, vd, thunk, selfArg, subs); // FIXME: Using the type from the ConstantInfo instead of looking at // getConstantOverrideInfo() for methods looks suspect in the presence // of covariant overrides and multiple vtable entries. SILFunctionConventions fromConv( SGM.Types.getConstantInfo(thunk).SILFnType, SGM.M); SILType resultTy = fromConv.getSingleSILResultType(); resultTy = F.mapTypeIntoContext(resultTy); auto substTy = toFn.getType().substGenericArgs(SGM.M, subs); // Partially apply the next uncurry level and return the result closure. selfArg = selfArg.ensurePlusOne(*this, vd); auto calleeConvention = ParameterConvention::Direct_Guaranteed; auto closureTy = SILGenBuilder::getPartialApplyResultType( toFn.getType(), /*appliedParams=*/1, SGM.M, subs, calleeConvention); ManagedValue toClosure = B.createPartialApply(vd, toFn, substTy, subs, {selfArg}, closureTy); if (resultTy != closureTy) { CanSILFunctionType resultFnTy = resultTy.castTo<SILFunctionType>(); CanSILFunctionType closureFnTy = closureTy.castTo<SILFunctionType>(); if (resultFnTy->isABICompatibleWith(closureFnTy).isCompatible()) { toClosure = B.createConvertFunction(vd, toClosure, resultTy); } else { toClosure = emitCanonicalFunctionThunk(vd, toClosure, closureFnTy, resultFnTy); } } B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(vd), toClosure); }
void SILGenFunction::emitEnumConstructor(EnumElementDecl *element) { CanType enumIfaceTy = element->getParentEnum() ->getDeclaredInterfaceType() ->getCanonicalType(); CanType enumTy = F.mapTypeIntoContext(enumIfaceTy) ->getCanonicalType(); auto &enumTI = getTypeLowering(enumTy); RegularLocation Loc(element); CleanupLocation CleanupLoc(element); Loc.markAutoGenerated(); // Emit the indirect return slot. std::unique_ptr<Initialization> dest; if (enumTI.isAddressOnly() && silConv.useLoweredAddresses()) { auto &AC = getASTContext(); auto VD = new (AC) ParamDecl(VarDecl::Specifier::InOut, SourceLoc(), SourceLoc(), AC.getIdentifier("$return_value"), SourceLoc(), AC.getIdentifier("$return_value"), Type(), element->getDeclContext()); VD->setInterfaceType(enumIfaceTy); auto resultSlot = F.begin()->createFunctionArgument(enumTI.getLoweredType(), VD); dest = std::unique_ptr<Initialization>( new KnownAddressInitialization(resultSlot)); } Scope scope(Cleanups, CleanupLoc); // Emit the exploded constructor argument. ArgumentSource payload; if (element->hasAssociatedValues()) { RValue arg = emitImplicitValueConstructorArg (*this, Loc, element->getArgumentInterfaceType()->getCanonicalType(), element->getDeclContext()); payload = ArgumentSource(Loc, std::move(arg)); } // Emit the metatype argument. emitConstructorMetatypeArg(*this, element); // If possible, emit the enum directly into the indirect return. SGFContext C = (dest ? SGFContext(dest.get()) : SGFContext()); ManagedValue mv = emitInjectEnum(Loc, std::move(payload), enumTI.getLoweredType(), element, C); // Return the enum. auto ReturnLoc = ImplicitReturnLocation::getImplicitReturnLoc(Loc); if (mv.isInContext()) { assert(enumTI.isAddressOnly()); scope.pop(); B.createReturn(ReturnLoc, emitEmptyTuple(Loc)); } else { assert(enumTI.isLoadable() || !silConv.useLoweredAddresses()); SILValue result = mv.ensurePlusOne(*this, ReturnLoc).forward(*this); scope.pop(); B.createReturn(ReturnLoc, result); } }
void SILGenFunction::emitCurryThunk(SILDeclRef thunk) { assert(thunk.isCurried); auto *vd = thunk.getDecl(); if (auto *fd = dyn_cast<AbstractFunctionDecl>(vd)) { assert(!SGM.M.Types.hasLoweredLocalCaptures(fd) && "methods cannot have captures"); (void) fd; } SILLocation loc(vd); Scope S(*this, vd); auto thunkInfo = SGM.Types.getConstantInfo(thunk); auto thunkFnTy = thunkInfo.SILFnType; SILFunctionConventions fromConv(thunkFnTy, SGM.M); auto selfTy = fromConv.getSILType(thunkFnTy->getSelfParameter()); selfTy = F.mapTypeIntoContext(selfTy); ManagedValue selfArg = B.createInputFunctionArgument(selfTy, loc); // Forward substitutions. auto subs = F.getForwardingSubstitutionMap(); auto toFnAndRef = getNextUncurryLevelRef(*this, loc, thunk, selfArg, subs); ManagedValue toFn = toFnAndRef.first; SILDeclRef calleeRef = toFnAndRef.second; SILType resultTy = fromConv.getSingleSILResultType(); resultTy = F.mapTypeIntoContext(resultTy); // Partially apply the next uncurry level and return the result closure. selfArg = selfArg.ensurePlusOne(*this, loc); auto calleeConvention = ParameterConvention::Direct_Guaranteed; ManagedValue toClosure = B.createPartialApply(loc, toFn, subs, {selfArg}, calleeConvention); if (resultTy != toClosure.getType()) { CanSILFunctionType resultFnTy = resultTy.castTo<SILFunctionType>(); CanSILFunctionType closureFnTy = toClosure.getType().castTo<SILFunctionType>(); if (resultFnTy->isABICompatibleWith(closureFnTy).isCompatible()) { toClosure = B.createConvertFunction(loc, toClosure, resultTy); } else { // Compute the partially-applied abstraction pattern for the callee: // just grab the pattern for the curried fn ref and "call" it. assert(!calleeRef.isCurried); calleeRef.isCurried = true; auto appliedFnPattern = SGM.Types.getConstantInfo(calleeRef).FormalPattern .getFunctionResultType(); auto appliedThunkPattern = thunkInfo.FormalPattern.getFunctionResultType(); // The formal type should be the same for the callee and the thunk. auto formalType = thunkInfo.FormalType; if (auto genericSubstType = dyn_cast<GenericFunctionType>(formalType)) { formalType = genericSubstType.substGenericArgs(subs); } formalType = cast<AnyFunctionType>(formalType.getResult()); toClosure = emitTransformedValue(loc, toClosure, appliedFnPattern, formalType, appliedThunkPattern, formalType); } } toClosure = S.popPreservingValue(toClosure); B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(loc), toClosure); }