SubstitutionMap GenericSignature::getSubstitutionMap(SubstitutionList subs) const { SubstitutionMap result(const_cast<GenericSignature *>(this)); enumeratePairedRequirements( [&](Type depTy, ArrayRef<Requirement> reqts) -> bool { auto sub = subs.front(); subs = subs.slice(1); auto canTy = depTy->getCanonicalType(); if (auto paramTy = dyn_cast<GenericTypeParamType>(canTy)) result.addSubstitution(paramTy, sub.getReplacement()); auto conformances = sub.getConformances(); assert(reqts.size() == conformances.size()); for (unsigned i = 0, e = conformances.size(); i < e; i++) { assert(reqts[i].getSecondType()->getAnyNominal() == conformances[i].getRequirement()); result.addConformance(canTy, conformances[i]); } return false; }); assert(subs.empty() && "did not use all substitutions?!"); result.verify(); return result; }
void cGraphMaster::do_substitutions(string& input, const SubstitutionList& subs_vec) const { for (SubstitutionList::const_iterator it = subs_vec.begin(); it != subs_vec.end(); ++it) { // from is already lowercase const string& from = it->from; const string& to = it->to; if (!it->regex) { for (size_t i = 0; i < input.length(); i++) { size_t j; for (j = 0; (i+j) < input.length() && j < from.length(); j++) { if (tolower(input[i+j]) != from[j]) break; } if (j == from.length()) { // even if there's a match I need that chars around the matching part be [^A-Za-z0-9'] if (((i > 0 && !isalnum(input[i-1]) && input[i-1] != '\'') || i == 0) && (((i + from.length()) < input.length() && !isalnum(input[i + from.length()]) && input[i + from.length()] != '\'') || i + from.length() >= input.length())) { input.replace(i, from.length(), to); if (!to.empty()) i += (to.length() - 1); } } } } else { #ifdef ENABLE_PCRECPP pcrecpp::RE(from).GlobalReplace(to, &input); #endif } } }
SubstitutionMap GenericEnvironment:: getSubstitutionMap(SubstitutionList subs) const { SubstitutionMap result; for (auto depTy : getGenericSignature()->getAllDependentTypes()) { // Map the interface type to a context type. auto contextTy = depTy.subst(QueryInterfaceTypeSubstitutions(this), MakeAbstractConformanceForGenericType()); auto sub = subs.front(); subs = subs.slice(1); // Record the replacement type and its conformances. if (auto *archetype = contextTy->getAs<ArchetypeType>()) { result.addSubstitution(CanArchetypeType(archetype), sub.getReplacement()); for (auto conformance : sub.getConformances()) result.addConformance(CanType(archetype), conformance); continue; } // FIXME: getAllDependentTypes() includes generic type parameters that // have been made concrete. assert(contextTy->hasError() || depTy->is<GenericTypeParamType>()); } assert(subs.empty() && "did not use all substitutions?!"); populateParentMap(result); return result; }
static void emitTypeTraitBuiltin(IRGenFunction &IGF, Explosion &out, Explosion &args, SubstitutionList substitutions, TypeTraitResult (TypeBase::*trait)()) { assert(substitutions.size() == 1 && "type trait should have gotten single type parameter"); args.claimNext(); // Lower away the trait to a tristate 0 = no, 1 = yes, 2 = maybe. unsigned result; switch ((substitutions[0].getReplacement().getPointer()->*trait)()) { case TypeTraitResult::IsNot: result = 0; break; case TypeTraitResult::Is: result = 1; break; case TypeTraitResult::CanBe: result = 2; break; } out.add(llvm::ConstantInt::get(IGF.IGM.Int8Ty, result)); }
/// Specialized emitter for Builtin.destroy. static ManagedValue emitBuiltinDestroy(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { assert(args.size() == 2 && "destroy should have two arguments"); assert(substitutions.size() == 1 && "destroy should have a single substitution"); // The substitution determines the type of the thing we're destroying. auto &ti = gen.getTypeLowering(substitutions[0].getReplacement()); // Destroy is a no-op for trivial types. if (ti.isTrivial()) return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc)); SILType destroyType = ti.getLoweredType(); // Convert the pointer argument to a SIL address. SILValue addr = gen.B.createPointerToAddress(loc, args[1].getUnmanagedValue(), destroyType.getAddressType(), /*isStrict*/ true); // Destroy the value indirectly. Canonicalization will promote to loads // and releases if appropriate. gen.B.createDestroyAddr(loc, addr); return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc)); }
static ManagedValue emitBuiltinAssign(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { assert(args.size() >= 2 && "assign should have two arguments"); assert(substitutions.size() == 1 && "assign should have a single substitution"); // The substitution determines the type of the thing we're destroying. CanType assignFormalType = substitutions[0].getReplacement()->getCanonicalType(); SILType assignType = gen.getLoweredType(assignFormalType); // Convert the destination pointer argument to a SIL address. SILValue addr = gen.B.createPointerToAddress(loc, args.back().getUnmanagedValue(), assignType.getAddressType(), /*isStrict*/ true); // Build the value to be assigned, reconstructing tuples if needed. auto src = RValue::withPreExplodedElements(args.slice(0, args.size() - 1), assignFormalType); std::move(src).assignInto(gen, loc, addr); return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc)); }
static ManagedValue emitCastFromReferenceType(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, SGFContext C) { assert(args.size() == 1 && "cast should have a single argument"); assert(substitutions.size() == 1 && "cast should have a single substitution"); // The substitution determines the destination type. SILType destType = gen.getLoweredType(substitutions[0].getReplacement()); // Bail if the source type is not a class reference of some kind. if (!substitutions[0].getReplacement()->isBridgeableObjectType() || !destType.isObject()) { gen.SGM.diagnose(loc, diag::invalid_sil_builtin, "castFromNativeObject dest must be an object type"); // Recover by propagating an undef result. SILValue result = SILUndef::get(destType, gen.SGM.M); return ManagedValue::forUnmanaged(result); } // Save the cleanup on the argument so we can forward it onto the cast // result. auto cleanup = args[0].getCleanup(); // Take the reference type argument and cast it. SILValue result = gen.B.createUncheckedRefCast(loc, args[0].getValue(), destType); // Return the cast result with the original cleanup. return ManagedValue(result, cleanup); }
/// Specialized emitter for Builtin.castReference. static ManagedValue emitBuiltinCastReference(SILGenFunction &SGF, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, SGFContext C) { assert(args.size() == 1 && "castReference should be given one argument"); assert(substitutions.size() == 2 && "castReference should have two subs"); auto fromTy = substitutions[0].getReplacement(); auto toTy = substitutions[1].getReplacement(); auto &fromTL = SGF.getTypeLowering(fromTy); auto &toTL = SGF.getTypeLowering(toTy); assert(!fromTL.isTrivial() && !toTL.isTrivial() && "expected ref type"); if (!fromTL.isAddress() || !toTL.isAddress()) { if (auto refCast = SGF.B.tryCreateUncheckedRefCast(loc, args[0].getValue(), toTL.getLoweredType())) { // Create a reference cast, forwarding the cleanup. // The cast takes the source reference. return ManagedValue(refCast, args[0].getCleanup()); } } // We are either casting between address-only types, or cannot promote to a // cast of reference values. // // If the from/to types are invalid, then use a cast that will fail at // runtime. We cannot catch these errors with SIL verification because they // may legitimately occur during code specialization on dynamically // unreachable paths. // // TODO: For now, we leave invalid casts in address form so that the runtime // will trap. We could emit a noreturn call here instead which would provide // more information to the optimizer. SILValue srcVal = args[0].forward(SGF); SILValue fromAddr; if (!fromTL.isAddress()) { // Move the loadable value into a "source temp". Since the source and // dest are RC identical, store the reference into the source temp without // a retain. The cast will load the reference from the source temp and // store it into a dest temp effectively forwarding the cleanup. fromAddr = SGF.emitTemporaryAllocation(loc, srcVal->getType()); fromTL.emitStore(SGF.B, loc, srcVal, fromAddr, StoreOwnershipQualifier::Init); } else { // The cast loads directly from the source address. fromAddr = srcVal; } // Create a "dest temp" to hold the reference after casting it. SILValue toAddr = SGF.emitTemporaryAllocation(loc, toTL.getLoweredType()); SGF.B.createUncheckedRefCastAddr(loc, fromAddr, fromTy->getCanonicalType(), toAddr, toTy->getCanonicalType()); // Forward it along and register a cleanup. if (toTL.isAddress()) return SGF.emitManagedBufferWithCleanup(toAddr); // Load the destination value. auto result = toTL.emitLoad(SGF.B, loc, toAddr, LoadOwnershipQualifier::Take); return SGF.emitManagedRValueWithCleanup(result); }
/// Specialized emitter for Builtin.castReferenceFromBridgeObject. static ManagedValue emitBuiltinCastReferenceFromBridgeObject( SILGenFunction &gen, SILLocation loc, SubstitutionList subs, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { assert(args.size() == 1 && "cast should have one argument"); assert(subs.size() == 1 && "cast should have a type substitution"); // The substitution determines the destination type. SILType destType = gen.getLoweredType(subs[0].getReplacement()); // Bail if the source type is not a class reference of some kind. if (!subs[0].getReplacement()->isBridgeableObjectType() || !destType.isObject()) { gen.SGM.diagnose(loc, diag::invalid_sil_builtin, "castReferenceFromBridgeObject dest must be an object type"); // Recover by propagating an undef result. SILValue result = SILUndef::get(destType, gen.SGM.M); return ManagedValue::forUnmanaged(result); } SILValue result = gen.B.createBridgeObjectToRef(loc, args[0].forward(gen), destType); return gen.emitManagedRValueWithCleanup(result); }
static ManagedValue emitBuiltinAllocWithTailElems(SILGenFunction &gen, SILLocation loc, SubstitutionList subs, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { unsigned NumTailTypes = subs.size() - 1; assert(args.size() == NumTailTypes * 2 + 1 && "wrong number of substitutions for allocWithTailElems"); // The substitution determines the element type for bound memory. SILType RefType = gen.getLoweredType(subs[0].getReplacement()-> getCanonicalType()).getObjectType(); SmallVector<ManagedValue, 4> Counts; SmallVector<SILType, 4> ElemTypes; for (unsigned Idx = 0; Idx < NumTailTypes; ++Idx) { Counts.push_back(args[Idx * 2 + 1]); ElemTypes.push_back(gen.getLoweredType(subs[Idx+1].getReplacement()-> getCanonicalType()).getObjectType()); } ManagedValue Metatype = args[0]; if (isa<MetatypeInst>(Metatype)) { assert(Metatype.getType().getMetatypeInstanceType(gen.SGM.M) == RefType && "substituted type does not match operand metatype"); return gen.B.createAllocRef(loc, RefType, false, false, ElemTypes, Counts); } else { return gen.B.createAllocRefDynamic(loc, Metatype, RefType, false, ElemTypes, Counts); } }
static ManagedValue emitCastToReferenceType(SILGenFunction &SGF, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, SGFContext C, SILType objPointerType) { assert(args.size() == 1 && "cast should have a single argument"); assert(substitutions.size() == 1 && "cast should have a type substitution"); // Bail if the source type is not a class reference of some kind. if (!substitutions[0].getReplacement()->mayHaveSuperclass() && !substitutions[0].getReplacement()->isClassExistentialType()) { SGF.SGM.diagnose(loc, diag::invalid_sil_builtin, "castToNativeObject source must be a class"); SILValue undef = SILUndef::get(objPointerType, SGF.SGM.M); return ManagedValue::forUnmanaged(undef); } // Grab the argument. ManagedValue arg = args[0]; // If the argument is existential, open it. if (substitutions[0].getReplacement()->isClassExistentialType()) { auto openedTy = ArchetypeType::getOpened(substitutions[0].getReplacement()); SILType loweredOpenedTy = SGF.getLoweredLoadableType(openedTy); arg = SGF.B.createOpenExistentialRef(loc, arg, loweredOpenedTy); } // Return the cast result. return SGF.B.createUncheckedRefCast(loc, arg, objPointerType); }
/// Specialized emitter for Builtin.reinterpretCast. static ManagedValue emitBuiltinReinterpretCast(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { assert(args.size() == 1 && "reinterpretCast should be given one argument"); assert(substitutions.size() == 2 && "reinterpretCast should have two subs"); auto &fromTL = gen.getTypeLowering(substitutions[0].getReplacement()); auto &toTL = gen.getTypeLowering(substitutions[1].getReplacement()); // If casting between address-only types, cast the address. if (!fromTL.isLoadable() || !toTL.isLoadable()) { SILValue fromAddr; // If the from value is loadable, move it to a buffer. if (fromTL.isLoadable()) { fromAddr = gen.emitTemporaryAllocation(loc, args[0].getValue()->getType()); fromTL.emitStore(gen.B, loc, args[0].getValue(), fromAddr, StoreOwnershipQualifier::Init); } else { fromAddr = args[0].getValue(); } auto toAddr = gen.B.createUncheckedAddrCast(loc, fromAddr, toTL.getLoweredType().getAddressType()); // Load and retain the destination value if it's loadable. Leave the cleanup // on the original value since we don't know anything about it's type. if (toTL.isLoadable()) { return gen.emitManagedLoadCopy(loc, toAddr, toTL); } // Leave the cleanup on the original value. if (toTL.isTrivial()) return ManagedValue::forUnmanaged(toAddr); // Initialize the +1 result buffer without taking the incoming value. The // source and destination cleanups will be independent. return gen.B.bufferForExpr( loc, toTL.getLoweredType(), toTL, C, [&](SILValue bufferAddr) { gen.B.createCopyAddr(loc, toAddr, bufferAddr, IsNotTake, IsInitialization); }); } // Create the appropriate bitcast based on the source and dest types. auto &in = args[0]; SILValue out = gen.B.createUncheckedBitCast(loc, in.getValue(), toTL.getLoweredType()); // If the cast reduces to unchecked_ref_cast, then the source and dest // have identical cleanup, so just forward the cleanup as an optimization. if (isa<UncheckedRefCastInst>(out)) return ManagedValue(out, in.getCleanup()); // Otherwise leave the original cleanup and retain the cast value. return gen.emitManagedRetain(loc, out, toTL); }
/// Compute substitutions for making a direct call to a SIL function with /// @convention(witness_method) convention. /// /// Such functions have a substituted generic signature where the /// abstract `Self` parameter from the original type of the protocol /// requirement is replaced by a concrete type. /// /// Thus, the original substitutions of the apply instruction that /// are written in terms of the requirement's generic signature need /// to be remapped to substitutions suitable for the witness signature. /// /// \param conformanceRef The (possibly-specialized) conformance /// \param requirementSig The generic signature of the requirement /// \param witnessThunkSig The generic signature of the witness method /// \param origSubs The substitutions from the call instruction /// \param newSubs New substitutions are stored here static void getWitnessMethodSubstitutions( SILModule &M, ProtocolConformanceRef conformanceRef, GenericSignature *requirementSig, GenericSignature *witnessThunkSig, SubstitutionList origSubs, bool isDefaultWitness, SmallVectorImpl<Substitution> &newSubs) { if (witnessThunkSig == nullptr) return; if (isDefaultWitness) { newSubs.append(origSubs.begin(), origSubs.end()); return; } assert(!conformanceRef.isAbstract()); auto conformance = conformanceRef.getConcrete(); // If `Self` maps to a bound generic type, this gives us the // substitutions for the concrete type's generic parameters. auto baseSubMap = getSubstitutionsForProtocolConformance(conformanceRef); unsigned baseDepth = 0; auto *rootConformance = conformance->getRootNormalConformance(); if (auto *witnessSig = rootConformance->getGenericSignature()) baseDepth = witnessSig->getGenericParams().back()->getDepth() + 1; auto origDepth = 1; auto origSubMap = requirementSig->getSubstitutionMap(origSubs); auto subMap = SubstitutionMap::combineSubstitutionMaps(baseSubMap, origSubMap, CombineSubstitutionMaps::AtDepth, baseDepth, origDepth, witnessThunkSig); witnessThunkSig->getSubstitutions(subMap, newSubs); }
static SubstitutionMap getSubstitutionsForProtocolConformance(ProtocolConformanceRef CRef) { auto C = CRef.getConcrete(); // Walk down to the base NormalProtocolConformance. SubstitutionList Subs; const ProtocolConformance *ParentC = C; while (!isa<NormalProtocolConformance>(ParentC)) { switch (ParentC->getKind()) { case ProtocolConformanceKind::Normal: llvm_unreachable("should have exited the loop?!"); case ProtocolConformanceKind::Inherited: ParentC = cast<InheritedProtocolConformance>(ParentC) ->getInheritedConformance(); break; case ProtocolConformanceKind::Specialized: { auto SC = cast<SpecializedProtocolConformance>(ParentC); ParentC = SC->getGenericConformance(); assert(Subs.empty() && "multiple conformance specializations?!"); Subs = SC->getGenericSubstitutions(); break; } } } const NormalProtocolConformance *NormalC = cast<NormalProtocolConformance>(ParentC); // If the normal conformance is for a generic type, and we didn't hit a // specialized conformance, collect the substitutions from the generic type. // FIXME: The AST should do this for us. if (!NormalC->getType()->isSpecialized()) return SubstitutionMap(); if (Subs.empty()) { auto *DC = NormalC->getDeclContext(); return NormalC->getType() ->getContextSubstitutionMap(DC->getParentModule(), DC); } return NormalC->getGenericSignature()->getSubstitutionMap(Subs); }
shared_ptr<Predicate> PredicateEntry::substitute(SubstitutionList & substitution_list) const { vector<shared_ptr<SymbolTableEntry>> symbols; for (auto i = _symbols.begin(); i != _symbols.end(); ++i) { symbols.push_back(substitution_list.find_value(*i)); } PredicateEntry p(string(_name), symbols); ostringstream s; s << "(" << p.text() << ")"; Parser parser(s.str()); return parser.parse_predicate(); }
// @brief Returns true if the PredicateEnry matches with other PredicateEntry // @return bool bool PredicateEntry::matches(shared_ptr<SymbolTableEntry> other, SubstitutionList & substitution_list) const { if (!other->is_predicate()) { return false; } shared_ptr<PredicateEntry> otherp = dynamic_pointer_cast<PredicateEntry>(other); if (_name != otherp->_name || _symbols.size() != otherp->_symbols.size()) { return false; } for (unsigned int i = 0; i < _symbols.size(); ++i) { shared_ptr<SymbolTableEntry> ci_value = substitution_list.find_value(_symbols[i]); shared_ptr<SymbolTableEntry> oi_value = substitution_list.find_value(otherp->_symbols[i]); shared_ptr<SymbolTableEntry> ci = substitution_list.find_non_null(_symbols[i]); shared_ptr<SymbolTableEntry> oi = substitution_list.find_non_null(otherp->_symbols[i]); if (!ci_value || !oi_value) { //semantic error return false; } if (!(*ci_value == *oi_value)) { if (ci_value->is_constant() && oi_value->is_constant()) { return false; } if (!ci_value->is_constant()) { substitution_list.add(ci, oi); } else { //!oi->is_constant() substitution_list.add(oi, ci); } } } return true; }
int Specialization::substituteVariablesWithConst(SgNode* node, ConstReporter* constReporter) { typedef pair<SgExpression*,int> SubstitutionPair; typedef list<SubstitutionPair > SubstitutionList; SubstitutionList substitutionList; RoseAst ast(node); for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) { if(constReporter->isConst(*i)) { int varIntValue=constReporter->getConstInt(); SgVarRefExp* varRefExp=constReporter->getVarRefExp(); SubstitutionPair p=make_pair(varRefExp,varIntValue); substitutionList.push_back(p); } } for(SubstitutionList::iterator i=substitutionList.begin(); i!=substitutionList.end(); ++i) { // buildSignedIntType() // buildFloatType() // buildDoubleType() // SgIntVal* buildIntVal(int) SgNodeHelper::replaceExpression((*i).first,SageBuilder::buildIntVal((*i).second),false); } return (int)substitutionList.size(); }
static ManagedValue emitBuiltinCastBitPatternFromBridgeObject( SILGenFunction &SGF, SILLocation loc, SubstitutionList subs, ArrayRef<ManagedValue> args, SGFContext C) { assert(args.size() == 1 && "cast should have one argument"); assert(subs.empty() && "cast should not have subs"); SILType wordType = SILType::getBuiltinWordType(SGF.getASTContext()); SILValue result = SGF.B.createBridgeObjectToWord(loc, args[0].getValue(), wordType); return ManagedValue::forUnmanaged(result); }
static ManagedValue emitBuiltinIsUniqueOrPinned(SILGenFunction &SGF, SILLocation loc, SubstitutionList subs, ArrayRef<ManagedValue> args, SGFContext C) { assert(subs.size() == 1 && "isUnique should have a single substitution"); assert(args.size() == 1 && "isUnique should have a single argument"); assert((args[0].getType().isAddress() && !args[0].hasCleanup()) && "Builtin.isUnique takes an address."); return ManagedValue::forUnmanaged( SGF.B.createIsUniqueOrPinned(loc, args[0].getValue())); }
static ManagedValue emitBuiltinIsUniqueOrPinned_native(SILGenFunction &SGF, SILLocation loc, SubstitutionList subs, ArrayRef<ManagedValue> args, SGFContext C) { assert(subs.size() == 1 && "isUniqueOrPinned_native should have one sub."); assert(args.size() == 1 && "isUniqueOrPinned_native should have one arg."); auto ToType = SILType::getNativeObjectType(SGF.getASTContext()).getAddressType(); auto toAddr = SGF.B.createUncheckedAddrCast(loc, args[0].getValue(), ToType); SILValue result = SGF.B.createIsUniqueOrPinned(loc, toAddr); return ManagedValue::forUnmanaged(result); }
static ManagedValue emitBuiltinBindMemory(SILGenFunction &SGF, SILLocation loc, SubstitutionList subs, ArrayRef<ManagedValue> args, SGFContext C) { assert(subs.size() == 1 && "bindMemory should have a single substitution"); assert(args.size() == 3 && "bindMemory should have three argument"); // The substitution determines the element type for bound memory. CanType boundFormalType = subs[0].getReplacement()->getCanonicalType(); SILType boundType = SGF.getLoweredType(boundFormalType); SGF.B.createBindMemory(loc, args[0].getValue(), args[1].getValue(), boundType); return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc)); }
/// Specialized emitter for Builtin.gep. static ManagedValue emitBuiltinGep(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { assert(substitutions.size() == 1 && "gep should have two substitutions"); assert(args.size() == 3 && "gep should be given three arguments"); SILType ElemTy = gen.getLoweredType(substitutions[0].getReplacement()); SILType RawPtrType = args[0].getUnmanagedValue()->getType(); SILValue addr = gen.B.createPointerToAddress(loc, args[0].getUnmanagedValue(), ElemTy.getAddressType(), true); addr = gen.B.createIndexAddr(loc, addr, args[1].getUnmanagedValue()); addr = gen.B.createAddressToPointer(loc, addr, RawPtrType); return ManagedValue::forUnmanaged(addr); }
static ManagedValue emitBuiltinTypeTrait(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { assert(substitutions.size() == 1 && "type trait should take a single type parameter"); assert(args.size() == 1 && "type trait should take a single argument"); unsigned result; auto traitTy = substitutions[0].getReplacement()->getCanonicalType(); switch ((traitTy.getPointer()->*Trait)()) { // If the type obviously has or lacks the trait, emit a constant result. case TypeTraitResult::IsNot: result = 0; break; case TypeTraitResult::Is: result = 1; break; // If not, emit the builtin call normally. Specialization may be able to // eliminate it later, or we'll lower it away at IRGen time. case TypeTraitResult::CanBe: { auto &C = gen.getASTContext(); auto int8Ty = BuiltinIntegerType::get(8, C)->getCanonicalType(); auto apply = gen.B.createBuiltin(loc, C.getIdentifier(getBuiltinName(Kind)), SILType::getPrimitiveObjectType(int8Ty), substitutions, args[0].getValue()); return ManagedValue::forUnmanaged(apply); } } // Produce the result as an integer literal constant. auto val = gen.B.createIntegerLiteral( loc, SILType::getBuiltinIntegerType(8, gen.getASTContext()), (uintmax_t)result); return ManagedValue::forUnmanaged(val); }
static ManagedValue emitBuiltinProjectTailElems(SILGenFunction &SGF, SILLocation loc, SubstitutionList subs, ArrayRef<ManagedValue> args, SGFContext C) { assert(subs.size() == 2 && "allocWithTailElems should have two substitutions"); assert(args.size() == 2 && "allocWithTailElems should have three arguments"); // The substitution determines the element type for bound memory. SILType ElemType = SGF.getLoweredType(subs[1].getReplacement()-> getCanonicalType()).getObjectType(); SILValue result = SGF.B.createRefTailAddr(loc, args[0].getValue(), ElemType.getAddressType()); SILType rawPointerType = SILType::getRawPointerType(SGF.F.getASTContext()); result = SGF.B.createAddressToPointer(loc, result, rawPointerType); return ManagedValue::forUnmanaged(result); }
/// Specialized emitter for Builtin.bridgeFromRawPointer. static ManagedValue emitBuiltinBridgeFromRawPointer(SILGenFunction &SGF, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, SGFContext C) { assert(substitutions.size() == 1 && "bridge should have a single substitution"); assert(args.size() == 1 && "bridge should have a single argument"); // The substitution determines the destination type. // FIXME: Archetype destination type? auto &destLowering = SGF.getTypeLowering(substitutions[0].getReplacement()); assert(destLowering.isLoadable()); SILType destType = destLowering.getLoweredType(); // Take the raw pointer argument and cast it to the destination type. SILValue result = SGF.B.createRawPointerToRef(loc, args[0].getUnmanagedValue(), destType); // The result has ownership semantics, so retain it with a cleanup. return SGF.emitManagedRetain(loc, result, destLowering); }
/// Specialized emitter for Builtin.getTailAddr. static ManagedValue emitBuiltinGetTailAddr(SILGenFunction &SGF, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, SGFContext C) { assert(substitutions.size() == 2 && "getTailAddr should have two substitutions"); assert(args.size() == 4 && "gep should be given four arguments"); SILType ElemTy = SGF.getLoweredType(substitutions[0].getReplacement()); SILType TailTy = SGF.getLoweredType(substitutions[1].getReplacement()); SILType RawPtrType = args[0].getUnmanagedValue()->getType(); SILValue addr = SGF.B.createPointerToAddress(loc, args[0].getUnmanagedValue(), ElemTy.getAddressType(), /*strict*/ true, /*invariant*/ false); addr = SGF.B.createTailAddr(loc, addr, args[1].getUnmanagedValue(), TailTy.getAddressType()); addr = SGF.B.createAddressToPointer(loc, addr, RawPtrType); return ManagedValue::forUnmanaged(addr); }
/// Specialized emitter for Builtin.castToBridgeObject. static ManagedValue emitBuiltinCastToBridgeObject(SILGenFunction &gen, SILLocation loc, SubstitutionList subs, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { assert(args.size() == 2 && "cast should have two arguments"); assert(subs.size() == 1 && "cast should have a type substitution"); // Take the reference type argument and cast it to BridgeObject. SILType objPointerType = SILType::getBridgeObjectType(gen.F.getASTContext()); // Bail if the source type is not a class reference of some kind. if (!subs[0].getReplacement()->mayHaveSuperclass() && !subs[0].getReplacement()->isClassExistentialType()) { gen.SGM.diagnose(loc, diag::invalid_sil_builtin, "castToBridgeObject source must be a class"); SILValue undef = SILUndef::get(objPointerType, gen.SGM.M); return ManagedValue::forUnmanaged(undef); } // Save the cleanup on the argument so we can forward it onto the cast // result. auto refCleanup = args[0].getCleanup(); SILValue ref = args[0].getValue(); SILValue bits = args[1].getUnmanagedValue(); // If the argument is existential, open it. if (subs[0].getReplacement()->isClassExistentialType()) { auto openedTy = ArchetypeType::getOpened(subs[0].getReplacement()); SILType loweredOpenedTy = gen.getLoweredLoadableType(openedTy); ref = gen.B.createOpenExistentialRef(loc, ref, loweredOpenedTy); gen.setArchetypeOpeningSite(openedTy, ref); } SILValue result = gen.B.createRefToBridgeObject(loc, ref, bits); return ManagedValue(result, refCleanup); }
static ManagedValue emitCastToReferenceType(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, SGFContext C, SILType objPointerType) { assert(args.size() == 1 && "cast should have a single argument"); assert(substitutions.size() == 1 && "cast should have a type substitution"); // Bail if the source type is not a class reference of some kind. if (!substitutions[0].getReplacement()->mayHaveSuperclass() && !substitutions[0].getReplacement()->isClassExistentialType()) { gen.SGM.diagnose(loc, diag::invalid_sil_builtin, "castToNativeObject source must be a class"); SILValue undef = SILUndef::get(objPointerType, gen.SGM.M); return ManagedValue::forUnmanaged(undef); } // Save the cleanup on the argument so we can forward it onto the cast // result. auto cleanup = args[0].getCleanup(); SILValue arg = args[0].getValue(); // If the argument is existential, open it. if (substitutions[0].getReplacement()->isClassExistentialType()) { auto openedTy = ArchetypeType::getOpened(substitutions[0].getReplacement()); SILType loweredOpenedTy = gen.getLoweredLoadableType(openedTy); arg = gen.B.createOpenExistentialRef(loc, arg, loweredOpenedTy); gen.setArchetypeOpeningSite(openedTy, arg); } SILValue result = gen.B.createUncheckedRefCast(loc, arg, objPointerType); // Return the cast result with the original cleanup. return ManagedValue(result, cleanup); }
/// Specialized emitter for Builtin.load and Builtin.take. static ManagedValue emitBuiltinLoadOrTake(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C, IsTake_t isTake, bool isStrict) { assert(substitutions.size() == 1 && "load should have single substitution"); assert(args.size() == 1 && "load should have a single argument"); // The substitution gives the type of the load. This is always a // first-class type; there is no way to e.g. produce a @weak load // with this builtin. auto &rvalueTL = gen.getTypeLowering(substitutions[0].getReplacement()); SILType loadedType = rvalueTL.getLoweredType(); // Convert the pointer argument to a SIL address. SILValue addr = gen.B.createPointerToAddress(loc, args[0].getUnmanagedValue(), loadedType.getAddressType(), isStrict); // Perform the load. return gen.emitLoad(loc, addr, rvalueTL, C, isTake); }
ManagedValue SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant, CanType expectedType, SubstitutionList subs) { auto closure = *constant.getAnyFunctionRef(); auto captureInfo = closure.getCaptureInfo(); auto loweredCaptureInfo = SGM.Types.getLoweredLocalCaptures(closure); auto hasCaptures = SGM.Types.hasLoweredLocalCaptures(closure); assert(((constant.uncurryLevel == 1 && hasCaptures) || (constant.uncurryLevel == 0 && !hasCaptures)) && "curried local functions not yet supported"); auto constantInfo = getConstantInfo(constant); SILValue functionRef = emitGlobalFunctionRef(loc, constant, constantInfo); SILType functionTy = functionRef->getType(); // Apply substitutions. auto pft = constantInfo.SILFnType; auto *dc = closure.getAsDeclContext()->getParent(); if (dc->isLocalContext() && !loweredCaptureInfo.hasGenericParamCaptures()) { // If the lowered function type is not polymorphic but we were given // substitutions, we have a closure in a generic context which does not // capture generic parameters. Just drop the substitutions. subs = { }; } else if (closure.getAbstractClosureExpr()) { // If we have a closure expression in generic context, Sema won't give // us substitutions, so we just use the forwarding substitutions from // context. subs = getForwardingSubstitutions(); } bool wasSpecialized = false; if (!subs.empty()) { auto specialized = pft->substGenericArgs(F.getModule(), subs); functionTy = SILType::getPrimitiveObjectType(specialized); wasSpecialized = true; } // If we're in top-level code, we don't need to physically capture script // globals, but we still need to mark them as escaping so that DI can flag // uninitialized uses. if (this == SGM.TopLevelSGF) { SGM.emitMarkFunctionEscapeForTopLevelCodeGlobals( loc, captureInfo); } if (!hasCaptures && !wasSpecialized) { auto result = ManagedValue::forUnmanaged(functionRef); return emitOrigToSubstValue(loc, result, AbstractionPattern(expectedType), expectedType); } SmallVector<ManagedValue, 4> capturedArgs; emitCaptures(loc, closure, CaptureEmission::PartialApplication, capturedArgs); // The partial application takes ownership of the context parameters. SmallVector<SILValue, 4> forwardedArgs; for (auto capture : capturedArgs) forwardedArgs.push_back(capture.forward(*this)); SILType closureTy = SILGenBuilder::getPartialApplyResultType(functionRef->getType(), capturedArgs.size(), SGM.M, subs, ParameterConvention::Direct_Owned); auto toClosure = B.createPartialApply(loc, functionRef, functionTy, subs, forwardedArgs, closureTy); auto result = emitManagedRValueWithCleanup(toClosure); // Get the lowered AST types: // - the original type auto origLoweredFormalType = AbstractionPattern(constantInfo.LoweredInterfaceType); if (hasCaptures) { // Get the unlowered formal type of the constant, stripping off // the first level of function application, which applies captures. origLoweredFormalType = AbstractionPattern(constantInfo.FormalInterfaceType) .getFunctionResultType(); // Lower it, being careful to use the right generic signature. origLoweredFormalType = AbstractionPattern( origLoweredFormalType.getGenericSignature(), SGM.Types.getLoweredASTFunctionType( cast<FunctionType>(origLoweredFormalType.getType()), 0, constant)); } // - the substituted type auto substFormalType = cast<FunctionType>(expectedType); auto substLoweredFormalType = SGM.Types.getLoweredASTFunctionType(substFormalType, 0, constant); // Generalize if necessary. result = emitOrigToSubstValue(loc, result, origLoweredFormalType, substLoweredFormalType); return result; }