Skip to content

Commit 7a196ac

Browse files
authored
Merge pull request #83739 from DougGregor/embedded-weak-definitions-of-imports
[Embedded] Emit weak definitions for imported symbols
2 parents 1cb6ab5 + 9a20eba commit 7a196ac

31 files changed

+507
-50
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ObjectOutliner.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ private func optimizeObjectAllocation(allocRef: AllocRefInstBase, _ context: Fun
109109
type: allocRef.type, linkage: .private,
110110
// Only if it's a COW object we can be sure that the object allocated in the global is not mutated.
111111
// If someone wants to mutate it, it has to be copied first.
112-
isLet: endOfInitInst is EndCOWMutationInst)
112+
isLet: endOfInitInst is EndCOWMutationInst,
113+
markedAsUsed: false)
113114

114115
constructObject(of: allocRef, inInitializerOf: outlinedGlobal, storesToClassFields, storesToTailElements, context)
115116
context.erase(instructions: storesToClassFields)
@@ -555,7 +556,7 @@ private func replace(findStringCall: ApplyInst,
555556

556557
// Create an "opaque" global variable which is passed as inout to
557558
// _findStringSwitchCaseWithCache and into which the function stores the "cache".
558-
let cacheVar = context.createGlobalVariable(name: name, type: cacheType, linkage: .private, isLet: false)
559+
let cacheVar = context.createGlobalVariable(name: name, type: cacheType, linkage: .private, isLet: false, markedAsUsed: false)
559560

560561
let varBuilder = Builder(staticInitializerOf: cacheVar, context)
561562
let zero = varBuilder.createIntegerLiteral(0, type: wordTy)

SwiftCompilerSources/Sources/SIL/Context.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,10 @@ extension MutatingContext {
114114
_bridged.notifyChanges(.Effects)
115115
}
116116

117-
public func createGlobalVariable(name: String, type: Type, linkage: Linkage, isLet: Bool) -> GlobalVariable {
117+
public func createGlobalVariable(name: String, type: Type, linkage: Linkage, isLet: Bool, markedAsUsed: Bool) -> GlobalVariable {
118118
let gv = name._withBridgedStringRef {
119-
_bridged.createGlobalVariable($0, type.bridged, linkage.bridged, isLet)
119+
_bridged.createGlobalVariable($0, type.bridged, linkage.bridged, isLet,
120+
markedAsUsed)
120121
}
121122
return gv.globalVar
122123
}

include/swift/IRGen/Linking.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,6 +1850,14 @@ class LinkEntity {
18501850
bool isTypeKind() const { return isTypeKind(getKind()); }
18511851

18521852
bool isAlwaysSharedLinkage() const;
1853+
1854+
/// Whether the link entity's definitions must be considered non-unique.
1855+
///
1856+
/// This applies only in the Embedded Swift linkage model, and is used for
1857+
/// any symbols that have not been explicitly requested to have unique
1858+
/// definitions (e.g., with @_used).
1859+
bool hasNonUniqueDefinition() const;
1860+
18531861
#undef LINKENTITY_GET_FIELD
18541862
#undef LINKENTITY_SET_FIELD
18551863

include/swift/SIL/SILBridging.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,8 @@ struct BridgedGlobalVar {
596596
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedStringRef getName() const;
597597
BRIDGED_INLINE bool isLet() const;
598598
BRIDGED_INLINE void setLet(bool value) const;
599+
BRIDGED_INLINE bool markedAsUsed() const;
600+
BRIDGED_INLINE void setMarkedAsUsed(bool value) const;
599601
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedType getType() const;
600602
BRIDGED_INLINE BridgedLinkage getLinkage() const;
601603
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE swift::SourceLoc getSourceLocation() const;
@@ -1449,7 +1451,8 @@ struct BridgedContext {
14491451
bool hasSelfParam,
14501452
BridgedFunction fromFunc) const;
14511453
SWIFT_IMPORT_UNSAFE BridgedGlobalVar createGlobalVariable(BridgedStringRef name, BridgedType type,
1452-
BridgedLinkage linkage, bool isLet) const;
1454+
BridgedLinkage linkage, bool isLet,
1455+
bool markedAsUsed) const;
14531456
void moveFunctionBody(BridgedFunction sourceFunc, BridgedFunction destFunc) const;
14541457

14551458
// Function-local SIL modifications

include/swift/SIL/SILBridgingImpl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,14 @@ bool BridgedGlobalVar::isLet() const { return getGlobal()->isLet(); }
932932

933933
void BridgedGlobalVar::setLet(bool value) const { getGlobal()->setLet(value); }
934934

935+
bool BridgedGlobalVar::markedAsUsed() const {
936+
return getGlobal()->markedAsUsed();
937+
}
938+
939+
void BridgedGlobalVar::setMarkedAsUsed(bool value) const {
940+
getGlobal()->setMarkedAsUsed(value);
941+
}
942+
935943
BridgedType BridgedGlobalVar::getType() const {
936944
return getGlobal()->getLoweredType();
937945
}

include/swift/SIL/SILDeclRef.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,14 @@ struct SILDeclRef {
399399
/// True if the function has the @backDeployed attribute.
400400
bool isBackDeployed() const;
401401

402+
/// True if this entity should have a non-unique definition based on the
403+
/// embedded linkage model.
404+
bool hasNonUniqueDefinition() const;
405+
406+
/// True if the declaration should have a non-unique definition based on the
407+
/// embedded linkage model.
408+
static bool declHasNonUniqueDefinition(const ValueDecl *decl);
409+
402410
/// Return the expected linkage for a definition of this declaration.
403411
SILLinkage getDefinitionLinkage() const;
404412

include/swift/SIL/SILFunction.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,10 @@ class SILFunction
659659

660660
bool isNoReturnFunction(TypeExpansionContext context) const;
661661

662+
/// True if this function should have a non-unique definition based on the
663+
/// embedded linkage model.
664+
bool hasNonUniqueDefinition() const;
665+
662666
/// Unsafely rewrite the lowered type of this function.
663667
///
664668
/// This routine does not touch the entry block arguments
@@ -916,6 +920,10 @@ class SILFunction
916920
return swift::isAvailableExternally(getLinkage());
917921
}
918922

923+
/// Helper method that determines whether this SILFunction is a Swift runtime
924+
/// function, such as swift_retain.
925+
bool isSwiftRuntimeFunction() const;
926+
919927
/// Helper method which returns true if the linkage of the SILFunction
920928
/// indicates that the object's definition might be required outside the
921929
/// current SILModule.

include/swift/SIL/SILGlobalVariable.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ class SILGlobalVariable
7575
/// once (either in its declaration, or once later), making it immutable.
7676
unsigned IsLet : 1;
7777

78+
/// Whether this declaration was marked `@_used`, meaning that it should be
79+
/// added to the llvm.used list.
80+
unsigned IsUsed : 1;
81+
7882
/// Whether or not this is a declaration.
7983
unsigned IsDeclaration : 1;
8084

@@ -147,6 +151,10 @@ class SILGlobalVariable
147151
/// might be referenced from outside the current compilation unit.
148152
bool isPossiblyUsedExternally() const;
149153

154+
/// True if this variable should have a non-unique definition based on the
155+
/// embedded linkage model.
156+
bool hasNonUniqueDefinition() const;
157+
150158
/// Returns true if this global variable should be preserved so it can
151159
/// potentially be inspected by the debugger.
152160
bool shouldBePreservedForDebugger() const;
@@ -207,10 +215,9 @@ class SILGlobalVariable
207215
}
208216

209217
/// Returns true if this global variable has `@_used` attribute.
210-
bool markedAsUsed() const {
211-
auto *V = getDecl();
212-
return V && V->getAttrs().hasAttribute<UsedAttr>();
213-
}
218+
bool markedAsUsed() const { return IsUsed; }
219+
220+
void setMarkedAsUsed(bool used) { IsUsed = used; }
214221

215222
/// Returns a SectionAttr if this global variable has `@_section` attribute.
216223
SectionAttr *getSectionAttr() const {

lib/IRGen/GenDecl.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,9 +1156,17 @@ static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) {
11561156
f.getLoweredFunctionType()->getSubstGenericSignature()) {
11571157
return true;
11581158
}
1159-
1160-
if (f.isPossiblyUsedExternally())
1159+
1160+
if (f.isPossiblyUsedExternally()) {
1161+
// Under the embedded linkage model, if it has a non-unique definition,
1162+
// treat it lazily.
1163+
if (f.hasNonUniqueDefinition() && !f.isSwiftRuntimeFunction()
1164+
&& !f.markedAsUsed()) {
1165+
return true;
1166+
}
1167+
11611168
return false;
1169+
}
11621170

11631171
if (f.getDynamicallyReplacedFunction())
11641172
return false;
@@ -2244,7 +2252,8 @@ void IRGenerator::emitEntryPointInfo() {
22442252
static IRLinkage
22452253
getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
22462254
SILLinkage linkage, ForDefinition_t isDefinition,
2247-
bool isWeakImported, bool isKnownLocal = false) {
2255+
bool isWeakImported, bool isKnownLocal,
2256+
bool hasNonUniqueDefinition) {
22482257
#define RESULT(LINKAGE, VISIBILITY, DLL_STORAGE) \
22492258
IRLinkage{llvm::GlobalValue::LINKAGE##Linkage, \
22502259
llvm::GlobalValue::VISIBILITY##Visibility, \
@@ -2275,7 +2284,9 @@ getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
22752284
case SILLinkage::Package: {
22762285
auto linkage = llvm::GlobalValue::ExternalLinkage;
22772286

2278-
if (info.MergeableSymbols)
2287+
if (hasNonUniqueDefinition)
2288+
linkage = llvm::GlobalValue::WeakODRLinkage;
2289+
else if (info.MergeableSymbols)
22792290
linkage = llvm::GlobalValue::WeakODRLinkage;
22802291

22812292
return {linkage, PublicDefinitionVisibility,
@@ -2293,6 +2304,8 @@ getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
22932304
: RESULT(External, Hidden, Default);
22942305

22952306
case SILLinkage::Hidden:
2307+
if (hasNonUniqueDefinition)
2308+
return RESULT(WeakODR, Hidden, Default);
22962309
if (info.MergeableSymbols)
22972310
return RESULT(WeakODR, Hidden, Default);
22982311

@@ -2301,7 +2314,7 @@ getIRLinkage(StringRef name, const UniversalLinkageInfo &info,
23012314
case SILLinkage::Private: {
23022315
if (info.forcePublicDecls() && !isDefinition)
23032316
return getIRLinkage(name, info, SILLinkage::PublicExternal, isDefinition,
2304-
isWeakImported, isKnownLocal);
2317+
isWeakImported, isKnownLocal, hasNonUniqueDefinition);
23052318

23062319
auto linkage = info.needLinkerToMergeDuplicateSymbols()
23072320
? llvm::GlobalValue::LinkOnceODRLinkage
@@ -2357,7 +2370,8 @@ void irgen::updateLinkageForDefinition(IRGenModule &IGM,
23572370
auto IRL =
23582371
getIRLinkage(global->hasName() ? global->getName() : StringRef(),
23592372
linkInfo, entity.getLinkage(ForDefinition), ForDefinition,
2360-
weakImported, isKnownLocal);
2373+
weakImported, isKnownLocal,
2374+
entity.hasNonUniqueDefinition());
23612375
ApplyIRLinkage(IRL).to(global);
23622376

23632377
LinkInfo link = LinkInfo::get(IGM, entity, ForDefinition);
@@ -2410,7 +2424,8 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
24102424
bool weakImported = entity.isWeakImported(swiftModule);
24112425
result.IRL = getIRLinkage(result.Name, linkInfo,
24122426
entity.getLinkage(isDefinition), isDefinition,
2413-
weakImported, isKnownLocal);
2427+
weakImported, isKnownLocal,
2428+
entity.hasNonUniqueDefinition());
24142429
result.ForDefinition = isDefinition;
24152430
return result;
24162431
}
@@ -2421,7 +2436,8 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo, StringRef name,
24212436
LinkInfo result;
24222437
result.Name += name;
24232438
result.IRL = getIRLinkage(name, linkInfo, linkage, isDefinition,
2424-
isWeakImported, linkInfo.Internalize);
2439+
isWeakImported, linkInfo.Internalize,
2440+
/*hasNonUniqueDefinition=*/false);
24252441
result.ForDefinition = isDefinition;
24262442
return result;
24272443
}

lib/IRGen/Linking.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1734,3 +1734,31 @@ bool LinkEntity::isAlwaysSharedLinkage() const {
17341734
return false;
17351735
}
17361736
}
1737+
1738+
bool LinkEntity::hasNonUniqueDefinition() const {
1739+
if (isDeclKind(getKind())) {
1740+
auto decl = getDecl();
1741+
return SILDeclRef::declHasNonUniqueDefinition(decl);
1742+
}
1743+
1744+
if (hasSILFunction()) {
1745+
return getSILFunction()->hasNonUniqueDefinition();
1746+
}
1747+
1748+
if (getKind() == Kind::SILGlobalVariable ||
1749+
getKind() == Kind::ReadOnlyGlobalObject)
1750+
return getSILGlobalVariable()->hasNonUniqueDefinition();
1751+
1752+
if (getKind() == Kind::TypeMetadata) {
1753+
// For a nominal type, check its declaration.
1754+
CanType type = getType();
1755+
if (auto nominal = type->getAnyNominal()) {
1756+
return SILDeclRef::declHasNonUniqueDefinition(nominal);
1757+
}
1758+
1759+
// All other type metadata is nonuniqued.
1760+
return true;
1761+
}
1762+
1763+
return false;
1764+
}

0 commit comments

Comments
 (0)