本文整理汇总了C++中ApplySite::getInstruction方法的典型用法代码示例。如果您正苦于以下问题:C++ ApplySite::getInstruction方法的具体用法?C++ ApplySite::getInstruction怎么用?C++ ApplySite::getInstruction使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类ApplySite
的用法示例。
在下文中一共展示了ApplySite::getInstruction方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: B
/// Generate a new apply of a function_ref to replace an apply of a
/// witness_method when we've determined the actual function we'll end
/// up calling.
static ApplySite
devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
ProtocolConformanceRef C, OptRemark::Emitter *ORE) {
// We know the witness thunk and the corresponding set of substitutions
// required to invoke the protocol method at this point.
auto &Module = AI.getModule();
// Collect all the required substitutions.
//
// The complete set of substitutions may be different, e.g. because the found
// witness thunk F may have been created by a specialization pass and have
// additional generic parameters.
auto SubMap = getWitnessMethodSubstitutions(Module, AI, F, C);
// Figure out the exact bound type of the function to be called by
// applying all substitutions.
auto CalleeCanType = F->getLoweredFunctionType();
auto SubstCalleeCanType = CalleeCanType->substGenericArgs(Module, SubMap);
// Collect arguments from the apply instruction.
auto Arguments = SmallVector<SILValue, 4>();
// Iterate over the non self arguments and add them to the
// new argument list, upcasting when required.
SILBuilderWithScope B(AI.getInstruction());
SILFunctionConventions substConv(SubstCalleeCanType, Module);
unsigned substArgIdx = AI.getCalleeArgIndexOfFirstAppliedArg();
for (auto arg : AI.getArguments()) {
auto paramType = substConv.getSILArgumentType(substArgIdx++);
if (arg->getType() != paramType)
arg = castValueToABICompatibleType(&B, AI.getLoc(), arg,
arg->getType(), paramType);
Arguments.push_back(arg);
}
assert(substArgIdx == substConv.getNumSILArguments());
// Replace old apply instruction by a new apply instruction that invokes
// the witness thunk.
SILBuilderWithScope Builder(AI.getInstruction());
SILLocation Loc = AI.getLoc();
FunctionRefInst *FRI = Builder.createFunctionRef(Loc, F);
ApplySite SAI = replaceApplySite(Builder, Loc, AI, FRI, SubMap, Arguments,
substConv);
if (ORE)
ORE->emit([&]() {
using namespace OptRemark;
return RemarkPassed("WitnessMethodDevirtualized", *AI.getInstruction())
<< "Devirtualized call to " << NV("Method", F);
});
NumWitnessDevirt++;
return SAI;
}
示例2: findConcreteType
/// Find the concrete type of the existential argument. Wrapper
/// for findInitExistential in Local.h/cpp. In future, this code
/// can move to Local.h/cpp.
static bool findConcreteType(ApplySite AI, int ArgIdx, CanType &ConcreteType) {
bool isCopied = false;
auto Arg = AI.getArgument(ArgIdx);
/// Ignore any unconditional cast instructions. Is it Safe? Do we need to
/// also add UnconditionalCheckedCastAddrInst? TODO.
if (auto *Instance = dyn_cast<UnconditionalCheckedCastInst>(Arg)) {
Arg = Instance->getOperand();
}
/// Return init_existential if the Arg is global_addr.
if (auto *GAI = dyn_cast<GlobalAddrInst>(Arg)) {
SILValue InitExistential =
findInitExistentialFromGlobalAddrAndApply(GAI, AI, ArgIdx);
/// If the Arg is already init_existential, return the concrete type.
if (InitExistential &&
findConcreteTypeFromInitExistential(InitExistential, ConcreteType)) {
return true;
}
}
/// Handle AllocStack instruction separately.
if (auto *Instance = dyn_cast<AllocStackInst>(Arg)) {
if (SILValue Src =
getAddressOfStackInit(Instance, AI.getInstruction(), isCopied)) {
Arg = Src;
}
}
/// If the Arg is already init_existential after getAddressofStackInit
/// call, return the concrete type.
if (findConcreteTypeFromInitExistential(Arg, ConcreteType)) {
return true;
}
/// Call findInitExistential and determine the init_existential.
ArchetypeType *OpenedArchetype = nullptr;
SILValue OpenedArchetypeDef;
auto FAS = FullApplySite::isa(AI.getInstruction());
if (!FAS)
return false;
SILInstruction *InitExistential =
findInitExistential(FAS.getArgumentOperands()[ArgIdx], OpenedArchetype,
OpenedArchetypeDef, isCopied);
if (!InitExistential) {
LLVM_DEBUG(llvm::dbgs() << "ExistentialSpecializer Pass: Bail! Due to "
"findInitExistential\n";);
示例3: specializeGeneric
ApplySite SILPerformanceInliner::specializeGeneric(
ApplySite Apply, llvm::SmallVectorImpl<ApplySite> &NewApplies) {
assert(NewApplies.empty() && "Expected out parameter for new applies!");
if (!Apply.hasSubstitutions())
return ApplySite();
auto *Callee = Apply.getCalleeFunction();
if (!Callee || Callee->isExternalDeclaration())
return ApplySite();
auto Filter = [](SILInstruction *I) -> bool {
return ApplySite::isa(I) != ApplySite();
};
CloneCollector Collector(Filter);
SILFunction *SpecializedFunction;
auto Specialized = trySpecializeApplyOfGeneric(Apply,
SpecializedFunction,
Collector);
if (!Specialized)
return ApplySite();
// Track the new applies from the specialization.
for (auto NewCallSite : Collector.getInstructionPairs())
NewApplies.push_back(ApplySite(NewCallSite.first));
auto FullApply = FullApplySite::isa(Apply.getInstruction());
if (!FullApply) {
assert(!FullApplySite::isa(Specialized.getInstruction()) &&
"Unexpected full apply generated!");
// Replace the old apply with the new and delete the old.
replaceDeadApply(Apply, Specialized.getInstruction());
return ApplySite(Specialized);
}
// Replace the old apply with the new and delete the old.
replaceDeadApply(Apply, Specialized.getInstruction());
return Specialized;
}
示例4: devirtualizeWitnessMethod
/// Generate a new apply of a function_ref to replace an apply of a
/// witness_method when we've determined the actual function we'll end
/// up calling.
static ApplySite devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
ArrayRef<Substitution> Subs) {
// We know the witness thunk and the corresponding set of substitutions
// required to invoke the protocol method at this point.
auto &Module = AI.getModule();
// Collect all the required substitutions.
//
// The complete set of substitutions may be different, e.g. because the found
// witness thunk F may have been created by a specialization pass and have
// additional generic parameters.
SmallVector<Substitution, 16> NewSubstList(Subs.begin(), Subs.end());
// Add the non-self-derived substitutions from the original application.
ArrayRef<Substitution> SubstList;
SubstList = AI.getSubstitutionsWithoutSelfSubstitution();
for (auto &origSub : SubstList)
if (!origSub.getArchetype()->isSelfDerived())
NewSubstList.push_back(origSub);
// Figure out the exact bound type of the function to be called by
// applying all substitutions.
auto CalleeCanType = F->getLoweredFunctionType();
auto SubstCalleeCanType = CalleeCanType->substGenericArgs(
Module, Module.getSwiftModule(), NewSubstList);
// Collect arguments from the apply instruction.
auto Arguments = SmallVector<SILValue, 4>();
auto ParamTypes = SubstCalleeCanType->getParameterSILTypes();
// Iterate over the non self arguments and add them to the
// new argument list, upcasting when required.
SILBuilderWithScope B(AI.getInstruction());
for (unsigned ArgN = 0, ArgE = AI.getNumArguments(); ArgN != ArgE; ++ArgN) {
SILValue A = AI.getArgument(ArgN);
auto ParamType = ParamTypes[ParamTypes.size() - AI.getNumArguments() + ArgN];
if (A.getType() != ParamType)
A = B.createUpcast(AI.getLoc(), A, ParamType);
Arguments.push_back(A);
}
// Replace old apply instruction by a new apply instruction that invokes
// the witness thunk.
SILBuilderWithScope Builder(AI.getInstruction());
SILLocation Loc = AI.getLoc();
FunctionRefInst *FRI = Builder.createFunctionRef(Loc, F);
auto SubstCalleeSILType = SILType::getPrimitiveObjectType(SubstCalleeCanType);
auto ResultSILType = SubstCalleeCanType->getSILResult();
ApplySite SAI;
if (auto *A = dyn_cast<ApplyInst>(AI))
SAI = Builder.createApply(Loc, FRI, SubstCalleeSILType,
ResultSILType, NewSubstList, Arguments,
A->isNonThrowing());
if (auto *TAI = dyn_cast<TryApplyInst>(AI))
SAI = Builder.createTryApply(Loc, FRI, SubstCalleeSILType,
NewSubstList, Arguments,
TAI->getNormalBB(), TAI->getErrorBB());
if (auto *PAI = dyn_cast<PartialApplyInst>(AI))
SAI = Builder.createPartialApply(Loc, FRI, SubstCalleeSILType,
NewSubstList, Arguments, PAI->getType());
NumWitnessDevirt++;
return SAI;
}
示例5: specializeAppliesInFunction
bool GenericSpecializer::specializeAppliesInFunction(SILFunction &F) {
bool Changed = false;
llvm::SmallVector<SILInstruction *, 8> DeadApplies;
for (auto &BB : F) {
for (auto It = BB.begin(), End = BB.end(); It != End;) {
auto &I = *It++;
// Skip non-apply instructions, apply instructions with no
// substitutions, apply instructions where we do not statically
// know the called function, and apply instructions where we do
// not have the body of the called function.
ApplySite Apply = ApplySite::isa(&I);
if (!Apply || !Apply.hasSubstitutions())
continue;
auto *Callee = Apply.getCalleeFunction();
if (!Callee || !Callee->isDefinition())
continue;
// We have a call that can potentially be specialized, so
// attempt to do so.
// The specializer helper function currently expects a collector
// argument, but we aren't going to make use of the results so
// we'll have our filter always return false;
auto Filter = [](SILInstruction *I) -> bool { return false; };
CloneCollector Collector(Filter);
SILFunction *SpecializedFunction;
auto Specialized =
trySpecializeApplyOfGeneric(Apply, SpecializedFunction, Collector);
if (Specialized) {
Changed = true;
// If calling the specialization utility resulted in a new
// function (as opposed to returning a previous
// specialization), we need to notify the pass manager so that
// the new function gets optimized.
if (SpecializedFunction)
notifyPassManagerOfFunction(SpecializedFunction);
auto *AI = Apply.getInstruction();
if (!isa<TryApplyInst>(AI))
AI->replaceAllUsesWith(Specialized.getInstruction());
DeadApplies.push_back(AI);
}
}
}
// Remove all the now-dead applies.
while (!DeadApplies.empty()) {
auto *AI = DeadApplies.pop_back_val();
recursivelyDeleteTriviallyDeadInstructions(AI, true);
}
return Changed;
}
示例6: specializeAppliesInFunction
bool GenericSpecializer::specializeAppliesInFunction(SILFunction &F) {
DeadInstructionSet DeadApplies;
llvm::SmallSetVector<SILInstruction *, 8> Applies;
bool Changed = false;
for (auto &BB : F) {
// Collect the applies for this block in reverse order so that we
// can pop them off the end of our vector and process them in
// forward order.
for (auto It = BB.rbegin(), End = BB.rend(); It != End; ++It) {
auto *I = &*It;
// Skip non-apply instructions, apply instructions with no
// substitutions, apply instructions where we do not statically
// know the called function, and apply instructions where we do
// not have the body of the called function.
ApplySite Apply = ApplySite::isa(I);
if (!Apply || !Apply.hasSubstitutions())
continue;
auto *Callee = Apply.getReferencedFunction();
if (!Callee || !Callee->isDefinition())
continue;
Applies.insert(Apply.getInstruction());
}
// Attempt to specialize each apply we collected, deleting any
// that we do specialize (along with other instructions we clone
// in the process of doing so). We pop from the end of the list to
// avoid tricky iterator invalidation issues.
while (!Applies.empty()) {
auto *I = Applies.pop_back_val();
auto Apply = ApplySite::isa(I);
assert(Apply && "Expected an apply!");
SILFunction *Callee = Apply.getReferencedFunction();
assert(Callee && "Expected to have a known callee");
// We have a call that can potentially be specialized, so
// attempt to do so.
llvm::SmallVector<SILFunction *, 2> NewFunctions;
trySpecializeApplyOfGeneric(Apply, DeadApplies, NewFunctions);
// Remove all the now-dead applies. We must do this immediately
// rather than defer it in order to avoid problems with cloning
// dead instructions when doing recursive specialization.
while (!DeadApplies.empty()) {
auto *AI = DeadApplies.pop_back_val();
// Remove any applies we are deleting so that we don't attempt
// to specialize them.
Applies.remove(AI);
recursivelyDeleteTriviallyDeadInstructions(AI, true);
Changed = true;
}
// If calling the specialization utility resulted in new functions
// (as opposed to returning a previous specialization), we need to notify
// the pass manager so that the new functions get optimized.
for (SILFunction *NewF : reverse(NewFunctions)) {
notifyPassManagerOfFunction(NewF, Callee);
}
}
}
return Changed;
}
示例7: devirtualizeWitnessMethod
/// Generate a new apply of a function_ref to replace an apply of a
/// witness_method when we've determined the actual function we'll end
/// up calling.
static ApplySite devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
ArrayRef<Substitution> Subs) {
// We know the witness thunk and the corresponding set of substitutions
// required to invoke the protocol method at this point.
auto &Module = AI.getModule();
// Collect all the required substitutions.
//
// The complete set of substitutions may be different, e.g. because the found
// witness thunk F may have been created by a specialization pass and have
// additional generic parameters.
SmallVector<Substitution, 16> NewSubstList(Subs.begin(), Subs.end());
if (auto generics = AI.getOrigCalleeType()->getGenericSignature()) {
ArrayRef<Substitution> origSubs = AI.getSubstitutions();
for (auto genericParam : generics->getAllDependentTypes()) {
auto origSub = origSubs.front();
origSubs = origSubs.slice(1);
// Ignore generic parameters derived from 'self', the generic
// parameter at depth 0, index 0.
auto type = genericParam->getCanonicalType();
while (auto memberType = dyn_cast<DependentMemberType>(type)) {
type = memberType.getBase();
}
auto paramType = cast<GenericTypeParamType>(type);
if (paramType->getDepth() == 0) {
// There shouldn't be any other parameters at this depth.
assert(paramType->getIndex() == 0);
continue;
}
// Okay, remember this substitution.
NewSubstList.push_back(origSub);
}
assert(origSubs.empty() && "subs not parallel to dependent types");
}
// Figure out the exact bound type of the function to be called by
// applying all substitutions.
auto CalleeCanType = F->getLoweredFunctionType();
auto SubstCalleeCanType = CalleeCanType->substGenericArgs(
Module, Module.getSwiftModule(), NewSubstList);
// Collect arguments from the apply instruction.
auto Arguments = SmallVector<SILValue, 4>();
// Iterate over the non self arguments and add them to the
// new argument list, upcasting when required.
SILBuilderWithScope B(AI.getInstruction());
for (unsigned ArgN = 0, ArgE = AI.getNumArguments(); ArgN != ArgE; ++ArgN) {
SILValue A = AI.getArgument(ArgN);
auto ParamType = SubstCalleeCanType->getSILArgumentType(
SubstCalleeCanType->getNumSILArguments() - AI.getNumArguments() + ArgN);
if (A->getType() != ParamType)
A = B.createUpcast(AI.getLoc(), A, ParamType);
Arguments.push_back(A);
}
// Replace old apply instruction by a new apply instruction that invokes
// the witness thunk.
SILBuilderWithScope Builder(AI.getInstruction());
SILLocation Loc = AI.getLoc();
FunctionRefInst *FRI = Builder.createFunctionRef(Loc, F);
auto SubstCalleeSILType = SILType::getPrimitiveObjectType(SubstCalleeCanType);
auto ResultSILType = SubstCalleeCanType->getSILResult();
ApplySite SAI;
if (auto *A = dyn_cast<ApplyInst>(AI))
SAI = Builder.createApply(Loc, FRI, SubstCalleeSILType,
ResultSILType, NewSubstList, Arguments,
A->isNonThrowing());
if (auto *TAI = dyn_cast<TryApplyInst>(AI))
SAI = Builder.createTryApply(Loc, FRI, SubstCalleeSILType,
NewSubstList, Arguments,
TAI->getNormalBB(), TAI->getErrorBB());
if (auto *PAI = dyn_cast<PartialApplyInst>(AI))
SAI = Builder.createPartialApply(Loc, FRI, SubstCalleeSILType,
NewSubstList, Arguments, PAI->getType());
NumWitnessDevirt++;
return SAI;
}
示例8: devirtualizeClassMethod
/// \brief Devirtualize an apply of a class method.
///
/// \p AI is the apply to devirtualize.
/// \p ClassOrMetatype is a class value or metatype value that is the
/// self argument of the apply we will devirtualize.
/// return the result value of the new ApplyInst if created one or null.
FullApplySite swift::devirtualizeClassMethod(FullApplySite AI,
SILValue ClassOrMetatype,
OptRemark::Emitter *ORE) {
LLVM_DEBUG(llvm::dbgs() << " Trying to devirtualize : "
<< *AI.getInstruction());
SILModule &Mod = AI.getModule();
auto *MI = cast<MethodInst>(AI.getCallee());
auto ClassOrMetatypeType = ClassOrMetatype->getType();
auto *F = getTargetClassMethod(Mod, ClassOrMetatypeType, MI);
CanSILFunctionType GenCalleeType = F->getLoweredFunctionType();
SubstitutionMap Subs =
getSubstitutionsForCallee(Mod, GenCalleeType,
ClassOrMetatypeType.getASTType(),
AI);
CanSILFunctionType SubstCalleeType = GenCalleeType;
if (GenCalleeType->isPolymorphic())
SubstCalleeType = GenCalleeType->substGenericArgs(Mod, Subs);
SILFunctionConventions substConv(SubstCalleeType, Mod);
SILBuilderWithScope B(AI.getInstruction());
SILLocation Loc = AI.getLoc();
FunctionRefInst *FRI = B.createFunctionRef(Loc, F);
// Create the argument list for the new apply, casting when needed
// in order to handle covariant indirect return types and
// contravariant argument types.
llvm::SmallVector<SILValue, 8> NewArgs;
auto IndirectResultArgIter = AI.getIndirectSILResults().begin();
for (auto ResultTy : substConv.getIndirectSILResultTypes()) {
NewArgs.push_back(
castValueToABICompatibleType(&B, Loc, *IndirectResultArgIter,
IndirectResultArgIter->getType(), ResultTy));
++IndirectResultArgIter;
}
auto ParamArgIter = AI.getArgumentsWithoutIndirectResults().begin();
// Skip the last parameter, which is `self`. Add it below.
for (auto param : substConv.getParameters().drop_back()) {
auto paramType = substConv.getSILType(param);
NewArgs.push_back(
castValueToABICompatibleType(&B, Loc, *ParamArgIter,
ParamArgIter->getType(), paramType));
++ParamArgIter;
}
// Add the self argument, upcasting if required because we're
// calling a base class's method.
auto SelfParamTy = substConv.getSILType(SubstCalleeType->getSelfParameter());
NewArgs.push_back(castValueToABICompatibleType(&B, Loc,
ClassOrMetatype,
ClassOrMetatypeType,
SelfParamTy));
ApplySite NewAS = replaceApplySite(B, Loc, AI, FRI, Subs, NewArgs, substConv);
FullApplySite NewAI = FullApplySite::isa(NewAS.getInstruction());
assert(NewAI);
LLVM_DEBUG(llvm::dbgs() << " SUCCESS: " << F->getName() << "\n");
if (ORE)
ORE->emit([&]() {
using namespace OptRemark;
return RemarkPassed("ClassMethodDevirtualized", *AI.getInstruction())
<< "Devirtualized call to class method " << NV("Method", F);
});
NumClassDevirt++;
return NewAI;
}
示例9: deleteDevirtualizedApply
/// Delete an apply site that's been successfully devirtualized.
void swift::deleteDevirtualizedApply(ApplySite Old) {
auto *OldApply = Old.getInstruction();
recursivelyDeleteTriviallyDeadInstructions(OldApply, true);
}
示例10: tryDevirtualizeApply
/// Attempt to devirtualize the given apply if possible, and return a
/// new instruction in that case, or nullptr otherwise.
ApplySite swift::tryDevirtualizeApply(ApplySite AI,
ClassHierarchyAnalysis *CHA,
OptRemark::Emitter *ORE) {
LLVM_DEBUG(llvm::dbgs() << " Trying to devirtualize: "
<< *AI.getInstruction());
// Devirtualize apply instructions that call witness_method instructions:
//
// %8 = witness_method $Optional<UInt16>, #LogicValue.boolValue!getter.1
// %9 = apply %8<Self = CodeUnit?>(%6#1) : ...
//
if (isa<WitnessMethodInst>(AI.getCallee()))
return tryDevirtualizeWitnessMethod(AI, ORE);
// TODO: check if we can also de-virtualize partial applies of class methods.
FullApplySite FAS = FullApplySite::isa(AI.getInstruction());
if (!FAS)
return ApplySite();
/// Optimize a class_method and alloc_ref pair into a direct function
/// reference:
///
/// \code
/// %XX = alloc_ref $Foo
/// %YY = class_method %XX : $Foo, #Foo.get!1 : [email protected](method)...
/// \endcode
///
/// or
///
/// %XX = metatype $...
/// %YY = class_method %XX : ...
///
/// into
///
/// %YY = function_ref @...
if (auto *CMI = dyn_cast<ClassMethodInst>(FAS.getCallee())) {
auto &M = FAS.getModule();
auto Instance = stripUpCasts(CMI->getOperand());
auto ClassType = Instance->getType();
if (ClassType.is<MetatypeType>())
ClassType = ClassType.getMetatypeInstanceType(M);
auto *CD = ClassType.getClassOrBoundGenericClass();
if (isEffectivelyFinalMethod(FAS, ClassType, CD, CHA))
return tryDevirtualizeClassMethod(FAS, Instance, ORE,
true /*isEffectivelyFinalMethod*/);
// Try to check if the exact dynamic type of the instance is statically
// known.
if (auto Instance = getInstanceWithExactDynamicType(CMI->getOperand(),
CMI->getModule(),
CHA))
return tryDevirtualizeClassMethod(FAS, Instance, ORE);
if (auto ExactTy = getExactDynamicType(CMI->getOperand(), CMI->getModule(),
CHA)) {
if (ExactTy == CMI->getOperand()->getType())
return tryDevirtualizeClassMethod(FAS, CMI->getOperand(), ORE);
}
}
if (isa<SuperMethodInst>(FAS.getCallee())) {
if (FAS.hasSelfArgument()) {
return tryDevirtualizeClassMethod(FAS, FAS.getSelfArgument(), ORE);
}
// It is an invocation of a class method.
// Last operand is the metatype that should be used for dispatching.
return tryDevirtualizeClassMethod(FAS, FAS.getArguments().back(), ORE);
}
return ApplySite();
}
示例11: devirtualizeWitnessMethod
/// Generate a new apply of a function_ref to replace an apply of a
/// witness_method when we've determined the actual function we'll end
/// up calling.
static ApplySite devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
ProtocolConformanceRef C) {
// We know the witness thunk and the corresponding set of substitutions
// required to invoke the protocol method at this point.
auto &Module = AI.getModule();
// Collect all the required substitutions.
//
// The complete set of substitutions may be different, e.g. because the found
// witness thunk F may have been created by a specialization pass and have
// additional generic parameters.
SmallVector<Substitution, 4> NewSubs;
getWitnessMethodSubstitutions(AI, F, C, NewSubs);
// Figure out the exact bound type of the function to be called by
// applying all substitutions.
auto CalleeCanType = F->getLoweredFunctionType();
auto SubstCalleeCanType = CalleeCanType->substGenericArgs(Module, NewSubs);
// Collect arguments from the apply instruction.
auto Arguments = SmallVector<SILValue, 4>();
// Iterate over the non self arguments and add them to the
// new argument list, upcasting when required.
SILBuilderWithScope B(AI.getInstruction());
SILFunctionConventions substConv(SubstCalleeCanType, Module);
unsigned substArgIdx = AI.getCalleeArgIndexOfFirstAppliedArg();
for (auto arg : AI.getArguments()) {
auto paramType = substConv.getSILArgumentType(substArgIdx++);
if (arg->getType() != paramType)
arg = castValueToABICompatibleType(&B, AI.getLoc(), arg,
arg->getType(), paramType);
Arguments.push_back(arg);
}
assert(substArgIdx == substConv.getNumSILArguments());
// Replace old apply instruction by a new apply instruction that invokes
// the witness thunk.
SILBuilderWithScope Builder(AI.getInstruction());
SILLocation Loc = AI.getLoc();
FunctionRefInst *FRI = Builder.createFunctionRef(Loc, F);
auto SubstCalleeSILType = SILType::getPrimitiveObjectType(SubstCalleeCanType);
auto ResultSILType = substConv.getSILResultType();
ApplySite SAI;
if (auto *A = dyn_cast<ApplyInst>(AI))
SAI = Builder.createApply(Loc, FRI, SubstCalleeSILType,
ResultSILType, NewSubs, Arguments,
A->isNonThrowing());
if (auto *TAI = dyn_cast<TryApplyInst>(AI))
SAI = Builder.createTryApply(Loc, FRI, SubstCalleeSILType,
NewSubs, Arguments,
TAI->getNormalBB(), TAI->getErrorBB());
if (auto *PAI = dyn_cast<PartialApplyInst>(AI))
SAI = Builder.createPartialApply(Loc, FRI, SubstCalleeSILType,
NewSubs, Arguments, PAI->getType());
NumWitnessDevirt++;
return SAI;
}
示例12: devirtualizeWitnessMethod
/// Generate a new apply of a function_ref to replace an apply of a
/// witness_method when we've determined the actual function we'll end
/// up calling.
static ApplySite devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
ProtocolConformanceRef C) {
// We know the witness thunk and the corresponding set of substitutions
// required to invoke the protocol method at this point.
auto &Module = AI.getModule();
// Collect all the required substitutions.
//
// The complete set of substitutions may be different, e.g. because the found
// witness thunk F may have been created by a specialization pass and have
// additional generic parameters.
SmallVector<Substitution, 4> NewSubs;
getWitnessMethodSubstitutions(AI, F, C, NewSubs);
// Figure out the exact bound type of the function to be called by
// applying all substitutions.
auto CalleeCanType = F->getLoweredFunctionType();
auto SubstCalleeCanType = CalleeCanType->substGenericArgs(Module, NewSubs);
// Bail if some of the arguments cannot be converted into
// types required by the found devirtualized method.
if (!canPassOrConvertAllArguments(AI, SubstCalleeCanType))
return ApplySite();
// Collect arguments from the apply instruction.
auto Arguments = SmallVector<SILValue, 4>();
// Iterate over the non self arguments and add them to the
// new argument list, upcasting when required.
SILBuilderWithScope B(AI.getInstruction());
for (unsigned ArgN = 0, ArgE = AI.getNumArguments(); ArgN != ArgE; ++ArgN) {
SILValue A = AI.getArgument(ArgN);
auto ParamType = SubstCalleeCanType->getSILArgumentType(
SubstCalleeCanType->getNumSILArguments() - AI.getNumArguments() + ArgN);
if (A->getType() != ParamType)
A = B.createUpcast(AI.getLoc(), A, ParamType);
Arguments.push_back(A);
}
// Replace old apply instruction by a new apply instruction that invokes
// the witness thunk.
SILBuilderWithScope Builder(AI.getInstruction());
SILLocation Loc = AI.getLoc();
FunctionRefInst *FRI = Builder.createFunctionRef(Loc, F);
auto SubstCalleeSILType = SILType::getPrimitiveObjectType(SubstCalleeCanType);
auto ResultSILType = SubstCalleeCanType->getSILResult();
ApplySite SAI;
if (auto *A = dyn_cast<ApplyInst>(AI))
SAI = Builder.createApply(Loc, FRI, SubstCalleeSILType,
ResultSILType, NewSubs, Arguments,
A->isNonThrowing());
if (auto *TAI = dyn_cast<TryApplyInst>(AI))
SAI = Builder.createTryApply(Loc, FRI, SubstCalleeSILType,
NewSubs, Arguments,
TAI->getNormalBB(), TAI->getErrorBB());
if (auto *PAI = dyn_cast<PartialApplyInst>(AI))
SAI = Builder.createPartialApply(Loc, FRI, SubstCalleeSILType,
NewSubs, Arguments, PAI->getType());
NumWitnessDevirt++;
return SAI;
}