RValue SILGenFunction::emitPointerToPointer(SILLocation loc, ManagedValue input, CanType inputType, CanType outputType, SGFContext C) { auto converter = getASTContext().getConvertPointerToPointerArgument(nullptr); // The generic function currently always requires indirection, but pointers // are always loadable. auto origBuf = emitTemporaryAllocation(loc, input.getType()); B.emitStoreValueOperation(loc, input.forward(*this), origBuf, StoreOwnershipQualifier::Init); auto origValue = emitManagedBufferWithCleanup(origBuf); // Invoke the conversion intrinsic to convert to the destination type. auto *M = SGM.M.getSwiftModule(); auto *proto = getPointerProtocol(); auto firstSubMap = inputType->getContextSubstitutionMap(M, proto); auto secondSubMap = outputType->getContextSubstitutionMap(M, proto); auto *genericSig = converter->getGenericSignature(); auto subMap = SubstitutionMap::combineSubstitutionMaps(firstSubMap, secondSubMap, CombineSubstitutionMaps::AtIndex, 1, 0, genericSig); return emitApplyOfLibraryIntrinsic(loc, converter, subMap, origValue, C); }
bool FulfillmentMap::searchNominalTypeMetadata(IRGenModule &IGM, CanType type, MetadataState metadataState, unsigned source, MetadataPath &&path, const InterestingKeysCallback &keys) { // Objective-C generics don't preserve their generic parameters at runtime, // so they aren't able to fulfill type metadata requirements. if (type.getAnyNominal()->hasClangNode()) { return false; } auto *nominal = type.getAnyNominal(); if (!nominal->isGenericContext() || isa<ProtocolDecl>(nominal)) { return false; } bool hadFulfillment = false; GenericTypeRequirements requirements(IGM, nominal); requirements.enumerateFulfillments( IGM, type->getContextSubstitutionMap(IGM.getSwiftModule(), nominal), [&](unsigned reqtIndex, CanType arg, Optional<ProtocolConformanceRef> conf) { // Skip uninteresting type arguments. if (!keys.hasInterestingType(arg)) return; // If the fulfilled value is type metadata, refine the path. if (!conf) { auto argState = getPresumedMetadataStateForTypeArgument(metadataState); MetadataPath argPath = path; argPath.addNominalTypeArgumentComponent(reqtIndex); hadFulfillment |= searchTypeMetadata(IGM, arg, IsExact, argState, source, std::move(argPath), keys); return; } // Otherwise, it's a conformance. // Ignore it unless the type itself is interesting. if (!keys.isInterestingType(arg)) return; // Refine the path. MetadataPath argPath = path; argPath.addNominalTypeArgumentConformanceComponent(reqtIndex); hadFulfillment |= searchWitnessTable(IGM, arg, conf->getRequirement(), source, std::move(argPath), keys); }); return hadFulfillment; }