Skip to content

Commit 8bc5dac

Browse files
committed
SIL: always update the linkage of a function with the serialized linkage in the swiftmodule.
The cross-module-optimization can change the linkage of a function to public. Then the SILLinkage is "out of sync" with the linkage derived from the AST. We need to make sure to read the correct SILLinkage from the module file.
1 parent 210fabb commit 8bc5dac

File tree

7 files changed

+41
-14
lines changed

7 files changed

+41
-14
lines changed

include/swift/SIL/SILModule.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,13 @@ class SILModule {
526526
/// succeeded, false otherwise.
527527
bool loadFunction(SILFunction *F);
528528

529+
/// Update the linkage of the SILFunction with the linkage of the serialized
530+
/// function.
531+
///
532+
/// The serialized SILLinkage can differ from the linkage derived from the
533+
/// AST, e.g. cross-module-optimization can change the SIL linkages.
534+
void updateFunctionLinkage(SILFunction *F);
535+
529536
/// Attempt to link the SILFunction. Returns true if linking succeeded, false
530537
/// otherwise.
531538
///

include/swift/Serialization/SerializedSILLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class SerializedSILLoader {
5656
}
5757
~SerializedSILLoader();
5858

59-
SILFunction *lookupSILFunction(SILFunction *Callee);
59+
SILFunction *lookupSILFunction(SILFunction *Callee, bool onlyUpdateLinkage);
6060
SILFunction *
6161
lookupSILFunction(StringRef Name, bool declarationOnly = false,
6262
Optional<SILLinkage> linkage = None);

lib/SIL/Linker.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ void SILLinkerVisitor::maybeAddFunctionToWorklist(SILFunction *F) {
114114
// So try deserializing HiddenExternal functions too.
115115
if (F->getLinkage() == SILLinkage::HiddenExternal)
116116
return addFunctionToWorklist(F);
117+
118+
// Update the linkage of the function in case it's different in the serialized
119+
// SIL than derived from the AST. This can be the case with cross-module-
120+
// optimizations.
121+
Mod.updateFunctionLinkage(F);
117122
}
118123

119124
/// Process F, recursively deserializing any thing F may reference.

lib/SIL/SILModule.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,14 +321,19 @@ SILFunction *SILModule::lookUpFunction(SILDeclRef fnRef) {
321321
}
322322

323323
bool SILModule::loadFunction(SILFunction *F) {
324-
SILFunction *NewF = getSILLoader()->lookupSILFunction(F);
324+
SILFunction *NewF =
325+
getSILLoader()->lookupSILFunction(F, /*onlyUpdateLinkage*/ false);
325326
if (!NewF)
326327
return false;
327328

328329
assert(F == NewF);
329330
return true;
330331
}
331332

333+
void SILModule::updateFunctionLinkage(SILFunction *F) {
334+
getSILLoader()->lookupSILFunction(F, /*onlyUpdateLinkage*/ true);
335+
}
336+
332337
bool SILModule::linkFunction(SILFunction *F, SILModule::LinkingMode Mode) {
333338
return SILLinkerVisitor(*this, Mode).processFunction(F);
334339
}

lib/Serialization/DeserializeSIL.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -527,12 +527,13 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn,
527527
replacedObjectiveCFunc = MF->getIdentifier(replacedFunctionID);
528528
}
529529

530-
auto linkage = fromStableSILLinkage(rawLinkage);
531-
if (!linkage) {
530+
auto linkageOpt = fromStableSILLinkage(rawLinkage);
531+
if (!linkageOpt) {
532532
LLVM_DEBUG(llvm::dbgs() << "invalid linkage code " << rawLinkage
533533
<< " for SILFunction\n");
534534
MF->fatal();
535535
}
536+
SILLinkage linkage = linkageOpt.getValue();
536537

537538
ValueDecl *clangNodeOwner = nullptr;
538539
if (clangNodeOwnerID != 0) {
@@ -569,16 +570,22 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn,
569570
fn->setSerialized(IsSerialized_t(isSerialized));
570571

571572
if (SILMod.getOptions().MergePartialModules)
572-
fn->setLinkage(*linkage);
573+
fn->setLinkage(linkage);
573574

574575
// Don't override the transparency or linkage of a function with
575576
// an existing declaration, except if we deserialized a
576577
// PublicNonABI function, which has HiddenExternal when
577578
// referenced as a declaration, and SharedExternal when it has
578579
// a deserialized body.
579-
if (isAvailableExternally(fn->getLinkage()) &&
580-
linkage == SILLinkage::PublicNonABI) {
581-
fn->setLinkage(SILLinkage::SharedExternal);
580+
if (isAvailableExternally(fn->getLinkage())) {
581+
if (linkage == SILLinkage::PublicNonABI) {
582+
fn->setLinkage(SILLinkage::SharedExternal);
583+
} else if (hasPublicVisibility(linkage)) {
584+
// Cross-module-optimization can change the linkage to public. In this
585+
// case we need to update the linkage of the function (which is
586+
// originally just derived from the AST).
587+
fn->setLinkage(SILLinkage::PublicExternal);
588+
}
582589
}
583590

584591
if (fn->isDynamicallyReplaceable() != isDynamic) {
@@ -589,7 +596,7 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn,
589596
} else {
590597
// Otherwise, create a new function.
591598
fn = builder.createDeclaration(name, ty, loc);
592-
fn->setLinkage(linkage.getValue());
599+
fn->setLinkage(linkage);
593600
fn->setTransparent(IsTransparent_t(isTransparent == 1));
594601
fn->setSerialized(IsSerialized_t(isSerialized));
595602
fn->setThunk(IsThunk_t(isThunk));
@@ -2545,16 +2552,18 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
25452552
return false;
25462553
}
25472554

2548-
SILFunction *SILDeserializer::lookupSILFunction(SILFunction *InFunc) {
2555+
SILFunction *SILDeserializer::lookupSILFunction(SILFunction *InFunc,
2556+
bool onlyUpdateLinkage) {
25492557
StringRef name = InFunc->getName();
25502558
if (!FuncTable)
25512559
return nullptr;
25522560
auto iter = FuncTable->find(name);
25532561
if (iter == FuncTable->end())
25542562
return nullptr;
25552563

2564+
// Re-reading the function as declaration will update the linkage.
25562565
auto maybeFunc = readSILFunctionChecked(*iter, InFunc, name,
2557-
/*declarationOnly*/ false);
2566+
/*declarationOnly*/ onlyUpdateLinkage);
25582567
if (!maybeFunc) {
25592568
// Ignore the error; treat it as if we didn't have a definition.
25602569
consumeError(maybeFunc.takeError());

lib/Serialization/DeserializeSIL.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ namespace swift {
140140
FileUnit *getFile() const {
141141
return MF->getFile();
142142
}
143-
SILFunction *lookupSILFunction(SILFunction *InFunc);
143+
SILFunction *lookupSILFunction(SILFunction *InFunc, bool onlyUpdateLinkage);
144144
SILFunction *lookupSILFunction(StringRef Name,
145145
bool declarationOnly = false);
146146
bool hasSILFunction(StringRef Name, Optional<SILLinkage> Linkage = None);

lib/Serialization/SerializedSILLoader.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,13 @@ SerializedSILLoader::SerializedSILLoader(
4242

4343
SerializedSILLoader::~SerializedSILLoader() {}
4444

45-
SILFunction *SerializedSILLoader::lookupSILFunction(SILFunction *Callee) {
45+
SILFunction *SerializedSILLoader::lookupSILFunction(SILFunction *Callee,
46+
bool onlyUpdateLinkage) {
4647
// It is possible that one module has a declaration of a SILFunction, while
4748
// another has the full definition.
4849
SILFunction *retVal = nullptr;
4950
for (auto &Des : LoadedSILSections) {
50-
if (auto Func = Des->lookupSILFunction(Callee)) {
51+
if (auto Func = Des->lookupSILFunction(Callee, onlyUpdateLinkage)) {
5152
LLVM_DEBUG(llvm::dbgs() << "Deserialized " << Func->getName() << " from "
5253
<< Des->getModuleIdentifier().str() << "\n");
5354
if (!Func->empty())

0 commit comments

Comments
 (0)