Skip to content

Commit 22c05ba

Browse files
committed
Fix the SIL verifier to handle openings of multiple element archetypes
1 parent fdfe507 commit 22c05ba

File tree

2 files changed

+78
-21
lines changed

2 files changed

+78
-21
lines changed

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,27 +1640,30 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
16401640
void checkApplyTypeDependentArguments(ApplySite AS) {
16411641
SILInstruction *AI = AS.getInstruction();
16421642

1643-
llvm::DenseSet<LocalArchetypeType *> FoundRootLocalArchetypes;
1643+
llvm::DenseSet<SILInstruction *> allOpeningInsts;
16441644
unsigned hasDynamicSelf = 0;
16451645

1646-
// Function to collect local archetypes in FoundRootLocalArchetypes
1647-
// and set hasDynamicSelf.
1648-
auto HandleType = [&](CanType Ty) {
1646+
// Function to collect local archetypes in allOpeningInsts and set
1647+
// hasDynamicSelf.
1648+
auto handleType = [&](CanType Ty) {
16491649
if (const auto A = dyn_cast<LocalArchetypeType>(Ty)) {
16501650
require(isArchetypeValidInFunction(A, AI->getFunction()),
16511651
"Archetype to be substituted must be valid in function.");
16521652

16531653
const auto root = A.getRoot();
16541654

1655-
// Collect all root local archetypes used in the substitutions list.
1656-
FoundRootLocalArchetypes.insert(root);
1657-
// Also check that they are properly tracked inside the current
1658-
// function.
1655+
// Check that opened archetypes are properly tracked inside
1656+
// the current function.
16591657
auto *openingInst = F.getModule().getRootLocalArchetypeDefInst(
16601658
root, AI->getFunction());
16611659
require(openingInst == AI || properlyDominates(openingInst, AI),
16621660
"Use of a local archetype should be dominated by a "
16631661
"definition of this root opened archetype");
1662+
1663+
// Remember all the opening instructions. We unique by instruction
1664+
// identity when building the list of type dependency operands, and
1665+
// some instructions can open multiple archetypes.
1666+
allOpeningInsts.insert(openingInst);
16641667
}
16651668
if (Ty->hasDynamicSelfType()) {
16661669
hasDynamicSelf = 1;
@@ -1669,11 +1672,11 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
16691672

16701673
// Search for local archetypes and dynamic self.
16711674
for (auto Replacement : AS.getSubstitutionMap().getReplacementTypes()) {
1672-
Replacement->getCanonicalType().visit(HandleType);
1675+
Replacement->getCanonicalType().visit(handleType);
16731676
}
1674-
AS.getSubstCalleeType().visit(HandleType);
1677+
AS.getSubstCalleeType().visit(handleType);
16751678

1676-
require(FoundRootLocalArchetypes.size() + hasDynamicSelf ==
1679+
require(allOpeningInsts.size() + hasDynamicSelf ==
16771680
AI->getTypeDependentOperands().size(),
16781681
"Number of local archetypes and dynamic self in the substitutions "
16791682
"list should match the number of type dependent operands");
@@ -1691,19 +1694,19 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
16911694
auto DI = V->getDefiningInstruction();
16921695
require(DI,
16931696
"local archetype operand should refer to a SIL instruction");
1694-
bool definesFoundArchetype = false;
1695-
bool definesAnyArchetype = false;
1697+
require(allOpeningInsts.count(DI),
1698+
"local archetype operand does not correspond to any local "
1699+
"archetype from the substitutions list");
1700+
1701+
bool matchedDependencyResult = false;
16961702
DI->forEachDefinedLocalArchetype(
16971703
[&](CanLocalArchetypeType archetype, SILValue dependency) {
1698-
definesAnyArchetype = true;
1699-
if (FoundRootLocalArchetypes.count(archetype))
1700-
definesFoundArchetype = true;
1704+
if (dependency == V)
1705+
matchedDependencyResult = true;
17011706
});
1702-
require(definesAnyArchetype,
1703-
"local archetype operand should define a local archetype");
1704-
require(definesFoundArchetype,
1705-
"local archetype operand does not correspond to any local "
1706-
"archetype from the substitutions list");
1707+
require(matchedDependencyResult,
1708+
"local archetype operand was not the dependency result "
1709+
"of the opening instruction");
17071710
}
17081711
}
17091712
}

test/SILGen/variadic-generic-results.swift

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,57 @@ func wrapTupleElements<each T>(_ value: repeat each T) -> (repeat Wrapper<each T
269269
// CHECK-NEXT: return [[RET]] : $()
270270
return values
271271
}
272+
273+
struct Pair<First, Second> {
274+
init(_ first: First, _ second: Second) {}
275+
}
276+
277+
// CHECK-LABEL: @$s4main9makePairs6firsts7secondsAA4PairVyxq_GxQp_txxQp_q_xQptq_RhzRvzRv_r0_lF
278+
// CHECK-SAME: $@convention(thin) <each First, each Second where (repeat (each First, each Second)) : Any> (@pack_guaranteed Pack{repeat each First}, @pack_guaranteed Pack{repeat each Second}) -> @pack_out Pack{repeat Pair<each First, each Second>}
279+
func makePairs<each First, each Second>(
280+
firsts first: repeat each First,
281+
seconds second: repeat each Second
282+
) -> (repeat Pair<each First, each Second>) {
283+
// CHECK: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0
284+
// CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1
285+
// CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each First}
286+
// CHECK-NEXT: br bb1([[ZERO]] : $Builtin.Word)
287+
// CHECK: bb1([[IDX:%.*]] : $Builtin.Word)
288+
// CHECK-NEXT: [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1
289+
// CHECK-NEXT: cond_br [[IDX_EQ_LEN]], bb3, bb2
290+
// CHECK: bb2:
291+
// CHECK-NEXT: [[INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat Pair<each First, each Second>}
292+
// CHECK-NEXT: open_pack_element [[INDEX]] of <each First, each Second where (repeat (each First, each Second)) : Any> at <Pack{repeat each First}, Pack{repeat each Second}>, shape $First, uuid [[UUID:".*"]]
293+
// CHECK-NEXT: [[OUT_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of %0 : $*Pack{repeat Pair<each First, each Second>} as $*Pair<@pack_element([[UUID]]) First, @pack_element([[UUID]]) Second>
294+
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Pair<@pack_element([[UUID]]) First, @pack_element([[UUID]]) Second>.Type
295+
// CHECK-NEXT: [[FIRST_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of %1 : $*Pack{repeat each First} as $*@pack_element([[UUID]]) First
296+
// CHECK-NEXT: [[FIRST_COPY:%.*]] = alloc_stack $@pack_element([[UUID]]) First
297+
// CHECK-NEXT: copy_addr [[FIRST_ELT_ADDR]] to [init] [[FIRST_COPY]] : $*@pack_element([[UUID]]) First
298+
// CHECK-NEXT: [[SECOND_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of %2 : $*Pack{repeat each Second} as $*@pack_element([[UUID]]) Second
299+
// CHECK-NEXT: [[SECOND_COPY:%.*]] = alloc_stack $@pack_element([[UUID]]) Second
300+
// CHECK-NEXT: copy_addr [[SECOND_ELT_ADDR]] to [init] [[SECOND_COPY]] : $*@pack_element([[UUID]]) Second
301+
// CHECK-NEXT: // function_ref
302+
// CHECK-NEXT: [[FN:%.*]] = function_ref
303+
// CHECK-NEXT: [[PAIR:%.*]] = apply [[FN]]<@pack_element([[UUID]]) First, @pack_element([[UUID]]) Second>([[FIRST_COPY]], [[SECOND_COPY]], [[METATYPE]])
304+
// CHECK-NEXT: dealloc_stack [[SECOND_COPY]] : $*@pack_element([[UUID]]) Second
305+
// CHECK-NEXT: dealloc_stack [[FIRST_COPY]] : $*@pack_element([[UUID]]) First
306+
// CHECK-NEXT: store [[PAIR]] to [trivial] [[OUT_ELT_ADDR]] : $*Pair<@pack_element([[UUID]]) First, @pack_element([[UUID]]) Second>
307+
// CHECK-NEXT: [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word
308+
// CHECK-NEXT: br bb1([[NEXT_IDX]] : $Builtin.Word)
309+
// CHECK: bb3:
310+
// CHECK-NEXT: [[RET:%.*]] = tuple ()
311+
// CHECK-NEXT: return [[RET]] : $()
312+
return (repeat Pair(each first, each second))
313+
}
314+
315+
protocol Container {
316+
associatedtype Contents
317+
var contents: Contents { get }
318+
}
319+
320+
func makeContentsPairs<each First: Container, each Second: Container>(
321+
firsts first: repeat each First,
322+
seconds second: repeat each Second
323+
) -> (repeat Pair<(each First).Contents, (each Second).Contents>) {
324+
return (repeat Pair((each first).contents, (each second).contents))
325+
}

0 commit comments

Comments
 (0)