static void emitCaptureArguments(SILGenFunction &SGF, AnyFunctionRef closure, CapturedValue capture, uint16_t ArgNo) { auto *VD = capture.getDecl(); SILLocation Loc(VD); Loc.markAsPrologue(); // Local function to get the captured variable type within the capturing // context. auto getVarTypeInCaptureContext = [&]() -> Type { auto interfaceType = VD->getInterfaceType(); return GenericEnvironment::mapTypeIntoContext( closure.getGenericEnvironment(), interfaceType); }; // FIXME: Expansion auto expansion = ResilienceExpansion::Minimal; switch (SGF.SGM.Types.getDeclCaptureKind(capture, expansion)) { case CaptureKind::None: break; case CaptureKind::Constant: { auto type = getVarTypeInCaptureContext(); auto &lowering = SGF.getTypeLowering(type); // Constant decls are captured by value. SILType ty = lowering.getLoweredType(); SILValue val = SGF.F.begin()->createFunctionArgument(ty, VD); bool NeedToDestroyValueAtExit = false; // If the original variable was settable, then Sema will have treated the // VarDecl as an lvalue, even in the closure's use. As such, we need to // allow formation of the address for this captured value. Create a // temporary within the closure to provide this address. if (VD->isSettable(VD->getDeclContext())) { auto addr = SGF.emitTemporaryAllocation(VD, ty); // We have created a copy that needs to be destroyed. val = SGF.B.emitCopyValueOperation(Loc, val); NeedToDestroyValueAtExit = true; lowering.emitStore(SGF.B, VD, val, addr, StoreOwnershipQualifier::Init); val = addr; } SGF.VarLocs[VD] = SILGenFunction::VarLoc::get(val); if (auto *AllocStack = dyn_cast<AllocStackInst>(val)) AllocStack->setArgNo(ArgNo); else { SILDebugVariable DbgVar(/*Constant*/ true, ArgNo); SGF.B.createDebugValue(Loc, val, DbgVar); } // TODO: Closure contexts should always be guaranteed. if (NeedToDestroyValueAtExit && !lowering.isTrivial()) SGF.enterDestroyCleanup(val); break; } case CaptureKind::Box: { // LValues are captured as a retained @box that owns // the captured value. auto type = getVarTypeInCaptureContext(); auto boxTy = SGF.SGM.Types.getContextBoxTypeForCapture(VD, SGF.SGM.Types.getLoweredRValueType(type), SGF.F.getGenericEnvironment(), /*mutable*/ true); SILValue box = SGF.F.begin()->createFunctionArgument( SILType::getPrimitiveObjectType(boxTy), VD); SILValue addr = SGF.B.createProjectBox(VD, box, 0); SGF.VarLocs[VD] = SILGenFunction::VarLoc::get(addr, box); SILDebugVariable DbgVar(/*Constant*/ false, ArgNo); SGF.B.createDebugValueAddr(Loc, addr, DbgVar); break; } case CaptureKind::StorageAddress: { // Non-escaping stored decls are captured as the address of the value. auto type = getVarTypeInCaptureContext(); SILType ty = SGF.getLoweredType(type).getAddressType(); SILValue addr = SGF.F.begin()->createFunctionArgument(ty, VD); SGF.VarLocs[VD] = SILGenFunction::VarLoc::get(addr); SILDebugVariable DbgVar(/*Constant*/ true, ArgNo); SGF.B.createDebugValueAddr(Loc, addr, DbgVar); break; } } }
static void emitCaptureArguments(SILGenFunction &gen, AnyFunctionRef closure, CapturedValue capture, unsigned ArgNo) { auto *VD = capture.getDecl(); SILLocation Loc(VD); Loc.markAsPrologue(); // Local function to get the captured variable type within the capturing // context. auto getVarTypeInCaptureContext = [&]() -> Type { auto interfaceType = VD->getInterfaceType(); return GenericEnvironment::mapTypeIntoContext( closure.getGenericEnvironment(), interfaceType); }; switch (gen.SGM.Types.getDeclCaptureKind(capture)) { case CaptureKind::None: break; case CaptureKind::Constant: { auto type = getVarTypeInCaptureContext(); auto &lowering = gen.getTypeLowering(type); // Constant decls are captured by value. SILType ty = lowering.getLoweredType(); SILValue val = gen.F.begin()->createFunctionArgument(ty, VD); // If the original variable was settable, then Sema will have treated the // VarDecl as an lvalue, even in the closure's use. As such, we need to // allow formation of the address for this captured value. Create a // temporary within the closure to provide this address. if (VD->isSettable(VD->getDeclContext())) { auto addr = gen.emitTemporaryAllocation(VD, ty); lowering.emitStore(gen.B, VD, val, addr, StoreOwnershipQualifier::Init); val = addr; } gen.VarLocs[VD] = SILGenFunction::VarLoc::get(val); if (auto *AllocStack = dyn_cast<AllocStackInst>(val)) AllocStack->setArgNo(ArgNo); else gen.B.createDebugValue(Loc, val, {/*Constant*/true, ArgNo}); // TODO: Closure contexts should always be guaranteed. if (!gen.SGM.M.getOptions().EnableGuaranteedClosureContexts && !lowering.isTrivial()) gen.enterDestroyCleanup(val); break; } case CaptureKind::Box: { // LValues are captured as a retained @box that owns // the captured value. auto type = getVarTypeInCaptureContext(); auto boxTy = gen.SGM.Types.getContextBoxTypeForCapture(VD, gen.getLoweredType(type).getSwiftRValueType(), gen.F.getGenericEnvironment(), /*mutable*/ true); SILValue box = gen.F.begin()->createFunctionArgument( SILType::getPrimitiveObjectType(boxTy), VD); SILValue addr = gen.B.createProjectBox(VD, box, 0); gen.VarLocs[VD] = SILGenFunction::VarLoc::get(addr, box); gen.B.createDebugValueAddr(Loc, addr, {/*Constant*/false, ArgNo}); if (!gen.SGM.M.getOptions().EnableGuaranteedClosureContexts) gen.Cleanups.pushCleanup<StrongReleaseCleanup>(box); break; } case CaptureKind::StorageAddress: { // Non-escaping stored decls are captured as the address of the value. auto type = getVarTypeInCaptureContext(); SILType ty = gen.getLoweredType(type).getAddressType(); SILValue addr = gen.F.begin()->createFunctionArgument(ty, VD); gen.VarLocs[VD] = SILGenFunction::VarLoc::get(addr); gen.B.createDebugValueAddr(Loc, addr, {/*Constant*/true, ArgNo}); break; } } }