blob: 6c6eafa76d969e10a336600dbeb1c588925053c3 [file] [log] [blame]
//===--- 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<typename ImplClass>
class SILCloner : protected SILInstructionVisitor<ImplClass> {
friend class SILVisitorBase<ImplClass>;
friend class SILInstructionVisitor<ImplClass>;
protected:
/// MARK: Context shared with CRTP extensions.
SILBuilder Builder;
TypeSubstitutionMap OpenedExistentialSubs;
SILOpenedArchetypesTracker OpenedArchetypesTracker;
private:
/// MARK: Private state hidden from CRTP extensions.
// The old-to-new value map.
llvm::DenseMap<SILValue, SILValue> ValueMap;
/// The old-to-new block map. Some entries may be premapped with original
/// blocks.
llvm::DenseMap<SILBasicBlock*, SILBasicBlock*> BBMap;
// 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<SILBasicBlock *, 8> preorderBlocks;
/// Set of basic blocks where unreachable was inserted.
SmallPtrSet<SILBasicBlock *, 32> 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<ImplClass>::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<SILInstruction*> *II) {
getBuilder().setTrackingList(II);
}
SmallVectorImpl<SILInstruction*> *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<SILBasicBlock *> exitBlocks,
SILBasicBlock *insertAfterBB = nullptr);
/// 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.
///
/// 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<SILValue> entryArgs);
/// 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() != nullptr : true)
&& "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<SILBasicBlock *> 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<ProtocolConformanceRef>
getOpConformances(Type ty,
ArrayRef<ProtocolConformanceRef> conformances) {
SmallVector<ProtocolConformanceRef, 4> 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 <size_t N, typename ArrayRefType>
SmallVector<SILValue, N> getOpValueArray(ArrayRefType Values) {
SmallVector<SILValue, N> 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 SomeSILCloner, unsigned N = 4>
class SILBuilderWithPostProcess : public SILBuilder {
SomeSILCloner &SC;
SILInstruction *Orig;
SmallVector<SILInstruction*, N> 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<typename ImplClass>
class SILClonerWithScopes : public SILCloner<ImplClass> {
friend class SILCloner<ImplClass>;
public:
SILClonerWithScopes(SILFunction &To,
SILOpenedArchetypesTracker &OpenedArchetypesTracker,
bool Disable = false)
: SILCloner<ImplClass>(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<ImplClass>(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> scopeCloner;
protected:
/// Clone the SILDebugScope for the cloned function.
void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
SILCloner<ImplClass>::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<SILFunctionCloner> {
using SuperTy = SILClonerWithScopes<SILFunctionCloner>;
friend class SILCloner<SILFunctionCloner>;
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<SILValue, 8> entryArgs;
entryArgs.reserve(newF->getArguments().size());
transform(newF->getArguments(), std::back_inserter(entryArgs),
[](SILArgument *arg) -> SILValue { return arg; });
SuperTy::cloneFunctionBody(origF, newEntryBB, entryArgs);
}
};
template<typename ImplClass>
SILValue
SILCloner<ImplClass>::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<SILUndef>(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 <typename ImplClass>
void SILCloner<ImplClass>::mapValue(SILValue origValue, SILValue mappedValue) {
auto iterAndInserted = ValueMap.insert({origValue, mappedValue});
(void)iterAndInserted;
assert(iterAndInserted.second && "Original value already mapped.");
}
template<typename ImplClass>
SILBasicBlock*
SILCloner<ImplClass>::remapBasicBlock(SILBasicBlock *BB) {
SILBasicBlock *MappedBB = BBMap[BB];
assert(MappedBB && "Unmapped basic block while cloning?");
return MappedBB;
}
template<typename ImplClass>
void
SILCloner<ImplClass>::postProcess(SILInstruction *orig,
SILInstruction *cloned) {
assert((orig->getDebugScope() ? cloned->getDebugScope()!=nullptr : true) &&
"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<typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::cloneReachableBlocks(
SILBasicBlock *startBB, ArrayRef<SILBasicBlock *> exitBlocks,
SILBasicBlock *insertAfterBB) {
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(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 <typename ImplClass>
void SILCloner<ImplClass>::cloneFunctionBody(SILFunction *F,
SILBasicBlock *clonedEntryBB,
ArrayRef<SILValue> entryArgs) {
assert(F != clonedEntryBB->getParent() && "Must clone into a new function.");
assert(BBMap.empty() && "This API does not allow clients to map blocks.");
assert(ValueMap.empty() && "Stale ValueMap.");
assert(entryArgs.size() == F->getArguments().size());
for (unsigned i = 0, e = entryArgs.size(); i != e; ++i)
ValueMap[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<typename ImplClass>
void SILCloner<ImplClass>::clonePhiArgs(SILBasicBlock *oldBB) {
auto *mappedBB = BBMap[oldBB];
// Create new arguments for each of the original block's arguments.
for (auto *Arg : oldBB->getPhiArguments()) {
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 <typename ImplClass>
void SILCloner<ImplClass>::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<SILBasicBlock *, 8> 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<typename ImplClass>
void
SILCloner<ImplClass>::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<CheckedCastBranchInst>(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<SwitchEnumInst>(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<UnreachableInst>(&I))
continue;
// Collect together all the instructions after this point
llvm::SmallVector<SILInstruction *, 32> 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<typename ImplClass>
void
SILCloner<ImplClass>::visitAllocStackInst(AllocStackInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createAllocStack(getOpLocation(Inst->getLoc()),
getOpType(Inst->getElementType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitAllocRefInst(AllocRefInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
auto CountArgs = getOpValueArray<8>(OperandValueArrayRef(Inst->
getTailAllocatedCounts()));
SmallVector<SILType, 4> 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<typename ImplClass>
void
SILCloner<ImplClass>::visitAllocRefDynamicInst(AllocRefDynamicInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
auto CountArgs = getOpValueArray<8>(OperandValueArrayRef(Inst->
getTailAllocatedCounts()));
SmallVector<SILType, 4> 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<typename ImplClass>
void
SILCloner<ImplClass>::visitAllocBoxInst(AllocBoxInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst,
getBuilder().createAllocBox(
getOpLocation(Inst->getLoc()),
this->getOpType(Inst->getType()).template castTo<SILBoxType>()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::visitAllocValueBufferInst(AllocValueBufferInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createAllocValueBuffer(
getOpLocation(Inst->getLoc()),
getOpType(Inst->getValueType()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::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<SILFunctionType>()->getCalleeConvention(),
Inst->isOnStack(),
GenericSpecializationInformation::create(Inst, getBuilder())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::visitAbortApplyInst(AbortApplyInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createAbortApply(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitEndApplyInst(EndApplyInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createEndApply(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitFunctionRefInst(FunctionRefInst *Inst) {
SILFunction *OpFunction = getOpFunction(Inst->getReferencedFunction());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createFunctionRef(
getOpLocation(Inst->getLoc()), OpFunction));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitDynamicFunctionRefInst(DynamicFunctionRefInst *Inst) {
SILFunction *OpFunction = getOpFunction(Inst->getReferencedFunction());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createDynamicFunctionRef(
getOpLocation(Inst->getLoc()), OpFunction));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitPreviousDynamicFunctionRefInst(
PreviousDynamicFunctionRefInst *Inst) {
SILFunction *OpFunction = getOpFunction(Inst->getReferencedFunction());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createPreviousDynamicFunctionRef(
getOpLocation(Inst->getLoc()), OpFunction));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitAllocGlobalInst(AllocGlobalInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createAllocGlobal(getOpLocation(Inst->getLoc()),
Inst->getReferencedGlobal()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitGlobalAddrInst(GlobalAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createGlobalAddr(getOpLocation(Inst->getLoc()),
Inst->getReferencedGlobal()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitGlobalValueInst(GlobalValueInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createGlobalValue(getOpLocation(Inst->getLoc()),
Inst->getReferencedGlobal()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitIntegerLiteralInst(IntegerLiteralInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createIntegerLiteral(getOpLocation(Inst->getLoc()),
getOpType(Inst->getType()),
Inst->getValue()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitFloatLiteralInst(FloatLiteralInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createFloatLiteral(getOpLocation(Inst->getLoc()),
getOpType(Inst->getType()),
Inst->getValue()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitStringLiteralInst(StringLiteralInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createStringLiteral(
getOpLocation(Inst->getLoc()),
Inst->getValue(), Inst->getEncoding()));
}
template <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::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()), SILValue()));
}
template <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::visitEndAccessInst(EndAccessInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createEndAccess(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->isAborting()));
}
template <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::visitAssignInst(AssignInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createAssign(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getSrc()),
getOpValue(Inst->getDest()),
Inst->getOwnershipQualifier()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitMarkUninitializedInst(MarkUninitializedInst *Inst) {
SILValue OpValue = getOpValue(Inst->getOperand());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createMarkUninitialized(getOpLocation(Inst->getLoc()),
OpValue, Inst->getKind()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::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 <typename ImplClass> \
void SILCloner<ImplClass>::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 <typename ImplClass> \
void SILCloner<ImplClass>::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 <typename ImplClass> \
void SILCloner<ImplClass>::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 <typename ImplClass> \
void SILCloner<ImplClass>::visit##Name##ToRefInst(Name##ToRefInst *Inst) { \
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \
recordClonedInstruction( \
Inst, getBuilder().create##Name##ToRef(getOpLocation(Inst->getLoc()), \
getOpValue(Inst->getOperand()), \
getOpType(Inst->getType()))); \
}
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
LOADABLE_REF_STORAGE_HELPER(Name, name) \
template <typename ImplClass> \
void SILCloner<ImplClass>::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 <typename ImplClass> \
void SILCloner<ImplClass>::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 <typename ImplClass> \
void SILCloner<ImplClass>::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())); \
} \
template <typename ImplClass> \
void SILCloner<ImplClass>::visitCopy##Name##ValueInst( \
Copy##Name##ValueInst *Inst) { \
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); \
recordClonedInstruction(Inst, getBuilder().createCopy##Name##Value( \
getOpLocation(Inst->getLoc()), \
getOpValue(Inst->getOperand()))); \
}
#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<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::visitConvertFunctionInst(ConvertFunctionInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createConvertFunction(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
getOpType(Inst->getType()), Inst->withoutActuallyEscaping()));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitConvertEscapeToNoEscapeInst(
ConvertEscapeToNoEscapeInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createConvertEscapeToNoEscape(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
getOpType(Inst->getType()), Inst->isLifetimeGuaranteed()));
}
template<typename ImplClass>
void SILCloner<ImplClass>::visitThinFunctionToPointerInst(
ThinFunctionToPointerInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createThinFunctionToPointer(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void SILCloner<ImplClass>::visitPointerToThinFunctionInst(
PointerToThinFunctionInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createPointerToThinFunction(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitUpcastInst(UpcastInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createUpcast(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitAddressToPointerInst(AddressToPointerInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createAddressToPointer(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::
visitUncheckedRefCastInst(UncheckedRefCastInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createUncheckedRefCast(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitUncheckedRefCastAddrInst(UncheckedRefCastAddrInst *Inst) {
SILLocation OpLoc = getOpLocation(Inst->getLoc());
SILValue SrcValue = getOpValue(Inst->getSrc());
SILValue DestValue = getOpValue(Inst->getDest());
CanType SrcType = getOpASTType(Inst->getSourceType());
CanType TargetType = getOpASTType(Inst->getTargetType());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createUncheckedRefCastAddr(OpLoc, SrcValue, SrcType,
DestValue, TargetType));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitUncheckedAddrCastInst(UncheckedAddrCastInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createUncheckedAddrCast(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitUncheckedTrivialBitCastInst(UncheckedTrivialBitCastInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createUncheckedTrivialBitCast(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitUncheckedBitwiseCastInst(UncheckedBitwiseCastInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createUncheckedBitwiseCast(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitRefToBridgeObjectInst(RefToBridgeObjectInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createRefToBridgeObject(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getConverted()),
getOpValue(Inst->getBitsOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitBridgeObjectToRefInst(BridgeObjectToRefInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createBridgeObjectToRef(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getConverted()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitBridgeObjectToWordInst(BridgeObjectToWordInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createBridgeObjectToWord(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getConverted()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitRefToRawPointerInst(RefToRawPointerInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createRefToRawPointer(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitValueToBridgeObjectInst(
ValueToBridgeObjectInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createValueToBridgeObject(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitRawPointerToRefInst(RawPointerToRefInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createRawPointerToRef(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitThinToThickFunctionInst(ThinToThickFunctionInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createThinToThickFunction(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitThickToObjCMetatypeInst(ThickToObjCMetatypeInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createThickToObjCMetatype(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitObjCToThickMetatypeInst(ObjCToThickMetatypeInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createObjCToThickMetatype(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitUnconditionalCheckedCastInst(
UnconditionalCheckedCastInst *Inst) {
SILLocation OpLoc = getOpLocation(Inst->getLoc());
SILValue OpValue = getOpValue(Inst->getOperand());
SILType OpType = getOpType(Inst->getType());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createUnconditionalCheckedCast(
OpLoc, OpValue, OpType));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitUnconditionalCheckedCastAddrInst(
UnconditionalCheckedCastAddrInst *Inst) {
SILLocation OpLoc = getOpLocation(Inst->getLoc());
SILValue SrcValue = getOpValue(Inst->getSrc());
SILValue DestValue = getOpValue(Inst->getDest());
CanType SrcType = getOpASTType(Inst->getSourceType());
CanType TargetType = getOpASTType(Inst->getTargetType());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst,
getBuilder().createUnconditionalCheckedCastAddr(
OpLoc, SrcValue, SrcType, DestValue, TargetType));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitUnconditionalCheckedCastValueInst(
UnconditionalCheckedCastValueInst *Inst) {
SILLocation OpLoc = getOpLocation(Inst->getLoc());
SILValue OpValue = getOpValue(Inst->getOperand());
SILType OpType = getOpType(Inst->getType());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst,
getBuilder().createUnconditionalCheckedCastValue(OpLoc, OpValue, OpType));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitRetainValueInst(RetainValueInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createRetainValue(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getAtomicity()));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitRetainValueAddrInst(RetainValueAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createRetainValueAddr(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getAtomicity()));
}
template <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::visitReleaseValueInst(ReleaseValueInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createReleaseValue(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getAtomicity()));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitReleaseValueAddrInst(
ReleaseValueAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createReleaseValueAddr(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getAtomicity()));
}
template <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::visitAutoreleaseValueInst(
AutoreleaseValueInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createAutoreleaseValue(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getAtomicity()));
}
template <typename ImplClass>
void SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::visitSetDeallocatingInst(SetDeallocatingInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createSetDeallocating(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getAtomicity()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::visitInitEnumDataAddrInst(InitEnumDataAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createInitEnumDataAddr(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
Inst->getElement(), getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitUncheckedEnumDataInst(UncheckedEnumDataInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createUncheckedEnumData(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
Inst->getElement(), getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitUncheckedTakeEnumDataAddrInst(UncheckedTakeEnumDataAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createUncheckedTakeEnumDataAddr(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
Inst->getElement(), getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitInjectEnumAddrInst(InjectEnumAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createInjectEnumAddr(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getElement()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitMetatypeInst(MetatypeInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createMetatype(getOpLocation(Inst->getLoc()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitValueMetatypeInst(ValueMetatypeInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createValueMetatype(getOpLocation(Inst->getLoc()),
getOpType(Inst->getType()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitExistentialMetatypeInst(ExistentialMetatypeInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createExistentialMetatype(
getOpLocation(Inst->getLoc()),
getOpType(Inst->getType()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitTupleExtractInst(TupleExtractInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createTupleExtract(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
Inst->getFieldNo(), getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitTupleElementAddrInst(TupleElementAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createTupleElementAddr(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
Inst->getFieldNo(), getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitStructExtractInst(StructExtractInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createStructExtract(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
Inst->getField(), getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitStructElementAddrInst(StructElementAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createStructElementAddr(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
Inst->getField(), getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitRefElementAddrInst(RefElementAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createRefElementAddr(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
Inst->getField(), getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitRefTailAddrInst(RefTailAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createRefTailAddr(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::visitClassMethodInst(ClassMethodInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createClassMethod(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getMember(), Inst->getType()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitSuperMethodInst(SuperMethodInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createSuperMethod(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getMember(), Inst->getType()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitObjCMethodInst(ObjCMethodInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createObjCMethod(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
Inst->getMember(), getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitObjCSuperMethodInst(ObjCSuperMethodInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createObjCSuperMethod(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getMember(), Inst->getType()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::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) &&
"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<typename ImplClass>
void
SILCloner<ImplClass>::visitOpenExistentialAddrInst(OpenExistentialAddrInst *Inst) {
// Create a new archetype for this opened existential type.
remapOpenedType(Inst->getType().castTo<OpenedArchetypeType>());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createOpenExistentialAddr(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
getOpType(Inst->getType()), Inst->getAccessKind()));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitOpenExistentialValueInst(
OpenExistentialValueInst *Inst) {
// Create a new archetype for this opened existential type.
remapOpenedType(Inst->getType().castTo<OpenedArchetypeType>());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createOpenExistentialValue(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
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<ExistentialMetatypeType>(exType)) {
exType = exMetatype.getInstanceType();
openedType = cast<MetatypeType>(openedType).getInstanceType();
}
remapOpenedType(cast<OpenedArchetypeType>(openedType));
if (!Inst->getOperand()->getType().canUseExistentialRepresentation(
Inst->getModule(), 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<typename ImplClass>
void
SILCloner<ImplClass>::
visitOpenExistentialRefInst(OpenExistentialRefInst *Inst) {
// Create a new archetype for this opened existential type.
remapOpenedType(Inst->getType().castTo<OpenedArchetypeType>());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createOpenExistentialRef(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitOpenExistentialBoxInst(OpenExistentialBoxInst *Inst) {
// Create a new archetype for this opened existential type.
remapOpenedType(Inst->getType().castTo<OpenedArchetypeType>());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createOpenExistentialBox(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::
visitOpenExistentialBoxValueInst(OpenExistentialBoxValueInst *Inst) {
// Create a new archetype for this opened existential type.
remapOpenedType(Inst->getType().castTo<OpenedArchetypeType>());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createOpenExistentialBoxValue(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::
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<typename ImplClass>
void
SILCloner<ImplClass>::
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<typename ImplClass>
void
SILCloner<ImplClass>::visitDeinitExistentialAddrInst(DeinitExistentialAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createDeinitExistentialAddr(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitDeinitExistentialValueInst(
DeinitExistentialValueInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createDeinitExistentialValue(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitCopyBlockInst(CopyBlockInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, Builder.createCopyBlock(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitCopyBlockWithoutEscapingInst(
CopyBlockWithoutEscapingInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, Builder.createCopyBlockWithoutEscaping(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getBlock()),
getOpValue(Inst->getClosure())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitStrongRetainInst(StrongRetainInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createStrongRetain(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getAtomicity()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitClassifyBridgeObjectInst(
ClassifyBridgeObjectInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createClassifyBridgeObject(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitFixLifetimeInst(FixLifetimeInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createFixLifetime(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}
template <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::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::Any) {
Kind = ValueOwnershipKind::Any;
}
recordClonedInstruction(Inst, getBuilder().createUncheckedOwnershipConversion(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()), Kind));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitMarkDependenceInst(MarkDependenceInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createMarkDependence(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getValue()),
getOpValue(Inst->getBase())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitStrongReleaseInst(StrongReleaseInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createStrongRelease(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getAtomicity()));
}
template<typename ImplClass>
void SILCloner<ImplClass>::visitIsUniqueInst(IsUniqueInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createIsUnique(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitIsEscapingClosureInst(
IsEscapingClosureInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createIsEscapingClosure(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getVerificationType()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitDeallocStackInst(DeallocStackInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createDeallocStack(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitDeallocRefInst(DeallocRefInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createDeallocRef(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->canAllocOnStack()));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitDeallocPartialRefInst(DeallocPartialRefInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createDeallocPartialRef(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getInstance()),
getOpValue(Inst->getMetatype())));
}
template<typename ImplClass>
void SILCloner<ImplClass>::visitDeallocValueBufferInst(
DeallocValueBufferInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createDeallocValueBuffer(
getOpLocation(Inst->getLoc()),
getOpType(Inst->getValueType()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitDeallocBoxInst(DeallocBoxInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createDeallocBox(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitDeallocExistentialBoxInst(
DeallocExistentialBoxInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createDeallocExistentialBox(
getOpLocation(Inst->getLoc()),
getOpASTType(Inst->getConcreteType()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitDestroyAddrInst(DestroyAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createDestroyAddr(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void SILCloner<ImplClass>::visitProjectValueBufferInst(
ProjectValueBufferInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createProjectValueBuffer(
getOpLocation(Inst->getLoc()),
getOpType(Inst->getValueType()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void SILCloner<ImplClass>::visitProjectBoxInst(ProjectBoxInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createProjectBox(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getFieldIndex()));
}
template<typename ImplClass>
void SILCloner<ImplClass>::visitProjectExistentialBoxInst(
ProjectExistentialBoxInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createProjectExistentialBox(
getOpLocation(Inst->getLoc()),
getOpType(Inst->getType()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitCondFailInst(CondFailInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createCondFail(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitIndexAddrInst(IndexAddrInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createIndexAddr(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getBase()),
getOpValue(Inst->getIndex())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::visitIndexRawPointerInst(IndexRawPointerInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createIndexRawPointer(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getBase()),
getOpValue(Inst->getIndex())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitUnreachableInst(UnreachableInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createUnreachable(getOpLocation(Inst->getLoc())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitReturnInst(ReturnInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createReturn(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitThrowInst(ThrowInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createThrow(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitUnwindInst(UnwindInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createUnwind(getOpLocation(Inst->getLoc())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::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<typename ImplClass>
void
SILCloner<ImplClass>::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->getCastType()),
OpSuccBB, OpFailBB, TrueCount, FalseCount));
}
template <typename ImplClass>
void SILCloner<ImplClass>::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()),
getOpType(Inst->getCastType()), OpSuccBB, OpFailBB));
}
template<typename ImplClass>
void SILCloner<ImplClass>::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->getSourceType());
CanType TargetType = getOpASTType(Inst->getTargetType());
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<typename ImplClass>
void
SILCloner<ImplClass>::visitSwitchValueInst(SwitchValueInst *Inst) {
SILBasicBlock *DefaultBB = nullptr;
if (Inst->hasDefault())
DefaultBB = getOpBasicBlock(Inst->getDefaultBB());
SmallVector<std::pair<SILValue, SILBasicBlock*>, 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<typename ImplClass>
void
SILCloner<ImplClass>::visitSwitchEnumInst(SwitchEnumInst *Inst) {
SILBasicBlock *DefaultBB = nullptr;
if (Inst->hasDefault())
DefaultBB = getOpBasicBlock(Inst->getDefaultBB());
SmallVector<std::pair<EnumElementDecl*, SILBasicBlock*>, 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<typename ImplClass>
void
SILCloner<ImplClass>::
visitSwitchEnumAddrInst(SwitchEnumAddrInst *Inst) {
SILBasicBlock *DefaultBB = nullptr;
if (Inst->hasDefault())
DefaultBB = getOpBasicBlock(Inst->getDefaultBB());
SmallVector<std::pair<EnumElementDecl*, SILBasicBlock*>, 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<typename ImplClass>
void
SILCloner<ImplClass>::visitSelectEnumInst(SelectEnumInst *Inst) {
SILValue DefaultResult;
if (Inst->hasDefault())
DefaultResult = getOpValue(Inst->getDefaultResult());
SmallVector<std::pair<EnumElementDecl*, SILValue>, 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<typename ImplClass>
void
SILCloner<ImplClass>::visitSelectEnumAddrInst(SelectEnumAddrInst *Inst) {
SILValue DefaultResult;
if (Inst->hasDefault())
DefaultResult = getOpValue(Inst->getDefaultResult());
SmallVector<std::pair<EnumElementDecl*, SILValue>, 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<typename ImplClass>
void
SILCloner<ImplClass>::visitSelectValueInst(SelectValueInst *Inst) {
SILValue DefaultResult;
if (Inst->hasDefault())
DefaultResult = getOpValue(Inst->getDefaultResult());
SmallVector<std::pair<SILValue, SILValue>, 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 <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::visitProjectBlockStorageInst(
ProjectBlockStorageInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createProjectBlockStorage(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template <typename ImplClass>
void SILCloner<ImplClass>::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 <typename ImplClass>
void SILCloner<ImplClass>::visitObjCMetatypeToObjectInst(
ObjCMetatypeToObjectInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(Inst, getBuilder().createObjCMetatypeToObject(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitObjCExistentialMetatypeToObjectInst(
ObjCExistentialMetatypeToObjectInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createObjCExistentialMetatypeToObject(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitObjCProtocolInst(ObjCProtocolInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
recordClonedInstruction(
Inst, getBuilder().createObjCProtocol(getOpLocation(Inst->getLoc()),
Inst->getProtocol(),
getOpType(Inst->getType())));
}
template <typename ImplClass>
void SILCloner<ImplClass>::visitKeyPathInst(KeyPathInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
SmallVector<SILValue, 4> 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())));
}
} // end namespace swift
#endif