void SILGenFunction::emitInjectOptionalValueInto(SILLocation loc, ArgumentSource &&value, SILValue dest, const TypeLowering &optTL) { SILType optType = optTL.getLoweredType(); OptionalTypeKind optionalKind; auto loweredPayloadTy = optType.getAnyOptionalObjectType(SGM.M, optionalKind); assert(optionalKind != OTK_None); // Project out the payload area. auto someDecl = getASTContext().getOptionalSomeDecl(optionalKind); auto destPayload = B.createInitEnumDataAddr(loc, dest, someDecl, loweredPayloadTy.getAddressType()); CanType formalOptType = optType.getSwiftRValueType(); auto archetype = formalOptType->getNominalOrBoundGenericNominal() ->getGenericParams()->getPrimaryArchetypes()[0]; AbstractionPattern origType(archetype); // Emit the value into the payload area. TemporaryInitialization emitInto(destPayload, CleanupHandle::invalid()); auto &payloadTL = getTypeLowering(origType, value.getSubstType()); std::move(value).forwardInto(*this, origType, &emitInto, payloadTL); // Inject the tag. B.createInjectEnumAddr(loc, dest, someDecl); }
/// Return a value for an optional ".Some(x)" of the specified type. This only /// works for loadable enum types. ManagedValue SILGenFunction:: getOptionalSomeValue(SILLocation loc, ManagedValue value, const TypeLowering &optTL) { assert(optTL.isLoadable() && "Address-only optionals cannot use this"); SILType optType = optTL.getLoweredType(); CanType formalOptType = optType.getSwiftRValueType(); OptionalTypeKind OTK; auto formalObjectType = formalOptType->getAnyOptionalObjectType(OTK) ->getCanonicalType(); assert(OTK != OTK_None); auto someDecl = getASTContext().getOptionalSomeDecl(OTK); auto archetype = formalOptType->getNominalOrBoundGenericNominal() ->getGenericParams()->getPrimaryArchetypes()[0]; AbstractionPattern origType(archetype); // Reabstract input value to the type expected by the enum. value = emitSubstToOrigValue(loc, value, origType, formalObjectType); SILValue result = B.createEnum(loc, value.forward(*this), someDecl, optTL.getLoweredType()); return emitManagedRValueWithCleanup(result, optTL); }
// Start with the substitutions from the apply. // Try to propagate them to find out the real substitutions required // to invoke the method. static ArrayRef<Substitution> getSubstitutionsForCallee(SILModule &M, CanSILFunctionType GenCalleeType, SILType ClassInstanceType, FullApplySite AI) { // *NOTE*: // Apply instruction substitutions are for the Member from a protocol or // class B, where this member was first defined, before it got overridden by // derived classes. // // The implementation F (the implementing method) which was found may have // a different set of generic parameters, e.g. because it is implemented by a // class D1 derived from B. // // ClassInstanceType may have a type different from both the type B // the Member belongs to and from the ClassInstanceType, e.g. if // ClassInstance is of a class D2, which is derived from D1, but does not // override the Member. // // As a result, substitutions provided by AI are for Member, whereas // substitutions in ClassInstanceType are for D2. And substitutions for D1 // are not available directly in a general case. Therefore, they have to // be computed. // // What we know for sure: // B is a superclass of D1 // D1 is a superclass of D2. // D1 can be the same as D2. D1 can be the same as B. // // So, substitutions from AI are for class B. // Substitutions for class D1 by means of bindSuperclass(), which starts // with a bound type ClassInstanceType and checks its superclasses until it // finds a bound superclass matching D1 and returns its substitutions. // Class F belongs to. CanType FSelfClass = GenCalleeType->getSelfParameter().getType(); SILType FSelfSubstType; Module *Module = M.getSwiftModule(); ArrayRef<Substitution> ClassSubs; if (GenCalleeType->isPolymorphic()) { // Declaration of the class F belongs to. if (auto *FSelfTypeDecl = FSelfClass.getNominalOrBoundGenericNominal()) { // Get the unbound generic type F belongs to. CanType FSelfGenericType = FSelfTypeDecl->getDeclaredType()->getCanonicalType(); assert((isa<BoundGenericType>(ClassInstanceType.getSwiftRValueType()) || isa<NominalType>(ClassInstanceType.getSwiftRValueType())) && "Self type should be either a bound generic type" "or a non-generic type"); assert((isa<UnboundGenericType>(FSelfGenericType) || isa<NominalType>(FSelfGenericType)) && "Method implementation self type should be generic"); if (isa<BoundGenericType>(ClassInstanceType.getSwiftRValueType())) { auto BoundBaseType = bindSuperclass(FSelfGenericType, ClassInstanceType); if (auto BoundTy = BoundBaseType->getAs<BoundGenericType>()) { ClassSubs = BoundTy->getSubstitutions(Module, nullptr); } } } } else { // If the callee is not polymorphic, no substitutions are required. return {}; } if (ClassSubs.empty()) return AI.getSubstitutions(); auto AISubs = AI.getSubstitutions(); CanSILFunctionType AIGenCalleeType = AI.getCallee().getType().castTo<SILFunctionType>(); CanType AISelfClass = AIGenCalleeType->getSelfParameter().getType(); unsigned NextMethodParamIdx = 0; unsigned NumMethodParams = 0; if (AIGenCalleeType->isPolymorphic()) { NextMethodParamIdx = 0; // Generic parameters of the method start after generic parameters // of the instance class. if (auto AISelfClassSig = AISelfClass.getClassBound()->getGenericSignature()) { NextMethodParamIdx = AISelfClassSig->getGenericParams().size(); } NumMethodParams = AISubs.size() - NextMethodParamIdx; } unsigned NumSubs = ClassSubs.size() + NumMethodParams; if (ClassSubs.size() == NumSubs) return ClassSubs; // Mix class subs with method specific subs from the AI substitutions. // Assumptions: AI substitutions contain first the substitutions for // a class of the method being invoked and then the substitutions // for a method being invoked. auto Subs = M.getASTContext().Allocate<Substitution>(NumSubs); unsigned i = 0; for (auto &S : ClassSubs) { Subs[i++] = S; } for (; i < NumSubs; ++i, ++NextMethodParamIdx) { Subs[i] = AISubs[NextMethodParamIdx]; } return Subs; }