//===--- SILGenFunction.cpp - Top-level lowering for functions ------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines the primary routines for creating and emitting // functions. // //===----------------------------------------------------------------------===// #include "SILGenFunction.h" #include "RValue.h" #include "Scope.h" #include "swift/Basic/Fallthrough.h" #include "swift/AST/AST.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILUndef.h" #include "swift/AST/DiagnosticsSIL.h" using namespace swift; using namespace Lowering; //===----------------------------------------------------------------------===// // SILGenFunction Class implementation //===----------------------------------------------------------------------===// SILGenFunction::SILGenFunction(SILGenModule &SGM, SILFunction &F) : SGM(SGM), F(F), B(*this, createBasicBlock()), CurrentSILLoc(F.getLocation()), Cleanups(*this) { B.setCurrentDebugScope(F.getDebugScope()); } /// SILGenFunction destructor - called after the entire function's AST has been /// visited. This handles "falling off the end of the function" logic. SILGenFunction::~SILGenFunction() { // If the end of the function isn't terminated, we screwed up somewhere. assert(!B.hasValidInsertionPoint() && "SILGenFunction did not terminate function?!"); // If we didn't clean up the rethrow destination, we screwed up somewhere. assert(!ThrowDest.isValid() && "SILGenFunction did not emit throw destination"); freeWritebackStack(); } //===----------------------------------------------------------------------===// // Function emission //===----------------------------------------------------------------------===// // Get the #function name for a declaration. DeclName SILGenModule::getMagicFunctionName(DeclContext *dc) { // For closures, use the parent name. if (auto closure = dyn_cast(dc)) { return getMagicFunctionName(closure->getParent()); } if (auto absFunc = dyn_cast(dc)) { if (auto func = dyn_cast(absFunc)) { // If this is an accessor, use the name of the storage. if (auto storage = func->getAccessorStorageDecl()) { return storage->getFullName(); } // If this is a defer body, use the parent name. if (func->isDeferBody()) { return getMagicFunctionName(func->getParent()); } } return absFunc->getFullName(); } if (auto init = dyn_cast(dc)) { return getMagicFunctionName(init->getParent()); } if (auto nominal = dyn_cast(dc)) { return nominal->getName(); } if (auto tl = dyn_cast(dc)) { return tl->getModuleContext()->getName(); } if (auto fu = dyn_cast(dc)) { return fu->getParentModule()->getName(); } if (auto m = dyn_cast(dc)) { return m->getName(); } if (auto e = dyn_cast(dc)) { assert(e->getExtendedType()->getAnyNominal() && "extension for nonnominal"); return e->getExtendedType()->getAnyNominal()->getName(); } llvm_unreachable("unexpected #function context"); } DeclName SILGenModule::getMagicFunctionName(SILDeclRef ref) { switch (ref.kind) { case SILDeclRef::Kind::Func: if (auto closure = ref.getAbstractClosureExpr()) return getMagicFunctionName(closure); return getMagicFunctionName(cast(ref.getDecl())); case SILDeclRef::Kind::Initializer: case SILDeclRef::Kind::Allocator: return getMagicFunctionName(cast(ref.getDecl())); case SILDeclRef::Kind::Deallocator: case SILDeclRef::Kind::Destroyer: return getMagicFunctionName(cast(ref.getDecl())); case SILDeclRef::Kind::GlobalAccessor: case SILDeclRef::Kind::GlobalGetter: return getMagicFunctionName(cast(ref.getDecl())->getDeclContext()); case SILDeclRef::Kind::DefaultArgGenerator: return getMagicFunctionName(cast(ref.getDecl())); case SILDeclRef::Kind::IVarInitializer: return getMagicFunctionName(cast(ref.getDecl())); case SILDeclRef::Kind::IVarDestroyer: return getMagicFunctionName(cast(ref.getDecl())); case SILDeclRef::Kind::EnumElement: return getMagicFunctionName(cast(ref.getDecl()) ->getDeclContext()); } } SILValue SILGenFunction::emitGlobalFunctionRef(SILLocation loc, SILDeclRef constant, SILConstantInfo constantInfo) { assert(constantInfo == getConstantInfo(constant)); // Builtins must be fully applied at the point of reference. if (constant.hasDecl() && isa(constant.getDecl()->getDeclContext())) { SGM.diagnose(loc.getSourceLoc(), diag::not_implemented, "delayed application of builtin"); return SILUndef::get(constantInfo.getSILType(), SGM.M); } // If the constant is a thunk we haven't emitted yet, emit it. if (!SGM.hasFunction(constant)) { if (constant.isCurried) { auto vd = constant.getDecl(); // Reference the next uncurrying level of the function. SILDeclRef next = SILDeclRef(vd, constant.kind, SILDeclRef::ConstructAtBestResilienceExpansion, constant.uncurryLevel + 1); // If the function is fully uncurried and natively foreign, reference its // foreign entry point. if (!next.isCurried) { if (requiresForeignToNativeThunk(vd)) next = next.asForeign(); } // Preserve whether the curry thunks lead to a direct reference to the // method implementation. next = next.asDirectReference(constant.isDirectReference); SGM.emitCurryThunk(vd, constant, next); } // Otherwise, if this is a calling convention thunk we haven't emitted yet, // emit it. else if (constant.isForeignToNativeThunk()) { SGM.emitForeignToNativeThunk(constant); } else if (constant.isNativeToForeignThunk()) { SGM.emitNativeToForeignThunk(constant); } else if (constant.kind == SILDeclRef::Kind::EnumElement) { SGM.emitEnumConstructor(cast(constant.getDecl())); } } auto f = SGM.getFunction(constant, NotForDefinition); assert(f->getLoweredFunctionType() == constantInfo.SILFnType); return B.createFunctionRef(loc, f); } std::tuple> SILGenFunction::emitSiblingMethodRef(SILLocation loc, SILValue selfValue, SILDeclRef methodConstant, ArrayRef subs) { SILValue methodValue; // If the method is dynamic, access it through runtime-hookable virtual // dispatch (viz. objc_msgSend for now). if (methodConstant.hasDecl() && methodConstant.getDecl()->getAttrs().hasAttribute()) methodValue = emitDynamicMethodRef(loc, methodConstant, SGM.Types.getConstantInfo(methodConstant)); else methodValue = emitGlobalFunctionRef(loc, methodConstant); SILType methodTy = methodValue->getType(); if (!subs.empty()) { // Specialize the generic method. methodTy = getLoweredLoadableType( methodTy.castTo() ->substGenericArgs(SGM.M, SGM.SwiftModule, subs)); } return std::make_tuple(ManagedValue::forUnmanaged(methodValue), methodTy, subs); } 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); } void SILGenFunction::emitCaptures(SILLocation loc, AnyFunctionRef TheClosure, CaptureEmission purpose, SmallVectorImpl &capturedArgs) { auto captureInfo = SGM.Types.getLoweredLocalCaptures(TheClosure); // For boxed captures, we need to mark the contained variables as having // escaped for DI diagnostics. SmallVector escapesToMark; // Partial applications take ownership of the context parameters, so we'll // need to pass ownership rather than merely guaranteeing parameters. bool canGuarantee; switch (purpose) { case CaptureEmission::PartialApplication: canGuarantee = false; break; case CaptureEmission::ImmediateApplication: canGuarantee = true; break; } // TODO: Or we always retain them when guaranteed contexts aren't enabled. if (!SGM.M.getOptions().EnableGuaranteedClosureContexts) canGuarantee = false; for (auto capture : captureInfo.getCaptures()) { auto *vd = capture.getDecl(); switch (SGM.Types.getDeclCaptureKind(capture)) { case CaptureKind::None: break; case CaptureKind::Constant: { // let declarations. auto Entry = VarLocs[vd]; auto &tl = getTypeLowering(vd->getType()->getReferenceStorageReferent()); SILValue Val = Entry.value; if (!Val->getType().isAddress()) { // Our 'let' binding can guarantee the lifetime for the callee, // if we don't need to do anything more to it. if (canGuarantee && !vd->getType()->is()) { auto guaranteed = ManagedValue::forUnmanaged(Val); capturedArgs.push_back(guaranteed); break; } // Just retain a by-val let. B.emitRetainValueOperation(loc, Val); } else { // If we have a mutable binding for a 'let', such as 'self' in an // 'init' method, load it. Val = emitLoad(loc, Val, tl, SGFContext(), IsNotTake).forward(*this); } // If we're capturing an unowned pointer by value, we will have just // loaded it into a normal retained class pointer, but we capture it as // an unowned pointer. Convert back now. if (vd->getType()->is()) { auto type = getTypeLowering(vd->getType()).getLoweredType(); Val = emitConversionFromSemanticValue(loc, Val, type); } capturedArgs.push_back(emitManagedRValueWithCleanup(Val)); break; } case CaptureKind::StorageAddress: { // No-escaping stored declarations are captured as the // address of the value. assert(VarLocs.count(vd) && "no location for captured var!"); VarLoc vl = VarLocs[vd]; assert(vl.value->getType().isAddress() && "no address for captured var!"); capturedArgs.push_back(ManagedValue::forLValue(vl.value)); break; } case CaptureKind::Box: { // LValues are captured as both the box owning the value and the // address of the value. assert(VarLocs.count(vd) && "no location for captured var!"); VarLoc vl = VarLocs[vd]; assert(vl.value->getType().isAddress() && "no address for captured var!"); // If this is a boxed variable, we can use it directly. if (vl.box) { // We can guarantee our own box to the callee. if (canGuarantee) { capturedArgs.push_back(ManagedValue::forUnmanaged(vl.box)); } else { B.createStrongRetain(loc, vl.box); capturedArgs.push_back(emitManagedRValueWithCleanup(vl.box)); } escapesToMark.push_back(vl.value); } else { // Address only 'let' values are passed by box. This isn't great, in // that a variable captured by multiple closures will be boxed for each // one. This could be improved by doing an "isCaptured" analysis when // emitting address-only let constants, and emit them into an alloc_box // like a variable instead of into an alloc_stack. // // TODO: This might not be profitable anymore with guaranteed captures, // since we could conceivably forward the copied value into the // closure context and pass it down to the partially applied function // in-place. AllocBoxInst *allocBox = B.createAllocBox(loc, vl.value->getType().getObjectType()); ProjectBoxInst *boxAddress = B.createProjectBox(loc, allocBox); B.createCopyAddr(loc, vl.value, boxAddress, IsNotTake,IsInitialization); capturedArgs.push_back(emitManagedRValueWithCleanup(allocBox)); } break; } } } // Mark box addresses as captured for DI purposes. The values must have // been fully initialized before we close over them. if (!escapesToMark.empty()) { B.createMarkFunctionEscape(loc, escapesToMark); } } ManagedValue SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant, AnyFunctionRef TheClosure) { assert(((constant.uncurryLevel == 1 && TheClosure.getCaptureInfo().hasLocalCaptures()) || (constant.uncurryLevel == 0 && !TheClosure.getCaptureInfo().hasLocalCaptures())) && "curried local functions not yet supported"); auto constantInfo = getConstantInfo(constant); SILValue functionRef = emitGlobalFunctionRef(loc, constant, constantInfo); SILType functionTy = functionRef->getType(); auto expectedType = cast(TheClosure.getType()->getCanonicalType()); // Forward substitutions from the outer scope. auto pft = constantInfo.SILFnType; auto forwardSubs = constantInfo.getForwardingSubstitutions(getASTContext()); bool wasSpecialized = false; if (pft->isPolymorphic() && !forwardSubs.empty()) { auto specialized = pft->substGenericArgs(F.getModule(), F.getModule().getSwiftModule(), forwardSubs); functionTy = SILType::getPrimitiveObjectType(specialized); wasSpecialized = true; } if (!TheClosure.getCaptureInfo().hasLocalCaptures() && !wasSpecialized) { auto result = ManagedValue::forUnmanaged(functionRef); return emitOrigToSubstValue(loc, result, AbstractionPattern(expectedType), expectedType); } SmallVector capturedArgs; emitCaptures(loc, TheClosure, CaptureEmission::PartialApplication, capturedArgs); // The partial application takes ownership of the context parameters. SmallVector forwardedArgs; for (auto capture : capturedArgs) forwardedArgs.push_back(capture.forward(*this)); SILType closureTy = SILGenBuilder::getPartialApplyResultType(functionRef->getType(), capturedArgs.size(), SGM.M, forwardSubs); auto toClosure = B.createPartialApply(loc, functionRef, functionTy, forwardSubs, forwardedArgs, closureTy); auto result = emitManagedRValueWithCleanup(toClosure); return emitOrigToSubstValue(loc, result, AbstractionPattern(expectedType), expectedType); } void SILGenFunction::emitFunction(FuncDecl *fd) { MagicFunctionName = SILGenModule::getMagicFunctionName(fd); Type resultTy = fd->getResultType(); emitProlog(fd, fd->getParameterLists(), resultTy); prepareEpilog(resultTy, fd->isBodyThrowing(), CleanupLocation(fd)); emitProfilerIncrement(fd->getBody()); emitStmt(fd->getBody()); emitEpilog(fd); } void SILGenFunction::emitClosure(AbstractClosureExpr *ace) { MagicFunctionName = SILGenModule::getMagicFunctionName(ace); emitProlog(ace, ace->getParameters(), ace->getResultType()); prepareEpilog(ace->getResultType(), ace->isBodyThrowing(), CleanupLocation(ace)); if (auto *ce = dyn_cast(ace)) { emitProfilerIncrement(ce); emitStmt(ce->getBody()); } else { auto *autoclosure = cast(ace); // Closure expressions implicitly return the result of their body // expression. emitProfilerIncrement(autoclosure); emitReturnExpr(ImplicitReturnLocation(ace), autoclosure->getSingleExpressionBody()); } emitEpilog(ace); } void SILGenFunction::emitArtificialTopLevel(ClassDecl *mainClass) { // Load argc and argv from the entry point arguments. SILValue argc = F.begin()->getBBArg(0); SILValue argv = F.begin()->getBBArg(1); switch (mainClass->getArtificialMainKind()) { case ArtificialMainKind::UIApplicationMain: { // Emit a UIKit main. // return UIApplicationMain(C_ARGC, C_ARGV, nil, ClassName); CanType NSStringTy = SGM.Types.getNSStringType(); CanType OptNSStringTy = OptionalType::get(NSStringTy)->getCanonicalType(); CanType IUOptNSStringTy = ImplicitlyUnwrappedOptionalType::get(NSStringTy)->getCanonicalType(); // Get the class name as a string using NSStringFromClass. CanType mainClassTy = mainClass->getDeclaredTypeInContext()->getCanonicalType(); CanType mainClassMetaty = CanMetatypeType::get(mainClassTy, MetatypeRepresentation::ObjC); ProtocolDecl *anyObjectProtocol = getASTContext().getProtocol(KnownProtocolKind::AnyObject); auto mainClassAnyObjectConformance = ProtocolConformanceRef( SGM.M.getSwiftModule()->lookupConformance(mainClassTy, anyObjectProtocol, nullptr) .getPointer()); CanType anyObjectTy = anyObjectProtocol ->getDeclaredTypeInContext() ->getCanonicalType(); CanType anyObjectMetaTy = CanExistentialMetatypeType::get(anyObjectTy, MetatypeRepresentation::ObjC); auto NSStringFromClassType = SILFunctionType::get(nullptr, SILFunctionType::ExtInfo() .withRepresentation(SILFunctionType::Representation:: CFunctionPointer), ParameterConvention::Direct_Unowned, SILParameterInfo(anyObjectMetaTy, ParameterConvention::Direct_Unowned), SILResultInfo(OptNSStringTy, ResultConvention::Autoreleased), /*error result*/ None, getASTContext()); auto NSStringFromClassFn = SGM.M.getOrCreateFunction(mainClass, "NSStringFromClass", SILLinkage::PublicExternal, NSStringFromClassType, IsBare, IsTransparent, IsNotFragile); auto NSStringFromClass = B.createFunctionRef(mainClass, NSStringFromClassFn); SILValue metaTy = B.createMetatype(mainClass, SILType::getPrimitiveObjectType(mainClassMetaty)); metaTy = B.createInitExistentialMetatype(mainClass, metaTy, SILType::getPrimitiveObjectType(anyObjectMetaTy), getASTContext().AllocateCopy( llvm::makeArrayRef(mainClassAnyObjectConformance))); SILValue optName = B.createApply(mainClass, NSStringFromClass, NSStringFromClass->getType(), SILType::getPrimitiveObjectType(OptNSStringTy), {}, metaTy); SILValue iuoptName = B.createUncheckedBitCast(mainClass, optName, SILType::getPrimitiveObjectType(IUOptNSStringTy)); // Call UIApplicationMain. SILParameterInfo argTypes[] = { SILParameterInfo(argc->getType().getSwiftRValueType(), ParameterConvention::Direct_Unowned), SILParameterInfo(argv->getType().getSwiftRValueType(), ParameterConvention::Direct_Unowned), SILParameterInfo(IUOptNSStringTy, ParameterConvention::Direct_Unowned), SILParameterInfo(IUOptNSStringTy, ParameterConvention::Direct_Unowned), }; auto UIApplicationMainType = SILFunctionType::get(nullptr, SILFunctionType::ExtInfo() .withRepresentation(SILFunctionType::Representation:: CFunctionPointer), ParameterConvention::Direct_Unowned, argTypes, SILResultInfo(argc->getType().getSwiftRValueType(), ResultConvention::Unowned), /*error result*/ None, getASTContext()); auto UIApplicationMainFn = SGM.M.getOrCreateFunction(mainClass, "UIApplicationMain", SILLinkage::PublicExternal, UIApplicationMainType, IsBare, IsTransparent, IsNotFragile); auto UIApplicationMain = B.createFunctionRef(mainClass, UIApplicationMainFn); auto nil = B.createEnum(mainClass, SILValue(), getASTContext().getImplicitlyUnwrappedOptionalNoneDecl(), SILType::getPrimitiveObjectType(IUOptNSStringTy)); SILValue args[] = { argc, argv, nil, iuoptName }; B.createApply(mainClass, UIApplicationMain, UIApplicationMain->getType(), argc->getType(), {}, args); SILValue r = B.createIntegerLiteral(mainClass, SILType::getBuiltinIntegerType(32, getASTContext()), 0); auto rType = F.getLoweredFunctionType()->getSingleResult().getSILType(); if (r->getType() != rType) r = B.createStruct(mainClass, rType, r); B.createReturn(mainClass, r); return; } case ArtificialMainKind::NSApplicationMain: { // Emit an AppKit main. // return NSApplicationMain(C_ARGC, C_ARGV); SILParameterInfo argTypes[] = { SILParameterInfo(argc->getType().getSwiftRValueType(), ParameterConvention::Direct_Unowned), SILParameterInfo(argv->getType().getSwiftRValueType(), ParameterConvention::Direct_Unowned), }; auto NSApplicationMainType = SILFunctionType::get(nullptr, SILFunctionType::ExtInfo() // Should be C calling convention, but NSApplicationMain // has an overlay to fix the type of argv. .withRepresentation(SILFunctionType::Representation::Thin), ParameterConvention::Direct_Unowned, argTypes, SILResultInfo(argc->getType().getSwiftRValueType(), ResultConvention::Unowned), /*error result*/ None, getASTContext()); auto NSApplicationMainFn = SGM.M.getOrCreateFunction(mainClass, "NSApplicationMain", SILLinkage::PublicExternal, NSApplicationMainType, IsBare, IsTransparent, IsNotFragile); auto NSApplicationMain = B.createFunctionRef(mainClass, NSApplicationMainFn); SILValue args[] = { argc, argv }; B.createApply(mainClass, NSApplicationMain, NSApplicationMain->getType(), argc->getType(), {}, args); SILValue r = B.createIntegerLiteral(mainClass, SILType::getBuiltinIntegerType(32, getASTContext()), 0); auto rType = F.getLoweredFunctionType()->getSingleResult().getSILType(); if (r->getType() != rType) r = B.createStruct(mainClass, rType, r); B.createReturn(mainClass, r); return; } } } static void forwardCaptureArgs(SILGenFunction &gen, SmallVectorImpl &args, CapturedValue capture) { auto addSILArgument = [&](SILType t, ValueDecl *d) { args.push_back(new (gen.SGM.M) SILArgument(gen.F.begin(), t, d)); }; auto *vd = capture.getDecl(); switch (gen.SGM.Types.getDeclCaptureKind(capture)) { case CaptureKind::None: break; case CaptureKind::Constant: addSILArgument(gen.getLoweredType(vd->getType()), vd); break; case CaptureKind::Box: { SILType ty = gen.getLoweredType(vd->getType()->getRValueType()) .getAddressType(); // Forward the captured owning box. SILType boxTy = SILType::getPrimitiveObjectType( SILBoxType::get(ty.getSwiftRValueType())); addSILArgument(boxTy, vd); break; } case CaptureKind::StorageAddress: { SILType ty = gen.getLoweredType(vd->getType()->getRValueType()) .getAddressType(); // Forward the captured value address. addSILArgument(ty, vd); break; } } } static SILValue getNextUncurryLevelRef(SILGenFunction &gen, SILLocation loc, SILDeclRef next, bool direct, ArrayRef curriedArgs, ArrayRef curriedSubs) { if (next.isForeign || next.isCurried || !next.hasDecl() || direct) return gen.emitGlobalFunctionRef(loc, next.asForeign(false)); auto constantInfo = gen.SGM.Types.getConstantInfo(next); SILValue thisArg; if (!curriedArgs.empty()) thisArg = curriedArgs.back(); if (isa(next.getDecl()) && getMethodDispatch(cast(next.getDecl())) == MethodDispatch::Class) { SILValue thisArg = curriedArgs.back(); // Use the dynamic thunk if dynamic. if (next.getDecl()->isDynamic()) { auto dynamicThunk = gen.SGM.getDynamicThunk(next, constantInfo); return gen.B.createFunctionRef(loc, dynamicThunk); } return gen.B.createClassMethod(loc, thisArg, next); } // If the fully-uncurried reference is to a generic method, look up the // witness. if (constantInfo.SILFnType->getRepresentation() == SILFunctionTypeRepresentation::WitnessMethod) { auto thisType = curriedSubs[0].getReplacement()->getCanonicalType(); assert(isa(thisType) && "no archetype for witness?!"); SILValue OpenedExistential; if (!cast(thisType)->getOpenedExistentialType().isNull()) OpenedExistential = thisArg; auto protocol = next.getDecl()->getDeclContext()->getAsProtocolOrProtocolExtensionContext(); auto conformance = ProtocolConformanceRef(protocol); return gen.B.createWitnessMethod(loc, thisType, conformance, next, constantInfo.getSILType(), OpenedExistential); } // Otherwise, emit a direct call. return gen.emitGlobalFunctionRef(loc, next); } void SILGenFunction::emitCurryThunk(ValueDecl *vd, SILDeclRef from, SILDeclRef to) { SmallVector curriedArgs; unsigned paramCount = from.uncurryLevel + 1; if (isa(vd) || isa(vd)) { // The first body parameter pattern for a constructor specifies the // "self" instance, but the constructor is invoked from outside on a // metatype. assert(from.uncurryLevel == 0 && to.uncurryLevel == 1 && "currying constructor at level other than one?!"); F.setBare(IsBare); auto selfMetaTy = vd->getType()->getAs()->getInput(); auto metatypeVal = new (F.getModule()) SILArgument(F.begin(), getLoweredLoadableType(selfMetaTy)); curriedArgs.push_back(metatypeVal); } else if (auto fd = dyn_cast(vd)) { // Forward implicit closure context arguments. bool hasCaptures = fd->getCaptureInfo().hasLocalCaptures(); if (hasCaptures) --paramCount; // Forward the curried formal arguments. auto forwardedPatterns = fd->getParameterLists().slice(0, paramCount); for (auto *paramPattern : reversed(forwardedPatterns)) bindParametersForForwarding(paramPattern, curriedArgs); // Forward captures. if (hasCaptures) { auto captureInfo = SGM.Types.getLoweredLocalCaptures(fd); for (auto capture : captureInfo.getCaptures()) forwardCaptureArgs(*this, curriedArgs, capture); } } else { llvm_unreachable("don't know how to curry this decl"); } // Forward substitutions. ArrayRef subs; if (auto gp = getConstantInfo(to).ContextGenericParams) { subs = gp->getForwardingSubstitutions(getASTContext()); } SILValue toFn = getNextUncurryLevelRef(*this, vd, to, from.isDirectReference, curriedArgs, subs); SILType resultTy = SGM.getConstantType(from).castTo() ->getSingleResult().getSILType(); resultTy = F.mapTypeIntoContext(resultTy); auto toTy = toFn->getType(); // Forward archetypes and specialize if the function is generic. if (!subs.empty()) { auto toFnTy = toFn->getType().castTo(); toTy = getLoweredLoadableType( toFnTy->substGenericArgs(SGM.M, SGM.SwiftModule, subs)); } // Partially apply the next uncurry level and return the result closure. auto closureTy = SILGenBuilder::getPartialApplyResultType(toFn->getType(), curriedArgs.size(), SGM.M, subs); SILInstruction *toClosure = B.createPartialApply(vd, toFn, toTy, subs, curriedArgs, closureTy); if (resultTy != closureTy) toClosure = B.createConvertFunction(vd, toClosure, resultTy); B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(vd), toClosure); } void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value) { MagicFunctionName = SILGenModule::getMagicFunctionName(function); RegularLocation Loc(value); Loc.markAutoGenerated(); // Override location for #file, #line etc. to an invalid one so that we // don't put extra strings into the default argument generator function that // is not going to be ever used anyway. overrideLocationForMagicIdentifiers = SourceLoc(); emitProlog({ }, value->getType(), function.getDecl()->getDeclContext()); prepareEpilog(value->getType(), false, CleanupLocation::get(Loc)); emitReturnExpr(Loc, value); emitEpilog(Loc); } SILGenBuilder::SILGenBuilder(SILGenFunction &gen) : SILBuilder(gen.F), SGM(gen.SGM) {} SILGenBuilder::SILGenBuilder(SILGenFunction &gen, SILBasicBlock *insertBB) : SILBuilder(insertBB), SGM(gen.SGM) {} SILGenBuilder::SILGenBuilder(SILGenFunction &gen, SILBasicBlock *insertBB, SmallVectorImpl *insertedInsts) : SILBuilder(insertBB, insertedInsts), SGM(gen.SGM) {} SILGenBuilder::SILGenBuilder(SILGenFunction &gen, SILBasicBlock *insertBB, SILInstruction *insertInst) : SILBuilder(insertBB, insertInst->getIterator()), SGM(gen.SGM) {} MetatypeInst *SILGenBuilder::createMetatype(SILLocation loc, SILType metatype) { auto theMetatype = metatype.castTo(); // Getting a nontrivial metatype requires forcing any conformances necessary // to instantiate the type. switch (theMetatype->getRepresentation()) { case MetatypeRepresentation::Thin: break; case MetatypeRepresentation::Thick: case MetatypeRepresentation::ObjC: { // Walk the type recursively to look for substitutions we may need. SmallVector subsBuf; theMetatype.getInstanceType().findIf([&](Type t) -> bool { if (!t->getAnyNominal()) return false; auto subs = t->gatherAllSubstitutions(SGM.SwiftModule, subsBuf, nullptr); SGM.useConformancesFromSubstitutions(subs); return false; }); break; } } return SILBuilder::createMetatype(loc, metatype); } ApplyInst *SILGenBuilder::createApply(SILLocation Loc, SILValue Fn, SILType SubstFnTy, SILType Result, ArrayRef Subs, ArrayRef Args) { SGM.useConformancesFromSubstitutions(Subs); return SILBuilder::createApply(Loc, Fn, SubstFnTy, Result, Subs, Args, false); } TryApplyInst *SILGenBuilder::createTryApply(SILLocation loc, SILValue Fn, SILType substFnTy, ArrayRef subs, ArrayRef args, SILBasicBlock *normalBB, SILBasicBlock *errorBB) { SGM.useConformancesFromSubstitutions(subs); return SILBuilder::createTryApply(loc, Fn, substFnTy, subs, args, normalBB, errorBB); } PartialApplyInst *SILGenBuilder::createPartialApply(SILLocation Loc, SILValue Fn, SILType SubstFnTy, ArrayRef Subs, ArrayRef Args, SILType ClosureTy) { SGM.useConformancesFromSubstitutions(Subs); return SILBuilder::createPartialApply(Loc, Fn, SubstFnTy, Subs, Args, ClosureTy); } BuiltinInst *SILGenBuilder::createBuiltin(SILLocation Loc, Identifier Name, SILType ResultTy, ArrayRef Subs, ArrayRef Args) { SGM.useConformancesFromSubstitutions(Subs); return SILBuilder::createBuiltin(Loc, Name, ResultTy, Subs, Args); } InitExistentialAddrInst * SILGenBuilder::createInitExistentialAddr(SILLocation Loc, SILValue Existential, CanType FormalConcreteType, SILType LoweredConcreteType, ArrayRef Conformances) { for (auto conformance : Conformances) SGM.useConformance(conformance); return SILBuilder::createInitExistentialAddr(Loc, Existential, FormalConcreteType, LoweredConcreteType, Conformances); } InitExistentialMetatypeInst * SILGenBuilder::createInitExistentialMetatype(SILLocation loc, SILValue metatype, SILType existentialType, ArrayRef conformances) { for (auto conformance : conformances) SGM.useConformance(conformance); return SILBuilder::createInitExistentialMetatype(loc, metatype, existentialType, conformances); } InitExistentialRefInst * SILGenBuilder::createInitExistentialRef(SILLocation Loc, SILType ExistentialType, CanType FormalConcreteType, SILValue Concrete, ArrayRef Conformances) { for (auto conformance : Conformances) SGM.useConformance(conformance); return SILBuilder::createInitExistentialRef(Loc, ExistentialType, FormalConcreteType, Concrete, Conformances); } AllocExistentialBoxInst * SILGenBuilder::createAllocExistentialBox(SILLocation Loc, SILType ExistentialType, CanType ConcreteType, ArrayRef Conformances) { for (auto conformance : Conformances) SGM.useConformance(conformance); return SILBuilder::createAllocExistentialBox(Loc, ExistentialType, ConcreteType, Conformances); } void SILGenFunction::checkForImportedUsedConformances(Type type) { // Recognize _BridgedNSError, which must pull in its witness table for // dynamic casts to work if (auto bridgedNSErrorProtocol = getASTContext().getProtocol(KnownProtocolKind::BridgedNSError)) { if (auto nominalDecl = type->getAnyNominal()) { SmallVector conformances; if (nominalDecl->lookupConformance( SGM.SwiftModule, bridgedNSErrorProtocol, conformances)) { SGM.useConformance(ProtocolConformanceRef(conformances.front())); } } } }