Skip to content

Commit 32fa74d

Browse files
authored
Merge pull request #64374 from rjmccall/verify-multiple-opening
Verify instructions depending on multiple archetypes from the same open_pack_element
2 parents 151e1c5 + 22c05ba commit 32fa74d

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

0 commit comments

Comments
 (0)