@@ -1016,13 +1016,6 @@ class ConstraintSystem {
10161016 // / \brief Whether to record failures or not.
10171017 bool recordFixes = false ;
10181018
1019- // / The list of constraints that have been retired along the
1020- // / current path.
1021- ConstraintList retiredConstraints;
1022-
1023- // / The current set of generated constraints.
1024- SmallVector<Constraint *, 4 > generatedConstraints;
1025-
10261019 // / \brief The set of type variable bindings that have changed while
10271020 // / processing this constraint system.
10281021 SavedTypeVariableBindings savedBindings;
@@ -1039,6 +1032,124 @@ class ConstraintSystem {
10391032 // Statistics
10401033 #define CS_STATISTIC (Name, Description ) unsigned Name = 0 ;
10411034 #include " ConstraintSolverStats.def"
1035+
1036+ // / \brief Register given scope to be tracked by the current solver state,
1037+ // / this helps to make sure that all of the retired/generated constraints
1038+ // / are dealt with correctly when the life time of the scope ends.
1039+ // /
1040+ // / \param scope The scope to associate with current solver state.
1041+ void registerScope (SolverScope *scope) {
1042+ scopes.insert ({ scope, std::make_pair (retiredConstraints.begin (),
1043+ generatedConstraints.size ()) });
1044+ }
1045+
1046+ // / \brief Check whether there are any retired constraints present.
1047+ bool hasRetiredConstraints () const {
1048+ return !retiredConstraints.empty ();
1049+ }
1050+
1051+ // / \brief Mark given constraint as retired along current solver path.
1052+ // /
1053+ // / \param constraint The constraint to retire temporarily.
1054+ void retireConstraint (Constraint *constraint) {
1055+ retiredConstraints.push_front (constraint);
1056+ }
1057+
1058+ // / \brief Iterate over all of the retired constraints registered with
1059+ // / current solver state.
1060+ // /
1061+ // / \param processor The processor function to be applied to each of
1062+ // / the constraints retrieved.
1063+ void forEachRetired (std::function<void (Constraint &)> processor) {
1064+ for (auto &constraint : retiredConstraints)
1065+ processor (constraint);
1066+ }
1067+
1068+ // / \brief Add new "generated" constraint along the current solver path.
1069+ // /
1070+ // / \param constraint The newly generated constraint.
1071+ void addGeneratedConstraint (Constraint *constraint) {
1072+ generatedConstraints.push_back (constraint);
1073+ }
1074+
1075+ // / \brief Erase given constraint from the list of generated constraints
1076+ // / along the current solver path. Note that this operation doesn't
1077+ // / guarantee any ordering of the after it's application.
1078+ // /
1079+ // / \param constraint The constraint to erase.
1080+ void removeGeneratedConstraint (Constraint *constraint) {
1081+ size_t index = 0 ;
1082+ for (auto generated : generatedConstraints) {
1083+ if (generated == constraint) {
1084+ unsigned last = generatedConstraints.size () - 1 ;
1085+ auto lastConstraint = generatedConstraints[last];
1086+ if (lastConstraint == generated) {
1087+ generatedConstraints.pop_back ();
1088+ break ;
1089+ } else {
1090+ generatedConstraints[index] = lastConstraint;
1091+ generatedConstraints[last] = constraint;
1092+ generatedConstraints.pop_back ();
1093+ break ;
1094+ }
1095+ }
1096+ index++;
1097+ }
1098+ }
1099+
1100+ // / \brief Restore all of the retired/generated constraints to the state
1101+ // / before given scope. This is required because retired constraints have
1102+ // / to be re-introduced to the system in order of arrival (LIFO) and list
1103+ // / of the generated constraints has to be truncated back to the
1104+ // / original size.
1105+ // /
1106+ // / \param scope The solver scope to rollback.
1107+ void rollback (SolverScope *scope) {
1108+ auto entry = scopes.find (scope);
1109+ assert (entry != scopes.end () && " Unknown solver scope" );
1110+
1111+ // Remove given scope from the circulation.
1112+ scopes.erase (scope);
1113+
1114+ // The position of last retired constraint before given scope.
1115+ ConstraintList::iterator lastRetiredPos;
1116+ // The original number of generated constraints before given scope.
1117+ unsigned numGenerated;
1118+
1119+ std::tie (lastRetiredPos, numGenerated) = entry->getSecond ();
1120+
1121+ // Restore all of the retired constraints.
1122+ CS.InactiveConstraints .splice (CS.InactiveConstraints .end (),
1123+ retiredConstraints,
1124+ retiredConstraints.begin (), lastRetiredPos);
1125+
1126+ // And remove all of the generated constraints.
1127+ auto genStart = generatedConstraints.begin () + numGenerated,
1128+ genEnd = generatedConstraints.end ();
1129+ for (auto genI = genStart; genI != genEnd; ++genI) {
1130+ CS.InactiveConstraints .erase (ConstraintList::iterator (*genI));
1131+ }
1132+
1133+ generatedConstraints.erase (genStart, genEnd);
1134+ }
1135+
1136+ private:
1137+ // / The list of constraints that have been retired along the
1138+ // / current path, this list is used in LIFO fasion when constaints
1139+ // / are added back to the circulation.
1140+ ConstraintList retiredConstraints;
1141+
1142+ // / The current set of generated constraints.
1143+ SmallVector<Constraint *, 4 > generatedConstraints;
1144+
1145+ // / The collection which holds association between solver scope
1146+ // / and position of the last retired constraint and number of
1147+ // / constraints generated before registration of given scope,
1148+ // / this helps to rollback all of the constraints retired/generated
1149+ // / each of the registered scopes correct (LIFO) order.
1150+ llvm::SmallDenseMap<SolverScope *,
1151+ std::pair<ConstraintList::iterator, unsigned >>
1152+ scopes;
10421153 };
10431154
10441155 class CacheExprTypes : public ASTWalker {
@@ -1126,12 +1237,6 @@ class ConstraintSystem {
11261237 // / \brief The length of \c SavedBindings.
11271238 unsigned numSavedBindings;
11281239
1129- // / The length of generatedConstraints.
1130- unsigned numGeneratedConstraints;
1131-
1132- // / \brief The last retired constraint in the list.
1133- ConstraintList::iterator firstRetired;
1134-
11351240 // / \brief The length of \c ConstraintRestrictions.
11361241 unsigned numConstraintRestrictions;
11371242
@@ -1512,8 +1617,8 @@ class ConstraintSystem {
15121617
15131618 // Record this as a newly-generated constraint.
15141619 if (solverState) {
1515- solverState->generatedConstraints . push_back (constraint);
1516- solverState->retiredConstraints . push_back (constraint);
1620+ solverState->addGeneratedConstraint (constraint);
1621+ solverState->retireConstraint (constraint);
15171622 }
15181623 }
15191624
@@ -1528,7 +1633,7 @@ class ConstraintSystem {
15281633
15291634 // Record this as a newly-generated constraint.
15301635 if (solverState)
1531- solverState->generatedConstraints . push_back (constraint);
1636+ solverState->addGeneratedConstraint (constraint);
15321637 }
15331638
15341639 // / \brief Remove an inactive constraint from the current constraint graph.
@@ -1537,7 +1642,7 @@ class ConstraintSystem {
15371642 InactiveConstraints.erase (constraint);
15381643
15391644 if (solverState)
1540- solverState->retiredConstraints . push_back (constraint);
1645+ solverState->retireConstraint (constraint);
15411646 }
15421647
15431648 // / Retrieve the list of inactive constraints.
0 commit comments