/// Emit a materializeForSet callback that stores the value from the /// result buffer back into the l-value. SILFunction * MaterializeForSetEmitter::createSetterCallback(SILFunction &F, const TypeLowering *indicesTL, CanType indicesFormalType) { return createCallback(F, [&](SILGenFunction &SGF, SILLocation loc, SILValue value, SILValue callbackBuffer, SILValue self) { // If this is a subscript, we need to handle the indices in the // callback storage. RValue indices; if (indicesTL) { assert(isa<SubscriptDecl>(WitnessStorage)); SILType indicesTy = indicesTL->getLoweredType(); // Enter a cleanup to deallocate the callback storage. SGF.Cleanups.pushCleanup<DeallocateValueBuffer>(indicesTy, callbackBuffer); // Project the value out, loading if necessary, and take // ownership of it. SILValue indicesV = SGF.B.createProjectValueBuffer(loc, indicesTy, callbackBuffer); if (indicesTL->isLoadable() || !SGF.silConv.useLoweredAddresses()) indicesV = indicesTL->emitLoad(SGF.B, loc, indicesV, LoadOwnershipQualifier::Take); ManagedValue mIndices = SGF.emitManagedRValueWithCleanup(indicesV, *indicesTL); // Explode as an r-value. indices = RValue(SGF, loc, indicesFormalType, mIndices); } // The callback gets the address of 'self' at +0. ManagedValue mSelf = ManagedValue::forLValue(self); // That's enough to build the l-value. LValue lvalue = buildLValue(SGF, loc, mSelf, std::move(indices), AccessKind::Write); // The callback gets the value at +1. auto &valueTL = SGF.getTypeLowering(lvalue.getTypeOfRValue()); value = SGF.B.createPointerToAddress( loc, value, valueTL.getLoweredType().getAddressType(), /*isStrict*/ true, /*isInvariant*/ false); if (valueTL.isLoadable() || !SGF.silConv.useLoweredAddresses()) value = valueTL.emitLoad(SGF.B, loc, value, LoadOwnershipQualifier::Take); ManagedValue mValue = SGF.emitManagedRValueWithCleanup(value, valueTL); RValue rvalue(SGF, loc, lvalue.getSubstFormalType(), mValue); // Finally, call the setter. SGF.emitAssignToLValue(loc, std::move(rvalue), std::move(lvalue)); }); }