diff --git a/lib/SILPasses/Link.cpp b/lib/SILPasses/Link.cpp index 39325f47e14..81b84ff1403 100644 --- a/lib/SILPasses/Link.cpp +++ b/lib/SILPasses/Link.cpp @@ -91,11 +91,12 @@ void swift::performSILLinking(SILModule *M) { if (ApplyInst *AI = dyn_cast(I)) { SILValue Callee = AI->getCallee(); // Handles FunctionRefInst only. - if (FunctionRefInst *FRI = dyn_cast(Callee.getDef())) + if (FunctionRefInst *FRI = dyn_cast(Callee.getDef())) { CalleeFunction = FRI->getReferencedFunction(); - - // When EnableLinkAll is true, we always link the Callee. - TryLinking = EnableLinkAll ? true : AI->isTransparent(); + // When EnableLinkAll is true, we always link the Callee. + TryLinking = EnableLinkAll || AI->isTransparent() || + CalleeFunction->getLinkage() == SILLinkage::Private; + } } else if (PartialApplyInst *PAI = dyn_cast(I)) { SILValue Callee = PAI->getCallee(); @@ -103,7 +104,8 @@ void swift::performSILLinking(SILModule *M) { if (FunctionRefInst *FRI = dyn_cast(Callee.getDef())) { CalleeFunction = FRI->getReferencedFunction(); // When EnableLinkAll is true, we always link the Callee. - TryLinking = EnableLinkAll ? true : CalleeFunction->isTransparent(); + TryLinking = EnableLinkAll || CalleeFunction->isTransparent() || + CalleeFunction->getLinkage() == SILLinkage::Private; } else { continue; } diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index fbdb5acbd7e..58799760be8 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -1333,8 +1333,12 @@ void SILSerializer::writeAllSILFunctions(const SILModule *SILMod) { // Helper function for whether to emit a function body. auto shouldEmitFunctionBody = [&](const SILFunction &F) { + // Emit function body if a private function is referenced in this module. + // This is needed for body of closure. return (!F.empty() && - (EnableSerializeAll || F.isTransparent())); + (EnableSerializeAll || F.isTransparent() || + (F.getLinkage() == SILLinkage::Private && + FuncsToDeclare.count(&F)))); }; // Go through all the SILFunctions in SILMod and write out any diff --git a/test/Serialization/Inputs/def_basic.sil b/test/Serialization/Inputs/def_basic.sil index 800835d2d42..3142d58f7a1 100644 --- a/test/Serialization/Inputs/def_basic.sil +++ b/test/Serialization/Inputs/def_basic.sil @@ -872,6 +872,30 @@ entry(%f : $@thin (@out Int, Int) -> (), %x : $Int): return %y : $Int } +// Make sure we serialize the body of closure even without -sil-serialize-all. +// CHECK_DECL-LABEL: @partial_apply_with_closure +sil [transparent] @partial_apply_with_closure : $@thin (@owned @callee_owned () -> Bool, @owned String, CString, Int64) -> () { +bb0(%0 : $@callee_owned () -> Bool, %1 : $String, %2 : $CString, %3 : $Int64): + %17 = function_ref @closure_body : $@thin (CString, CString, Int64) -> () +// CHECK_DECL: function_ref @closure_body + %18 = partial_apply %17(%2, %3) : $@thin (CString, CString, Int64) -> () +// CHECK_DECL: partial_apply + %30 = tuple () + return %30 : $() +} + +// CHECK_DECL-LABEL: @closure_body : $@thin (CString, CString, Int64) -> () { +sil private @closure_body : $@thin (CString, CString, Int64) -> () { +bb0(%0 : $CString, %1 : $CString, %2 : $Int64): +// CHECK_DECL: function_ref @assert_fail + %3 = function_ref @assert_fail : $@thin (CString, CString, Int64) -> () + %4 = apply %3(%0, %1, %2) : $@thin (CString, CString, Int64) -> () + %5 = tuple () + return %5 : $() +} + +sil @assert_fail : $@thin (CString, CString, Int64) -> () + @fragile class Foo { subscript (x: Int, y: Int) -> Int @@ -964,7 +988,7 @@ sil_witness_table ConformingAssoc: AssocReqt module def_basic { method #AssocReqt.requiredMethod!1: @_TTWV14witness_tables15ConformingAssocS_9AssocReqtS_FS1_14requiredMethodU_fRQPS1_FT_T_ } -sil @_TF9def_basic13serialize_allFT_T_ : $@thin () -> () { +sil [transparent] @_TF9def_basic13serialize_allFT_T_ : $@thin () -> () { bb0: %1 = function_ref @_TFV18lazy_global_access4Type10staticPropSia : $@thin () -> Builtin.RawPointer %2 = function_ref @test1 : $@thin () -> () @@ -1022,6 +1046,7 @@ bb0: %120 = function_ref @test_forward_ref : $@thin (UInt8, UInt8) -> UInt8 %121 = function_ref @partial_apply : $@thin (@thin (@out Int, Int) -> (), Int) -> Int + %122 = function_ref @partial_apply_with_closure : $@thin (@owned @callee_owned () -> Bool, @owned String, CString, Int64) -> () %119 = tuple () return %119 : $()