//===--- SILCloner.h - Defines the SILCloner class --------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines the SILCloner class, used for cloning SIL instructions. // //===----------------------------------------------------------------------===// #ifndef SWIFT_SIL_SILCLONER_H #define SWIFT_SIL_SILCLONER_H #include "swift/AST/ConformanceLookup.h" #include "swift/AST/GenericEnvironment.h" #include "swift/AST/LocalArchetypeRequirementCollector.h" #include "swift/AST/ProtocolConformance.h" #include "swift/SIL/BasicBlockUtils.h" #include "swift/SIL/DebugUtils.h" #include "swift/SIL/Dominance.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILDebugScope.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILVisitor.h" namespace swift { struct SubstitutionMapWithLocalArchetypes { std::optional SubsMap; llvm::DenseMap LocalArchetypeSubs; GenericSignature BaseGenericSig; llvm::ArrayRef CapturedEnvs; bool hasLocalArchetypes() const { return !LocalArchetypeSubs.empty() || !CapturedEnvs.empty(); } SubstitutionMapWithLocalArchetypes() {} SubstitutionMapWithLocalArchetypes(SubstitutionMap subs) : SubsMap(subs) {} Type operator()(SubstitutableType *type) { if (auto *local = dyn_cast(type)) { auto *origEnv = local->getGenericEnvironment(); // Special handling of captured environments, which don't appear in // LocalArchetypeSubs. This only happens with the LocalArchetypeTransform // in SILGenLocalArchetype.cpp. auto found = LocalArchetypeSubs.find(origEnv); if (found == LocalArchetypeSubs.end()) { if (std::find(CapturedEnvs.begin(), CapturedEnvs.end(), origEnv) == CapturedEnvs.end()) { return Type(); } // Map the local archetype to an interface type in the new generic // signature. auto interfaceTy = mapLocalArchetypesOutOfContext( local, BaseGenericSig, CapturedEnvs); // Map this interface type into the new generic environment to get // a primary archetype. return interfaceTy.subst(*SubsMap); } auto *newEnv = found->second; auto interfaceTy = local->getInterfaceType(); return newEnv->mapTypeIntoContext(interfaceTy); } if (SubsMap) return Type(type).subst(*SubsMap); return Type(type); } ProtocolConformanceRef operator()(InFlightSubstitution &IFS, Type origType, ProtocolDecl *proto) { if (origType->is()) return swift::lookupConformance(origType.subst(IFS), proto); if (SubsMap) { if (origType->is() || origType->is()) { origType = origType->mapTypeOutOfContext(); } return SubsMap->lookupConformance( origType->getCanonicalType(), proto); } return ProtocolConformanceRef::forAbstract( origType.subst(IFS), proto); } void dump(llvm::raw_ostream &out) const { if (SubsMap) SubsMap->dump(out); for (auto pair : LocalArchetypeSubs) { out << "---\n"; pair.first->dump(out); pair.second->dump(out); } } }; /// SILCloner - Abstract SIL visitor which knows how to clone instructions and /// whose behavior can be customized by subclasses via the CRTP. This is meant /// to be subclassed to implement inlining, function specialization, and other /// operations requiring cloning (while possibly modifying, at the same time) /// instruction sequences. /// /// By default, this visitor will not do anything useful when called on a /// basic block, or function; subclasses that want to handle those should /// implement the appropriate visit functions and/or provide other entry points. template class SILCloner : protected SILInstructionVisitor { friend class SILVisitorBase; friend class SILInstructionVisitor; protected: /// MARK: Context shared with CRTP extensions. SILBuilder Builder; DominanceInfo *DomTree = nullptr; SubstitutionMapWithLocalArchetypes Functor; // The old-to-new value map. llvm::DenseMap ValueMap; /// The old-to-new block map. Some entries may be premapped with original /// blocks. llvm::DenseMap BBMap; /// Blocks, where edge-spitting may have "converted" terminator result /// arguments to phi-arguments. llvm::SmallVector blocksWithNewPhiArgs; private: /// MARK: Private state hidden from CRTP extensions. // The original blocks in DFS preorder. All blocks in this list are mapped. // After cloning, this represents the entire cloned CFG. // // This could always be rediscovered by the client, but caching it is a // convenient way to iterate over the cloned region. SmallVector preorderBlocks; // Keep track of the last cloned block in function order. For single block // regions, this will be the start block. SILBasicBlock *lastClonedBB = nullptr; public: using SILInstructionVisitor::asImpl; explicit SILCloner(SILFunction &F, DominanceInfo *DT = nullptr) : Builder(F), DomTree(DT) {} explicit SILCloner(SILGlobalVariable *GlobVar) : Builder(GlobVar) {} void clearClonerState() { ValueMap.clear(); BBMap.clear(); preorderBlocks.clear(); } /// Clients of SILCloner who want to know about any newly created /// instructions can install a SmallVector into the builder to collect them. void setTrackingList(SmallVectorImpl *II) { getBuilder().setTrackingList(II); } SmallVectorImpl *getTrackingList() { return getBuilder().getTrackingList(); } SILBuilder &getBuilder() { return Builder; } // After cloning, returns a non-null pointer to the last cloned block in // function order. For single block regions, this will be the start block. SILBasicBlock *getLastClonedBB() { return lastClonedBB; } /// Visit all blocks reachable from the given `StartBB` and all instructions /// in those blocks. /// /// This is used to clone a region within a function and mutates the original /// function. `StartBB` cannot be the function entry block. /// /// The entire CFG is discovered in DFS preorder while cloning non-terminator /// instructions. `visitTerminator` is called in the same order, but only /// after mapping all blocks. void cloneReachableBlocks(SILBasicBlock *startBB, ArrayRef exitBlocks, SILBasicBlock *insertAfterBB = nullptr, bool havePrepopulatedFunctionArgs = false); /// Clone all blocks in this function and all instructions in those /// blocks. /// /// This is used to clone an entire function and should not mutate the /// original function except if \p replaceOriginalFunctionInPlace is true. /// /// entryArgs must have a SILValue from the cloned function corresponding to /// each argument in the original function `F`. /// /// Cloned instructions are inserted starting at the end of clonedEntryBB. void cloneFunctionBody(SILFunction *F, SILBasicBlock *clonedEntryBB, ArrayRef entryArgs, bool replaceOriginalFunctionInPlace = false); /// Clone all blocks in this function and all instructions in those /// blocks. /// /// This is used to clone an entire function without mutating the original /// function. /// /// The new function is expected to be completely empty. Clone the entry /// blocks arguments here. The cloned arguments become the inputs to the /// general SILCloner, which expects the new entry block to be ready to emit /// instructions into. void cloneFunction(SILFunction *origF); /// The same as clone function body, except the caller can provide a callback /// that allows for an entry arg to be assigned to a custom old argument. This /// is useful if one re-arranges parameters when converting from inout to out. void cloneFunctionBody(SILFunction *F, SILBasicBlock *clonedEntryBB, ArrayRef entryArgs, llvm::function_ref entryArgToOldArgMap); /// MARK: Callback utilities used from CRTP extensions during cloning. /// These should only be called from within an instruction cloning visitor. /// Visitor callback that registers a cloned instruction. All the original /// instruction's results are mapped onto the cloned instruction's results for /// use within the cloned region. /// /// CRTP extensions can /// override the implementation via `postProcess`. void recordClonedInstruction(SILInstruction *Orig, SILInstruction *Cloned) { asImpl().postProcess(Orig, Cloned); assert((!Orig->getDebugScope() || Cloned->getDebugScope() || Builder.isInsertingIntoGlobal()) && "cloned instruction dropped debug scope"); } /// Visitor callback that maps an original value to an existing value when the /// original instruction will not be cloned. This is used when the instruction /// visitor can fold away the cloned instruction, and it skips the usual /// `postProcess()` callback. recordClonedInstruction() and /// recordFoldedValue() are the only two ways for a visitor to map an original /// value to another value for use within the cloned region. void recordFoldedValue(SILValue origValue, SILValue mappedValue) { asImpl().mapValue(origValue, mappedValue); } /// Register a re-mapping for local archetypes such as opened existentials. void registerLocalArchetypeRemapping(GenericEnvironment *From, GenericEnvironment *To) { ASSERT(From->getGenericSignature().getPointer() == To->getGenericSignature().getPointer()); auto result = Functor.LocalArchetypeSubs.insert(std::make_pair(From, To)); assert(result.second); (void)result; } /// MARK: Public access to the cloned state, during and after cloning. /// After cloning, provides a list of all cloned blocks in DFS preorder. ArrayRef originalPreorderBlocks() const { return preorderBlocks; } SILLocation getOpLocation(SILLocation Loc) { return asImpl().remapLocation(Loc); } const SILDebugScope *getOpScope(const SILDebugScope *DS) { return asImpl().remapScope(DS); } SubstitutionMap getOpSubstitutionMap(SubstitutionMap Subs) { auto substSubs = asImpl().remapSubstitutionMap(Subs) .getCanonical(/*canonicalizeSignature*/false); #ifndef NDEBUG for (auto substConf : substSubs.getConformances()) { if (substConf.isInvalid()) { llvm::errs() << "Invalid conformance in SIL cloner:\n"; Functor.dump(llvm::errs()); llvm::errs() << "\nsubstitution map:\n"; Subs.dump(llvm::errs()); llvm::errs() << "\n"; llvm::errs() << "\ncomposed substitution map:\n"; substSubs.dump(llvm::errs()); llvm::errs() << "\n"; abort(); } } #endif return substSubs; } SILType getOpType(SILType Ty) { return asImpl().remapType(Ty); } CanType getOpASTType(CanType ty) { return asImpl().remapASTType(ty); } /// Remap a structural index into a pack so that it will point to the /// corresponding structural index in the remapped pack type. unsigned getOpStructuralPackIndex(CanPackType origPackType, unsigned origIndex) { assert(origIndex < origPackType->getNumElements()); unsigned newIndex = 0; for (unsigned i = 0; i != origIndex; ++i) { auto origComponentType = origPackType.getElementType(i); if (auto origExpansionType = dyn_cast(origComponentType)) { auto newShapeClass = getOpASTType(origExpansionType.getCountType()); if (auto newShapePack = dyn_cast(newShapeClass)) newIndex += newShapePack->getNumElements(); else newIndex++; } else { newIndex++; } } return newIndex; } /// Does type substitution make the given tuple type no longer a tuple? bool doesOpTupleDisappear(CanTupleType type) { // Fast-path the empty tuple. if (type->getNumElements() == 0) return false; // Do a first pass over the tuple elements to check out the // non-expansions. If there's more than one of them we definitely // stay a tuple and don't need to substitute any of the expansions. unsigned numScalarElements = type->getNumScalarElements(); if (numScalarElements > 1) return false; // Okay, we need to substitute the count types for the expansions. for (auto index : indices(type->getElements())) { // Ignore non-expansions because we've already counted them. auto expansion = dyn_cast(type.getElementType(index)); if (!expansion) { // If we have a non-expansion with a label, we stay a tuple. if (type->getElement(index).hasName()) return false; continue; } // Substitute the shape class of the expansion. If this doesn't // give us a pack (e.g. if this isn't a substituting clone), // we're never erasing tuple structure. auto newShapeClass = getOpASTType(expansion.getCountType()); auto newShapePack = dyn_cast(newShapeClass); if (!newShapePack) return false; // If the element has a name, then the tuple sticks around unless // the expansion disappears completely. if (type->getElement(index).hasName()) { if (newShapePack->getNumElements() == 0) continue; return false; } // Otherwise, walk the substituted shape components. for (auto newShapeElement : newShapePack.getElementTypes()) { // If there's an expansion in the shape, we'll have an expansion // in the tuple elements, which forces the tuple structure to remain. if (isa(newShapeElement)) return false; // Otherwise, add another scalar element. if (++numScalarElements > 1) return false; } } // All of the packs expanded to scalars. We should've short-circuited // if we ever saw a second or labeled scalar, so all we need to test // is whether we have exactly one scalar. assert(numScalarElements <= 1); return numScalarElements == 1; } void remapRootOpenedType(CanExistentialArchetypeType archetypeTy) { auto *origEnv = archetypeTy->getGenericEnvironment(); auto genericSig = origEnv->getGenericSignature(); auto existentialTy = origEnv->getOpenedExistentialType(); auto subMap = origEnv->getOuterSubstitutions(); auto *newEnv = GenericEnvironment::forOpenedExistential( genericSig, existentialTy, getOpSubstitutionMap(subMap), UUID::fromTime()); registerLocalArchetypeRemapping(origEnv, newEnv); } /// SILCloner will take care of debug scope on the instruction /// and this helper will remap the auxiliary debug scope too, if there is any. void remapDebugVariable(std::optional &VarInfo) { if (!VarInfo) return; if (VarInfo->Type) VarInfo->Type = getOpType(*VarInfo->Type); // Don't remap locations for debug values. if (VarInfo->Scope) VarInfo->Scope = getOpScope(VarInfo->Scope); } ProtocolConformanceRef getOpConformance(ProtocolConformanceRef conformance) { return asImpl().remapConformance(conformance); } ArrayRef getOpConformances(ArrayRef conformances) { SmallVector newConformances; for (auto conformance : conformances) newConformances.push_back(getOpConformance(conformance)); return getBuilder().getASTContext().AllocateCopy(newConformances); } bool isValueCloned(SILValue OrigValue) const { return ValueMap.count(OrigValue); } /// Return the possibly new value representing the given value within the /// cloned region. /// /// Assumes that `isValueCloned` is true. SILValue getOpValue(SILValue Value) { return asImpl().getMappedValue(Value); } template SmallVector getOpValueArray(ArrayRefType Values) { SmallVector Ret(Values.size()); for (unsigned i = 0, e = Values.size(); i != e; ++i) Ret[i] = asImpl().getMappedValue(Values[i]); return Ret; } SILFunction *getOpFunction(SILFunction *Func) { return asImpl().remapFunction(Func); } bool isBlockCloned(SILBasicBlock *OrigBB) const { auto bbIter = BBMap.find(OrigBB); if (bbIter == BBMap.end()) return false; // Exit blocks are mapped to themselves during region cloning. return bbIter->second != OrigBB; } /// Return the new block within the cloned region analagous to the given /// original block. /// /// Assumes that `isBlockCloned` is true. SILBasicBlock *getOpBasicBlock(SILBasicBlock *BB) { return asImpl().remapBasicBlock(BB); } protected: /// MARK: CRTP visitors and other CRTP overrides. #define INST(CLASS, PARENT) void visit##CLASS(CLASS *I); #include "swift/SIL/SILNodes.def" // Visit the instructions in a single basic block, not including the block // terminator. void visitInstructionsInBlock(SILBasicBlock *BB); // Visit a block's terminator. This is called with each block in DFS preorder // after visiting and mapping all basic blocks and after visiting all // non-terminator instructions in the block. void visitTerminator(SILBasicBlock *BB) { asImpl().visit(BB->getTerminator()); } // CFG cloning requires cloneFunction() or cloneReachableBlocks(). void visitSILBasicBlock(SILFunction *F) = delete; // Function cloning requires cloneFunction(). void visitSILFunction(SILFunction *F) = delete; // MARK: SILCloner subclasses use the CRTP to customize the following callback // implementations. Remap functions are called before cloning to modify // constructor arguments. The postProcess function is called afterwards on // the result. SILLocation remapLocation(SILLocation Loc) { return Loc; } const SILDebugScope *remapScope(const SILDebugScope *DS) { return DS; } bool shouldSubstOpaqueArchetypes() const { return false; } SILType remapType(SILType Ty) { if (Functor.SubsMap || Ty.hasLocalArchetype()) { SubstOptions options = SubstFlags::SubstitutePrimaryArchetypes; if (Functor.hasLocalArchetypes()) options |= SubstFlags::SubstituteLocalArchetypes; Ty = Ty.subst(Builder.getModule(), Functor, Functor, CanGenericSignature(), options); } if (asImpl().shouldSubstOpaqueArchetypes()) { auto context = getBuilder().getTypeExpansionContext(); if (!Ty.hasOpaqueArchetype() || !context.shouldLookThroughOpaqueTypeArchetypes()) return Ty; // Remap types containing opaque result types in the current context. Ty = getBuilder().getTypeLowering(Ty).getLoweredType().getCategoryType( Ty.getCategory()); } return Ty; } CanType remapASTType(CanType ty) { if (Functor.SubsMap || ty->hasLocalArchetype()) { SubstOptions options = SubstFlags::SubstitutePrimaryArchetypes; if (Functor.hasLocalArchetypes()) options |= SubstFlags::SubstituteLocalArchetypes; ty = ty.subst(Functor, Functor, options)->getCanonicalType(); } if (asImpl().shouldSubstOpaqueArchetypes()) { auto context = getBuilder().getTypeExpansionContext(); if (!ty->hasOpaqueArchetype() || !context.shouldLookThroughOpaqueTypeArchetypes()) return ty; // Remap types containing opaque result types in the current context. return substOpaqueTypesWithUnderlyingTypes(ty, context); } return ty; } ProtocolConformanceRef remapConformance(ProtocolConformanceRef conformance) { auto substConf = conformance; if (Functor.SubsMap || substConf.getType()->hasLocalArchetype()) { SubstOptions options = SubstFlags::SubstitutePrimaryArchetypes; if (Functor.hasLocalArchetypes()) options |= SubstFlags::SubstituteLocalArchetypes; substConf = substConf.subst(Functor, Functor, options); } if (substConf.isInvalid()) { ABORT([&](auto &out) { out << "Invalid substituted conformance in SIL cloner:\n"; Functor.dump(out); out << "\noriginal conformance:\n"; conformance.dump(out); }); } if (asImpl().shouldSubstOpaqueArchetypes()) { auto context = getBuilder().getTypeExpansionContext(); if (substConf.getType()->hasOpaqueArchetype() && context.shouldLookThroughOpaqueTypeArchetypes()) { return substOpaqueTypesWithUnderlyingTypes(substConf, context); } } return substConf; } SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) { // If we have local archetypes to substitute, do so now. if (Functor.SubsMap || Subs.getRecursiveProperties().hasLocalArchetype()) { SubstOptions options = SubstFlags::SubstitutePrimaryArchetypes; if (Functor.hasLocalArchetypes()) options |= SubstFlags::SubstituteLocalArchetypes; Subs = Subs.subst(Functor, Functor, options); } if (asImpl().shouldSubstOpaqueArchetypes()) { auto context = getBuilder().getTypeExpansionContext(); if (!Subs.getRecursiveProperties().hasOpaqueArchetype() || !context.shouldLookThroughOpaqueTypeArchetypes()) return Subs; return substOpaqueTypesWithUnderlyingTypes(Subs, context); } return Subs; } /// Get the value that takes the place of the given `Value` within the cloned /// region. The given value must already have been mapped by this cloner. SILValue getMappedValue(SILValue Value); void mapValue(SILValue origValue, SILValue mappedValue); SILFunction *remapFunction(SILFunction *Func) { return Func; } SILBasicBlock *remapBasicBlock(SILBasicBlock *BB); void postProcess(SILInstruction *Orig, SILInstruction *Cloned); /// This is called by either of the top-level visitors, cloneReachableBlocks /// or cloneSILFunction, after all other visitors are have been called. /// `preFixUp` is called first. void preFixUp(SILFunction *F) {} /// After postFixUp, the SIL must be valid and semantically equivalent to the /// SIL before cloning. /// /// Common fix-ups are handled first in `commonFixUp` and may not be /// overridden. void postFixUp(SILFunction *F) {} private: /// MARK: SILCloner implementation details hidden from CRTP extensions. void clonePhiArgs(SILBasicBlock *oldBB); void visitBlocksDepthFirst(SILBasicBlock *StartBB); /// Also perform fundamental cleanup first, then call the CRTP extension, /// `postFixUp`. void commonFixUp(SILFunction *F); }; /// A SILBuilder that automatically invokes postprocess on each /// inserted instruction. template class SILBuilderWithPostProcess : public SILBuilder { SomeSILCloner &SC; SILInstruction *Orig; SmallVector InsertedInstrs; public: SILBuilderWithPostProcess(SomeSILCloner *sc, SILInstruction *Orig) : SILBuilder(sc->getBuilder().getInsertionBB(), &InsertedInstrs), SC(*sc), Orig(Orig) { setInsertionPoint(SC.getBuilder().getInsertionBB(), SC.getBuilder().getInsertionPoint()); } ~SILBuilderWithPostProcess() { for (auto *I : InsertedInstrs) { SC.recordClonedInstruction(Orig, I); } } }; /// SILClonerWithScopes - a SILCloner that automatically clones /// SILDebugScopes. In contrast to inline scopes, this generates a /// deep copy of the scope tree. template class SILClonerWithScopes : public SILCloner { friend class SILCloner; public: SILClonerWithScopes(SILFunction &To, DominanceInfo *DT = nullptr, bool Disable = false) : SILCloner(To, DT) { // We only want to do this when we generate cloned functions, not // when we inline. // FIXME: This is due to having TypeSubstCloner inherit from // SILClonerWithScopes, and having TypeSubstCloner be used // both by passes that clone whole functions and ones that // inline functions. if (Disable) return; scopeCloner.reset(new ScopeCloner(To)); } private: std::unique_ptr scopeCloner; protected: /// Clone the SILDebugScope for the cloned function. void postProcess(SILInstruction *Orig, SILInstruction *Cloned) { SILCloner::postProcess(Orig, Cloned); } const SILDebugScope *remapScope(const SILDebugScope *DS) { return scopeCloner ? scopeCloner->getOrCreateClonedScope(DS) : DS; } }; /// Clone a function without transforming it. class SILFunctionCloner : public SILClonerWithScopes { using SuperTy = SILClonerWithScopes; friend class SILCloner; public: SILFunctionCloner(SILFunction *newF) : SILClonerWithScopes(*newF) {} }; template SILValue SILCloner::getMappedValue(SILValue Value) { auto VI = ValueMap.find(Value); if (VI != ValueMap.end()) return VI->second; // If we have undef, just remap the type. if (auto *U = dyn_cast(Value)) { auto type = getOpType(U->getType()); return SILUndef::get(Builder.getFunction(), type); } llvm_unreachable("Unmapped value while cloning?"); } template void SILCloner::mapValue(SILValue origValue, SILValue mappedValue) { auto iterAndInserted = ValueMap.insert({origValue, mappedValue}); (void)iterAndInserted; assert(iterAndInserted.second && "Original value already mapped."); } template SILBasicBlock* SILCloner::remapBasicBlock(SILBasicBlock *BB) { SILBasicBlock *MappedBB = BBMap[BB]; assert(MappedBB && "Unmapped basic block while cloning?"); return MappedBB; } template void SILCloner::postProcess(SILInstruction *orig, SILInstruction *cloned) { assert((!orig->getDebugScope() || cloned->getDebugScope() || Builder.isInsertingIntoGlobal()) && "cloned function dropped debug scope"); // It sometimes happens that an instruction with no results gets mapped // to an instruction with results, e.g. when specializing a cast. // Just ignore this. auto origResults = orig->getResults(); if (origResults.empty()) return; // Otherwise, map the results over one-by-one. auto clonedResults = cloned->getResults(); assert(origResults.size() == clonedResults.size()); for (auto i : indices(origResults)) asImpl().mapValue(origResults[i], clonedResults[i]); } template void SILCloner::visitInstructionsInBlock(SILBasicBlock* BB) { // Iterate over and visit all instructions other than the terminator to clone. for (auto I = BB->begin(), E = --BB->end(); I != E; ++I) { asImpl().visit(&*I); } } template void SILCloner::cloneReachableBlocks( SILBasicBlock *startBB, ArrayRef exitBlocks, SILBasicBlock *insertAfterBB, bool havePrepopulatedFunctionArgs) { SILFunction *F = startBB->getParent(); assert(F == &Builder.getFunction() && "cannot clone region across functions."); assert(BBMap.empty() && "This API does not allow clients to map blocks."); assert((havePrepopulatedFunctionArgs || ValueMap.empty()) && "Stale ValueMap."); auto *clonedStartBB = insertAfterBB ? F->createBasicBlockAfter(insertAfterBB) : F->createBasicBlock(); BBMap.insert(std::make_pair(startBB, clonedStartBB)); getBuilder().setInsertionPoint(clonedStartBB); clonePhiArgs(startBB); // Premap exit blocks to terminate so that visitBlocksDepthFirst terminates // after discovering the cloned region. Mapping an exit block to itself // provides the correct destination block during visitTerminator. for (auto *exitBB : exitBlocks) BBMap[exitBB] = exitBB; // Discover and map the region to be cloned. visitBlocksDepthFirst(startBB); commonFixUp(F); } template void SILCloner::cloneFunctionBody(SILFunction *F, SILBasicBlock *clonedEntryBB, ArrayRef entryArgs, bool replaceOriginalFunctionInPlace) { assert((replaceOriginalFunctionInPlace || F != clonedEntryBB->getParent()) && "Must clone into a new function."); assert(BBMap.empty() && "This API does not allow clients to map blocks."); assert(ValueMap.empty() && "Stale ValueMap."); assert(entryArgs.size() == F->getArguments().size()); for (unsigned i = 0, e = entryArgs.size(); i != e; ++i) ValueMap[F->getArgument(i)] = entryArgs[i]; BBMap.insert(std::make_pair(&*F->begin(), clonedEntryBB)); Builder.setInsertionPoint(clonedEntryBB); // This will layout all newly cloned blocks immediate after clonedEntryBB. visitBlocksDepthFirst(&*F->begin()); commonFixUp(F); } template void SILCloner::cloneFunction(SILFunction *origF) { SILFunction *newF = &Builder.getFunction(); auto *newEntryBB = newF->createBasicBlock(); newEntryBB->cloneArgumentList(origF->getEntryBlock()); // Copy the new entry block arguments into a separate vector purely to // resolve the type mismatch between SILArgument* and SILValue. SmallVector entryArgs; entryArgs.reserve(newF->getArguments().size()); llvm::transform(newF->getArguments(), std::back_inserter(entryArgs), [](SILArgument *arg) -> SILValue { return arg; }); cloneFunctionBody(origF, newEntryBB, entryArgs); } template void SILCloner::cloneFunctionBody( SILFunction *F, SILBasicBlock *clonedEntryBB, ArrayRef entryArgs, llvm::function_ref entryArgIndexToOldArgIndex) { assert(F != clonedEntryBB->getParent() && "Must clone into a new function."); assert(BBMap.empty() && "This API does not allow clients to map blocks."); assert(ValueMap.empty() && "Stale ValueMap."); assert(entryArgs.size() == F->getArguments().size()); for (unsigned i = 0, e = entryArgs.size(); i != e; ++i) { ValueMap[entryArgIndexToOldArgIndex(entryArgs[i])] = entryArgs[i]; } BBMap.insert(std::make_pair(&*F->begin(), clonedEntryBB)); Builder.setInsertionPoint(clonedEntryBB); // This will layout all newly cloned blocks immediate after clonedEntryBB. visitBlocksDepthFirst(&*F->begin()); commonFixUp(F); } template void SILCloner::clonePhiArgs(SILBasicBlock *oldBB) { auto *mappedBB = BBMap[oldBB]; // Create new arguments for each of the original block's arguments. for (auto *Arg : oldBB->getSILPhiArguments()) { SILValue mappedArg = mappedBB->createPhiArgument( getOpType(Arg->getType()), Arg->getOwnershipKind(), Arg->getDecl(), Arg->isReborrow(), Arg->hasPointerEscape()); asImpl().mapValue(Arg, mappedArg); } } // This private helper visits BBs in depth-first preorder (only processing // blocks on the first visit), mapping newly visited BBs to new BBs and cloning // all instructions into the caller. template void SILCloner::visitBlocksDepthFirst(SILBasicBlock *startBB) { // The caller clones startBB because it may be a function header, which // requires special handling. assert(BBMap.count(startBB) && "The caller must map the first BB."); assert(preorderBlocks.empty()); // First clone the CFG region. // // FIXME: Add reverse iteration to SILSuccessor, then convert this to an RPOT // traversal. We would prefer to keep CFG regions in RPO order, and this would // not create as large a worklist for functions with many large switches. SmallVector dfsWorklist(1, startBB); // Keep a reference to the last cloned BB so blocks can be laid out in the // order they are created, which differs from the order they are // cloned. Blocks are created in BFS order but cloned in DFS preorder (when no // critical edges are present). lastClonedBB = BBMap[startBB]; while (!dfsWorklist.empty()) { auto *BB = dfsWorklist.pop_back_val(); preorderBlocks.push_back(BB); // Phis are cloned during the first preorder walk so that successor phis // exist before predecessor terminators are generated. if (BB != startBB) clonePhiArgs(BB); // Non-terminating instructions are cloned in the first preorder walk. getBuilder().setInsertionPoint(BBMap[BB]); asImpl().visitInstructionsInBlock(BB); unsigned dfsSuccStartIdx = dfsWorklist.size(); // splitEdge may rewrite BB's successors during this loop. for (unsigned succIdx = 0, numSucc = BB->getSuccessors().size(); succIdx != numSucc; ++succIdx) { // Only visit a successor that has not already been visited and was not // premapped by the client. if (BBMap.count(BB->getSuccessors()[succIdx])) { // After cloning BB, this successor may be a new CFG merge. If it is // valid to branch directly from the BB to its clone do nothing; if not, // split the edge from BB->succ and clone the new block. // // A CFG merge may require new block arguments, so check for both a // critical edge and the ability to add branch arguments (BranchInst). if (BB->getSingleSuccessorBlock() && isa(BB->getTerminator())) { continue; } TermInst *term = BB->getTerminator(); // After edge-spitting, terminator result arguments become phi arguments. if (!isa(term)) blocksWithNewPhiArgs.push_back(BB->getSuccessors()[succIdx]); // This predecessor has multiple successors, so cloning it without // cloning its successors would create a critical edge. splitEdge(term, succIdx, DomTree); assert(!BBMap.count(BB->getSuccessors()[succIdx])); } // Map the successor to a new BB. Layout the cloned blocks in the order // they are visited and cloned. lastClonedBB = getBuilder().getFunction().createBasicBlockAfter(lastClonedBB); // After splitting, BB has stable successors. auto &succ = BB->getSuccessors()[succIdx]; BBMap.insert(std::make_pair(succ.getBB(), lastClonedBB)); dfsWorklist.push_back(succ); } // Reverse the worklist to pop the successors in forward order. This // precisely yields DFS preorder when no critical edges are present. std::reverse(dfsWorklist.begin() + dfsSuccStartIdx, dfsWorklist.end()); } // Visit terminators only after the CFG is valid so all branch targets exist. // // Visiting in pre-order provides a nice property for the individual // instruction visitors. It allows those visitors to make use of dominance // relationships, particularly the fact that operand values will be mapped. for (auto *origBB : preorderBlocks) { // Set the insertion point to the new mapped BB getBuilder().setInsertionPoint(BBMap[origBB]); asImpl().visitTerminator(origBB); } } /// Clean-up after cloning. template void SILCloner::commonFixUp(SILFunction *F) { // Call any cleanup specific to the CRTP extensions. asImpl().preFixUp(F); // If our source function is in ossa form, but the function into which we are // cloning is not in ossa, after we clone, eliminate default arguments. if (!getBuilder().hasOwnership() && F->hasOwnership()) { for (auto &Block : getBuilder().getFunction()) { auto *Term = Block.getTerminator(); if (auto *CCBI = dyn_cast(Term)) { // Check if we have a default argument. auto *FailureBlock = CCBI->getFailureBB(); assert(FailureBlock->getNumArguments() <= 1 && "We should either have no args or a single default arg"); if (0 == FailureBlock->getNumArguments()) continue; FailureBlock->getArgument(0)->replaceAllUsesWith(CCBI->getOperand()); FailureBlock->eraseArgument(0); continue; } if (auto *SEI = dyn_cast(Term)) { if (auto DefaultBlock = SEI->getDefaultBBOrNull()) { assert(DefaultBlock.get()->getNumArguments() <= 1 && "We should either have no args or a single default arg"); if (0 == DefaultBlock.get()->getNumArguments()) continue; DefaultBlock.get()->getArgument(0)->replaceAllUsesWith( SEI->getOperand()); DefaultBlock.get()->eraseArgument(0); continue; } } } } // Call any cleanup specific to the CRTP extensions. asImpl().postFixUp(F); } template void SILCloner::visitAllocStackInst(AllocStackInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); // Drop the debug info from mandatory-inlined instructions. It's the law! SILLocation Loc = getOpLocation(Inst->getLoc()); std::optional VarInfo = Inst->getVarInfo(); if (Loc.getKind() == SILLocation::MandatoryInlinedKind) { Loc = MandatoryInlinedLocation::getAutoGeneratedLocation(); VarInfo = std::nullopt; } remapDebugVariable(VarInfo); auto *NewInst = getBuilder().createAllocStack( Loc, getOpType(Inst->getElementType()), VarInfo, Inst->hasDynamicLifetime(), Inst->isLexical(), Inst->isFromVarDecl(), Inst->usesMoveableValueDebugInfo() #ifndef NDEBUG , true #endif ); recordClonedInstruction(Inst, NewInst); } template void SILCloner::visitAllocPackMetadataInst( AllocPackMetadataInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createAllocPackMetadata( getOpLocation(Inst->getLoc()))); } template void SILCloner::visitAllocPackInst(AllocPackInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); SILLocation Loc = getOpLocation(Inst->getLoc()); auto *NewInst = getBuilder().createAllocPack( Loc, getOpType(Inst->getType().getObjectType())); recordClonedInstruction(Inst, NewInst); } template void SILCloner::visitAllocRefInst(AllocRefInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto CountArgs = getOpValueArray<8>(OperandValueArrayRef(Inst-> getTailAllocatedCounts())); SmallVector ElemTypes; for (SILType OrigElemType : Inst->getTailAllocatedTypes()) { ElemTypes.push_back(getOpType(OrigElemType)); } auto *NewInst = getBuilder().createAllocRef(getOpLocation(Inst->getLoc()), getOpType(Inst->getType()), Inst->isObjC(), Inst->canAllocOnStack(), Inst->isBare(), ElemTypes, CountArgs); recordClonedInstruction(Inst, NewInst); } template void SILCloner::visitAllocRefDynamicInst(AllocRefDynamicInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto CountArgs = getOpValueArray<8>(OperandValueArrayRef(Inst-> getTailAllocatedCounts())); SmallVector ElemTypes; for (SILType OrigElemType : Inst->getTailAllocatedTypes()) { ElemTypes.push_back(getOpType(OrigElemType)); } auto *NewInst = getBuilder().createAllocRefDynamic( getOpLocation(Inst->getLoc()), getOpValue(Inst->getMetatypeOperand()), getOpType(Inst->getType()), Inst->isObjC(), Inst->canAllocOnStack(), ElemTypes, CountArgs); recordClonedInstruction(Inst, NewInst); } template void SILCloner::visitAllocBoxInst(AllocBoxInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); // Drop the debug info from mandatory-inlined instructions. SILLocation Loc = getOpLocation(Inst->getLoc()); std::optional VarInfo = Inst->getVarInfo(); if (Loc.getKind() == SILLocation::MandatoryInlinedKind) { Loc = MandatoryInlinedLocation::getAutoGeneratedLocation(); VarInfo = std::nullopt; } recordClonedInstruction( Inst, getBuilder().createAllocBox( Loc, this->getOpType(Inst->getType()).template castTo(), VarInfo, Inst->hasDynamicLifetime(), Inst->emitReflectionMetadata(), Inst->usesMoveableValueDebugInfo(), /*skipVarDeclAssert*/ true, Inst->hasPointerEscape())); } template void SILCloner::visitAllocExistentialBoxInst( AllocExistentialBoxInst *Inst) { auto origExistentialType = Inst->getExistentialType(); auto origFormalType = Inst->getFormalConcreteType(); auto conformances = getOpConformances(Inst->getConformances()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createAllocExistentialBox( getOpLocation(Inst->getLoc()), getOpType(origExistentialType), getOpASTType(origFormalType), conformances)); } template void SILCloner::visitBuiltinInst(BuiltinInst *Inst) { auto Args = getOpValueArray<8>(Inst->getArguments()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createBuiltin( getOpLocation(Inst->getLoc()), Inst->getName(), getOpType(Inst->getType()), getOpSubstitutionMap(Inst->getSubstitutions()), Args)); } template void SILCloner::visitMergeIsolationRegionInst( MergeIsolationRegionInst *Inst) { auto Args = getOpValueArray<8>(Inst->getOperandValues()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createMergeIsolationRegion( getOpLocation(Inst->getLoc()), Args)); } template void SILCloner::visitApplyInst(ApplyInst *Inst) { auto Args = getOpValueArray<8>(Inst->getArguments()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createApply( getOpLocation(Inst->getLoc()), getOpValue(Inst->getCallee()), getOpSubstitutionMap(Inst->getSubstitutionMap()), Args, Inst->getApplyOptions(), GenericSpecializationInformation::create(Inst, getBuilder()))); } template void SILCloner::visitTryApplyInst(TryApplyInst *Inst) { auto Args = getOpValueArray<8>(Inst->getArguments()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createTryApply( getOpLocation(Inst->getLoc()), getOpValue(Inst->getCallee()), getOpSubstitutionMap(Inst->getSubstitutionMap()), Args, getOpBasicBlock(Inst->getNormalBB()), getOpBasicBlock(Inst->getErrorBB()), Inst->getApplyOptions(), GenericSpecializationInformation::create(Inst, getBuilder()))); } template void SILCloner::visitPartialApplyInst(PartialApplyInst *Inst) { auto Args = getOpValueArray<8>(Inst->getArguments()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createPartialApply( getOpLocation(Inst->getLoc()), getOpValue(Inst->getCallee()), getOpSubstitutionMap(Inst->getSubstitutionMap()), Args, Inst->getCalleeConvention(), Inst->getResultIsolation(), Inst->isOnStack(), GenericSpecializationInformation::create(Inst, getBuilder()))); } template void SILCloner::visitBeginApplyInst(BeginApplyInst *Inst) { auto Args = getOpValueArray<8>(Inst->getArguments()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createBeginApply( getOpLocation(Inst->getLoc()), getOpValue(Inst->getCallee()), getOpSubstitutionMap(Inst->getSubstitutionMap()), Args, Inst->getApplyOptions(), GenericSpecializationInformation::create(Inst, getBuilder()))); } template void SILCloner::visitAbortApplyInst(AbortApplyInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createAbortApply(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitEndApplyInst(EndApplyInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createEndApply(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner::visitFunctionRefInst(FunctionRefInst *Inst) { SILFunction *OpFunction = getOpFunction(Inst->getReferencedFunction()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createFunctionRef( getOpLocation(Inst->getLoc()), OpFunction)); } template void SILCloner::visitDynamicFunctionRefInst( DynamicFunctionRefInst *Inst) { SILFunction *OpFunction = getOpFunction(Inst->getInitiallyReferencedFunction()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createDynamicFunctionRef( getOpLocation(Inst->getLoc()), OpFunction)); } template void SILCloner::visitPreviousDynamicFunctionRefInst( PreviousDynamicFunctionRefInst *Inst) { SILFunction *OpFunction = getOpFunction(Inst->getInitiallyReferencedFunction()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createPreviousDynamicFunctionRef( getOpLocation(Inst->getLoc()), OpFunction)); } template void SILCloner::visitAllocGlobalInst(AllocGlobalInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createAllocGlobal(getOpLocation(Inst->getLoc()), Inst->getReferencedGlobal())); } template void SILCloner::visitGlobalAddrInst(GlobalAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createGlobalAddr(getOpLocation(Inst->getLoc()), Inst->getReferencedGlobal(), Inst->hasOperand() ? getOpValue(Inst->getDependencyToken()) : SILValue())); } template void SILCloner::visitGlobalValueInst(GlobalValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createGlobalValue(getOpLocation(Inst->getLoc()), Inst->getReferencedGlobal(), Inst->isBare())); } template void SILCloner::visitBaseAddrForOffsetInst(BaseAddrForOffsetInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createBaseAddrForOffset(getOpLocation(Inst->getLoc()), getOpType(Inst->getType()))); } template void SILCloner::visitIntegerLiteralInst(IntegerLiteralInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createIntegerLiteral(getOpLocation(Inst->getLoc()), getOpType(Inst->getType()), Inst->getValue())); } template void SILCloner::visitFloatLiteralInst(FloatLiteralInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createFloatLiteral(getOpLocation(Inst->getLoc()), getOpType(Inst->getType()), Inst->getValue())); } template void SILCloner::visitStringLiteralInst(StringLiteralInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createStringLiteral( getOpLocation(Inst->getLoc()), Inst->getValue(), Inst->getEncoding())); } template void SILCloner::visitLoadInst(LoadInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { switch (Inst->getOwnershipQualifier()) { case LoadOwnershipQualifier::Copy: { auto *li = getBuilder().createLoad(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), LoadOwnershipQualifier::Unqualified); // This will emit a retain_value/strong_retain as appropriate. getBuilder().emitCopyValueOperation(getOpLocation(Inst->getLoc()), li); return recordClonedInstruction(Inst, li); } case LoadOwnershipQualifier::Take: case LoadOwnershipQualifier::Trivial: case LoadOwnershipQualifier::Unqualified: break; } return recordClonedInstruction( Inst, getBuilder().createLoad(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), LoadOwnershipQualifier::Unqualified)); } return recordClonedInstruction( Inst, getBuilder().createLoad(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getOwnershipQualifier())); } template void SILCloner::visitLoadBorrowInst(LoadBorrowInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); // If we are not inlining into an ownership function, just use a load. if (!getBuilder().hasOwnership()) { return recordClonedInstruction( Inst, getBuilder().createLoad(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), LoadOwnershipQualifier::Unqualified)); } recordClonedInstruction( Inst, getBuilder().createLoadBorrow(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitBeginBorrowInst(BeginBorrowInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { return recordFoldedValue(Inst, getOpValue(Inst->getOperand())); } recordClonedInstruction(Inst, getBuilder().createBeginBorrow( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->isLexical(), Inst->hasPointerEscape(), Inst->isFromVarDecl())); } template void SILCloner::visitBorrowedFromInst(BorrowedFromInst *bfi) { getBuilder().setCurrentDebugScope(getOpScope(bfi->getDebugScope())); if (!getBuilder().hasOwnership()) { return recordFoldedValue(bfi, getOpValue(bfi->getBorrowedValue())); } auto enclosingValues = getOpValueArray<8>(bfi->getEnclosingValues()); recordClonedInstruction(bfi, getBuilder().createBorrowedFrom( getOpLocation(bfi->getLoc()), getOpValue(bfi->getBorrowedValue()), enclosingValues)); } template void SILCloner::visitStoreInst(StoreInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { switch (Inst->getOwnershipQualifier()) { case StoreOwnershipQualifier::Assign: { auto *li = getBuilder().createLoad(getOpLocation(Inst->getLoc()), getOpValue(Inst->getDest()), LoadOwnershipQualifier::Unqualified); auto *si = getBuilder().createStore( getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()), StoreOwnershipQualifier::Unqualified); getBuilder().emitDestroyValueOperation(getOpLocation(Inst->getLoc()), li); return recordClonedInstruction(Inst, si); } case StoreOwnershipQualifier::Init: case StoreOwnershipQualifier::Trivial: case StoreOwnershipQualifier::Unqualified: break; } return recordClonedInstruction( Inst, getBuilder().createStore(getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()), StoreOwnershipQualifier::Unqualified)); } recordClonedInstruction( Inst, getBuilder().createStore( getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()), Inst->getOwnershipQualifier())); } template void SILCloner::visitStoreBorrowInst(StoreBorrowInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { getBuilder().createStore( getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()), StoreOwnershipQualifier::Unqualified); mapValue(Inst, getOpValue(Inst->getDest())); return; } recordClonedInstruction( Inst, getBuilder().createStoreBorrow(getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()))); } template void SILCloner::visitEndBorrowInst(EndBorrowInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); // Do not clone any end_borrow. if (!getBuilder().hasOwnership()) return; recordClonedInstruction( Inst, getBuilder().createEndBorrow(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitBeginAccessInst(BeginAccessInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createBeginAccess( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAccessKind(), Inst->getEnforcement(), Inst->hasNoNestedConflict(), Inst->isFromBuiltin())); } template void SILCloner::visitEndAccessInst(EndAccessInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createEndAccess(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->isAborting())); } template void SILCloner::visitBeginUnpairedAccessInst( BeginUnpairedAccessInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createBeginUnpairedAccess( getOpLocation(Inst->getLoc()), getOpValue(Inst->getSource()), getOpValue(Inst->getBuffer()), Inst->getAccessKind(), Inst->getEnforcement(), Inst->hasNoNestedConflict(), Inst->isFromBuiltin())); } template void SILCloner::visitEndUnpairedAccessInst( EndUnpairedAccessInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createEndUnpairedAccess( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getEnforcement(), Inst->isAborting(), Inst->isFromBuiltin())); } template void SILCloner::visitAssignInst(AssignInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createAssign(getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()), Inst->getOwnershipQualifier())); } template void SILCloner::visitAssignByWrapperInst(AssignByWrapperInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createAssignByWrapper( getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()), getOpValue(Inst->getInitializer()), getOpValue(Inst->getSetter()), Inst->getMode())); } template void SILCloner::visitAssignOrInitInst(AssignOrInitInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createAssignOrInit( getOpLocation(Inst->getLoc()), Inst->getProperty(), getOpValue(Inst->getSelf()), getOpValue(Inst->getSrc()), getOpValue(Inst->getInitializer()), getOpValue(Inst->getSetter()), Inst->getMode())); } template void SILCloner::visitMarkUninitializedInst(MarkUninitializedInst *Inst) { SILValue OpValue = getOpValue(Inst->getOperand()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createMarkUninitialized( getOpLocation(Inst->getLoc()), OpValue, Inst->getMarkUninitializedKind())); } template void SILCloner::visitMarkFunctionEscapeInst(MarkFunctionEscapeInst *Inst){ auto OpElements = getOpValueArray<8>(Inst->getElements()); auto OpLoc = getOpLocation(Inst->getLoc()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createMarkFunctionEscape(OpLoc, OpElements)); } template void SILCloner::visitDebugValueInst(DebugValueInst *Inst) { // We cannot inline/clone debug intrinsics without a scope. If they // describe function arguments there is no way to determine which // function they belong to. if (!Inst->getDebugScope()) return; // Since we want the debug info to survive, we do not remap the location here. std::optional VarInfo = Inst->getVarInfo(); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); remapDebugVariable(VarInfo); auto *NewInst = getBuilder().createDebugValue( Inst->getLoc(), getOpValue(Inst->getOperand()), *VarInfo, Inst->poisonRefs(), Inst->usesMoveableValueDebugInfo(), Inst->hasTrace()); recordClonedInstruction(Inst, NewInst); } template void SILCloner::visitDebugStepInst(DebugStepInst *Inst) { recordClonedInstruction(Inst, getBuilder().createDebugStep(Inst->getLoc())); } template void SILCloner::visitUnownedCopyValueInst( UnownedCopyValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createUnownedCopyValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitWeakCopyValueInst(WeakCopyValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createWeakCopyValue(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } #define COPYABLE_STORAGE_HELPER(Name, name) \ template \ void SILCloner::visitStrongCopy##Name##ValueInst( \ StrongCopy##Name##ValueInst *Inst) { \ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \ recordClonedInstruction(Inst, getBuilder().createStrongCopy##Name##Value( \ getOpLocation(Inst->getLoc()), \ getOpValue(Inst->getOperand()))); \ } #define LOADABLE_STORAGE_HELPER(Name, name) \ template \ void SILCloner::visitLoad##Name##Inst(Load##Name##Inst *Inst) { \ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \ recordClonedInstruction( \ Inst, getBuilder().createLoad##Name(getOpLocation(Inst->getLoc()), \ getOpValue(Inst->getOperand()), \ Inst->isTake())); \ } \ template \ void SILCloner::visitStore##Name##Inst(Store##Name##Inst *Inst) { \ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \ recordClonedInstruction( \ Inst, getBuilder().createStore##Name(getOpLocation(Inst->getLoc()), \ getOpValue(Inst->getSrc()), \ getOpValue(Inst->getDest()), \ Inst->isInitializationOfDest())); \ } #define LOADABLE_REF_STORAGE_HELPER(Name, name) \ template \ void SILCloner::visitRefTo##Name##Inst(RefTo##Name##Inst *Inst) { \ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \ recordClonedInstruction( \ Inst, getBuilder().createRefTo##Name(getOpLocation(Inst->getLoc()), \ getOpValue(Inst->getOperand()), \ getOpType(Inst->getType()))); \ } \ template \ void SILCloner::visit##Name##ToRefInst(Name##ToRefInst *Inst) { \ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \ recordClonedInstruction( \ Inst, getBuilder().create##Name##ToRef(getOpLocation(Inst->getLoc()), \ getOpValue(Inst->getOperand()), \ getOpType(Inst->getType()))); \ } #define RETAINABLE_STORAGE_HELPER(Name, name) \ template \ void SILCloner::visitStrongRetain##Name##Inst( \ StrongRetain##Name##Inst *Inst) { \ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \ recordClonedInstruction(Inst, getBuilder().createStrongRetain##Name( \ getOpLocation(Inst->getLoc()), \ getOpValue(Inst->getOperand()), \ Inst->getAtomicity())); \ } \ template \ void SILCloner::visit##Name##RetainInst(Name##RetainInst *Inst) { \ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \ recordClonedInstruction(Inst, getBuilder().create##Name##Retain( \ getOpLocation(Inst->getLoc()), \ getOpValue(Inst->getOperand()), \ Inst->getAtomicity())); \ } \ template \ void SILCloner::visit##Name##ReleaseInst( \ Name##ReleaseInst *Inst) { \ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \ recordClonedInstruction(Inst, getBuilder().create##Name##Release( \ getOpLocation(Inst->getLoc()), \ getOpValue(Inst->getOperand()), \ Inst->getAtomicity())); \ } #define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ COPYABLE_STORAGE_HELPER(Name, name) \ LOADABLE_STORAGE_HELPER(Name, name) #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ COPYABLE_STORAGE_HELPER(Name, name) \ LOADABLE_REF_STORAGE_HELPER(Name, name) \ RETAINABLE_STORAGE_HELPER(Name, name) #define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ COPYABLE_STORAGE_HELPER(Name, name) \ LOADABLE_REF_STORAGE_HELPER(Name, name) \ LOADABLE_STORAGE_HELPER(Name, name) \ RETAINABLE_STORAGE_HELPER(Name, name) #define UNCHECKED_REF_STORAGE(Name, name, ...) \ COPYABLE_STORAGE_HELPER(Name, name) \ LOADABLE_REF_STORAGE_HELPER(Name, name) #include "swift/AST/ReferenceStorage.def" #undef LOADABLE_STORAGE_HELPER #undef LOADABLE_REF_STORAGE_HELPER #undef COPYABLE_STORAGE_HELPER #undef RETAINABLE_STORAGE_HELPER template void SILCloner::visitCopyAddrInst(CopyAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createCopyAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()), Inst->isTakeOfSrc(), Inst->isInitializationOfDest())); } template void SILCloner::visitExplicitCopyAddrInst( ExplicitCopyAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { recordClonedInstruction( Inst, getBuilder().createCopyAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()), Inst->isTakeOfSrc(), Inst->isInitializationOfDest())); } else { // preserve the explicit_* recordClonedInstruction( Inst, getBuilder().createExplicitCopyAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()), Inst->isTakeOfSrc(), Inst->isInitializationOfDest())); } } template void SILCloner::visitMarkUnresolvedMoveAddrInst( MarkUnresolvedMoveAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto *MVI = getBuilder().createMarkUnresolvedMoveAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest())); recordClonedInstruction(Inst, MVI); } template void SILCloner::visitBindMemoryInst(BindMemoryInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createBindMemory( getOpLocation(Inst->getLoc()), getOpValue(Inst->getBase()), getOpValue(Inst->getIndex()), getOpType(Inst->getBoundType()))); } template void SILCloner::visitRebindMemoryInst(RebindMemoryInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createRebindMemory(getOpLocation(Inst->getLoc()), getOpValue(Inst->getBase()), getOpValue(Inst->getInToken()))); } template void SILCloner::visitConvertFunctionInst(ConvertFunctionInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createConvertFunction( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), Inst->withoutActuallyEscaping(), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitThunkInst(ThunkInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createThunk(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getThunkKind())); } template void SILCloner::visitConvertEscapeToNoEscapeInst( ConvertEscapeToNoEscapeInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createConvertEscapeToNoEscape( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), Inst->isLifetimeGuaranteed())); } template void SILCloner::visitUpcastInst(UpcastInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createUpcast( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitAddressToPointerInst(AddressToPointerInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createAddressToPointer(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), Inst->needsStackProtection())); } template void SILCloner::visitPointerToAddressInst(PointerToAddressInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createPointerToAddress( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), Inst->isStrict(), Inst->isInvariant(), Inst->alignment())); } template void SILCloner:: visitUncheckedRefCastInst(UncheckedRefCastInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createUncheckedRefCast( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner:: visitUncheckedRefCastAddrInst(UncheckedRefCastAddrInst *Inst) { SILLocation OpLoc = getOpLocation(Inst->getLoc()); SILValue SrcValue = getOpValue(Inst->getSrc()); SILValue DestValue = getOpValue(Inst->getDest()); CanType SrcType = getOpASTType(Inst->getSourceFormalType()); CanType TargetType = getOpASTType(Inst->getTargetFormalType()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createUncheckedRefCastAddr(OpLoc, SrcValue, SrcType, DestValue, TargetType)); } template void SILCloner:: visitUncheckedAddrCastInst(UncheckedAddrCastInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createUncheckedAddrCast(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner:: visitUncheckedTrivialBitCastInst(UncheckedTrivialBitCastInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createUncheckedTrivialBitCast( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner:: visitUncheckedBitwiseCastInst(UncheckedBitwiseCastInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createUncheckedBitwiseCast( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner::visitUncheckedValueCastInst( UncheckedValueCastInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { recordClonedInstruction(Inst, getBuilder().createUncheckedBitwiseCast( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); return; } recordClonedInstruction( Inst, getBuilder().createUncheckedValueCast( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner:: visitRefToBridgeObjectInst(RefToBridgeObjectInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createRefToBridgeObject( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand(0)), getOpValue(Inst->getBitsOperand()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner:: visitBridgeObjectToRefInst(BridgeObjectToRefInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createBridgeObjectToRef( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner:: visitBridgeObjectToWordInst(BridgeObjectToWordInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createBridgeObjectToWord( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner::visitRefToRawPointerInst(RefToRawPointerInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createRefToRawPointer(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner::visitValueToBridgeObjectInst( ValueToBridgeObjectInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createValueToBridgeObject( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitRawPointerToRefInst(RawPointerToRefInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createRawPointerToRef(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner:: visitThinToThickFunctionInst(ThinToThickFunctionInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createThinToThickFunction( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner:: visitThickToObjCMetatypeInst(ThickToObjCMetatypeInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createThickToObjCMetatype( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner:: visitObjCToThickMetatypeInst(ObjCToThickMetatypeInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createObjCToThickMetatype( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner::visitUnconditionalCheckedCastInst( UnconditionalCheckedCastInst *Inst) { SILLocation OpLoc = getOpLocation(Inst->getLoc()); SILValue OpValue = getOpValue(Inst->getOperand()); SILType OpLoweredType = getOpType(Inst->getTargetLoweredType()); CanType OpFormalType = getOpASTType(Inst->getTargetFormalType()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createUnconditionalCheckedCast( OpLoc, Inst->getCheckedCastOptions(), OpValue, OpLoweredType, OpFormalType, getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitUnconditionalCheckedCastAddrInst( UnconditionalCheckedCastAddrInst *Inst) { SILLocation OpLoc = getOpLocation(Inst->getLoc()); SILValue SrcValue = getOpValue(Inst->getSrc()); SILValue DestValue = getOpValue(Inst->getDest()); CanType SrcType = getOpASTType(Inst->getSourceFormalType()); CanType TargetType = getOpASTType(Inst->getTargetFormalType()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createUnconditionalCheckedCastAddr( OpLoc, Inst->getCheckedCastOptions(), SrcValue, SrcType, DestValue, TargetType)); } template void SILCloner::visitRetainValueInst(RetainValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createRetainValue(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } template void SILCloner::visitRetainValueAddrInst(RetainValueAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createRetainValueAddr(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } template void SILCloner::visitUnmanagedRetainValueInst( UnmanagedRetainValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { return recordClonedInstruction( Inst, getBuilder().createRetainValue(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } recordClonedInstruction(Inst, getBuilder().createUnmanagedRetainValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } template void SILCloner::visitCopyValueInst(CopyValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { // Noescape closures become trivial after OSSA. if (auto fnTy = Inst->getType().getAs()) { if (fnTy->isTrivialNoEscape()) { return recordFoldedValue(Inst, getOpValue(Inst->getOperand())); } } SILValue newValue = getBuilder().emitCopyValueOperation( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())); return recordFoldedValue(Inst, newValue); } recordClonedInstruction( Inst, getBuilder().createCopyValue(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitExplicitCopyValueInst( ExplicitCopyValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { SILValue newValue = getBuilder().emitCopyValueOperation( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())); return recordFoldedValue(Inst, newValue); } recordClonedInstruction( Inst, getBuilder().createExplicitCopyValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitMoveValueInst(MoveValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { return recordFoldedValue(Inst, getOpValue(Inst->getOperand())); } auto *MVI = getBuilder().createMoveValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->isLexical(), Inst->hasPointerEscape(), Inst->isFromVarDecl()); MVI->setAllowsDiagnostics(Inst->getAllowDiagnostics()); recordClonedInstruction(Inst, MVI); } template void SILCloner::visitDropDeinitInst(DropDeinitInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { return recordFoldedValue(Inst, getOpValue(Inst->getOperand())); } auto *MVI = getBuilder().createDropDeinit(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())); recordClonedInstruction(Inst, MVI); } template void SILCloner::visitMarkUnresolvedNonCopyableValueInst( MarkUnresolvedNonCopyableValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto *MVI = getBuilder().createMarkUnresolvedNonCopyableValueInst( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getCheckKind()); recordClonedInstruction(Inst, MVI); } template void SILCloner::visitMarkUnresolvedReferenceBindingInst( MarkUnresolvedReferenceBindingInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto *MVI = getBuilder().createMarkUnresolvedReferenceBindingInst( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getKind()); recordClonedInstruction(Inst, MVI); } template void SILCloner::visitMoveOnlyWrapperToCopyableValueInst( MoveOnlyWrapperToCopyableValueInst *inst) { getBuilder().setCurrentDebugScope(getOpScope(inst->getDebugScope())); MoveOnlyWrapperToCopyableValueInst *cvt; if (inst->getOwnershipKind() == OwnershipKind::Owned) { cvt = getBuilder().createOwnedMoveOnlyWrapperToCopyableValue( getOpLocation(inst->getLoc()), getOpValue(inst->getOperand())); } else { assert(inst->getOwnershipKind() == OwnershipKind::Guaranteed); cvt = getBuilder().createGuaranteedMoveOnlyWrapperToCopyableValue( getOpLocation(inst->getLoc()), getOpValue(inst->getOperand())); } recordClonedInstruction(inst, cvt); } template void SILCloner::visitMoveOnlyWrapperToCopyableBoxInst( MoveOnlyWrapperToCopyableBoxInst *inst) { getBuilder().setCurrentDebugScope(getOpScope(inst->getDebugScope())); recordClonedInstruction( inst, getBuilder().createMoveOnlyWrapperToCopyableBox( getOpLocation(inst->getLoc()), getOpValue(inst->getOperand()))); } template void SILCloner::visitMoveOnlyWrapperToCopyableAddrInst( MoveOnlyWrapperToCopyableAddrInst *inst) { getBuilder().setCurrentDebugScope(getOpScope(inst->getDebugScope())); recordClonedInstruction( inst, getBuilder().createMoveOnlyWrapperToCopyableAddr( getOpLocation(inst->getLoc()), getOpValue(inst->getOperand()))); } template void SILCloner::visitCopyableToMoveOnlyWrapperAddrInst( CopyableToMoveOnlyWrapperAddrInst *inst) { getBuilder().setCurrentDebugScope(getOpScope(inst->getDebugScope())); recordClonedInstruction( inst, getBuilder().createCopyableToMoveOnlyWrapperAddr( getOpLocation(inst->getLoc()), getOpValue(inst->getOperand()))); } template void SILCloner::visitCopyableToMoveOnlyWrapperValueInst( CopyableToMoveOnlyWrapperValueInst *inst) { getBuilder().setCurrentDebugScope(getOpScope(inst->getDebugScope())); CopyableToMoveOnlyWrapperValueInst *cvt; if (inst->getOwnershipKind() == OwnershipKind::Owned) { cvt = getBuilder().createOwnedCopyableToMoveOnlyWrapperValue( getOpLocation(inst->getLoc()), getOpValue(inst->getOperand())); } else { assert(inst->getOwnershipKind() == OwnershipKind::Guaranteed); cvt = getBuilder().createGuaranteedCopyableToMoveOnlyWrapperValue( getOpLocation(inst->getLoc()), getOpValue(inst->getOperand())); } recordClonedInstruction(inst, cvt); } template void SILCloner::visitReleaseValueInst(ReleaseValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createReleaseValue(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } template void SILCloner::visitReleaseValueAddrInst( ReleaseValueAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createReleaseValueAddr(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } template void SILCloner::visitUnmanagedReleaseValueInst( UnmanagedReleaseValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { return recordClonedInstruction( Inst, getBuilder().createReleaseValue(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } recordClonedInstruction(Inst, getBuilder().createUnmanagedReleaseValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } template void SILCloner::visitDestroyValueInst(DestroyValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { // Noescape closures become trivial after OSSA. if (auto fnTy = Inst->getOperand()->getType().getAs()) { if (fnTy->isTrivialNoEscape()) { // Destroying the partial_apply [stack] becomes the stack deallocation // of the context. if (auto origPA = Inst->getNonescapingClosureAllocation()) { recordClonedInstruction(Inst, getBuilder().createDeallocStack(getOpLocation(Inst->getLoc()), getOpValue(origPA))); } return; } } return recordClonedInstruction( Inst, getBuilder().createReleaseValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), RefCountingInst::Atomicity::Atomic)); } recordClonedInstruction(Inst, getBuilder().createDestroyValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->poisonRefs(), Inst->isDeadEnd())); } template void SILCloner::visitAutoreleaseValueInst( AutoreleaseValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createAutoreleaseValue(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } template void SILCloner::visitUnmanagedAutoreleaseValueInst( UnmanagedAutoreleaseValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { return recordClonedInstruction(Inst, getBuilder().createAutoreleaseValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } recordClonedInstruction(Inst, getBuilder().createUnmanagedAutoreleaseValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } template void SILCloner::visitBeginDeallocRefInst(BeginDeallocRefInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createBeginDeallocRef(getOpLocation(Inst->getLoc()), getOpValue(Inst->getReference()), getOpValue(Inst->getAllocation()))); } template void SILCloner::visitEndInitLetRefInst(EndInitLetRefInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createEndInitLetRef(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitObjectInst(ObjectInst *Inst) { auto Elements = getOpValueArray<8>(Inst->getAllElements()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createObject(getOpLocation(Inst->getLoc()), Inst->getType(), Elements, Inst->getBaseElements().size())); } template void SILCloner::visitVectorInst(VectorInst *Inst) { auto Elements = getOpValueArray<8>(Inst->getElements()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createVector(getOpLocation(Inst->getLoc()), Elements)); } template void SILCloner::visitStructInst(StructInst *Inst) { auto Elements = getOpValueArray<8>(Inst->getElements()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createStruct(getOpLocation(Inst->getLoc()), getOpType(Inst->getType()), Elements, getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitTupleInst(TupleInst *Inst) { auto Elements = getOpValueArray<8>(Inst->getElements()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createTuple(getOpLocation(Inst->getLoc()), getOpType(Inst->getType()), Elements, getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitTupleAddrConstructorInst( TupleAddrConstructorInst *Inst) { SmallVector Elements; for (auto e : Inst->getElements()) { SILValue mappedValue = getOpValue(e); // Check if mappedValue only consists of empty tuple elements. If it does, // then we do not add it to our result. This is because we know that the // corresponding elements in getOpValue(Inst->getDest()) will also change // into an empty exploded tuple. Since we only have leaf non-empty non-tuple // elements as operands, these are not represented. bool FoundNonTuple = false; mappedValue->getType().getASTType().visit( [&](CanType ty) { FoundNonTuple |= !ty->is(); }); if (FoundNonTuple) Elements.push_back(mappedValue); } if (Elements.empty()) return; getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createTupleAddrConstructor( getOpLocation(Inst->getLoc()), getOpValue(Inst->getDest()), Elements, Inst->isInitializationOfDest())); } template void SILCloner::visitEnumInst(EnumInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createEnum( getOpLocation(Inst->getLoc()), Inst->hasOperand() ? getOpValue(Inst->getOperand()) : SILValue(), Inst->getElement(), getOpType(Inst->getType()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitInitEnumDataAddrInst(InitEnumDataAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createInitEnumDataAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getElement(), getOpType(Inst->getType()))); } template void SILCloner::visitUncheckedEnumDataInst(UncheckedEnumDataInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createUncheckedEnumData( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getElement(), getOpType(Inst->getType()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitUncheckedTakeEnumDataAddrInst(UncheckedTakeEnumDataAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createUncheckedTakeEnumDataAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getElement(), getOpType(Inst->getType()))); } template void SILCloner::visitInjectEnumAddrInst(InjectEnumAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createInjectEnumAddr(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getElement())); } template void SILCloner::visitMetatypeInst(MetatypeInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createMetatype(getOpLocation(Inst->getLoc()), getOpType(Inst->getType()))); } template void SILCloner::visitValueMetatypeInst(ValueMetatypeInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createValueMetatype(getOpLocation(Inst->getLoc()), getOpType(Inst->getType()), getOpValue(Inst->getOperand()))); } template void SILCloner:: visitExistentialMetatypeInst(ExistentialMetatypeInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createExistentialMetatype( getOpLocation(Inst->getLoc()), getOpType(Inst->getType()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitTupleExtractInst(TupleExtractInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createTupleExtract( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getFieldIndex(), getOpType(Inst->getType()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitTupleElementAddrInst(TupleElementAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createTupleElementAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getFieldIndex(), getOpType(Inst->getType()))); } template void SILCloner::visitStructExtractInst(StructExtractInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createStructExtract( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getField(), getOpType(Inst->getType()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitStructElementAddrInst(StructElementAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createStructElementAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getField(), getOpType(Inst->getType()))); } template void SILCloner::visitVectorBaseAddrInst(VectorBaseAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createVectorBaseAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getVector()))); } template void SILCloner::visitRefElementAddrInst(RefElementAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createRefElementAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getField(), getOpType(Inst->getType()), Inst->isImmutable())); } template void SILCloner::visitRefTailAddrInst(RefTailAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createRefTailAddr(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), Inst->isImmutable())); } template void SILCloner::visitDestructureStructInst( DestructureStructInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { getBuilder().emitDestructureValueOperation( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), [&](unsigned index, SILValue value) { recordFoldedValue(Inst->getResults()[index], value); }); return; } recordClonedInstruction( Inst, getBuilder().createDestructureStruct( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitDestructureTupleInst( DestructureTupleInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { getBuilder().emitDestructureValueOperation( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), [&](unsigned index, SILValue value) { recordFoldedValue(Inst->getResults()[index], value); }); return; } recordClonedInstruction( Inst, getBuilder().createDestructureTuple( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitClassMethodInst(ClassMethodInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createClassMethod(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getMember(), Inst->getType())); } template void SILCloner::visitSuperMethodInst(SuperMethodInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createSuperMethod(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getMember(), Inst->getType())); } template void SILCloner::visitObjCMethodInst(ObjCMethodInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createObjCMethod( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getMember(), getOpType(Inst->getType()))); } template void SILCloner::visitObjCSuperMethodInst(ObjCSuperMethodInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createObjCSuperMethod( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getMember(), Inst->getType())); } template void SILCloner::visitWitnessMethodInst(WitnessMethodInst *Inst) { auto conformance = getOpConformance(Inst->getConformance()); auto lookupType = getOpASTType(Inst->getLookupType()); if (conformance.isConcrete()) { auto conformingType = conformance.getConcrete()->getType()->getCanonicalType(); if (conformingType != lookupType) { assert( (conformingType->isExactSuperclassOf(lookupType) || getBuilder().getModule().Types.getLoweredRValueType( getBuilder().getTypeExpansionContext(), conformingType) == lookupType) && "Should only create upcasts for sub class."); // We use the super class as the new look up type. lookupType = conformingType; } } getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createWitnessMethod( getOpLocation(Inst->getLoc()), lookupType, conformance, Inst->getMember(), getOpType(Inst->getType()))); } template void SILCloner::visitOpenExistentialAddrInst(OpenExistentialAddrInst *Inst) { // Create a new archetype for this opened existential type. remapRootOpenedType(Inst->getDefinedOpenedArchetype()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createOpenExistentialAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), Inst->getAccessKind())); } template void SILCloner::visitOpenExistentialValueInst( OpenExistentialValueInst *Inst) { // Create a new archetype for this opened existential type. remapRootOpenedType(Inst->getDefinedOpenedArchetype()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createOpenExistentialValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner:: visitOpenExistentialMetatypeInst(OpenExistentialMetatypeInst *Inst) { remapRootOpenedType(Inst->getDefinedOpenedArchetype()); if (!Inst->getOperand()->getType().canUseExistentialRepresentation( ExistentialRepresentation::Class)) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createOpenExistentialMetatype( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); return; } getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createOpenExistentialMetatype( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner:: visitOpenExistentialRefInst(OpenExistentialRefInst *Inst) { // Create a new archetype for this opened existential type. remapRootOpenedType(Inst->getDefinedOpenedArchetype()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createOpenExistentialRef( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner:: visitOpenExistentialBoxInst(OpenExistentialBoxInst *Inst) { // Create a new archetype for this opened existential type. remapRootOpenedType(Inst->getDefinedOpenedArchetype()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createOpenExistentialBox( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner:: visitOpenExistentialBoxValueInst(OpenExistentialBoxValueInst *Inst) { // Create a new archetype for this opened existential type. remapRootOpenedType(Inst->getDefinedOpenedArchetype()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createOpenExistentialBoxValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitInitExistentialAddrInst(InitExistentialAddrInst *Inst) { CanType origFormalType = Inst->getFormalConcreteType(); auto conformances = getOpConformances(Inst->getConformances()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createInitExistentialAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpASTType(origFormalType), getOpType(Inst->getLoweredConcreteType()), conformances)); } template void SILCloner::visitInitExistentialValueInst( InitExistentialValueInst *Inst) { CanType origFormalType = Inst->getFormalConcreteType(); auto conformances = getOpConformances(Inst->getConformances()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createInitExistentialValue( getOpLocation(Inst->getLoc()), getOpType(Inst->getType()), getOpASTType(origFormalType), getOpValue(Inst->getOperand()), conformances)); } template void SILCloner:: visitInitExistentialMetatypeInst(InitExistentialMetatypeInst *Inst) { auto conformances = getOpConformances(Inst->getConformances()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createInitExistentialMetatype( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), conformances)); } template void SILCloner:: visitInitExistentialRefInst(InitExistentialRefInst *Inst) { CanType origFormalType = Inst->getFormalConcreteType(); auto conformances = getOpConformances(Inst->getConformances()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createInitExistentialRef( getOpLocation(Inst->getLoc()), getOpType(Inst->getType()), getOpASTType(origFormalType), getOpValue(Inst->getOperand()), conformances)); } template void SILCloner::visitDeinitExistentialAddrInst(DeinitExistentialAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDeinitExistentialAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitDeinitExistentialValueInst( DeinitExistentialValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDeinitExistentialValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitTypeValueInst(TypeValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createTypeValue(getOpLocation(Inst->getLoc()), getOpType(Inst->getType()), getOpASTType(Inst->getParamType()))); } template void SILCloner::visitPackLengthInst(PackLengthInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto loc = getOpLocation(Inst->getLoc()); auto newPackType = cast(getOpASTType(Inst->getPackType())); recordClonedInstruction( Inst, getBuilder().createPackLength(loc, newPackType)); } template void SILCloner::visitDynamicPackIndexInst( DynamicPackIndexInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto newIndexValue = getOpValue(Inst->getOperand()); auto loc = getOpLocation(Inst->getLoc()); auto newPackType = cast(getOpASTType(Inst->getIndexedPackType())); recordClonedInstruction( Inst, getBuilder().createDynamicPackIndex(loc, newIndexValue, newPackType)); } template void SILCloner::visitPackPackIndexInst(PackPackIndexInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto newIndexValue = getOpValue(Inst->getOperand()); auto loc = getOpLocation(Inst->getLoc()); auto newPackType = cast(getOpASTType(Inst->getIndexedPackType())); auto newComponentStartIndex = getOpStructuralPackIndex(Inst->getIndexedPackType(), Inst->getComponentStartIndex()); recordClonedInstruction( Inst, getBuilder().createPackPackIndex(loc, newComponentStartIndex, newIndexValue, newPackType)); } template void SILCloner::visitScalarPackIndexInst( ScalarPackIndexInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto loc = getOpLocation(Inst->getLoc()); auto newPackType = cast(getOpASTType(Inst->getIndexedPackType())); auto newComponentIndex = getOpStructuralPackIndex(Inst->getIndexedPackType(), Inst->getComponentIndex()); recordClonedInstruction( Inst, getBuilder().createScalarPackIndex(loc, newComponentIndex, newPackType)); } template void SILCloner::visitOpenPackElementInst( OpenPackElementInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto newIndexValue = getOpValue(Inst->getIndexOperand()); auto loc = getOpLocation(Inst->getLoc()); // We need to make a new opened-element environment. This is *not* // a refinement of the contextual environment of the new insertion // site; we just substitute the contextual substitutions in the // opened environment and build a new one. auto origEnv = Inst->getOpenedGenericEnvironment(); // Substitute the contextual substitutions. auto newContextSubs = getOpSubstitutionMap(origEnv->getOuterSubstitutions()); // The opened shape class is a parameter of the original signature, // which is unchanged. auto openedShapeClass = origEnv->getOpenedElementShapeClass(); // Build the new environment. auto newEnv = GenericEnvironment::forOpenedElement(origEnv->getGenericSignature(), UUID::fromTime(), openedShapeClass, newContextSubs); registerLocalArchetypeRemapping(origEnv, newEnv); recordClonedInstruction( Inst, getBuilder().createOpenPackElement(loc, newIndexValue, newEnv)); } template void SILCloner::visitPackElementGetInst(PackElementGetInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto loc = getOpLocation(Inst->getLoc()); auto newIndex = getOpValue(Inst->getIndex()); auto newPack = getOpValue(Inst->getPack()); auto newElementType = getOpType(Inst->getElementType()); recordClonedInstruction( Inst, getBuilder().createPackElementGet(loc, newIndex, newPack, newElementType)); } template void SILCloner::visitPackElementSetInst(PackElementSetInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto loc = getOpLocation(Inst->getLoc()); auto newElementValue = getOpValue(Inst->getValue()); auto newIndex = getOpValue(Inst->getIndex()); auto newPack = getOpValue(Inst->getPack()); recordClonedInstruction( Inst, getBuilder().createPackElementSet(loc, newElementValue, newIndex, newPack)); } template void SILCloner::visitTuplePackElementAddrInst( TuplePackElementAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto loc = getOpLocation(Inst->getLoc()); auto newIndex = getOpValue(Inst->getIndex()); auto newTuple = getOpValue(Inst->getTuple()); auto newElementType = getOpType(Inst->getElementType()); // If the tuple-ness of the operand disappears due to substitution, // replace this instruction with an unchecked_addr_cast. // FIXME: use type_refine_addr instead if (doesOpTupleDisappear(Inst->getTupleType())) { recordClonedInstruction( Inst, getBuilder().createUncheckedAddrCast(loc, newTuple, newElementType)); return; } recordClonedInstruction( Inst, getBuilder().createTuplePackElementAddr(loc, newIndex, newTuple, newElementType)); } template void SILCloner::visitTuplePackExtractInst( TuplePackExtractInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto loc = getOpLocation(Inst->getLoc()); auto newIndex = getOpValue(Inst->getIndex()); auto newTuple = getOpValue(Inst->getTuple()); auto newElementType = getOpType(Inst->getElementType()); // If the tuple-ness of the operand disappears due to substitution, // replace this instruction with an unchecked_value_cast. if (doesOpTupleDisappear(Inst->getTupleType())) { recordClonedInstruction(Inst, getBuilder().createUncheckedValueCast( loc, newTuple, newElementType)); return; } recordClonedInstruction(Inst, getBuilder().createTuplePackExtract( loc, newIndex, newTuple, newElementType)); } template void SILCloner::visitCopyBlockInst(CopyBlockInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, Builder.createCopyBlock(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitCopyBlockWithoutEscapingInst( CopyBlockWithoutEscapingInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, Builder.createCopyBlockWithoutEscaping( getOpLocation(Inst->getLoc()), getOpValue(Inst->getBlock()), getOpValue(Inst->getClosure()))); } template void SILCloner::visitStrongRetainInst(StrongRetainInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createStrongRetain(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } template void SILCloner::visitClassifyBridgeObjectInst( ClassifyBridgeObjectInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createClassifyBridgeObject( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitFixLifetimeInst(FixLifetimeInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createFixLifetime(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitEndLifetimeInst(EndLifetimeInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); // These are only needed in OSSA. if (!getBuilder().hasOwnership()) return; recordClonedInstruction( Inst, getBuilder().createEndLifetime(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitExtendLifetimeInst(ExtendLifetimeInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) return; recordClonedInstruction( Inst, getBuilder().createExtendLifetime(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitUncheckedOwnershipConversionInst( UncheckedOwnershipConversionInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); if (!getBuilder().hasOwnership()) { return recordFoldedValue(Inst, getOpValue(Inst->getOperand())); } ValueOwnershipKind Kind = SILValue(Inst)->getOwnershipKind(); if (getOpValue(Inst->getOperand())->getOwnershipKind() == OwnershipKind::None) { Kind = OwnershipKind::None; } recordClonedInstruction(Inst, getBuilder().createUncheckedOwnershipConversion( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Kind)); } template void SILCloner::visitMarkDependenceInst(MarkDependenceInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createMarkDependence( getOpLocation(Inst->getLoc()), getOpValue(Inst->getValue()), getOpValue(Inst->getBase()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None), Inst->dependenceKind())); } template void SILCloner:: visitMarkDependenceAddrInst(MarkDependenceAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createMarkDependenceAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getAddress()), getOpValue(Inst->getBase()), Inst->dependenceKind())); } template void SILCloner::visitStrongReleaseInst(StrongReleaseInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createStrongRelease(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } template void SILCloner::visitIsUniqueInst(IsUniqueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createIsUnique(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitBeginCOWMutationInst(BeginCOWMutationInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createBeginCOWMutation(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->isNative())); } template void SILCloner::visitEndCOWMutationInst(EndCOWMutationInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createEndCOWMutation(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->doKeepUnique())); } template void SILCloner::visitEndCOWMutationAddrInst( EndCOWMutationAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createEndCOWMutationAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitDestroyNotEscapedClosureInst( DestroyNotEscapedClosureInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDestroyNotEscapedClosure(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getVerificationType())); } template void SILCloner::visitDeallocStackInst(DeallocStackInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDeallocStack(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitDeallocPackInst(DeallocPackInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDeallocPack(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitDeallocPackMetadataInst( DeallocPackMetadataInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDeallocPackMetadata( getOpLocation(Inst->getLoc()), Inst->getOperand())); } template void SILCloner::visitDeallocRefInst(DeallocRefInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDeallocRef(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitDeallocStackRefInst(DeallocStackRefInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDeallocStackRef(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitDeallocPartialRefInst(DeallocPartialRefInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createDeallocPartialRef( getOpLocation(Inst->getLoc()), getOpValue(Inst->getInstance()), getOpValue(Inst->getMetatype()))); } template void SILCloner::visitDeallocBoxInst(DeallocBoxInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDeallocBox(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->isDeadEnd())); } template void SILCloner::visitDeallocExistentialBoxInst( DeallocExistentialBoxInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createDeallocExistentialBox( getOpLocation(Inst->getLoc()), getOpASTType(Inst->getConcreteType()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitDestroyAddrInst(DestroyAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDestroyAddr(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitProjectBoxInst(ProjectBoxInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createProjectBox(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getFieldIndex())); } template void SILCloner::visitProjectExistentialBoxInst( ProjectExistentialBoxInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createProjectExistentialBox( getOpLocation(Inst->getLoc()), getOpType(Inst->getType()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitCondFailInst(CondFailInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createCondFail(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getMessage())); } template void SILCloner::visitIncrementProfilerCounterInst( IncrementProfilerCounterInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createIncrementProfilerCounter( getOpLocation(Inst->getLoc()), Inst->getCounterIndex(), Inst->getPGOFuncName(), Inst->getNumCounters(), Inst->getPGOFuncHash())); } template void SILCloner::visitSpecifyTestInst(SpecifyTestInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createSpecifyTestInst( getOpLocation(Inst->getLoc()), Inst->getArgumentsSpecification())); } template void SILCloner::visitIndexAddrInst(IndexAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createIndexAddr(getOpLocation(Inst->getLoc()), getOpValue(Inst->getBase()), getOpValue(Inst->getIndex()), Inst->needsStackProtection())); } template void SILCloner::visitTailAddrInst(TailAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createTailAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getBase()), getOpValue(Inst->getIndex()), getOpType(Inst->getType()))); } template void SILCloner::visitIndexRawPointerInst(IndexRawPointerInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createIndexRawPointer(getOpLocation(Inst->getLoc()), getOpValue(Inst->getBase()), getOpValue(Inst->getIndex()))); } template void SILCloner::visitUnreachableInst(UnreachableInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createUnreachable(getOpLocation(Inst->getLoc()))); } template void SILCloner::visitReturnInst(ReturnInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createReturn(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitThrowInst(ThrowInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createThrow(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitThrowAddrInst(ThrowAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createThrowAddr(getOpLocation(Inst->getLoc()))); } template void SILCloner::visitUnwindInst(UnwindInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createUnwind(getOpLocation(Inst->getLoc()))); } template void SILCloner::visitYieldInst(YieldInst *Inst) { auto Values = getOpValueArray<8>(Inst->getYieldedValues()); auto ResumeBB = getOpBasicBlock(Inst->getResumeBB()); auto UnwindBB = getOpBasicBlock(Inst->getUnwindBB()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createYield(getOpLocation(Inst->getLoc()), Values, ResumeBB, UnwindBB)); } template void SILCloner::visitBranchInst(BranchInst *Inst) { auto Args = getOpValueArray<8>(Inst->getArgs()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createBranch( getOpLocation(Inst->getLoc()), getOpBasicBlock(Inst->getDestBB()), Args)); } template void SILCloner::visitCondBranchInst(CondBranchInst *Inst) { auto TrueArgs = getOpValueArray<8>(Inst->getTrueArgs()); auto FalseArgs = getOpValueArray<8>(Inst->getFalseArgs()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createCondBranch( getOpLocation(Inst->getLoc()), getOpValue(Inst->getCondition()), getOpBasicBlock(Inst->getTrueBB()), TrueArgs, getOpBasicBlock(Inst->getFalseBB()), FalseArgs, Inst->getTrueBBCount(), Inst->getFalseBBCount())); } template void SILCloner::visitCheckedCastBranchInst(CheckedCastBranchInst *Inst) { SILBasicBlock *OpSuccBB = getOpBasicBlock(Inst->getSuccessBB()); SILBasicBlock *OpFailBB = getOpBasicBlock(Inst->getFailureBB()); auto TrueCount = Inst->getTrueBBCount(); auto FalseCount = Inst->getFalseBBCount(); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createCheckedCastBranch( getOpLocation(Inst->getLoc()), Inst->isExact(), Inst->getCheckedCastOptions(), getOpValue(Inst->getOperand()), getOpASTType(Inst->getSourceFormalType()), getOpType(Inst->getTargetLoweredType()), getOpASTType(Inst->getTargetFormalType()), OpSuccBB, OpFailBB, Inst->getForwardingOwnershipKind(), TrueCount, FalseCount)); } template void SILCloner::visitCheckedCastAddrBranchInst( CheckedCastAddrBranchInst *Inst) { SILBasicBlock *OpSuccBB = getOpBasicBlock(Inst->getSuccessBB()); SILBasicBlock *OpFailBB = getOpBasicBlock(Inst->getFailureBB()); SILValue SrcValue = getOpValue(Inst->getSrc()); SILValue DestValue = getOpValue(Inst->getDest()); CanType SrcType = getOpASTType(Inst->getSourceFormalType()); CanType TargetType = getOpASTType(Inst->getTargetFormalType()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto TrueCount = Inst->getTrueBBCount(); auto FalseCount = Inst->getFalseBBCount(); recordClonedInstruction(Inst, getBuilder().createCheckedCastAddrBranch( getOpLocation(Inst->getLoc()), Inst->getCheckedCastOptions(), Inst->getConsumptionKind(), SrcValue, SrcType, DestValue, TargetType, OpSuccBB, OpFailBB, TrueCount, FalseCount)); } template void SILCloner::visitSwitchValueInst(SwitchValueInst *Inst) { SILBasicBlock *DefaultBB = nullptr; if (Inst->hasDefault()) DefaultBB = getOpBasicBlock(Inst->getDefaultBB()); SmallVector, 8> CaseBBs; for (int i = 0, e = Inst->getNumCases(); i != e; ++i) CaseBBs.push_back(std::make_pair(getOpValue(Inst->getCase(i).first), getOpBasicBlock(Inst->getCase(i).second))); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createSwitchValue(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), DefaultBB, CaseBBs)); } template void SILCloner::visitSwitchEnumInst(SwitchEnumInst *Inst) { SILBasicBlock *DefaultBB = nullptr; if (Inst->hasDefault()) DefaultBB = getOpBasicBlock(Inst->getDefaultBB()); SmallVector, 8> CaseBBs; for (unsigned i = 0, e = Inst->getNumCases(); i != e; ++i) CaseBBs.push_back(std::make_pair(Inst->getCase(i).first, getOpBasicBlock(Inst->getCase(i).second))); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createSwitchEnum( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), DefaultBB, CaseBBs, std::nullopt, ProfileCounter(), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner:: visitSwitchEnumAddrInst(SwitchEnumAddrInst *Inst) { SILBasicBlock *DefaultBB = nullptr; if (Inst->hasDefault()) DefaultBB = getOpBasicBlock(Inst->getDefaultBB()); SmallVector, 8> CaseBBs; for (unsigned i = 0, e = Inst->getNumCases(); i != e; ++i) CaseBBs.push_back(std::make_pair(Inst->getCase(i).first, getOpBasicBlock(Inst->getCase(i).second))); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createSwitchEnumAddr(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), DefaultBB, CaseBBs)); } template void SILCloner::visitSelectEnumInst(SelectEnumInst *Inst) { SILValue DefaultResult; if (Inst->hasDefault()) DefaultResult = getOpValue(Inst->getDefaultResult()); SmallVector, 8> CaseResults; for (unsigned i = 0, e = Inst->getNumCases(); i != e; ++i) CaseResults.push_back(std::make_pair(Inst->getCase(i).first, getOpValue(Inst->getCase(i).second))); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createSelectEnum( getOpLocation(Inst->getLoc()), getOpValue(Inst->getEnumOperand()), getOpType(Inst->getType()), DefaultResult, CaseResults, std::nullopt, ProfileCounter())); } template void SILCloner::visitSelectEnumAddrInst(SelectEnumAddrInst *Inst) { SILValue DefaultResult; if (Inst->hasDefault()) DefaultResult = getOpValue(Inst->getDefaultResult()); SmallVector, 8> CaseResults; for (unsigned i = 0, e = Inst->getNumCases(); i != e; ++i) CaseResults.push_back(std::make_pair(Inst->getCase(i).first, getOpValue(Inst->getCase(i).second))); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createSelectEnumAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getEnumOperand()), getOpType(Inst->getType()), DefaultResult, CaseResults)); } template void SILCloner::visitDynamicMethodBranchInst( DynamicMethodBranchInst *Inst) { SILBasicBlock *OpHasMethodBB = getOpBasicBlock(Inst->getHasMethodBB()); SILBasicBlock *OpHasNoMethodBB = getOpBasicBlock(Inst->getNoMethodBB()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDynamicMethodBranch( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getMember(), OpHasMethodBB, OpHasNoMethodBB)); } template void SILCloner::visitProjectBlockStorageInst( ProjectBlockStorageInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createProjectBlockStorage( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner::visitInitBlockStorageHeaderInst( InitBlockStorageHeaderInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createInitBlockStorageHeader( getOpLocation(Inst->getLoc()), getOpValue(Inst->getBlockStorage()), getOpValue(Inst->getInvokeFunction()), getOpType(Inst->getType()), getOpSubstitutionMap(Inst->getSubstitutions()))); } template void SILCloner::visitObjCMetatypeToObjectInst( ObjCMetatypeToObjectInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createObjCMetatypeToObject( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner::visitObjCExistentialMetatypeToObjectInst( ObjCExistentialMetatypeToObjectInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createObjCExistentialMetatypeToObject( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner::visitObjCProtocolInst(ObjCProtocolInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createObjCProtocol(getOpLocation(Inst->getLoc()), Inst->getProtocol(), getOpType(Inst->getType()))); } template void SILCloner::visitKeyPathInst(KeyPathInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); SmallVector opValues; for (Operand *op : Inst->getRealOperands()) opValues.push_back(getOpValue(op->get())); recordClonedInstruction(Inst, getBuilder().createKeyPath( getOpLocation(Inst->getLoc()), Inst->getPattern(), getOpSubstitutionMap(Inst->getSubstitutions()), opValues, getOpType(Inst->getType()))); } template void SILCloner::visitDifferentiableFunctionInst( DifferentiableFunctionInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); std::optional> derivativeFns = std::nullopt; if (Inst->hasDerivativeFunctions()) derivativeFns = std::make_pair(getOpValue(Inst->getJVPFunction()), getOpValue(Inst->getVJPFunction())); recordClonedInstruction( Inst, getBuilder().createDifferentiableFunction( getOpLocation(Inst->getLoc()), Inst->getParameterIndices(), Inst->getResultIndices(), getOpValue(Inst->getOriginalFunction()), derivativeFns, getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitLinearFunctionInst(LinearFunctionInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); auto transpose = Inst->getOptionalTransposeFunction(); if (transpose) transpose = getOpValue(*transpose); recordClonedInstruction( Inst, getBuilder().createLinearFunction( getOpLocation(Inst->getLoc()), Inst->getParameterIndices(), getOpValue(Inst->getOriginalFunction()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None), transpose)); } template void SILCloner::visitDifferentiableFunctionExtractInst( DifferentiableFunctionExtractInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); std::optional explicitExtracteeType = std::nullopt; if (Inst->hasExplicitExtracteeType()) explicitExtracteeType = Inst->getType(); recordClonedInstruction( Inst, getBuilder().createDifferentiableFunctionExtract( getOpLocation(Inst->getLoc()), Inst->getExtractee(), getOpValue(Inst->getOperand()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None), explicitExtracteeType)); } template void SILCloner:: visitLinearFunctionExtractInst(LinearFunctionExtractInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createLinearFunctionExtract( getOpLocation(Inst->getLoc()), Inst->getExtractee(), getOpValue(Inst->getOperand()), getBuilder().hasOwnership() ? Inst->getForwardingOwnershipKind() : ValueOwnershipKind(OwnershipKind::None))); } template void SILCloner::visitDifferentiabilityWitnessFunctionInst( DifferentiabilityWitnessFunctionInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createDifferentiabilityWitnessFunction( getOpLocation(Inst->getLoc()), Inst->getWitnessKind(), Inst->getWitness())); } template void SILCloner ::visitGetAsyncContinuationInst(GetAsyncContinuationInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createGetAsyncContinuation( getOpLocation(Inst->getLoc()), getOpASTType(Inst->getFormalResumeType()), Inst->throws())); } template void SILCloner ::visitGetAsyncContinuationAddrInst(GetAsyncContinuationAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createGetAsyncContinuationAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpASTType(Inst->getFormalResumeType()), Inst->throws())); } template void SILCloner ::visitAwaitAsyncContinuationInst(AwaitAsyncContinuationInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createAwaitAsyncContinuation( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpBasicBlock(Inst->getResumeBB()), Inst->getErrorBB() ? getOpBasicBlock(Inst->getErrorBB()) : nullptr)); } template void SILCloner ::visitHopToExecutorInst(HopToExecutorInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createHopToExecutor( getOpLocation(Inst->getLoc()), getOpValue(Inst->getTargetExecutor()), Inst->isMandatory())); } template void SILCloner ::visitExtractExecutorInst(ExtractExecutorInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createExtractExecutor( getOpLocation(Inst->getLoc()), getOpValue(Inst->getExpectedExecutor()))); } template void SILCloner ::visitFunctionExtractIsolationInst(FunctionExtractIsolationInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createFunctionExtractIsolation( getOpLocation(Inst->getLoc()), getOpValue(Inst->getFunction()))); } template void SILCloner::visitHasSymbolInst(HasSymbolInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createHasSymbol(getOpLocation(Inst->getLoc()), Inst->getDecl())); } template void SILCloner::visitIgnoredUseInst(IgnoredUseInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createIgnoredUse(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } } // end namespace swift #endif