Skip to content

Commit 3aadede

Browse files
committed
[sil-combine] Make sure that (apply (partial_apply)) -> (apply') bails if we have an argument with a dependent type.
What is going on here is that currently this optimization if itneeds to perform lfietime extension always creates an alloc_stack at the beginning/end of a function. If the object whose lifetime is being extended has a dependent type, then the alloc_stack will be created before the dependent type exists resulting in the compiler crashing. rdar://33595317
1 parent fcafd6b commit 3aadede

File tree

2 files changed

+41
-9
lines changed

2 files changed

+41
-9
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,25 +151,34 @@ bool PartialApplyCombiner::allocateTemporaries() {
151151
// Emit a destroy value for each captured closure argument.
152152
ArrayRef<SILParameterInfo> Params = PAITy->getParameters();
153153
auto Args = PAI->getArguments();
154-
unsigned Delta = Params.size() - Args.size();
154+
Params = Params.drop_front(Params.size() - Args.size());
155155

156156
llvm::SmallVector<std::pair<SILValue, unsigned>, 8> ArgsToHandle;
157-
for (unsigned AI = 0, AE = Args.size(); AI != AE; ++AI) {
158-
SILValue Arg = Args[AI];
159-
SILParameterInfo Param = Params[AI + Delta];
157+
for (unsigned i : indices(Args)) {
158+
SILValue Arg = Args[i];
159+
SILParameterInfo Param = Params[i];
160160
if (Param.isIndirectMutating())
161161
continue;
162+
162163
// Create a temporary and copy the argument into it, if:
163164
// - the argument stems from an alloc_stack
164165
// - the argument is consumed by the callee and is indirect
165166
// (e.g. it is an @in argument)
166167
if (isa<AllocStackInst>(Arg)
167168
|| (Param.isConsumed()
168169
&& PAI->getSubstCalleeConv().isSILIndirect(Param))) {
170+
// If the argument has a dependent type, then we can not create a
171+
// temporary for it at the beginning of the function, so we must bail.
172+
//
173+
// TODO: This is because we are inserting alloc_stack at the beginning/end
174+
// of functions where the dependent type may not exist yet.
175+
if (Arg->getType().hasOpenedExistential())
176+
return false;
177+
169178
// If the temporary is non-trivial, we need to release it later.
170179
if (!Arg->getType().isTrivial(PAI->getModule()))
171180
needsReleases = true;
172-
ArgsToHandle.push_back(std::make_pair(Arg, AI));
181+
ArgsToHandle.push_back(std::make_pair(Arg, i));
173182
}
174183
}
175184

test/SILOptimizer/sil_combine_apply.sil

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ sil @generic_callee : $@convention(thin) <T, U> (@in T, @in U) -> ()
1111

1212
protocol Error {}
1313

14+
protocol SwiftP {
15+
func foo()
16+
}
17+
1418
/////////////////////////////////
1519
// Tests for SILCombinerApply. //
1620
/////////////////////////////////
@@ -235,10 +239,6 @@ bb6(%5 : $Error):
235239
throw %5 : $Error
236240
}
237241

238-
protocol SwiftP {
239-
func foo()
240-
}
241-
242242
// Make sure that we do not optimize this case. If we do optimize this case,
243243
// given the current algorithm which puts alloc_stack at the beginning/end of
244244
// the function, we will have a fatal error.
@@ -285,4 +285,27 @@ bb0(%0 : $*T, %1 : $*T):
285285
%a1 = apply %pa(%0) : $@callee_owned (@in T) -> ()
286286
%r = tuple ()
287287
return %r : $()
288+
}
289+
290+
// Today when we optimize (apply (partial_apply)) -> apply, we can not handle
291+
// dependent types since the algorithm attempts to create an alloc_stack at the
292+
// beginning/end of the function. In such a case, the dependent type may not be
293+
// alive at that point, so the compiler will crash. This test ensures that we do
294+
// not optimize this case.
295+
//
296+
// CHECK-LABEL: sil @sil_combine_applied_partialapply_to_apply_with_dependent_type : $@convention(thin) (@in SwiftP) -> () {
297+
// CHECK: [[PAI:%.*]] = partial_apply
298+
// CHECK: apply [[PAI]]
299+
sil @sil_combine_applied_partialapply_to_apply_with_dependent_type : $@convention(thin) (@in SwiftP) -> () {
300+
bb0(%0 : $*SwiftP):
301+
%0b = alloc_stack $SwiftP
302+
%1 = open_existential_addr mutable_access %0b : $*SwiftP to $*@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP
303+
%2 = witness_method $@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP, #SwiftP.foo!1, %1 : $*@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP : $@convention(witness_method) <τ_0_0 where τ_0_0 : SwiftP> (@in_guaranteed τ_0_0) -> ()
304+
%0c = alloc_stack $@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP
305+
%3 = partial_apply %2<@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP>(%0c) : $@convention(witness_method) <τ_0_0 where τ_0_0 : SwiftP> (@in_guaranteed τ_0_0) -> ()
306+
dealloc_stack %0c : $*@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP
307+
dealloc_stack %0b : $*SwiftP
308+
%4 = apply %3() : $@callee_owned () -> ()
309+
%9999 = tuple()
310+
return %9999 : $()
288311
}

0 commit comments

Comments
 (0)