Skip to content

Add the open_pack_element instruction #62955

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 11, 2023
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: 8 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,10 @@ ERROR(sil_moveonlytocopyable_invalid_attribute,none,
"Attribute '[%0]' can not be applied to moveonlywrapper_to_copyable", (StringRef))
ERROR(sil_moveonlytocopyable_requires_attribute,none,
"moveonlywrapper_to_copyable requires either a [guaranteed] or [owned] attribute", ())
ERROR(expected_generic_signature,none,
"expected a generic signature", ())
ERROR(sil_expected_uuid,none,
"expected a UUID string literal", ())

// SIL Basic Blocks
ERROR(expected_sil_block_name,none,
Expand Down Expand Up @@ -890,6 +894,10 @@ ERROR(deprecated_protocol_composition_single,none,
ERROR(deprecated_any_composition,none,
"'protocol<>' syntax has been removed; use 'Any' instead", ())

// Pack Types
ERROR(expected_rbrace_pack_type_list,none,
"expected '}' at end of pack type list", ())

// SIL box Types
ERROR(sil_box_expected_var_or_let,none,
"expected 'var' or 'let' to introduce SIL box field type", ())
Expand Down
22 changes: 13 additions & 9 deletions include/swift/AST/GenericEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,19 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
/// Retrieve the UUID for an opened element environment.
UUID getOpenedElementUUID() const;

using PackElementBinding =
std::pair<ElementArchetypeType *, PackArchetypeType *>;

/// Retrieve the bindings for the opened pack element archetypes in this
/// generic environment to the pack archetypes that contain them.
///
/// \param bindings The vector to populate with the pack element bindings.
void getPackElementBindings(
SmallVectorImpl<PackElementBinding> &bindings) const;
void forEachPackElementArchetype(
llvm::function_ref<void(ElementArchetypeType*)> function) const;

using PackElementBindingCallback =
llvm::function_ref<void(ElementArchetypeType *elementType,
PackType *packSubstitution)>;

/// Given that this is an opened element environment, iterate the
/// opened pack element bindings: the pack archetype that's been opened
/// (which may not be meaningful in the surrounding context), the element
/// archetype that it has been opened as, and the pack type whose elements
/// are opened.
void forEachPackElementBinding(PackElementBindingCallback function) const;

/// Create a new, primary generic environment.
static GenericEnvironment *forPrimary(GenericSignature signature);
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/PrintOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ struct PrintOptions {

bool PrintImplicitAttrs = true;

/// Whether to print the \c each keyword for pack archetypes.
bool PrintExplicitEach = false;

/// Whether to print the \c any keyword for existential
/// types.
bool PrintExplicitAny = false;
Expand Down
54 changes: 54 additions & 0 deletions include/swift/AST/TypeRepr.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ class alignas(1 << TypeReprAlignInBits) TypeRepr
NumFields : 32
);

SWIFT_INLINE_BITFIELD_FULL(PackTypeRepr, TypeRepr, 32,
/// The number of elements contained.
NumElements : 32
);

} Bits;

TypeRepr(TypeReprKind K) {
Expand Down Expand Up @@ -758,6 +763,54 @@ class PackExpansionTypeRepr final : public TypeRepr {
friend class TypeRepr;
};

/// An explicit pack grouping, `Pack{...}`.
///
/// This allows packs to be explicitly grouped. It is currently only
/// allowed in SIL files.
class PackTypeRepr final
: public TypeRepr,
private llvm::TrailingObjects<PackTypeRepr, TypeRepr *> {
friend TrailingObjects;
SourceLoc KeywordLoc;
SourceRange BraceLocs;

size_t numTrailingObjects(OverloadToken<TypeRepr*>) const {
return Bits.PackTypeRepr.NumElements;
}

PackTypeRepr(SourceLoc keywordLoc, SourceRange braceLocs,
ArrayRef<TypeRepr*> elements);
public:
static PackTypeRepr *create(const ASTContext &ctx,
SourceLoc keywordLoc,
SourceRange braceLocs,
ArrayRef<TypeRepr*> elements);

SourceLoc getKeywordLoc() const { return KeywordLoc; }
SourceRange getBracesRange() const { return BraceLocs; }

MutableArrayRef<TypeRepr*> getMutableElements() {
return llvm::makeMutableArrayRef(getTrailingObjects<TypeRepr*>(),
Bits.PackTypeRepr.NumElements);
}
ArrayRef<TypeRepr*> getElements() const {
return llvm::makeArrayRef(getTrailingObjects<TypeRepr*>(),
Bits.PackTypeRepr.NumElements);
}

static bool classof(const TypeRepr *T) {
return T->getKind() == TypeReprKind::Pack;
}
static bool classof(const PackTypeRepr *T) { return true; }

private:
SourceLoc getStartLocImpl() const { return KeywordLoc; }
SourceLoc getEndLocImpl() const { return BraceLocs.End; }
SourceLoc getLocImpl() const { return KeywordLoc; }
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
friend class TypeRepr;
};

/// A pack reference spelled with the \c each keyword.
///
/// Pack references can only appear inside pack expansions and in
Expand Down Expand Up @@ -1398,6 +1451,7 @@ inline bool TypeRepr::isSimple() const {
case TypeReprKind::ImplicitlyUnwrappedOptional:
case TypeReprKind::Vararg:
case TypeReprKind::PackExpansion:
case TypeReprKind::Pack:
case TypeReprKind::Tuple:
case TypeReprKind::Fixed:
case TypeReprKind::Array:
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/TypeReprNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ TYPEREPR(Protocol, TypeRepr)
TYPEREPR(OpaqueReturn, TypeRepr)
TYPEREPR(NamedOpaqueReturn, TypeRepr)
TYPEREPR(Existential, TypeRepr)
TYPEREPR(Pack, TypeRepr)
TYPEREPR(PackReference, TypeRepr)
TYPEREPR(Placeholder, TypeRepr)
ABSTRACT_TYPEREPR(Specifier, TypeRepr)
Expand Down
6 changes: 6 additions & 0 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ namespace swift {
class SourceManager;
class TupleType;
class TypeLoc;
class UUID;

struct EnumElementInfo;

Expand Down Expand Up @@ -1018,6 +1019,11 @@ class Parser {
parseExtendedAvailabilitySpecList(SourceLoc AtLoc, SourceLoc AttrLoc,
StringRef AttrName);

/// Parse a string literal whose contents can be interpreted as a UUID.
///
/// \returns false on success, true on error.
bool parseUUIDString(UUID &uuid, Diag<> diag);

/// Parse the Objective-C selector inside @objc
void parseObjCSelector(SmallVector<Identifier, 4> &Names,
SmallVector<SourceLoc, 4> &NameLocs,
Expand Down
8 changes: 8 additions & 0 deletions include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1936,6 +1936,14 @@ class SILBuilder {
getSILDebugLocation(Loc), Existential));
}

OpenPackElementInst *
createOpenPackElement(SILLocation loc, SILValue packIndex,
GenericEnvironment *openedElementEnvironment) {
return insert(OpenPackElementInst::create(getFunction(),
getSILDebugLocation(loc),
packIndex, openedElementEnvironment));
}

ProjectBlockStorageInst *createProjectBlockStorage(SILLocation Loc,
SILValue Storage) {
auto CaptureTy = Storage->getType()
Expand Down
96 changes: 71 additions & 25 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {

SILBuilder Builder;
DominanceInfo *DomTree = nullptr;
TypeSubstitutionMap OpenedExistentialSubs;
TypeSubstitutionMap LocalArchetypeSubs;

// The old-to-new value map.
llvm::DenseMap<SILValue, SILValue> ValueMap;
Expand Down Expand Up @@ -164,10 +164,10 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
asImpl().mapValue(origValue, mappedValue);
}

/// Register a re-mapping for opened existentials.
void registerOpenedExistentialRemapping(ArchetypeType *From,
ArchetypeType *To) {
auto result = OpenedExistentialSubs.insert(
/// Register a re-mapping for local archetypes such as opened existentials.
void registerLocalArchetypeRemapping(ArchetypeType *From,
ArchetypeType *To) {
auto result = LocalArchetypeSubs.insert(
std::make_pair(CanArchetypeType(From), CanType(To)));
assert(result.second);
(void)result;
Expand All @@ -189,15 +189,15 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
}

SubstitutionMap getOpSubstitutionMap(SubstitutionMap Subs) {
// If we have open existentials to substitute, check whether that's
// If we have local archetypes to substitute, check whether that's
// relevant to this particular substitution.
if (!OpenedExistentialSubs.empty()) {
if (!LocalArchetypeSubs.empty()) {
for (auto ty : Subs.getReplacementTypes()) {
// If we found a type containing an opened existential, substitute
// If we found a type containing a local archetype, substitute
// open existentials throughout the substitution map.
if (ty->hasOpenedExistential()) {
if (ty->hasLocalArchetype()) {
Subs = Subs.subst(QueryTypeSubstitutionMapOrIdentity{
OpenedExistentialSubs},
LocalArchetypeSubs},
MakeAbstractConformanceForGenericType());
break;
}
Expand All @@ -209,19 +209,19 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {

SILType getTypeInClonedContext(SILType Ty) {
auto objectTy = Ty.getASTType();
// Do not substitute opened existential types, if we do not have any.
if (!objectTy->hasOpenedExistential())
// Do not substitute local archetypes, if we do not have any.
if (!objectTy->hasLocalArchetype())
return Ty;
// Do not substitute opened existential types, if it is not required.
// Do not substitute local archetypes, if it is not required.
// This is often the case when cloning basic blocks inside the same
// function.
if (OpenedExistentialSubs.empty())
if (LocalArchetypeSubs.empty())
return Ty;

// Substitute opened existential types, if we have any.
// Substitute local archetypes, if we have any.
return Ty.subst(
Builder.getModule(),
QueryTypeSubstitutionMapOrIdentity{OpenedExistentialSubs},
QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs},
MakeAbstractConformanceForGenericType());
}
SILType getOpType(SILType Ty) {
Expand All @@ -230,17 +230,17 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
}

CanType getASTTypeInClonedContext(Type ty) {
// Do not substitute opened existential types, if we do not have any.
if (!ty->hasOpenedExistential())
// Do not substitute local archetypes, if we do not have any.
if (!ty->hasLocalArchetype())
return ty->getCanonicalType();
// Do not substitute opened existential types, if it is not required.
// Do not substitute local archetypes, if it is not required.
// This is often the case when cloning basic blocks inside the same
// function.
if (OpenedExistentialSubs.empty())
if (LocalArchetypeSubs.empty())
return ty->getCanonicalType();

return ty.subst(
QueryTypeSubstitutionMapOrIdentity{OpenedExistentialSubs},
QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs},
MakeAbstractConformanceForGenericType()
)->getCanonicalType();
}
Expand All @@ -258,7 +258,7 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
->getCanonicalType();
auto substExistentialTy = getOpASTType(origExistentialTy);
auto replacementTy = OpenedArchetypeType::get(substExistentialTy, sig);
registerOpenedExistentialRemapping(archetypeTy, replacementTy);
registerLocalArchetypeRemapping(archetypeTy, replacementTy);
}

// SILCloner will take care of debug scope on the instruction
Expand All @@ -273,12 +273,12 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {

ProtocolConformanceRef getOpConformance(Type ty,
ProtocolConformanceRef conformance) {
// If we have open existentials to substitute, do so now.
if (ty->hasOpenedExistential() && !OpenedExistentialSubs.empty()) {
// If we have local archetypes to substitute, do so now.
if (ty->hasLocalArchetype() && !LocalArchetypeSubs.empty()) {
conformance =
conformance.subst(ty,
QueryTypeSubstitutionMapOrIdentity{
OpenedExistentialSubs},
LocalArchetypeSubs},
MakeAbstractConformanceForGenericType());
}

Expand Down Expand Up @@ -2392,6 +2392,52 @@ void SILCloner<ImplClass>::visitDeinitExistentialValueInst(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
}

template <typename ImplClass>
void SILCloner<ImplClass>::visitOpenPackElementInst(
OpenPackElementInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));

auto newIndexValue = getOpValue(Inst->getIndexOperand());
auto loc = getOpLocation(Inst->getLoc());

// We need to make a new opened-element environment. This is *not*
// a refinement of the contextual environment of the new insertion
// site; we just substitute the contextual substitutions in the
// opened environment and build a new one.
auto origEnv = Inst->getOpenedGenericEnvironment();

// Substitute the contextual substitutions.
auto newContextSubs =
getOpSubstitutionMap(origEnv->getPackElementContextSubstitutions());

// Substitute the shape class.
auto newShapeClass = getOpASTType(origEnv->getOpenedElementShapeClass());

// Build the new environment.
auto newEnv =
GenericEnvironment::forOpenedElement(origEnv->getGenericSignature(),
UUID::fromTime(), newShapeClass,
newContextSubs);

// Associate the old opened archetypes with the new ones.
SmallVector<ArchetypeType*, 4> oldOpenedArchetypes;
origEnv->forEachPackElementArchetype([&](ElementArchetypeType *oldType) {
oldOpenedArchetypes.push_back(oldType);
});
{
size_t nextOldIndex = 0;
newEnv->forEachPackElementArchetype([&](ElementArchetypeType *newType) {
ArchetypeType *oldType = oldOpenedArchetypes[nextOldIndex++];
registerLocalArchetypeRemapping(oldType, newType);
});
assert(nextOldIndex == oldOpenedArchetypes.size() &&
"different opened archetype count");
}

recordClonedInstruction(
Inst, getBuilder().createOpenPackElement(loc, newIndexValue, newEnv));
}

template<typename ImplClass>
void
SILCloner<ImplClass>::visitCopyBlockInst(CopyBlockInst *Inst) {
Expand Down
Loading