@@ -2064,6 +2064,90 @@ ArrayRef<LifetimeDependenceInfo> LifetimeDependenceInfo::uncurry(
20642064 return ctx.AllocateCopy (uncurried);
20652065}
20662066
2067+ ArrayRef<LifetimeDependenceInfo> LifetimeDependenceInfo::partialApply (
2068+ ASTContext &ctx, ArrayRef<LifetimeDependenceInfo> lifetimes,
2069+ unsigned numFormalParams, unsigned numBoundParams) {
2070+
2071+ if (numBoundParams == 0 )
2072+ return lifetimes;
2073+
2074+ ASSERT (numBoundParams <= numFormalParams &&
2075+ " A partial application can only bind as many parameters as the "
2076+ " function has." );
2077+
2078+ // How many parameters the resulting closure will have.
2079+ const unsigned numClosureParams = numFormalParams - numBoundParams;
2080+
2081+ SmallVector<LifetimeDependenceInfo, 2 > curried;
2082+
2083+ for (const auto &dep : lifetimes) {
2084+ // Determine the new target index.
2085+ unsigned targetIndex;
2086+ if (dep.getTargetIndex () == numFormalParams) {
2087+ // The target is the result.
2088+ // Its index is the number of parameters.
2089+ targetIndex = numClosureParams;
2090+ } else if (dep.getTargetIndex () >= numClosureParams) {
2091+ // The target is a captured parameter.
2092+ // The resulting closure does not need a lifetime dependence entry for it.
2093+ continue ;
2094+ } else {
2095+ // The target is an uncaptured parameter.
2096+ // Its index remains the same.
2097+ targetIndex = dep.getTargetIndex ();
2098+ }
2099+
2100+ auto flags = dep.flags ;
2101+
2102+ const auto captureBoundParams = [&](IndexSubset *indices) -> IndexSubset * {
2103+ if (!indices)
2104+ return nullptr ;
2105+
2106+ ASSERT (indices->getCapacity () <= numFormalParams &&
2107+ " There should be at most 1 index per parameter. SIL functions "
2108+ " cannot have "
2109+ " an implicit self parameter." );
2110+
2111+ auto bits = indices->getBitVector ();
2112+
2113+ if (bits.find_last () >= int (numClosureParams)) {
2114+ // One of the lifetime source parameters is bound by the partial_apply.
2115+ // This becomes a captures dependence in the resulting closure.
2116+ flags.setCaptures (true );
2117+ }
2118+
2119+ // Remove the indices of the captured parameters, leaving only those of
2120+ // the closure parameters.
2121+
2122+ if (bits.find_first () >= int (numClosureParams)) {
2123+ // All lifetime sources are captured. The resulting empty list of
2124+ // indices should be represented with a nullptr.
2125+ return nullptr ;
2126+ }
2127+
2128+ if (bits.size () > numClosureParams)
2129+ bits.resize (numClosureParams);
2130+
2131+ return IndexSubset::get (ctx, bits);
2132+ };
2133+
2134+ auto inherit = captureBoundParams (dep.getInheritIndices ());
2135+ auto scope = captureBoundParams (dep.getScopeIndices ());
2136+ auto addressable = captureBoundParams (dep.getAddressableIndices ());
2137+ auto conditionallyAddressable =
2138+ captureBoundParams (dep.getConditionallyAddressableIndices ());
2139+
2140+ curried.push_back (LifetimeDependenceInfo (inherit, scope, targetIndex,
2141+ addressable,
2142+ conditionallyAddressable, flags));
2143+ }
2144+
2145+ // FIXME: Avoid allocating context memory for every partial apply. Instead,
2146+ // cache a single uniqueLifetimeDependenceInfo array for each combination
2147+ // of FunctionType + numBoundParams.
2148+ return ctx.AllocateCopy (curried);
2149+ }
2150+
20672151void LifetimeDependenceInfo::dump () const {
20682152 llvm::errs () << " target: " << getTargetIndex () << ' \n ' ;
20692153 if (hasImmortalSpecifier ()) {
0 commit comments