Skip to content

Commit 5e77efe

Browse files
authored
Merge pull request #12085 from swiftix/open-archtypes-tracker-fixes
Fix the hang in the SILBuilder::addOpenedArchetypeOperands
2 parents f633136 + 7f4c4f7 commit 5e77efe

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

lib/SIL/SILBuilder.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,10 +410,13 @@ void SILBuilder::addOpenedArchetypeOperands(SILInstruction *I) {
410410
if (I && I->getNumTypeDependentOperands() > 0)
411411
return;
412412

413+
// Keep track of already visited instructions to avoid infinite loops.
414+
SmallPtrSet<SILInstruction *, 8> Visited;
415+
413416
while (I && I->getNumOperands() == 1 &&
414417
I->getNumTypeDependentOperands() == 0) {
415418
I = dyn_cast<SILInstruction>(I->getOperand(0));
416-
if (!I)
419+
if (!I || !Visited.insert(I).second)
417420
return;
418421
// If it is a definition of an opened archetype,
419422
// register it and exit.

test/SILOptimizer/opened_archetype_operands_tracking.sil

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -sil-inline-generics -enable-sil-verify-all %s -O | %FileCheck %s
2+
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -simplify-cfg -enable-sil-verify-all %s -O | %FileCheck --check-prefix=CHECK-SIMPLIFY-CFG %s
23

34
// Check some corner cases related to tracking of opened archetypes.
45
// For example, the compiler used to crash compiling the "process" function (rdar://28024272)
@@ -262,3 +263,53 @@ bb0(%0 : $AnyObject):
262263
return %8 : $()
263264
} // end sil function 'check_removal_of_unregistered_archetype_def'
264265

266+
// Check that even in case of unreacheable blocks the compiler does not hang
267+
// in SILBuilder::addOpenedArchetypeOperands. rdar://problem/34602036
268+
269+
enum MyOptional<T> {
270+
case none
271+
case some(T)
272+
}
273+
274+
class C {
275+
var this : MyOptional<C>
276+
init()
277+
}
278+
279+
// CHECK-SIMPLIFY-CFG-LABEL: sil @test_infinite_loop_in_unreachable_block
280+
// CHECK-SIMPLIFY-CFG: bb0
281+
// CHECK-SIMPLIFY-CFG-NOT: bb1
282+
// CHECK-SIMPLIFY-CFG: end sil function 'test_infinite_loop_in_unreachable_block'
283+
sil @test_infinite_loop_in_unreachable_block : $@convention(method) (@guaranteed C) -> () {
284+
bb0(%0 : $C):
285+
%1 = enum $MyOptional<C>, #MyOptional.some!enumelt.1, %0 : $C
286+
%2 = integer_literal $Builtin.Int64, 0
287+
strong_retain %0 : $C
288+
release_value %1 : $MyOptional<C>
289+
%6 = integer_literal $Builtin.Int1, -1
290+
cond_br %6, bb5, bb1
291+
292+
bb1:
293+
%8 = enum $MyOptional<C>, #MyOptional.some!enumelt.1, %0 : $C
294+
strong_retain %0 : $C
295+
br bb2(%8 : $MyOptional<C>)
296+
297+
bb2(%11 : $MyOptional<C>):
298+
%12 = unchecked_enum_data %11 : $MyOptional<C>, #MyOptional.some!enumelt.1
299+
%13 = ref_element_addr %12 : $C, #C.this
300+
%14 = load %13 : $*MyOptional<C>
301+
switch_enum %14 : $MyOptional<C>, case #MyOptional.some!enumelt.1: bb3, case #MyOptional.none!enumelt: bb4
302+
303+
bb3(%16 : $C):
304+
retain_value %14 : $MyOptional<C>
305+
release_value %11 : $MyOptional<C>
306+
br bb2(%14 : $MyOptional<C>)
307+
308+
bb4:
309+
release_value %11 : $MyOptional<C>
310+
br bb5
311+
312+
bb5:
313+
%22 = tuple ()
314+
return %22 : $()
315+
} // end sil function 'test_infinite_loop_in_unreachable_block'

0 commit comments

Comments
 (0)