/// Emit a materializeForSet operation that simply loads the l-value /// into the result buffer. This operation creates a callback to write /// the l-value back. SILValue MaterializeForSetEmitter::emitUsingGetterSetter(SILGenFunction &SGF, SILLocation loc, ManagedValue self, RValue &&indices, SILValue resultBuffer, SILValue callbackBuffer, SILFunction *&callback) { // Copy the indices into the callback storage. const TypeLowering *indicesTL = nullptr; CleanupHandle indicesCleanup = CleanupHandle::invalid(); CanType indicesFormalType; if (isa<SubscriptDecl>(WitnessStorage)) { indicesFormalType = indices.getType(); indicesTL = &SGF.getTypeLowering(indicesFormalType); SILValue allocatedCallbackBuffer = SGF.B.createAllocValueBuffer(loc, indicesTL->getLoweredType(), callbackBuffer); // Emit into the buffer. auto init = SGF.useBufferAsTemporary(allocatedCallbackBuffer, *indicesTL); indicesCleanup = init->getInitializedCleanup(); indices.copyInto(SGF, loc, init.get()); } // Set up the result buffer. resultBuffer = SGF.B.createPointerToAddress(loc, resultBuffer, RequirementStorageType.getAddressType(), /*isStrict*/ true, /*isInvariant*/ false); TemporaryInitialization init(resultBuffer, CleanupHandle::invalid()); // Evaluate the getter into the result buffer. LValue lv = buildLValue(SGF, loc, self, std::move(indices), AccessKind::Read); RValue result = SGF.emitLoadOfLValue(loc, std::move(lv), SGFContext(&init)); if (!result.isInContext()) { std::move(result).forwardInto(SGF, loc, &init); } // Forward the cleanup on the saved indices. if (indicesCleanup.isValid()) { SGF.Cleanups.setCleanupState(indicesCleanup, CleanupState::Dead); } callback = createSetterCallback(SGF.F, indicesTL, indicesFormalType); return resultBuffer; }