static std::pair<ManagedValue, SILDeclRef> getNextUncurryLevelRef(SILGenFunction &SGF, SILLocation loc, SILDeclRef thunk, ManagedValue selfArg, SubstitutionMap curriedSubs) { auto *vd = thunk.getDecl(); // Reference the next uncurrying level of the function. SILDeclRef next = SILDeclRef(vd, thunk.kind); assert(!next.isCurried); auto constantInfo = SGF.SGM.Types.getConstantInfo(next); // If the function is natively foreign, reference its foreign entry point. if (requiresForeignToNativeThunk(vd)) return {ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next)), next}; // If the thunk is a curry thunk for a direct method reference, we are // doing a direct dispatch (eg, a fragile 'super.foo()' call). if (thunk.isDirectReference) return {ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next)), next}; if (auto *func = dyn_cast<AbstractFunctionDecl>(vd)) { if (getMethodDispatch(func) == MethodDispatch::Class) { // Use the dynamic thunk if dynamic. if (vd->isObjCDynamic()) { return {SGF.emitDynamicMethodRef(loc, next, constantInfo.SILFnType), next}; } auto methodTy = SGF.SGM.Types.getConstantOverrideType(next); SILValue result = SGF.emitClassMethodRef(loc, selfArg.getValue(), next, methodTy); return {ManagedValue::forUnmanaged(result), next.getOverriddenVTableEntry()}; } // If the fully-uncurried reference is to a generic method, look up the // witness. if (constantInfo.SILFnType->getRepresentation() == SILFunctionTypeRepresentation::WitnessMethod) { auto protocol = func->getDeclContext()->getSelfProtocolDecl(); auto origSelfType = protocol->getSelfInterfaceType()->getCanonicalType(); auto substSelfType = origSelfType.subst(curriedSubs)->getCanonicalType(); auto conformance = curriedSubs.lookupConformance(origSelfType, protocol); auto result = SGF.B.createWitnessMethod(loc, substSelfType, *conformance, next, constantInfo.getSILType()); return {ManagedValue::forUnmanaged(result), next}; } } // Otherwise, emit a direct call. return {ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next)), next}; }
static SILValue getNextUncurryLevelRef(SILGenFunction &gen, SILLocation loc, SILDeclRef next, bool direct, ArrayRef<SILValue> curriedArgs, ArrayRef<Substitution> curriedSubs) { // For a foreign function, reference the native thunk. if (next.isForeign) return gen.emitGlobalFunctionRef(loc, next.asForeign(false)); // If the fully-uncurried reference is to a native dynamic class method, emit // the dynamic dispatch. auto fullyAppliedMethod = !next.isCurried && !next.isForeign && !direct && next.hasDecl(); auto constantInfo = gen.SGM.Types.getConstantInfo(next); SILValue thisArg; if (!curriedArgs.empty()) thisArg = curriedArgs.back(); if (fullyAppliedMethod && isa<AbstractFunctionDecl>(next.getDecl()) && gen.getMethodDispatch(cast<AbstractFunctionDecl>(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 (fullyAppliedMethod && constantInfo.SILFnType->getRepresentation() == SILFunctionTypeRepresentation::WitnessMethod) { auto thisType = curriedSubs[0].getReplacement()->getCanonicalType(); assert(isa<ArchetypeType>(thisType) && "no archetype for witness?!"); SILValue OpenedExistential; if (!cast<ArchetypeType>(thisType)->getOpenedExistentialType().isNull()) OpenedExistential = thisArg; return gen.B.createWitnessMethod(loc, thisType, nullptr, next, constantInfo.getSILType(), OpenedExistential); } // Otherwise, emit a direct call. return gen.emitGlobalFunctionRef(loc, next); }
static ManagedValue emitBridgeCollectionToNative(SILGenFunction &gen, SILLocation loc, SILDeclRef bridgeFnRef, ManagedValue collection, SILType nativeTy) { SILValue bridgeFn = gen.emitGlobalFunctionRef(loc, bridgeFnRef); auto collectionTy = nativeTy.getSwiftRValueType()->castTo<BoundGenericType>(); auto subs = collectionTy->getSubstitutions(gen.SGM.M.getSwiftModule(), nullptr); auto substFnType = bridgeFn.getType().substGenericArgs(gen.SGM.M, subs); Type inputType = collection.getType().getSwiftRValueType(); if (!inputType->getOptionalObjectType()) { SILType loweredOptTy = gen.SGM.getLoweredType(OptionalType::get(inputType)); auto *someDecl = gen.getASTContext().getOptionalSomeDecl(); auto *enumInst = gen.B.createEnum(loc, collection.getValue(), someDecl, loweredOptTy); collection = ManagedValue(enumInst, collection.getCleanup()); } SILValue result = gen.B.createApply(loc, bridgeFn, substFnType, nativeTy, subs, { collection.forward(gen) }); return gen.emitManagedRValueWithCleanup(result); }
static ManagedValue emitBridgeCollectionFromNative(SILGenFunction &gen, SILLocation loc, SILDeclRef bridgeFnRef, ManagedValue collection, SILType bridgedTy) { SILValue bridgeFn = gen.emitGlobalFunctionRef(loc, bridgeFnRef); // If the expected return is optional, we'll need to wrap it. OptionalTypeKind OTK = OTK_None; SILType origBridgedTy = bridgedTy; if (auto bridgedObjTy = bridgedTy.getAnyOptionalObjectType(gen.SGM.M, OTK)) { bridgedTy = bridgedObjTy; } // Figure out the type parameters. auto inputTy = collection.getType().getSwiftRValueType()->castTo<BoundGenericType>(); auto subs = inputTy->getSubstitutions(gen.SGM.M.getSwiftModule(), nullptr); auto substFnType = bridgeFn.getType().substGenericArgs(gen.SGM.M, subs); SILValue bridged = gen.B.createApply(loc, bridgeFn, substFnType, bridgedTy, subs, { collection.forward(gen) }); // Wrap the result if necessary. if (OTK != OTK_None) { bridged = gen.B.createEnum(loc, bridged, gen.getASTContext().getOptionalSomeDecl(OTK), origBridgedTy); } return gen.emitManagedRValueWithCleanup(bridged); }
static ManagedValue emitBridgeForeignBoolToBool(SILGenFunction &gen, SILLocation loc, ManagedValue foreignBool, SILDeclRef bridgingFnRef) { // func _convertObjCBoolToBool(ObjCBool) -> Bool SILValue bridgingFn = gen.emitGlobalFunctionRef(loc, bridgingFnRef); SILType resultTy = gen.getLoweredLoadableType(gen.SGM.Types.getBoolType()); SILValue result = gen.B.createApply(loc, bridgingFn, bridgingFn->getType(), resultTy, {}, foreignBool.forward(gen)); return gen.emitManagedRValueWithCleanup(result); }
static ManagedValue emitBridgeStringToNSString(SILGenFunction &gen, SILLocation loc, ManagedValue str) { // func _convertStringToNSString(String) -> NSString SILValue stringToNSStringFn = gen.emitGlobalFunctionRef(loc, gen.SGM.getStringToNSStringFn()); SILValue nsstr = gen.B.createApply(loc, stringToNSStringFn, stringToNSStringFn.getType(), gen.getLoweredType(gen.SGM.Types.getNSStringType()), {}, str.forward(gen)); return gen.emitManagedRValueWithCleanup(nsstr); }
static ManagedValue emitBridgeBoolToObjCBool(SILGenFunction &gen, SILLocation loc, ManagedValue swiftBool) { // func _convertBoolToObjCBool(Bool) -> ObjCBool SILValue boolToObjCBoolFn = gen.emitGlobalFunctionRef(loc, gen.SGM.getBoolToObjCBoolFn()); SILType resultTy =gen.getLoweredLoadableType(gen.SGM.Types.getObjCBoolType()); SILValue result = gen.B.createApply(loc, boolToObjCBoolFn, boolToObjCBoolFn->getType(), resultTy, {}, swiftBool.forward(gen)); return gen.emitManagedRValueWithCleanup(result); }
/// Bridge the given Swift value to its corresponding Objective-C /// object, using the appropriate witness for the /// _ObjectiveCBridgeable._bridgeToObjectiveC requirement. static Optional<ManagedValue> emitBridgeNativeToObjectiveC(SILGenFunction &gen, SILLocation loc, ManagedValue swiftValue, ProtocolConformance *conformance) { // Dig out the nominal type we're bridging from. Type swiftValueType = swiftValue.getSwiftType()->getRValueType(); // Find the _bridgeToObjectiveC requirement. auto requirement = gen.SGM.getBridgeToObjectiveCRequirement(loc); if (!requirement) return None; // Retrieve the _bridgeToObjectiveC witness. auto witness = conformance->getWitness(requirement, nullptr); assert(witness); // Determine the type we're bridging to. auto objcTypeReq = gen.SGM.getBridgedObjectiveCTypeRequirement(loc); if (!objcTypeReq) return None; Type objcType = conformance->getTypeWitness(objcTypeReq, nullptr).getReplacement(); assert(objcType); // Create a reference to the witness. SILDeclRef witnessConstant(witness.getDecl()); auto witnessRef = gen.emitGlobalFunctionRef(loc, witnessConstant); // Determine the substitutions. ArrayRef<Substitution> substitutions; auto witnessFnTy = witnessRef->getType(); if (auto valueTypeBGT = swiftValueType->getAs<BoundGenericType>()) { // Compute the substitutions. substitutions = valueTypeBGT->getSubstitutions(gen.SGM.SwiftModule, nullptr); // Substitute into the witness function tye. witnessFnTy = witnessFnTy.substGenericArgs(gen.SGM.M, substitutions); } // Call the witness. SILType resultTy = gen.getLoweredType(objcType); SILValue bridgedValue = gen.B.createApply(loc, witnessRef, witnessFnTy, resultTy, substitutions, swiftValue.borrow() .getUnmanagedValue()); return gen.emitManagedRValueWithCleanup(bridgedValue); }
static ManagedValue emitBridgeNSStringToString(SILGenFunction &gen, SILLocation loc, ManagedValue nsstr) { SILValue bridgeFn = gen.emitGlobalFunctionRef(loc, gen.SGM.getNSStringToStringFn()); Type inputType = nsstr.getType().getSwiftRValueType(); if (!inputType->getOptionalObjectType()) { SILType loweredOptTy = gen.SGM.getLoweredType(OptionalType::get(inputType)); auto *someDecl = gen.getASTContext().getOptionalSomeDecl(); auto *enumInst = gen.B.createEnum(loc, nsstr.getValue(), someDecl, loweredOptTy); nsstr = ManagedValue(enumInst, nsstr.getCleanup()); } SILType nativeTy = gen.getLoweredType(gen.SGM.Types.getStringType()); SILValue str = gen.B.createApply(loc, bridgeFn, bridgeFn.getType(), nativeTy, {}, { nsstr.forward(gen) }); return gen.emitManagedRValueWithCleanup(str); }
static SILValue getThunkedForeignFunctionRef(SILGenFunction &gen, SILLocation loc, SILDeclRef foreign, ArrayRef<ManagedValue> args, ArrayRef<Substitution> subs, const SILConstantInfo &foreignCI) { assert(!foreign.isCurried && "should not thunk calling convention when curried"); // Produce a witness_method when thunking ObjC protocol methods. auto dc = foreign.getDecl()->getDeclContext(); if (isa<ProtocolDecl>(dc) && cast<ProtocolDecl>(dc)->isObjC()) { assert(subs.size() == 1); auto thisType = subs[0].getReplacement()->getCanonicalType(); assert(isa<ArchetypeType>(thisType) && "no archetype for witness?!"); SILValue thisArg = args.back().getValue(); SILValue OpenedExistential; if (!cast<ArchetypeType>(thisType)->getOpenedExistentialType().isNull()) OpenedExistential = thisArg; auto conformance = ProtocolConformanceRef(cast<ProtocolDecl>(dc)); return gen.B.createWitnessMethod(loc, thisType, conformance, foreign, foreignCI.getSILType(), OpenedExistential); // Produce a class_method when thunking imported ObjC methods. } else if (foreignCI.SILFnType->getRepresentation() == SILFunctionTypeRepresentation::ObjCMethod) { assert(subs.empty()); SILValue thisArg = args.back().getValue(); return gen.B.createClassMethod(loc, thisArg, foreign, SILType::getPrimitiveObjectType(foreignCI.SILFnType), /*volatile*/ true); } // Otherwise, emit a function_ref. return gen.emitGlobalFunctionRef(loc, foreign); }
/// Bridge the given Objective-C object to its corresponding Swift /// value, using the appropriate witness for the /// _ObjectiveCBridgeable._unconditionallyBridgeFromObjectiveC requirement. static Optional<ManagedValue> emitBridgeObjectiveCToNative(SILGenFunction &gen, SILLocation loc, ManagedValue objcValue, ProtocolConformance *conformance) { // Find the _unconditionallyBridgeFromObjectiveC requirement. auto requirement = gen.SGM.getUnconditionallyBridgeFromObjectiveCRequirement(loc); if (!requirement) return None; // Retrieve the _unconditionallyBridgeFromObjectiveC witness. auto witness = conformance->getWitness(requirement, nullptr); assert(witness); // Create a reference to the witness. SILDeclRef witnessConstant(witness.getDecl()); auto witnessRef = gen.emitGlobalFunctionRef(loc, witnessConstant); // Determine the substitutions. ArrayRef<Substitution> substitutions; auto witnessFnTy = witnessRef->getType().castTo<SILFunctionType>(); Type swiftValueType = conformance->getType(); if (auto valueTypeBGT = swiftValueType->getAs<BoundGenericType>()) { // Compute the substitutions. substitutions = valueTypeBGT->getSubstitutions(gen.SGM.SwiftModule, nullptr); } // Substitute into the witness function type. if (!substitutions.empty()) witnessFnTy = witnessFnTy->substGenericArgs(gen.SGM.M, gen.SGM.SwiftModule, substitutions); // If the Objective-C value isn't optional, wrap it in an optional. Type objcValueType = objcValue.getType().getSwiftRValueType(); if (!objcValueType->getOptionalObjectType()) { SILType loweredOptTy = gen.SGM.getLoweredType(OptionalType::get(objcValueType)); auto *someDecl = gen.getASTContext().getOptionalSomeDecl(); auto *enumInst = gen.B.createEnum(loc, objcValue.getValue(), someDecl, loweredOptTy); objcValue = ManagedValue(enumInst, objcValue.getCleanup()); } // Call the witness. Type metatype = MetatypeType::get(swiftValueType); SILValue metatypeValue = gen.B.createMetatype(loc, gen.getLoweredType(metatype)); auto witnessCI = gen.getConstantInfo(witnessConstant); CanType formalResultTy = witnessCI.LoweredInterfaceType.getResult(); // Set up the generic signature. CanGenericSignature witnessGenericSignature; if (auto genericSig = cast<AbstractFunctionDecl>(witness.getDecl())->getGenericSignature()) witnessGenericSignature = genericSig->getCanonicalSignature(); GenericContextScope genericContextScope(gen.SGM.Types, witnessGenericSignature); return gen.emitApply(loc, ManagedValue::forUnmanaged(witnessRef), substitutions, { objcValue, ManagedValue::forUnmanaged(metatypeValue) }, witnessFnTy, AbstractionPattern(witnessGenericSignature, formalResultTy), swiftValueType->getCanonicalType(), ApplyOptions::None, None, None, SGFContext()) .getAsSingleValue(gen, loc); }