Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions include/swift/Basic/Generators.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
// concept SimpleGenerator : Generator {
// type reference;
//
// // Get the current value.
// reference get();
//
// // Get the current value and then advance the generator.
// reference claimNext();
// }
//
Expand Down Expand Up @@ -103,15 +107,15 @@ class ArrayRefGenerator {
}

/// Return the current element of the array.
reference getCurrent() const {
reference get() const {
assert(!isFinished());
return values.front();
}

/// Claim the current element of the array and advance past it.
reference claimNext() {
assert(!isFinished());
reference result = getCurrent();
reference result = get();
advance();
return result;
}
Expand Down
22 changes: 8 additions & 14 deletions include/swift/SIL/AbstractionPattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace clang {
namespace swift {
namespace Lowering {
class FunctionParamGenerator;
class TupleElementGenerator;

/// A pattern for the abstraction of a value.
///
Expand Down Expand Up @@ -783,7 +784,8 @@ class AbstractionPattern {
/// Note that, for most purposes, you should lower a field's type against its
/// *unsubstituted* interface type.
AbstractionPattern
unsafeGetSubstFieldType(ValueDecl *member, CanType origMemberType) const;
unsafeGetSubstFieldType(ValueDecl *member, CanType origMemberType,
SubstitutionMap subMap) const;

private:
/// Return an abstraction pattern for the curried type of an
Expand Down Expand Up @@ -1173,6 +1175,10 @@ class AbstractionPattern {
return CXXMethod;
}

bool isOpaqueTuple() const {
return getKind() == Kind::Tuple;
}

bool isOpaqueFunctionOrOpaqueDerivativeFunction() const {
return (getKind() == Kind::OpaqueFunction ||
getKind() == Kind::OpaqueDerivativeFunction);
Expand Down Expand Up @@ -1355,20 +1361,8 @@ class AbstractionPattern {
/// expand to.
///
/// This pattern must be a tuple pattern.
///
/// Calls handleScalar or handleExpansion as appropriate for each
/// element of the original tuple, in order.
void forEachTupleElement(CanTupleType substType,
llvm::function_ref<void(unsigned origEltIndex,
unsigned substEltIndex,
AbstractionPattern origEltType,
CanType substEltType)>
handleScalar,
llvm::function_ref<void(unsigned origEltIndex,
unsigned substEltIndex,
AbstractionPattern origExpansionType,
CanTupleEltTypeArrayRef substEltTypes)>
handleExpansion) const;
llvm::function_ref<void(TupleElementGenerator &element)> fn) const;

/// Perform a parallel visitation of the elements of a tuple type,
/// expanding the elements of the type. This preserves the structure
Expand Down
127 changes: 125 additions & 2 deletions include/swift/SIL/AbstractionPatternGenerators.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class FunctionParamGenerator {
unsigned substParamIndex = 0;

/// The number of subst parameters corresponding to the current
/// subst parameter.
/// orig parameter.
unsigned numSubstParamsForOrigParam;

/// Whether the orig function type is opaque, i.e. does not permit us to
Expand Down Expand Up @@ -125,7 +125,7 @@ class FunctionParamGenerator {
}

/// Return whether the current orig parameter type is a pack expansion.
bool isPackExpansion() const {
bool isOrigPackExpansion() const {
assert(!isFinished());
return origParamIsExpansion;
}
Expand All @@ -148,6 +148,129 @@ class FunctionParamGenerator {
}
};

/// A generator for traversing the formal elements of a tuple type
/// while properly respecting variadic generics.
class TupleElementGenerator {
// The steady state of the generator.

/// The abstraction pattern of the entire tuple type. Set once
/// during construction.
AbstractionPattern origTupleType;

/// The substitute tuple type. Set once during construction.
CanTupleType substTupleType;

/// The number of orig elements to traverse. Set once during
/// construction.
unsigned numOrigElts;

/// The index of the current orig element.
/// Incremented during advance().
unsigned origEltIndex = 0;

/// The (start) index of the current subst elements.
/// Incremented during advance().
unsigned substEltIndex = 0;

/// The number of subst elements corresponding to the current
/// orig element.
unsigned numSubstEltsForOrigElt;

/// Whether the orig tuple type is opaque, i.e. does not permit us to
/// call getNumTupleElements() and similar accessors. Set once during
/// construction.
bool origTupleTypeIsOpaque;

/// Whether the current orig element is a pack expansion.
bool origEltIsExpansion;

/// The abstraction pattern of the current orig element.
/// If it is a pack expansion, this is the expansion type, not the
/// pattern type.
AbstractionPattern origEltType = AbstractionPattern::getInvalid();

/// Load the informaton for the current orig element into the
/// fields above for it.
void loadElement() {
origEltType = origTupleType.getTupleElementType(origEltIndex);
origEltIsExpansion = origEltType.isPackExpansion();
numSubstEltsForOrigElt =
(origEltIsExpansion
? origEltType.getNumPackExpandedComponents()
: 1);
}

public:
TupleElementGenerator(AbstractionPattern origTupleType,
CanTupleType substTupleType);

/// Is the traversal finished? If so, none of the getters below
/// are allowed to be called.
bool isFinished() const {
return origEltIndex == numOrigElts;
}

/// Advance to the next orig element.
void advance() {
assert(!isFinished());
origEltIndex++;
substEltIndex += numSubstEltsForOrigElt;
if (!isFinished()) loadElement();
}

/// Return the index of the current orig element.
unsigned getOrigIndex() const {
assert(!isFinished());
return origEltIndex;
}

/// Return the index of the (first) subst element corresponding
/// to the current orig element.
unsigned getSubstIndex() const {
assert(!isFinished());
return origEltIndex;
}

/// Return a tuple element for the current orig element.
TupleTypeElt getOrigElement() const {
assert(!isFinished());
return (origTupleTypeIsOpaque
? substTupleType->getElement(substEltIndex)
: cast<TupleType>(origTupleType.getType())
->getElement(origEltIndex));
}

/// Return the type of the current orig element.
const AbstractionPattern &getOrigType() const {
assert(!isFinished());
return origEltType;
}

/// Return whether the current orig element type is a pack expansion.
bool isOrigPackExpansion() const {
assert(!isFinished());
return origEltIsExpansion;
}

/// Return the substituted elements corresponding to the current
/// orig element type. If the current orig element is not a
/// pack expansion, this will have exactly one element.
CanTupleEltTypeArrayRef getSubstTypes() const {
assert(!isFinished());
return substTupleType.getElementTypes().slice(substEltIndex,
numSubstEltsForOrigElt);
}

/// Call this to finalize the traversal and assert that it was done
/// properly.
void finish() {
assert(isFinished() && "didn't finish the traversal");
assert(substEltIndex == substTupleType->getNumElements() &&
"didn't exhaust subst elements; possible missing subs on "
"orig tuple type");
}
};

} // end namespace Lowering
} // end namespace swift

Expand Down
Loading