Skip to content

Commit f3cc081

Browse files
committed
[NFC] Fix verification in TypeLowering.
1 parent 8232270 commit f3cc081

File tree

4 files changed

+153
-119
lines changed

4 files changed

+153
-119
lines changed

include/swift/SIL/SILType.h

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "swift/AST/SILLayout.h"
2222
#include "swift/AST/Types.h"
23+
#include "swift/SIL/AbstractionPattern.h"
2324
#include "swift/SIL/Lifetime.h"
2425
#include "llvm/ADT/Hashing.h"
2526
#include "llvm/ADT/PointerIntPair.h"
@@ -753,25 +754,6 @@ class SILType {
753754
void dump() const;
754755
void print(raw_ostream &OS,
755756
const PrintOptions &PO = PrintOptions::printSIL()) const;
756-
757-
#ifndef NDEBUG
758-
/// Visit the distinct types of the fields out of which a type is aggregated.
759-
///
760-
/// As we walk into the field types, if an aggregate is encountered, it may
761-
/// still be a leaf. It is a leaf if the \p isLeafAggregate predicate
762-
/// returns true.
763-
///
764-
/// Returns false if the leaves cannot be visited or if any invocation of the
765-
/// visitor returns false.
766-
///
767-
/// NOTE: This function is meant for use in verification. For real use-cases,
768-
/// recursive walks of type leaves should be done via
769-
/// TypeLowering::RecursiveProperties.
770-
bool visitAggregateLeaves(
771-
Lowering::TypeConverter &TC, TypeExpansionContext context,
772-
std::function<bool(SILType, SILType, VarDecl *)> isLeafAggregate,
773-
std::function<bool(SILType, SILType, VarDecl *)> visit) const;
774-
#endif
775757
};
776758

777759
// Statically prevent SILTypes from being directly cast to a type

include/swift/SIL/TypeLowering.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,15 @@ class TypeConverter {
12501250
/// getTypeLowering(AbstractionPattern,Type,TypeExpansionContext).
12511251
void verifyLowering(const TypeLowering &, AbstractionPattern origType,
12521252
Type origSubstType, TypeExpansionContext forExpansion);
1253+
bool visitAggregateLeaves(
1254+
Lowering::AbstractionPattern origType, Type substType,
1255+
TypeExpansionContext context,
1256+
std::function<bool(Type, Lowering::AbstractionPattern,
1257+
Optional<TaggedUnion<ValueDecl *, unsigned>>)>
1258+
isLeafAggregate,
1259+
std::function<bool(Type, Lowering::AbstractionPattern,
1260+
Optional<TaggedUnion<ValueDecl *, unsigned>>)>
1261+
visit);
12531262
#endif
12541263
};
12551264

lib/SIL/IR/SILType.cpp

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -942,66 +942,3 @@ bool SILType::isMoveOnly() const {
942942
return true;
943943
return isMoveOnlyWrapped();
944944
}
945-
946-
#ifndef NDEBUG
947-
bool SILType::visitAggregateLeaves(
948-
Lowering::TypeConverter &TC, TypeExpansionContext context,
949-
std::function<bool(SILType, SILType, VarDecl *)> isLeaf,
950-
std::function<bool(SILType, SILType, VarDecl *)> visit) const {
951-
952-
llvm::SmallSet<std::tuple<SILType::ValueType, SILType::ValueType, VarDecl *>,
953-
16>
954-
visited;
955-
llvm::SmallVector<
956-
std::tuple<SILType::ValueType, SILType::ValueType, VarDecl *>, 16>
957-
worklist;
958-
auto insertIntoWorklist = [&visited, &worklist](SILType parent, SILType type,
959-
VarDecl *decl) -> bool {
960-
if (!visited.insert({parent.value, type.value, decl}).second) {
961-
return false;
962-
}
963-
worklist.push_back({parent.value, type.value, decl});
964-
return true;
965-
};
966-
auto popFromWorklist =
967-
[&worklist]() -> std::tuple<SILType, SILType, VarDecl *> {
968-
SILType::ValueType parentOpaqueType;
969-
SILType::ValueType opaqueType;
970-
VarDecl *decl;
971-
std::tie(parentOpaqueType, opaqueType, decl) = worklist.pop_back_val();
972-
return {parentOpaqueType, opaqueType, decl};
973-
};
974-
insertIntoWorklist(SILType(), *this, nullptr);
975-
while (!worklist.empty()) {
976-
SILType parent;
977-
SILType ty;
978-
VarDecl *decl;
979-
std::tie(parent, ty, decl) = popFromWorklist();
980-
if (ty.isAggregate() && !isLeaf(parent, ty, decl)) {
981-
if (auto tupleTy = ty.getAs<TupleType>()) {
982-
for (unsigned index = 0, num = tupleTy->getNumElements(); index < num;
983-
++index) {
984-
insertIntoWorklist(ty, ty.getTupleElementType(index), nullptr);
985-
}
986-
} else if (auto *decl = ty.getStructOrBoundGenericStruct()) {
987-
for (auto *field : decl->getStoredProperties()) {
988-
insertIntoWorklist(ty, ty.getFieldType(field, TC, context), field);
989-
}
990-
} else if (auto *decl = ty.getEnumOrBoundGenericEnum()) {
991-
for (auto *field : decl->getStoredProperties()) {
992-
insertIntoWorklist(ty, ty.getFieldType(field, TC, context), field);
993-
}
994-
} else {
995-
llvm_unreachable("unknown aggregate kind!");
996-
}
997-
continue;
998-
}
999-
1000-
// This type is a leaf. Visit it.
1001-
auto success = visit(parent, ty, decl);
1002-
if (!success)
1003-
return false;
1004-
}
1005-
return true;
1006-
}
1007-
#endif

lib/SIL/IR/TypeLowering.cpp

Lines changed: 143 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,74 +2422,180 @@ TypeConverter::getTypeLowering(AbstractionPattern origType,
24222422
}
24232423

24242424
#ifndef NDEBUG
2425-
verifyLowering(*lowering, origType, origSubstType, forExpansion);
2425+
verifyLowering(*lowering, origType, loweredSubstType, forExpansion);
24262426
#endif
24272427

24282428
return *lowering;
24292429
}
24302430

24312431
#ifndef NDEBUG
2432+
bool TypeConverter::visitAggregateLeaves(
2433+
Lowering::AbstractionPattern origType, Type substType,
2434+
TypeExpansionContext context,
2435+
std::function<bool(Type, Lowering::AbstractionPattern,
2436+
Optional<TaggedUnion<ValueDecl *, unsigned>>)>
2437+
isLeafAggregate,
2438+
std::function<bool(Type, Lowering::AbstractionPattern,
2439+
Optional<TaggedUnion<ValueDecl *, unsigned>>)>
2440+
visit) {
2441+
llvm::SmallSet<std::tuple<TypeBase *, ValueDecl *, unsigned>, 16> visited;
2442+
llvm::SmallVector<
2443+
std::tuple<TypeBase *, AbstractionPattern, ValueDecl *, unsigned>, 16>
2444+
worklist;
2445+
auto insertIntoWorklist =
2446+
[&visited,
2447+
&worklist](Type substTy, AbstractionPattern origTy,
2448+
Optional<TaggedUnion<ValueDecl *, unsigned>> either) -> bool {
2449+
ValueDecl *field;
2450+
unsigned index;
2451+
if (either) {
2452+
if (either->isa<ValueDecl *>()) {
2453+
field = either->get<ValueDecl *>();
2454+
index = UINT_MAX;
2455+
} else {
2456+
field = nullptr;
2457+
index = either->get<unsigned>();
2458+
}
2459+
} else {
2460+
field = nullptr;
2461+
index = UINT_MAX;
2462+
}
2463+
if (!visited.insert({substTy.getPointer(), field, index}).second)
2464+
return false;
2465+
worklist.push_back({substTy.getPointer(), origTy, field, index});
2466+
return true;
2467+
};
2468+
auto popFromWorklist = [&worklist]()
2469+
-> std::tuple<Type, AbstractionPattern,
2470+
Optional<TaggedUnion<ValueDecl *, unsigned>>> {
2471+
TypeBase *ty;
2472+
AbstractionPattern origTy = AbstractionPattern::getOpaque();
2473+
Optional<TaggedUnion<ValueDecl *, unsigned>> either;
2474+
ValueDecl *field;
2475+
unsigned index = 0;
2476+
std::tie(ty, origTy, field, index) = worklist.pop_back_val();
2477+
if (field) {
2478+
either = TaggedUnion<ValueDecl *, unsigned>(field);
2479+
} else if (index != UINT_MAX) {
2480+
either = TaggedUnion<ValueDecl *, unsigned>(index);
2481+
} else {
2482+
either = llvm::None;
2483+
}
2484+
return {ty->getCanonicalType(), origTy, either};
2485+
};
2486+
auto isAggregate = [](Type ty) {
2487+
return ty->is<TupleType>() || ty->getEnumOrBoundGenericEnum() ||
2488+
ty->getStructOrBoundGenericStruct();
2489+
};
2490+
insertIntoWorklist(substType, origType, llvm::None);
2491+
while (!worklist.empty()) {
2492+
Type ty;
2493+
AbstractionPattern origTy = AbstractionPattern::getOpaque();
2494+
Optional<TaggedUnion<ValueDecl *, unsigned>> path;
2495+
std::tie(ty, origTy, path) = popFromWorklist();
2496+
if (isAggregate(ty) && !isLeafAggregate(ty, origTy, path)) {
2497+
if (auto tupleTy = ty->getAs<TupleType>()) {
2498+
for (unsigned index = 0, num = tupleTy->getNumElements(); index < num;
2499+
++index) {
2500+
auto origElementTy = origTy.getTupleElementType(index);
2501+
auto substElementTy =
2502+
tupleTy->getElementType(index)->getCanonicalType();
2503+
substElementTy =
2504+
computeLoweredRValueType(context, origElementTy, substElementTy);
2505+
insertIntoWorklist(substElementTy, origElementTy,
2506+
TaggedUnion<ValueDecl *, unsigned>(index));
2507+
}
2508+
} else if (auto *decl = ty->getStructOrBoundGenericStruct()) {
2509+
for (auto *field : decl->getStoredProperties()) {
2510+
auto subMap = ty->getContextSubstitutionMap(&M, decl);
2511+
auto substFieldTy =
2512+
field->getInterfaceType().subst(subMap)->getCanonicalType();
2513+
auto sig = field->getDeclContext()->getGenericSignatureOfContext();
2514+
auto interfaceTy = field->getInterfaceType()->getReducedType(sig);
2515+
auto origFieldType =
2516+
origTy.unsafeGetSubstFieldType(field, interfaceTy);
2517+
insertIntoWorklist(substFieldTy, origFieldType,
2518+
TaggedUnion<ValueDecl *, unsigned>(
2519+
static_cast<ValueDecl *>(field)));
2520+
}
2521+
} else if (auto *decl = ty->getEnumOrBoundGenericEnum()) {
2522+
auto subMap = ty->getContextSubstitutionMap(&M, decl);
2523+
for (auto *element : decl->getAllElements()) {
2524+
if (!element->hasAssociatedValues())
2525+
continue;
2526+
// TODO: Callback for indirect elements.
2527+
if (element->isIndirect())
2528+
continue;
2529+
auto substElementType = element->getArgumentInterfaceType()
2530+
.subst(subMap)
2531+
->getCanonicalType();
2532+
auto origElementTy = origTy.unsafeGetSubstFieldType(
2533+
element, element->getArgumentInterfaceType()->getReducedType(
2534+
decl->getGenericSignature()));
2535+
2536+
insertIntoWorklist(substElementType, origElementTy,
2537+
TaggedUnion<ValueDecl *, unsigned>(
2538+
static_cast<ValueDecl *>(element)));
2539+
}
2540+
} else {
2541+
llvm_unreachable("unknown aggregate kind!");
2542+
}
2543+
continue;
2544+
}
2545+
2546+
// This type is a leaf. Visit it.
2547+
auto success = visit(ty, origTy, path);
2548+
if (!success)
2549+
return false;
2550+
}
2551+
return true;
2552+
}
2553+
24322554
void TypeConverter::verifyLowering(const TypeLowering &lowering,
2433-
AbstractionPattern origType,
2434-
Type origSubstType,
2555+
AbstractionPattern origType, Type substType,
24352556
TypeExpansionContext forExpansion) {
24362557
// Non-trivial lowerings should always be lexical unless all non-trivial
24372558
// fields are eager move.
24382559
if (!lowering.isTrivial() && !lowering.isLexical()) {
2439-
auto getLifetimeAnnotation = [](SILType ty) -> LifetimeAnnotation {
2560+
if (lowering.getRecursiveProperties().isInfinite())
2561+
return;
2562+
auto getLifetimeAnnotation = [](Type ty) -> LifetimeAnnotation {
24402563
NominalTypeDecl *nominal;
2441-
if (!(nominal = ty.getASTType().getAnyNominal()))
2564+
if (!(nominal = ty->getAnyNominal()))
24422565
return LifetimeAnnotation::None;
24432566
return nominal->getLifetimeAnnotation();
24442567
};
2445-
auto loweredType = lowering.getLoweredType();
2446-
bool hasNoNontrivialLexicalLeaf = loweredType.visitAggregateLeaves(
2447-
*this, forExpansion,
2568+
bool hasNoNontrivialLexicalLeaf = visitAggregateLeaves(
2569+
origType, substType, forExpansion,
24482570
/*isLeaf=*/
2449-
[&](auto parent, auto ty, auto *fieldDecl) -> bool {
2571+
[&](auto ty, auto origTy, auto either) -> bool {
24502572
// The field's type is an aggregate. Treat it as a leaf if it
24512573
// has a lifetime annotation.
24522574

2453-
// If we don't have a field decl, it's either a field of a tuple
2454-
// or the top-level type. Either way, there's no var decl on
2455-
// which to look for an attribute.
2456-
//
2457-
// It's a leaf if the type has a lifetime annotation.
2458-
if (!fieldDecl)
2575+
// If it's the top-level type or a field of a tuple, there's no var
2576+
// decl on which to look for an attribute. It's a leaf iff the type
2577+
// has a lifetime annotation.
2578+
if (!either || either->template isa<unsigned>())
24592579
return getLifetimeAnnotation(ty).isSome();
24602580

24612581
// It's a field of a struct or an enum. It's a leaf if the type
24622582
// or the var decl has a lifetime annotation.
2463-
return fieldDecl->getLifetimeAnnotation().isSome() ||
2583+
return either->template get<ValueDecl *>()
2584+
->getLifetimeAnnotation()
2585+
.isSome() ||
24642586
getLifetimeAnnotation(ty);
24652587
},
24662588
/*visit=*/
2467-
[&](auto parent, auto ty, auto *fieldDecl) -> bool {
2589+
[&](auto ty, auto origTy, auto either) -> bool {
24682590
// Look at each leaf: if it is non-trivial, verify that it is
24692591
// attributed @_eagerMove.
24702592

24712593
// If the leaf is the whole type, verify that it is annotated
24722594
// @_eagerMove.
2473-
if (ty == loweredType)
2595+
if (ty->getCanonicalType() == substType->getCanonicalType())
24742596
return getLifetimeAnnotation(ty) == LifetimeAnnotation::EagerMove;
24752597

2476-
// Get ty's lowering.
2477-
CanGenericSignature sig;
2478-
if (fieldDecl) {
2479-
AbstractionPattern origFieldTy = getAbstractionPattern(fieldDecl);
2480-
CanType substFieldTy;
2481-
if (fieldDecl->hasClangNode()) {
2482-
substFieldTy = origFieldTy.getType();
2483-
} else {
2484-
substFieldTy = parent.getASTType()
2485-
->getTypeOfMember(&M, fieldDecl)
2486-
->getCanonicalType();
2487-
}
2488-
sig = getAbstractionPattern(fieldDecl).getGenericSignatureOrNull();
2489-
} else {
2490-
sig = CanGenericSignature();
2491-
}
2492-
auto &tyLowering = getTypeLowering(ty, forExpansion, sig);
2598+
auto &tyLowering = getTypeLowering(origTy, ty, forExpansion);
24932599

24942600
// Leaves which are trivial aren't of interest.
24952601
if (tyLowering.isTrivial())
@@ -2499,7 +2605,7 @@ void TypeConverter::verifyLowering(const TypeLowering &lowering,
24992605
// not lexical. The leaf must be annotated @_eagerMove.
25002606
// Otherwise, the whole type would be lexical.
25012607

2502-
if (!fieldDecl) {
2608+
if (!either || either->template isa<unsigned>()) {
25032609
// There is no field decl that might be annotated @_eagerMove. The
25042610
// field is @_eagerMove iff its type is annotated @_eagerMove.
25052611
return getLifetimeAnnotation(ty) == LifetimeAnnotation::EagerMove;
@@ -2508,7 +2614,7 @@ void TypeConverter::verifyLowering(const TypeLowering &lowering,
25082614
// The field is non-trivial and the whole type is non-lexical.
25092615
// That's fine as long as the field or its type is annotated
25102616
// @_eagerMove.
2511-
return fieldDecl->getLifetimeAnnotation() ==
2617+
return either->template get<ValueDecl *>()->getLifetimeAnnotation() ==
25122618
LifetimeAnnotation::EagerMove ||
25132619
getLifetimeAnnotation(ty) == LifetimeAnnotation::EagerMove;
25142620
});

0 commit comments

Comments
 (0)