Skip to content

Commit 40eb142

Browse files
committed
IRGen/SIL: Fix IR linkage computation for inlined function references from modules imported @_weakLinked.
Include the parent `ModuleDecl` when serializing a `SILFunction` so that it is available on deserialized functions even though the full `DeclContext` is not present. With the parent module always available we can reliably compute whether the `SILFunction` comes from a module that was imported `@_weakLinked`. Serialize the `DeclContext` member of `SILFunction` so that it can be used to look up the module that a function belongs to in order to compute weak import status. Resolves rdar://98521248
1 parent df66f27 commit 40eb142

17 files changed

+112
-70
lines changed

include/swift/AST/Module.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -685,9 +685,8 @@ class ModuleDecl
685685
// Is \p spiGroup accessible as an explicitly imported SPI from this module?
686686
bool isImportedAsSPI(Identifier spiGroup, const ModuleDecl *fromModule) const;
687687

688-
/// Is \p targetDecl from a module that is imported as \c @_weakLinked from
689-
/// this module?
690-
bool isImportedAsWeakLinked(const Decl *targetDecl) const;
688+
/// Is \p module imported as \c @_weakLinked from this module?
689+
bool isImportedAsWeakLinked(const ModuleDecl *module) const;
691690

692691
/// \sa getImportedModules
693692
enum class ImportFilterKind {

include/swift/SIL/SILFunction.h

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "swift/AST/ASTNode.h"
2121
#include "swift/AST/Availability.h"
22+
#include "swift/AST/Module.h"
2223
#include "swift/AST/ResilienceExpansion.h"
2324
#include "swift/Basic/ProfileCounter.h"
2425
#include "swift/Basic/SwiftObjectHeader.h"
@@ -64,11 +65,6 @@ enum IsDistributed_t {
6465
IsNotDistributed,
6566
IsDistributed,
6667
};
67-
enum IsWeakImported_t {
68-
IsNotWeakImported,
69-
IsWeakImportedByModule,
70-
IsAlwaysWeakImported,
71-
};
7268

7369
enum class PerformanceConstraints : uint8_t {
7470
None = 0,
@@ -222,6 +218,10 @@ class SILFunction
222218
/// The AST decl context of the function.
223219
DeclContext *DeclCtxt = nullptr;
224220

221+
/// The module that defines this function. This member should only be set as
222+
/// a fallback when a \c DeclCtxt is unavailable.
223+
ModuleDecl *ParentModule = nullptr;
224+
225225
/// The profiler for instrumentation based profiling, or null if profiling is
226226
/// disabled.
227227
SILProfiler *Profiler = nullptr;
@@ -322,8 +322,9 @@ class SILFunction
322322
/// would indicate.
323323
unsigned HasCReferences : 1;
324324

325-
/// Whether cross-module references to this function should use weak linking.
326-
unsigned IsWeakImported : 2;
325+
/// Whether cross-module references to this function should always use weak
326+
/// linking.
327+
unsigned IsAlwaysWeakImported : 1;
327328

328329
/// Whether the implementation can be dynamically replaced.
329330
unsigned IsDynamicReplaceable : 1;
@@ -801,19 +802,11 @@ class SILFunction
801802

802803
/// Returns whether this function's symbol must always be weakly referenced
803804
/// across module boundaries.
804-
bool isAlwaysWeakImported() const {
805-
return IsWeakImported == IsWeakImported_t::IsAlwaysWeakImported;
806-
}
807-
808-
/// Returns whether this function's symbol was referenced by a module that
809-
/// imports the defining module \c @_weakLinked.
810-
bool isWeakImportedByModule() const {
811-
return IsWeakImported == IsWeakImported_t::IsWeakImportedByModule;
812-
}
805+
bool isAlwaysWeakImported() const { return IsAlwaysWeakImported; }
813806

814-
void setIsWeakImported(IsWeakImported_t value) { IsWeakImported = value; }
807+
void setIsAlwaysWeakImported(bool value) { IsAlwaysWeakImported = value; }
815808

816-
bool isWeakImported() const;
809+
bool isWeakImported(ModuleDecl *module) const;
817810

818811
/// Returns whether this function implementation can be dynamically replaced.
819812
IsDynamicallyReplaceable_t isDynamicallyReplaceable() const {
@@ -960,6 +953,18 @@ class SILFunction
960953
DeclCtxt = (DS ? DebugScope->Loc.getAsDeclContext() : nullptr);
961954
}
962955

956+
/// Returns the module that defines this function.
957+
ModuleDecl *getParentModule() const {
958+
return DeclCtxt ? DeclCtxt->getParentModule() : ParentModule;
959+
}
960+
961+
/// Sets \c ParentModule as fallback if \c DeclCtxt is not available to
962+
/// provide the parent module.
963+
void setParentModule(ModuleDecl *module) {
964+
assert(!DeclCtxt && "already have a DeclCtxt");
965+
ParentModule = module;
966+
}
967+
963968
/// Initialize the debug scope for debug info on SIL level
964969
/// (-sil-based-debuginfo).
965970
void setSILDebugScope(const SILDebugScope *DS) {

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,7 @@ bool Decl::isWeakImported(ModuleDecl *fromModule) const {
10021002
if (isAlwaysWeakImported())
10031003
return true;
10041004

1005-
if (fromModule->isImportedAsWeakLinked(this))
1005+
if (fromModule->isImportedAsWeakLinked(this->getModuleContext()))
10061006
return true;
10071007

10081008
auto availability = getAvailabilityForLinkage();

lib/AST/Module.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2663,10 +2663,9 @@ bool ModuleDecl::isImportedAsSPI(Identifier spiGroup,
26632663
return importedSPIGroups.count(spiGroup);
26642664
}
26652665

2666-
bool ModuleDecl::isImportedAsWeakLinked(const Decl *targetDecl) const {
2667-
const auto *declaringModule = targetDecl->getModuleContext();
2666+
bool ModuleDecl::isImportedAsWeakLinked(const ModuleDecl *module) const {
26682667
for (auto file : getFiles()) {
2669-
if (file->importsModuleAsWeakLinked(declaringModule))
2668+
if (file->importsModuleAsWeakLinked(module))
26702669
return true;
26712670
}
26722671
return false;

lib/IRGen/GenDecl.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2520,7 +2520,8 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
25202520
// FIXME: We should be able to set the linkage unconditionally here but
25212521
// some fixes are needed for Cxx interop.
25222522
if (auto globalVar = dyn_cast<llvm::GlobalVariable>(addr)) {
2523-
if (getSwiftModule()->isImportedAsWeakLinked(var->getDecl()))
2523+
auto varModule = var->getDecl()->getModuleContext();
2524+
if (getSwiftModule()->isImportedAsWeakLinked(varModule))
25242525
globalVar->setLinkage(link.getLinkage());
25252526
}
25262527

@@ -3275,13 +3276,16 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
32753276
fn = dyn_cast<llvm::Function>(clangAddr->stripPointerCasts());
32763277

32773278
if (fn) {
3278-
// Override the linkage computed by Clang if the decl is from another
3279-
// module that imported @_weakLinked.
3280-
//
3281-
// FIXME: We should be able to set the linkage unconditionally here but
3282-
// some fixes are needed for Cxx interop.
3283-
if (!forDefinition && f->isWeakImportedByModule())
3284-
fn->setLinkage(link.getLinkage());
3279+
if (!forDefinition) {
3280+
// Override the linkage computed by Clang if the decl is from another
3281+
// module that imported @_weakLinked.
3282+
//
3283+
// FIXME: We should be able to set the linkage unconditionally here but
3284+
// some fixes are needed for Cxx interop.
3285+
if (auto *DC = f->getDeclContext())
3286+
if (getSwiftModule()->isImportedAsWeakLinked(DC->getParentModule()))
3287+
fn->setLinkage(link.getLinkage());
3288+
}
32853289

32863290
// If we have a function, move it to the appropriate position.
32873291
if (hasOrderNumber) {

lib/IRGen/Linking.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1177,7 +1177,7 @@ bool LinkEntity::isWeakImported(ModuleDecl *module) const {
11771177
case Kind::DynamicallyReplaceableFunctionVariable:
11781178
case Kind::SILFunction:
11791179
case Kind::DistributedAccessor: {
1180-
return getSILFunction()->isWeakImported();
1180+
return getSILFunction()->isWeakImported(module);
11811181
}
11821182

11831183
case Kind::AssociatedConformanceDescriptor:

lib/SIL/IR/Linker.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@
1616
/// deserializing functions, vtables and witness tables.
1717
///
1818
/// The behavior of the linker is controlled by a LinkMode value. The LinkMode
19-
/// has three possible values:
20-
///
21-
/// - LinkNone: The linker does not deserialize anything. This is only used for
22-
/// debugging and testing purposes, and never during normal operation.
19+
/// has two possible values:
2320
///
2421
/// - LinkNormal: The linker deserializes bodies for declarations that must be
2522
/// emitted into the client because they do not have definitions available

lib/SIL/IR/SILFunction.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ void SILFunction::init(
182182
this->InlineStrategy = inlineStrategy;
183183
this->Linkage = unsigned(Linkage);
184184
this->HasCReferences = false;
185-
this->IsWeakImported = false;
185+
this->IsAlwaysWeakImported = false;
186186
this->IsDynamicReplaceable = isDynamic;
187187
this->ExactSelfClass = isExactSelfClass;
188188
this->IsDistributed = isDistributed;
@@ -260,7 +260,7 @@ void SILFunction::createSnapshot(int id) {
260260
newSnapshot->perfConstraints = perfConstraints;
261261
newSnapshot->GlobalInitFlag = GlobalInitFlag;
262262
newSnapshot->HasCReferences = HasCReferences;
263-
newSnapshot->IsWeakImported = IsWeakImported;
263+
newSnapshot->IsAlwaysWeakImported = IsAlwaysWeakImported;
264264
newSnapshot->HasOwnership = HasOwnership;
265265
newSnapshot->IsWithoutActuallyEscapingThunk = IsWithoutActuallyEscapingThunk;
266266
newSnapshot->OptMode = OptMode;
@@ -452,9 +452,10 @@ bool SILFunction::isTypeABIAccessible(SILType type) const {
452452
return getModule().isTypeABIAccessible(type, TypeExpansionContext(*this));
453453
}
454454

455-
bool SILFunction::isWeakImported() const {
456-
if (isWeakImportedByModule())
457-
return true;
455+
bool SILFunction::isWeakImported(ModuleDecl *module) const {
456+
if (auto *parent = getParentModule())
457+
if (module->isImportedAsWeakLinked(parent))
458+
return true;
458459

459460
// For imported functions check the Clang declaration.
460461
if (ClangNodeOwner)

lib/SIL/IR/SILFunctionBuilder.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -312,14 +312,7 @@ SILFunction *SILFunctionBuilder::getOrCreateFunction(
312312
F->setClangNodeOwner(decl);
313313

314314
F->setAvailabilityForLinkage(decl->getAvailabilityForLinkage());
315-
316-
if (decl->isAlwaysWeakImported()) {
317-
F->setIsWeakImported(IsWeakImported_t::IsAlwaysWeakImported);
318-
} else if (decl->isWeakImported(mod.getSwiftModule())) {
319-
F->setIsWeakImported(IsWeakImported_t::IsWeakImportedByModule);
320-
} else {
321-
F->setIsWeakImported(IsWeakImported_t::IsNotWeakImported);
322-
}
315+
F->setIsAlwaysWeakImported(decl->isAlwaysWeakImported());
323316

324317
if (auto *accessor = dyn_cast<AccessorDecl>(decl)) {
325318
auto *storage = accessor->getStorage();

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6514,9 +6514,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
65146514
if (!objCReplacementFor.empty())
65156515
FunctionState.F->setObjCReplacement(objCReplacementFor);
65166516
FunctionState.F->setSpecialPurpose(specialPurpose);
6517-
FunctionState.F->setIsWeakImported(
6518-
isWeakImported ? IsWeakImported_t::IsAlwaysWeakImported
6519-
: IsWeakImported_t::IsNotWeakImported);
6517+
FunctionState.F->setIsAlwaysWeakImported(isWeakImported);
65206518
FunctionState.F->setAvailabilityForLinkage(availability);
65216519
FunctionState.F->setWithoutActuallyEscapingThunk(
65226520
isWithoutActuallyEscapingThunk);

0 commit comments

Comments
 (0)