//===--- 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/ProtocolConformance.h" #include "swift/SIL/SILOpenedArchetypesTracker.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILDebugScope.h" #include "swift/SIL/SILVisitor.h" namespace swift { /// 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; TypeSubstitutionMap OpenedExistentialSubs; SILOpenedArchetypesTracker OpenedArchetypesTracker; // 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; 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; /// Set of basic blocks where unreachable was inserted. SmallPtrSet BlocksWithUnreachables; // 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, SILOpenedArchetypesTracker &OpenedArchetypesTracker) : Builder(F), OpenedArchetypesTracker(OpenedArchetypesTracker) { Builder.setOpenedArchetypesTracker(&OpenedArchetypesTracker); } explicit SILCloner(SILFunction &F) : Builder(F), OpenedArchetypesTracker(&F) { Builder.setOpenedArchetypesTracker(&OpenedArchetypesTracker); } explicit SILCloner(SILGlobalVariable *GlobVar) : Builder(GlobVar), OpenedArchetypesTracker(nullptr) {} void clearClonerState() { ValueMap.clear(); BBMap.clear(); preorderBlocks.clear(); BlocksWithUnreachables.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); /// 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); } /// Mark a block containing an unreachable instruction for use in the `fixUp` /// callback. void addBlockWithUnreachable(SILBasicBlock *BB) { BlocksWithUnreachables.insert(BB); } /// Register a re-mapping for opened existentials. void registerOpenedExistentialRemapping(ArchetypeType *From, ArchetypeType *To) { auto result = OpenedExistentialSubs.insert( std::make_pair(CanArchetypeType(From), CanType(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) { // If we have open existentials to substitute, check whether that's // relevant to this this particular substitution. if (!OpenedExistentialSubs.empty()) { for (auto ty : Subs.getReplacementTypes()) { // If we found a type containing an opened existential, substitute // open existentials throughout the substitution map. if (ty->hasOpenedExistential()) { Subs = Subs.subst(QueryTypeSubstitutionMapOrIdentity{ OpenedExistentialSubs}, MakeAbstractConformanceForGenericType()); break; } } } return asImpl().remapSubstitutionMap(Subs).getCanonical(); } SILType getTypeInClonedContext(SILType Ty) { auto objectTy = Ty.getASTType(); // Do not substitute opened existential types, if we do not have any. if (!objectTy->hasOpenedExistential()) return Ty; // Do not substitute opened existential types, if it is not required. // This is often the case when cloning basic blocks inside the same // function. if (OpenedExistentialSubs.empty()) return Ty; // Substitute opened existential types, if we have any. return Ty.subst( Builder.getModule(), QueryTypeSubstitutionMapOrIdentity{OpenedExistentialSubs}, MakeAbstractConformanceForGenericType()); } SILType getOpType(SILType Ty) { Ty = getTypeInClonedContext(Ty); return asImpl().remapType(Ty); } CanType getASTTypeInClonedContext(Type ty) { // Do not substitute opened existential types, if we do not have any. if (!ty->hasOpenedExistential()) return ty->getCanonicalType(); // Do not substitute opened existential types, if it is not required. // This is often the case when cloning basic blocks inside the same // function. if (OpenedExistentialSubs.empty()) return ty->getCanonicalType(); return ty.subst( QueryTypeSubstitutionMapOrIdentity{OpenedExistentialSubs}, MakeAbstractConformanceForGenericType() )->getCanonicalType(); } CanType getOpASTType(CanType ty) { ty = getASTTypeInClonedContext(ty); return asImpl().remapASTType(ty); } void remapOpenedType(CanOpenedArchetypeType archetypeTy) { auto existentialTy = archetypeTy->getOpenedExistentialType()->getCanonicalType(); auto replacementTy = OpenedArchetypeType::get(getOpASTType(existentialTy)); registerOpenedExistentialRemapping(archetypeTy, replacementTy); } ProtocolConformanceRef getOpConformance(Type ty, ProtocolConformanceRef conformance) { // If we have open existentials to substitute, do so now. if (ty->hasOpenedExistential() && !OpenedExistentialSubs.empty()) { conformance = conformance.subst(ty, QueryTypeSubstitutionMapOrIdentity{ OpenedExistentialSubs}, MakeAbstractConformanceForGenericType()); } return asImpl().remapConformance(getASTTypeInClonedContext(ty), conformance); } ArrayRef getOpConformances(Type ty, ArrayRef conformances) { SmallVector newConformances; for (auto conformance : conformances) newConformances.push_back(getOpConformance(ty, conformance)); return ty->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; } SILType remapType(SILType Ty) { return Ty; } CanType remapASTType(CanType Ty) { return Ty; } ProtocolConformanceRef remapConformance(Type Ty, ProtocolConformanceRef C) { return C; } /// 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); SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) { return Subs; } /// This is called by either of the top-level visitors, cloneReachableBlocks /// or cloneSILFunction, after all other visitors are have been called. /// /// After fixUp, the SIL must be valid and semantically equivalent to the SIL /// before cloning. /// /// Common fix-ups are handled first in `doFixUp` and may not be overridden. void fixUp(SILFunction *F) {} private: /// MARK: SILCloner implementation details hidden from CRTP extensions. /// SILVisitor CRTP callback. Preprocess any instruction before cloning. void beforeVisit(SILInstruction *Orig) { // Update the set of available opened archetypes with the opened // archetypes used by the current instruction. auto TypeDependentOperands = Orig->getTypeDependentOperands(); Builder.getOpenedArchetypes().addOpenedArchetypeOperands( TypeDependentOperands); } void clonePhiArgs(SILBasicBlock *oldBB); void visitBlocksDepthFirst(SILBasicBlock *StartBB); /// Also perform fundamental cleanup first, then call the CRTP extension, /// `fixUp`. void doFixUp(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()); setOpenedArchetypesTracker(SC.getBuilder().getOpenedArchetypesTracker()); } ~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, SILOpenedArchetypesTracker &OpenedArchetypesTracker, bool Disable = false) : SILCloner(To, OpenedArchetypesTracker) { // 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)); } SILClonerWithScopes(SILFunction &To, bool Disable = false) : SILCloner(To) { // 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) {} /// 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) { 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; }); SuperTy::cloneFunctionBody(origF, newEntryBB, entryArgs); } }; 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()); ValueBase *undef = (type == U->getType() ? U : SILUndef::get(type, Builder.getFunction())); return SILValue(undef); } 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); doFixUp(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()); doFixUp(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()); 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 so // that all opened existentials are registered with OpenedArchetypesTracker // before phi argument type substitution in successors. getBuilder().setInsertionPoint(BBMap[BB]); asImpl().visitInstructionsInBlock(BB); unsigned dfsSuccStartIdx = dfsWorklist.size(); for (auto &succ : BB->getSuccessors()) { // Only visit a successor that has not already been visited and was not // premapped by the client. if (BBMap.count(succ)) continue; // Map the successor to a new BB. Layout the cloned blocks in the order // they are visited and cloned. lastClonedBB = getBuilder().getFunction().createBasicBlockAfter(lastClonedBB); 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::doFixUp(SILFunction *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; } } } } // Remove any code after unreachable instructions. // NOTE: It is unfortunate that it essentially duplicates the code from // sil-combine, but doing so allows for avoiding any cross-layer invocations // between SIL and SILOptimizer layers. for (auto *BB : BlocksWithUnreachables) { for (auto &I : *BB) { if (!isa(&I)) continue; // Collect together all the instructions after this point llvm::SmallVector ToRemove; for (auto Inst = BB->rbegin(); &*Inst != &I; ++Inst) ToRemove.push_back(&*Inst); for (auto *Inst : ToRemove) { // Replace any non-dead results with SILUndef values Inst->replaceAllUsesOfAllResultsWithUndef(); Inst->eraseFromParent(); } } } BlocksWithUnreachables.clear(); // Call any cleanup specific to the CRTP extensions. asImpl().fixUp(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()); Optional VarInfo = Inst->getVarInfo(); if (Loc.getKind() == SILLocation::MandatoryInlinedKind) { Loc = MandatoryInlinedLocation::getAutoGeneratedLocation(); VarInfo = None; } recordClonedInstruction(Inst, getBuilder().createAllocStack( Loc, getOpType(Inst->getElementType()), VarInfo)); } 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(), 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(), 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()); Optional VarInfo = Inst->getVarInfo(); if (Loc.getKind() == SILLocation::MandatoryInlinedKind) { Loc = MandatoryInlinedLocation::getAutoGeneratedLocation(); VarInfo = None; } recordClonedInstruction( Inst, getBuilder().createAllocBox( Loc, this->getOpType(Inst->getType()).template castTo(), VarInfo)); } template void SILCloner::visitAllocExistentialBoxInst( AllocExistentialBoxInst *Inst) { auto origExistentialType = Inst->getExistentialType(); auto origFormalType = Inst->getFormalConcreteType(); auto conformances = getOpConformances(origFormalType, Inst->getConformances()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createAllocExistentialBox( getOpLocation(Inst->getLoc()), getOpType(origExistentialType), getOpASTType(origFormalType), conformances)); } template void SILCloner::visitAllocValueBufferInst(AllocValueBufferInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createAllocValueBuffer( getOpLocation(Inst->getLoc()), getOpType(Inst->getValueType()), getOpValue(Inst->getOperand()))); } 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::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->isNonThrowing(), 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()), 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->getType().getAs()->getCalleeConvention(), 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->isNonThrowing(), 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()))); } template void SILCloner::visitFunctionRefInst(FunctionRefInst *Inst) { SILFunction *OpFunction = getOpFunction(Inst->getInitiallyReferencedFunction()); 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())); } template void SILCloner::visitGlobalValueInst(GlobalValueInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createGlobalValue(getOpLocation(Inst->getLoc()), Inst->getReferencedGlobal())); } 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()))); } 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()) { // TODO: Eliminate store_borrow result so we can use // recordClonedInstruction. It is not "technically" necessary, but it is // better from an invariant perspective. getBuilder().createStore( getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()), StoreOwnershipQualifier::Unqualified); 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->getOwnershipQualifier())); } 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->getKind())); } 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. getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDebugValue(Inst->getLoc(), getOpValue(Inst->getOperand()), *Inst->getVarInfo())); } template void SILCloner::visitDebugValueAddrInst(DebugValueAddrInst *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; // Do not remap the location for a debug Instruction. SILValue OpValue = getOpValue(Inst->getOperand()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDebugValueAddr(Inst->getLoc(), OpValue, *Inst->getVarInfo())); } #define NEVER_LOADABLE_CHECKED_REF_STORAGE(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()))); \ } \ 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 ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ LOADABLE_REF_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 SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, "...") \ ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, "...") #define UNCHECKED_REF_STORAGE(Name, name, ...) \ LOADABLE_REF_STORAGE_HELPER(Name, name) #include "swift/AST/ReferenceStorage.def" #undef LOADABLE_REF_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::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::visitConvertFunctionInst(ConvertFunctionInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createConvertFunction( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()), Inst->withoutActuallyEscaping())); } 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::visitThinFunctionToPointerInst( ThinFunctionToPointerInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createThinFunctionToPointer( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner::visitPointerToThinFunctionInst( PointerToThinFunctionInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createPointerToThinFunction( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner::visitUpcastInst(UpcastInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createUpcast(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner::visitAddressToPointerInst(AddressToPointerInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createAddressToPointer(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } 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())); } template void SILCloner:: visitUncheckedRefCastInst(UncheckedRefCastInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createUncheckedRefCast(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } 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:: visitRefToBridgeObjectInst(RefToBridgeObjectInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createRefToBridgeObject( getOpLocation(Inst->getLoc()), getOpValue(Inst->getConverted()), getOpValue(Inst->getBitsOperand()))); } template void SILCloner:: visitBridgeObjectToRefInst(BridgeObjectToRefInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createBridgeObjectToRef( getOpLocation(Inst->getLoc()), getOpValue(Inst->getConverted()), getOpType(Inst->getType()))); } template void SILCloner:: visitBridgeObjectToWordInst(BridgeObjectToWordInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createBridgeObjectToWord( getOpLocation(Inst->getLoc()), getOpValue(Inst->getConverted()), 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()))); } 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, OpValue, OpLoweredType, OpFormalType)); } 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, SrcValue, SrcType, DestValue, TargetType)); } template void SILCloner::visitUnconditionalCheckedCastValueInst( UnconditionalCheckedCastValueInst *Inst) { SILLocation OpLoc = getOpLocation(Inst->getLoc()); SILValue OpValue = getOpValue(Inst->getOperand()); CanType SrcFormalType = getOpASTType(Inst->getSourceFormalType()); SILType OpLoweredType = getOpType(Inst->getTargetLoweredType()); CanType OpFormalType = getOpASTType(Inst->getTargetFormalType()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createUnconditionalCheckedCastValue(OpLoc, OpValue, SrcFormalType, OpLoweredType, OpFormalType)); } 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()) { 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::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()) { return recordClonedInstruction( Inst, getBuilder().createReleaseValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), RefCountingInst::Atomicity::Atomic)); } recordClonedInstruction( Inst, getBuilder().createDestroyValue(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } 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::visitSetDeallocatingInst(SetDeallocatingInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createSetDeallocating(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getAtomicity())); } 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::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)); } 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)); } 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()))); } 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()))); } 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->getFieldNo(), getOpType(Inst->getType()))); } template void SILCloner::visitTupleElementAddrInst(TupleElementAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createTupleElementAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getFieldNo(), 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()))); } 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::visitRefElementAddrInst(RefElementAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createRefElementAddr( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->getField(), getOpType(Inst->getType()))); } template void SILCloner::visitRefTailAddrInst(RefTailAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createRefTailAddr(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } 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()))); } 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()))); } 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 lookupType = Inst->getLookupType(); auto conformance = getOpConformance(lookupType, Inst->getConformance()); auto newLookupType = getOpASTType(lookupType); if (conformance.isConcrete()) { CanType Ty = conformance.getConcrete()->getType()->getCanonicalType(); if (Ty != newLookupType) { assert( (Ty->isExactSuperclassOf(newLookupType) || getBuilder().getModule().Types.getLoweredRValueType( getBuilder().getTypeExpansionContext(), Ty) == newLookupType) && "Should only create upcasts for sub class."); // We use the super class as the new look up type. newLookupType = Ty; } } getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createWitnessMethod( getOpLocation(Inst->getLoc()), newLookupType, conformance, Inst->getMember(), Inst->getType())); } template void SILCloner::visitOpenExistentialAddrInst(OpenExistentialAddrInst *Inst) { // Create a new archetype for this opened existential type. remapOpenedType(Inst->getType().castTo()); 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. remapOpenedType(Inst->getType().castTo()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createOpenExistentialValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner:: visitOpenExistentialMetatypeInst(OpenExistentialMetatypeInst *Inst) { // Create a new archetype for this opened existential type. auto openedType = Inst->getType().getASTType(); auto exType = Inst->getOperand()->getType().getASTType(); while (auto exMetatype = dyn_cast(exType)) { exType = exMetatype.getInstanceType(); openedType = cast(openedType).getInstanceType(); } remapOpenedType(cast(openedType)); 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. remapOpenedType(Inst->getType().castTo()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createOpenExistentialRef( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner:: visitOpenExistentialBoxInst(OpenExistentialBoxInst *Inst) { // Create a new archetype for this opened existential type. remapOpenedType(Inst->getType().castTo()); 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. remapOpenedType(Inst->getType().castTo()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createOpenExistentialBoxValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpType(Inst->getType()))); } template void SILCloner::visitInitExistentialAddrInst(InitExistentialAddrInst *Inst) { CanType origFormalType = Inst->getFormalConcreteType(); auto conformances = getOpConformances(origFormalType, 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(origFormalType, 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 origFormalType = Inst->getFormalErasedObjectType(); auto conformances = getOpConformances(origFormalType, 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(origFormalType, 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::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::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() == ValueOwnershipKind::None) { Kind = ValueOwnershipKind::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()))); } 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::visitIsEscapingClosureInst( IsEscapingClosureInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createIsEscapingClosure(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::visitDeallocRefInst(DeallocRefInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDeallocRef(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), Inst->canAllocOnStack())); } 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::visitDeallocValueBufferInst( DeallocValueBufferInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createDeallocValueBuffer( getOpLocation(Inst->getLoc()), getOpType(Inst->getValueType()), getOpValue(Inst->getOperand()))); } template void SILCloner::visitDeallocBoxInst(DeallocBoxInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createDeallocBox(getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()))); } 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::visitProjectValueBufferInst( ProjectValueBufferInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createProjectValueBuffer( getOpLocation(Inst->getLoc()), getOpType(Inst->getValueType()), 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::visitIndexAddrInst(IndexAddrInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createIndexAddr(getOpLocation(Inst->getLoc()), getOpValue(Inst->getBase()), getOpValue(Inst->getIndex()))); } 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::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(), getOpValue(Inst->getOperand()), getOpType(Inst->getTargetLoweredType()), getOpASTType(Inst->getTargetFormalType()), OpSuccBB, OpFailBB, TrueCount, FalseCount)); } template void SILCloner::visitCheckedCastValueBranchInst( CheckedCastValueBranchInst *Inst) { SILBasicBlock *OpSuccBB = getOpBasicBlock(Inst->getSuccessBB()); SILBasicBlock *OpFailBB = getOpBasicBlock(Inst->getFailureBB()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createCheckedCastValueBranch( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), getOpASTType(Inst->getSourceFormalType()), getOpType(Inst->getTargetLoweredType()), getOpASTType(Inst->getTargetFormalType()), OpSuccBB, OpFailBB)); } 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->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)); } 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)); } 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::visitSelectValueInst(SelectValueInst *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(getOpValue(Inst->getCase(i).first), getOpValue(Inst->getCase(i).second))); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createSelectValue( getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), 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 (auto &op : Inst->getAllOperands()) 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())); Optional> derivativeFns = None; if (Inst->hasDerivativeFunctions()) derivativeFns = std::make_pair(getOpValue(Inst->getJVPFunction()), getOpValue(Inst->getVJPFunction())); recordClonedInstruction( Inst, getBuilder().createDifferentiableFunction( getOpLocation(Inst->getLoc()), Inst->getParameterIndices(), getOpValue(Inst->getOriginalFunction()), derivativeFns)); } 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()), transpose)); } template void SILCloner::visitDifferentiableFunctionExtractInst( DifferentiableFunctionExtractInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); Optional explicitExtracteeType = None; if (Inst->hasExplicitExtracteeType()) explicitExtracteeType = Inst->getType(); recordClonedInstruction( Inst, getBuilder().createDifferentiableFunctionExtract( getOpLocation(Inst->getLoc()), Inst->getExtractee(), getOpValue(Inst->getOperand()), explicitExtracteeType)); } template void SILCloner:: visitLinearFunctionExtractInst(LinearFunctionExtractInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createLinearFunctionExtract( getOpLocation(Inst->getLoc()), Inst->getExtractee(), getOpValue(Inst->getFunctionOperand()))); } template void SILCloner::visitDifferentiabilityWitnessFunctionInst( DifferentiabilityWitnessFunctionInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction(Inst, getBuilder().createDifferentiabilityWitnessFunction( getOpLocation(Inst->getLoc()), Inst->getWitnessKind(), Inst->getWitness())); } } // end namespace swift #endif