@@ -948,6 +948,256 @@ bool GatherClosureUseVisitor::visitUse(Operand *op, AccessUseType useTy) {
948
948
return true ;
949
949
}
950
950
951
+ // ===----------------------------------------------------------------------===//
952
+ // Closure Argument Cloner
953
+ // ===----------------------------------------------------------------------===//
954
+
955
+ namespace {
956
+
957
+ struct ClosureArgumentInOutToOutCloner
958
+ : SILClonerWithScopes<ClosureArgumentInOutToOutCloner> {
959
+ friend class SILInstructionVisitor <ClosureArgumentInOutToOutCloner>;
960
+ friend class SILCloner <ClosureArgumentInOutToOutCloner>;
961
+
962
+ ConsumingClosureArgDataflowState &argDataflowState;
963
+ SILFunction *orig;
964
+ SmallBitVector &argsToConvertIndices;
965
+ SmallVector<SILValue, 4 > newConvertedArgs;
966
+
967
+ // The values in the original function that are promoted to stack
968
+ // references.
969
+ SmallPtrSet<SILValue, 4 > origFunctionValues;
970
+
971
+ public:
972
+ ClosureArgumentInOutToOutCloner (
973
+ SILOptFunctionBuilder &funcBuilder, SILFunction *orig,
974
+ IsSerialized_t isSerialized,
975
+ ConsumingClosureArgDataflowState &argDataflowState,
976
+ SmallBitVector &argsToConvertIndices);
977
+
978
+ void populateCloned ();
979
+
980
+ SILFunction *getCloned () { return &getBuilder ().getFunction (); }
981
+
982
+ void visitDestroyValueInst (DestroyValueInst *inst) {
983
+ if (!argDataflowState.postDominatingConsumingUsers .erase (inst)) {
984
+ SILCloner<ClosureArgumentInOutToOutCloner>::visitDestroyValueInst (inst);
985
+ }
986
+
987
+ // Don't do anything if we have a destroy.
988
+ }
989
+
990
+ void visitCopyAddrInst (CopyAddrInst *inst) {
991
+ if (!argDataflowState.postDominatingConsumingUsers .erase (inst)) {
992
+ return SILCloner<ClosureArgumentInOutToOutCloner>::visitCopyAddrInst (
993
+ inst);
994
+ }
995
+
996
+ // If this copy_addr is one of the copies that we need to fixup, convert it
997
+ // to an init from a reinit.
998
+ assert (!inst->isInitializationOfDest () && " Should be a reinit" );
999
+ getBuilder ().setCurrentDebugScope (getOpScope (inst->getDebugScope ()));
1000
+ recordClonedInstruction (
1001
+ inst, getBuilder ().createCopyAddr (
1002
+ getOpLocation (inst->getLoc ()), getOpValue (inst->getSrc ()),
1003
+ getOpValue (inst->getDest ()), inst->isTakeOfSrc (),
1004
+ IsInitialization_t::IsInitialization));
1005
+ }
1006
+
1007
+ void visitStoreInst (StoreInst *inst) {
1008
+ if (!argDataflowState.postDominatingConsumingUsers .erase (inst)) {
1009
+ return SILCloner<ClosureArgumentInOutToOutCloner>::visitStoreInst (inst);
1010
+ }
1011
+
1012
+ // If this store is one of the copies that we need to fixup, convert it
1013
+ // to an init from being an assign.
1014
+ assert (inst->getOwnershipQualifier () == StoreOwnershipQualifier::Assign);
1015
+ getBuilder ().setCurrentDebugScope (getOpScope (inst->getDebugScope ()));
1016
+ recordClonedInstruction (
1017
+ inst, getBuilder ().createStore (
1018
+ getOpLocation (inst->getLoc ()), getOpValue (inst->getSrc ()),
1019
+ getOpValue (inst->getDest ()), StoreOwnershipQualifier::Init));
1020
+ }
1021
+
1022
+ private:
1023
+ static SILFunction *
1024
+ initCloned (SILOptFunctionBuilder &funcBuilder, SILFunction *orig,
1025
+ IsSerialized_t isSerialized,
1026
+ ConsumingClosureArgDataflowState &argDataflowState,
1027
+ SmallBitVector &argsToConvertIndices, StringRef cloneName);
1028
+ };
1029
+
1030
+ } // namespace
1031
+
1032
+ static std::string getClonedName (SILFunction *func, IsSerialized_t serialized,
1033
+ SmallBitVector &argsToConvertIndices) {
1034
+ auto kind = Demangle::SpecializationPass::MoveDiagnosticInOutToOut;
1035
+ Mangle::FunctionSignatureSpecializationMangler Mangler (kind, serialized,
1036
+ func);
1037
+ for (int i = argsToConvertIndices.find_first (); i != -1 ;
1038
+ i = argsToConvertIndices.find_next (i)) {
1039
+ Mangler.setArgumentInOutToOut (i);
1040
+ }
1041
+ return Mangler.mangle ();
1042
+ }
1043
+
1044
+ ClosureArgumentInOutToOutCloner::ClosureArgumentInOutToOutCloner (
1045
+ SILOptFunctionBuilder &funcBuilder, SILFunction *orig,
1046
+ IsSerialized_t isSerialized,
1047
+ ConsumingClosureArgDataflowState &argDataflowState,
1048
+ SmallBitVector &argsToConvertIndices)
1049
+ : SILClonerWithScopes<ClosureArgumentInOutToOutCloner>(
1050
+ *initCloned (funcBuilder, orig, isSerialized, argDataflowState,
1051
+ argsToConvertIndices,
1052
+ getClonedName (orig, isSerialized, argsToConvertIndices))),
1053
+ argDataflowState(argDataflowState), orig(orig),
1054
+ argsToConvertIndices(argsToConvertIndices) {
1055
+ newConvertedArgs.reserve (argsToConvertIndices.size ());
1056
+ assert (orig->getDebugScope ()->getParentFunction () !=
1057
+ getCloned ()->getDebugScope ()->getParentFunction ());
1058
+ }
1059
+
1060
+ // / Create the function corresponding to the clone of the
1061
+ // / original closure with the signature modified to reflect promoted
1062
+ // / parameters (which are specified by PromotedArgIndices).
1063
+ SILFunction *ClosureArgumentInOutToOutCloner::initCloned (
1064
+ SILOptFunctionBuilder &funcBuilder, SILFunction *orig,
1065
+ IsSerialized_t serialized,
1066
+ ConsumingClosureArgDataflowState &argDataflowState,
1067
+ SmallBitVector &argsToConvertIndices, StringRef clonedName) {
1068
+ SILModule &mod = orig->getModule ();
1069
+ SmallVector<SILParameterInfo, 4 > clonedInterfaceArgTys;
1070
+ SmallVector<SILResultInfo, 4 > clonedResultInfos;
1071
+ SILFunctionType *origFTI = orig->getLoweredFunctionType ();
1072
+
1073
+ // First initialized cloned result infos with the old results.
1074
+ for (auto result : origFTI->getResults ())
1075
+ clonedResultInfos.push_back (result);
1076
+
1077
+ // Generate a new parameter list with deleted parameters removed...
1078
+ unsigned initArgIndex = orig->getConventions ().getSILArgIndexOfFirstParam ();
1079
+ for (auto state :
1080
+ llvm::enumerate (origFTI->getParameters ().drop_front (initArgIndex))) {
1081
+ unsigned index = state.index ();
1082
+ auto paramInfo = state.value ();
1083
+
1084
+ // If we are supposed to convert this, add the parameter to the result list.
1085
+ if (argsToConvertIndices.test (index)) {
1086
+ clonedResultInfos.emplace_back (paramInfo.getInterfaceType (),
1087
+ ResultConvention::Indirect);
1088
+ continue ;
1089
+ }
1090
+
1091
+ // Otherwise, just let it through.
1092
+ clonedInterfaceArgTys.push_back (paramInfo);
1093
+ ++index;
1094
+ }
1095
+
1096
+ // Create the new function type for the cloned function with some of
1097
+ // the parameters moved to be results.
1098
+ auto clonedTy = SILFunctionType::get (
1099
+ origFTI->getInvocationGenericSignature (), origFTI->getExtInfo (),
1100
+ origFTI->getCoroutineKind (), origFTI->getCalleeConvention (),
1101
+ clonedInterfaceArgTys, origFTI->getYields (), clonedResultInfos,
1102
+ origFTI->getOptionalErrorResult (), origFTI->getPatternSubstitutions (),
1103
+ origFTI->getInvocationSubstitutions (), mod.getASTContext (),
1104
+ origFTI->getWitnessMethodConformanceOrInvalid ());
1105
+
1106
+ assert ((orig->isTransparent () || orig->isBare () || orig->getLocation ()) &&
1107
+ " SILFunction missing location" );
1108
+ assert ((orig->isTransparent () || orig->isBare () || orig->getDebugScope ()) &&
1109
+ " SILFunction missing DebugScope" );
1110
+ assert (!orig->isGlobalInit () && " Global initializer cannot be cloned" );
1111
+ auto *Fn = funcBuilder.createFunction (
1112
+ swift::getSpecializedLinkage (orig, orig->getLinkage ()), clonedName,
1113
+ clonedTy, orig->getGenericEnvironment (), orig->getLocation (),
1114
+ orig->isBare (), orig->isTransparent (), serialized, IsNotDynamic,
1115
+ IsNotDistributed, orig->getEntryCount (), orig->isThunk (),
1116
+ orig->getClassSubclassScope (), orig->getInlineStrategy (),
1117
+ orig->getEffectsKind (), orig, orig->getDebugScope ());
1118
+ for (auto &Attr : orig->getSemanticsAttrs ()) {
1119
+ Fn->addSemanticsAttr (Attr);
1120
+ }
1121
+ if (!orig->hasOwnership ()) {
1122
+ Fn->setOwnershipEliminated ();
1123
+ }
1124
+ return Fn;
1125
+ }
1126
+
1127
+ // / Populate the body of the cloned closure, modifying instructions as
1128
+ // / necessary to take into consideration the removed parameters.
1129
+ void ClosureArgumentInOutToOutCloner::populateCloned () {
1130
+ SILFunction *cloned = getCloned ();
1131
+
1132
+ // Create arguments for the entry block
1133
+ SILBasicBlock *origEntryBlock = &*orig->begin ();
1134
+ SILBasicBlock *clonedEntryBlock = cloned->createBasicBlock ();
1135
+
1136
+ SmallVector<SILValue, 4 > entryArgs;
1137
+ entryArgs.reserve (origEntryBlock->getArguments ().size ());
1138
+
1139
+ // Initialize all new arg slots to an invalid value.
1140
+ newConvertedArgs.resize (origEntryBlock->getArguments ().size ());
1141
+
1142
+ // First process all of the indirect results and add our new results after
1143
+ // them.
1144
+ auto oldArgs = origEntryBlock->getArguments ();
1145
+ auto origConventions = orig->getConventions ();
1146
+ for (unsigned i : range (origConventions.getSILArgIndexOfFirstIndirectResult (),
1147
+ origConventions.getSILArgIndexOfFirstParam ())) {
1148
+ auto *a = oldArgs[i];
1149
+ // Create a new argument which copies the original argument.
1150
+ entryArgs.push_back (
1151
+ clonedEntryBlock->createFunctionArgument (a->getType (), a->getDecl ()));
1152
+ }
1153
+
1154
+ // To avoid needing to mess with types, just go through our original arguments
1155
+ // in the entry block to get the right types.
1156
+ llvm::SmallMapVector<SILValue, SILValue, 4 > movedArgs;
1157
+ SmallBitVector newResults (origEntryBlock->getNumArguments ());
1158
+ for (auto state : llvm::enumerate (origEntryBlock->getArguments ())) {
1159
+ unsigned argNo = state.index ();
1160
+ if (!argsToConvertIndices.test (argNo))
1161
+ continue ;
1162
+
1163
+ auto *arg = state.value ();
1164
+ auto *newArg = clonedEntryBlock->createFunctionArgument (arg->getType (),
1165
+ arg->getDecl ());
1166
+ movedArgs[arg] = newArg;
1167
+ entryArgs.push_back (newArg);
1168
+ }
1169
+
1170
+ // Finally, recreate the rest of the arguments which we did not specialize.
1171
+ for (auto state : llvm::enumerate (origEntryBlock->getArguments ())) {
1172
+ unsigned argNo = state.index ();
1173
+ if (argsToConvertIndices.test (argNo))
1174
+ continue ;
1175
+
1176
+ auto *arg = state.value ();
1177
+ entryArgs.push_back (clonedEntryBlock->createFunctionArgument (
1178
+ arg->getType (), arg->getDecl ()));
1179
+ }
1180
+
1181
+ // Visit original BBs in depth-first preorder, starting with the
1182
+ // entry block, cloning all instructions and terminators.
1183
+ cloneFunctionBody (orig, clonedEntryBlock, entryArgs,
1184
+ [&](SILValue clonedArg) -> SILValue {
1185
+ auto iter = movedArgs.find (clonedArg);
1186
+ if (iter == movedArgs.end ())
1187
+ return clonedArg;
1188
+ return iter->second ;
1189
+ });
1190
+
1191
+ // As we clone instructions, any that we handled specially will have been
1192
+ // erased from postDominatingConsumingUsers. If we didn't erase all of them,
1193
+ // then there is a bug in the implementation.
1194
+ assert (llvm::all_of (argDataflowState.postDominatingConsumingUsers ,
1195
+ [&](Optional<SILInstruction *> user) {
1196
+ return user.hasValue ();
1197
+ }) &&
1198
+ " Did not handle a post dominating consuming user?!" );
1199
+ }
1200
+
951
1201
// ===----------------------------------------------------------------------===//
952
1202
// Global Dataflow
953
1203
// ===----------------------------------------------------------------------===//
0 commit comments