From ef7f16ccbfe6b936e420d2dbe9a55bf02ac74c3c Mon Sep 17 00:00:00 2001 From: Roman Levenstein Date: Fri, 26 Aug 2016 09:53:58 -0700 Subject: [PATCH] Fix a bug related to the opened archetypes tracking If a SILBuilder creates a new instruction based on an old instruction and a new instruction is supposed to use some opened archetypes, one needs to set a proper opened archetypes context in the builder based on the opened archetypes used by the old instruction. This fixes rdar://28024272 --- include/swift/SIL/SILBuilder.h | 13 ++++ .../SILCombiner/SILCombinerApplyVisitors.cpp | 2 + .../Transforms/SpeculativeDevirtualizer.cpp | 1 + .../opened_archetype_operands_tracking.sil | 64 +++++++++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 test/SILOptimizer/opened_archetype_operands_tracking.sil diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h index 05774995aad27..10ace6feeb07c 100644 --- a/include/swift/SIL/SILBuilder.h +++ b/include/swift/SIL/SILBuilder.h @@ -135,6 +135,11 @@ class SILBuilder { void setInsertionPoint(SILBasicBlock *BB, SILBasicBlock::iterator InsertPt) { this->BB = BB; this->InsertPt = InsertPt; + if (InsertPt == BB->end()) + return; + // Set the opened archetype context from the instruction. + this->getOpenedArchetypes().addOpenedArchetypeOperands( + InsertPt->getTypeDependentOperands()); } /// setInsertionPoint - Set the insertion point to insert before the specified @@ -177,6 +182,14 @@ class SILBuilder { return InsertedInstrs; } + //===--------------------------------------------------------------------===// + // Opened archetypes handling + //===--------------------------------------------------------------------===// + void addOpenedArchetypeOperands(SILInstruction *I) { + getOpenedArchetypes().addOpenedArchetypeOperands( + I->getTypeDependentOperands()); + } + //===--------------------------------------------------------------------===// // Type remapping //===--------------------------------------------------------------------===// diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp index 9cb4456604917..4205261ef0c57 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp @@ -721,6 +721,7 @@ SILCombiner::createApplyWithConcreteType(FullApplySite AI, FullApplySite NewAI; Builder.setCurrentDebugScope(AI.getDebugScope()); + Builder.addOpenedArchetypeOperands(AI.getInstruction()); if (auto *TAI = dyn_cast(AI)) NewAI = Builder.createTryApply(AI.getLoc(), AI.getCallee(), @@ -1156,6 +1157,7 @@ SILInstruction *SILCombiner::visitApplyInst(ApplyInst *AI) { // The type of the substitution is the source type of the thin to thick // instruction. SILType substTy = TTTFI->getOperand()->getType(); + Builder.addOpenedArchetypeOperands(AI); auto *NewAI = Builder.createApply(AI->getLoc(), TTTFI->getOperand(), substTy, AI->getType(), AI->getSubstitutions(), Arguments, diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp index 5c4ddf53f1398..0fe0ad3ffe068 100644 --- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp +++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp @@ -50,6 +50,7 @@ STATISTIC(NumTargetsPredicted, "Number of monomorphic functions predicted"); static FullApplySite CloneApply(FullApplySite AI, SILBuilder &Builder) { // Clone the Apply. Builder.setCurrentDebugScope(AI.getDebugScope()); + Builder.addOpenedArchetypeOperands(AI.getInstruction()); auto Args = AI.getArguments(); SmallVector Ret(Args.size()); for (unsigned i = 0, e = Args.size(); i != e; ++i) diff --git a/test/SILOptimizer/opened_archetype_operands_tracking.sil b/test/SILOptimizer/opened_archetype_operands_tracking.sil new file mode 100644 index 0000000000000..68477e3e042d8 --- /dev/null +++ b/test/SILOptimizer/opened_archetype_operands_tracking.sil @@ -0,0 +1,64 @@ +// RUN: %target-sil-opt -enable-sil-verify-all %s -O | %FileCheck %s + +// Check some corner cases related to tracking of opened archetypes. +// For example, the compiler used to crash compiling the "process" function (rdar://28024272) + +sil_stage canonical + +import Builtin +import Swift +import SwiftShims + +public protocol P { +} + +extension P { + func invokeClosure(_ closure: () throws -> ()) rethrows +} + +public func process(s: P) + +sil @invokeClosure : $@convention(method) (@owned @callee_owned () -> @error Error, @in_guaranteed Self) -> @error Error { +bb0(%0 : $@callee_owned () -> @error Error, %1 : $*Self): + strong_release %0 : $@callee_owned () -> @error Error + %5 = tuple () + return %5 : $() +} + +sil @closure : $@convention(thin) () -> () { +bb0: + %0 = tuple () + debug_value %0 : $() + %2 = tuple () + return %2 : $() +} + +// CHECK-LABEL: sil @process +// CHECK: bb0 +// CHECK-NOT: try_apply +// CHECK-NOT: unreachable +// CHECK: apply +// CHECK-NOT: unreachable +// CHECK: return +sil @process : $@convention(thin) (@in P) -> () { +bb0(%0 : $*P): + %2 = open_existential_addr %0 : $*P to $*@opened("4C22C24E-6BAA-11E6-B904-B8E856428C60") P + %3 = function_ref @invokeClosure : $@convention(method) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @error Error, @in_guaranteed τ_0_0) -> @error Error + // function_ref (process(s : P) -> ()).(closure #1) + %4 = function_ref @closure : $@convention(thin) () -> () + %5 = thin_to_thick_function %4 : $@convention(thin) () -> () to $@callee_owned () -> () + %6 = convert_function %5 : $@callee_owned () -> () to $@callee_owned () -> @error Error + try_apply %3<@opened("4C22C24E-6BAA-11E6-B904-B8E856428C60") P>(%6, %2) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @error Error, @in_guaranteed τ_0_0) -> @error Error, normal bb1, error bb2 + +bb1(%8 : $()): + destroy_addr %0 : $*P + %10 = tuple () + return %10 : $() + +bb2(%12 : $Error): + unreachable +} + +sil_default_witness_table P { +} +