mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
CapturePromotion: Fix promotion of resilient but locally non-resilient types
Pass the resilience expansion to the cloner so that it can correctly (in agreement with the caller) decide whether something is address only. rdar://52263202
This commit is contained in:
@@ -197,10 +197,9 @@ public:
|
||||
friend class SILInstructionVisitor<ClosureCloner>;
|
||||
friend class SILCloner<ClosureCloner>;
|
||||
|
||||
ClosureCloner(SILOptFunctionBuilder &FuncBuilder,
|
||||
SILFunction *Orig, IsSerialized_t Serialized,
|
||||
StringRef ClonedName,
|
||||
IndicesSet &PromotableIndices);
|
||||
ClosureCloner(SILOptFunctionBuilder &FuncBuilder, SILFunction *Orig,
|
||||
IsSerialized_t Serialized, StringRef ClonedName,
|
||||
IndicesSet &PromotableIndices, ResilienceExpansion expansion);
|
||||
|
||||
void populateCloned();
|
||||
|
||||
@@ -210,7 +209,8 @@ private:
|
||||
static SILFunction *initCloned(SILOptFunctionBuilder &FuncBuilder,
|
||||
SILFunction *Orig, IsSerialized_t Serialized,
|
||||
StringRef ClonedName,
|
||||
IndicesSet &PromotableIndices);
|
||||
IndicesSet &PromotableIndices,
|
||||
ResilienceExpansion expansion);
|
||||
|
||||
SILValue getProjectBoxMappedVal(SILValue Operand);
|
||||
|
||||
@@ -224,6 +224,7 @@ private:
|
||||
void visitBeginAccessInst(BeginAccessInst *Inst);
|
||||
void visitEndAccessInst(EndAccessInst *Inst);
|
||||
|
||||
ResilienceExpansion resilienceExpansion;
|
||||
SILFunction *Orig;
|
||||
IndicesSet &PromotableIndices;
|
||||
llvm::DenseMap<SILArgument *, SILValue> BoxArgumentMap;
|
||||
@@ -311,10 +312,12 @@ ReachabilityInfo::isReachable(SILBasicBlock *From, SILBasicBlock *To) {
|
||||
ClosureCloner::ClosureCloner(SILOptFunctionBuilder &FuncBuilder,
|
||||
SILFunction *Orig, IsSerialized_t Serialized,
|
||||
StringRef ClonedName,
|
||||
IndicesSet &PromotableIndices)
|
||||
: SILClonerWithScopes<ClosureCloner>(
|
||||
*initCloned(FuncBuilder, Orig, Serialized, ClonedName, PromotableIndices)),
|
||||
Orig(Orig), PromotableIndices(PromotableIndices) {
|
||||
IndicesSet &PromotableIndices,
|
||||
ResilienceExpansion resilienceExpansion)
|
||||
: SILClonerWithScopes<ClosureCloner>(
|
||||
*initCloned(FuncBuilder, Orig, Serialized, ClonedName,
|
||||
PromotableIndices, resilienceExpansion)),
|
||||
Orig(Orig), PromotableIndices(PromotableIndices) {
|
||||
assert(Orig->getDebugScope()->Parent != getCloned()->getDebugScope()->Parent);
|
||||
}
|
||||
|
||||
@@ -326,9 +329,9 @@ ClosureCloner::ClosureCloner(SILOptFunctionBuilder &FuncBuilder,
|
||||
/// 2. Replace container box value arguments for the cloned closure with the
|
||||
/// transformed address or value argument.
|
||||
static void
|
||||
computeNewArgInterfaceTypes(SILFunction *F,
|
||||
IndicesSet &PromotableIndices,
|
||||
SmallVectorImpl<SILParameterInfo> &OutTys) {
|
||||
computeNewArgInterfaceTypes(SILFunction *F, IndicesSet &PromotableIndices,
|
||||
SmallVectorImpl<SILParameterInfo> &OutTys,
|
||||
ResilienceExpansion expansion) {
|
||||
auto fnConv = F->getConventions();
|
||||
auto Parameters = fnConv.funcTy->getParameters();
|
||||
|
||||
@@ -365,11 +368,9 @@ computeNewArgInterfaceTypes(SILFunction *F,
|
||||
assert(paramBoxTy->getLayout()->getFields().size() == 1
|
||||
&& "promoting compound box not implemented yet");
|
||||
auto paramBoxedTy = paramBoxTy->getFieldType(F->getModule(), 0);
|
||||
// FIXME: Expansion
|
||||
auto ¶mTL = Types.getTypeLowering(paramBoxedTy,
|
||||
ResilienceExpansion::Minimal);
|
||||
auto ¶mTL = Types.getTypeLowering(paramBoxedTy, expansion);
|
||||
ParameterConvention convention;
|
||||
if (paramTL.isFormallyPassedIndirectly()) {
|
||||
if (paramTL.isAddressOnly()) {
|
||||
convention = ParameterConvention::Indirect_In;
|
||||
} else if (paramTL.isTrivial()) {
|
||||
convention = ParameterConvention::Direct_Unowned;
|
||||
@@ -407,16 +408,17 @@ static std::string getSpecializedName(SILFunction *F,
|
||||
///
|
||||
/// *NOTE* PromotableIndices only contains the container value of the box, not
|
||||
/// the address value.
|
||||
SILFunction*
|
||||
SILFunction *
|
||||
ClosureCloner::initCloned(SILOptFunctionBuilder &FunctionBuilder,
|
||||
SILFunction *Orig, IsSerialized_t Serialized,
|
||||
StringRef ClonedName,
|
||||
IndicesSet &PromotableIndices) {
|
||||
StringRef ClonedName, IndicesSet &PromotableIndices,
|
||||
ResilienceExpansion resilienceExpansion) {
|
||||
SILModule &M = Orig->getModule();
|
||||
|
||||
// Compute the arguments for our new function.
|
||||
SmallVector<SILParameterInfo, 4> ClonedInterfaceArgTys;
|
||||
computeNewArgInterfaceTypes(Orig, PromotableIndices, ClonedInterfaceArgTys);
|
||||
computeNewArgInterfaceTypes(Orig, PromotableIndices, ClonedInterfaceArgTys,
|
||||
resilienceExpansion);
|
||||
|
||||
SILFunctionType *OrigFTI = Orig->getLoweredFunctionType();
|
||||
|
||||
@@ -1149,7 +1151,8 @@ examineAllocBoxInst(AllocBoxInst *ABI, ReachabilityInfo &RI,
|
||||
static SILFunction *
|
||||
constructClonedFunction(SILOptFunctionBuilder &FuncBuilder,
|
||||
PartialApplyInst *PAI, FunctionRefInst *FRI,
|
||||
IndicesSet &PromotableIndices) {
|
||||
IndicesSet &PromotableIndices,
|
||||
ResilienceExpansion resilienceExpansion) {
|
||||
SILFunction *F = PAI->getFunction();
|
||||
|
||||
// Create the Cloned Name for the function.
|
||||
@@ -1168,7 +1171,8 @@ constructClonedFunction(SILOptFunctionBuilder &FuncBuilder,
|
||||
}
|
||||
|
||||
// Otherwise, create a new clone.
|
||||
ClosureCloner cloner(FuncBuilder, Orig, Serialized, ClonedName, PromotableIndices);
|
||||
ClosureCloner cloner(FuncBuilder, Orig, Serialized, ClonedName,
|
||||
PromotableIndices, resilienceExpansion);
|
||||
cloner.populateCloned();
|
||||
return cloner.getCloned();
|
||||
}
|
||||
@@ -1252,7 +1256,8 @@ processPartialApplyInst(SILOptFunctionBuilder &FuncBuilder,
|
||||
auto *FRI = dyn_cast<FunctionRefInst>(PAI->getCallee());
|
||||
|
||||
// Clone the closure with the given promoted captures.
|
||||
SILFunction *ClonedFn = constructClonedFunction(FuncBuilder, PAI, FRI, PromotableIndices);
|
||||
SILFunction *ClonedFn = constructClonedFunction(
|
||||
FuncBuilder, PAI, FRI, PromotableIndices, F->getResilienceExpansion());
|
||||
Worklist.push_back(ClonedFn);
|
||||
|
||||
// Initialize a SILBuilder and create a function_ref referencing the cloned
|
||||
|
||||
45
test/SILOptimizer/capture_promotion_resilient.sil
Normal file
45
test/SILOptimizer/capture_promotion_resilient.sil
Normal file
@@ -0,0 +1,45 @@
|
||||
// RUN: %target-sil-opt -enable-library-evolution -enable-sil-verify-all %s -capture-promotion | %FileCheck %s
|
||||
|
||||
sil_stage raw
|
||||
|
||||
import Swift
|
||||
|
||||
public struct ResilientStruct {
|
||||
var x : Int64
|
||||
}
|
||||
|
||||
sil @closure0 : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } <ResilientStruct>) -> () {
|
||||
bb0(%0 : $<τ_0_0> { var τ_0_0 } <ResilientStruct>):
|
||||
%1 = project_box %0 : $<τ_0_0> { var τ_0_0 } <ResilientStruct>, 0
|
||||
%2 = tuple ()
|
||||
return %2 : $()
|
||||
}
|
||||
|
||||
// Primarily don't crash.
|
||||
|
||||
// CHECK-LABEL: sil @$s8closure0Tf2i_n : $@convention(thin) (ResilientStruct) -> () {
|
||||
// CHECK: bb0(%0 : $ResilientStruct):
|
||||
// CHECK: return {{.*}} : $()
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: sil @test_capture_promotion : $@convention(thin) (@in_guaranteed ResilientStruct) -> @owned @callee_guaranteed () -> () {
|
||||
// CHECK: bb0([[ARG:%.*]] : $*ResilientStruct):
|
||||
// CHECK: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <ResilientStruct>
|
||||
// CHECK: [[F1:%.*]] = project_box [[BOX]]
|
||||
// CHECK: [[F2:%.*]] = project_box [[BOX]]
|
||||
// CHECK: copy_addr [[ARG]] to [initialization] [[F2]] : $*ResilientStruct
|
||||
// CHECK: [[F:%.*]] = function_ref @$s8closure0Tf2i_n : $@convention(thin) (ResilientStruct) -> () // user: %8
|
||||
// CHECK: [[R:%.*]] = load [[F1]] : $*ResilientStruct
|
||||
// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[R]])
|
||||
// CHECK: return [[C]] : $@callee_guaranteed () -> ()
|
||||
// CHECK: }
|
||||
|
||||
sil @test_capture_promotion : $@convention(thin) (@in_guaranteed ResilientStruct) -> @owned @callee_guaranteed () -> () {
|
||||
bb0(%0 : $*ResilientStruct):
|
||||
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <ResilientStruct>
|
||||
%2 = project_box %1 : $<τ_0_0> { var τ_0_0 } <ResilientStruct>, 0
|
||||
copy_addr %0 to [initialization] %2 : $*ResilientStruct
|
||||
%4 = function_ref @closure0 : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } <ResilientStruct>) -> ()
|
||||
%5 = partial_apply [callee_guaranteed] %4(%1) : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } <ResilientStruct>) -> ()
|
||||
return %5 : $@callee_guaranteed () -> ()
|
||||
}
|
||||
Reference in New Issue
Block a user