Skip to content

Commit 1785855

Browse files
authored
Merge pull request #14660 from jrose-apple/one-weak-since-you-looked-at-me
Add @_weakSymbol and a corresponding SIL attribute
2 parents c8e3724 + bb33977 commit 1785855

22 files changed

+378
-32
lines changed

include/swift/AST/Attr.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,12 @@ DECL_ATTR(_clangImporterSynthesizedType, ClangImporterSynthesizedType,
308308
LongAttribute | NotSerialized | RejectByParser | UserInaccessible,
309309
/*Not serialized*/74)
310310

311+
SIMPLE_DECL_ATTR(_weakLinked, WeakLinked,
312+
OnEnum | OnStruct | OnClass | OnProtocol |
313+
OnFunc | OnVar | OnSubscript | OnConstructor | OnEnumElement |
314+
UserInaccessible,
315+
75)
316+
311317
#undef TYPE_ATTR
312318
#undef DECL_ATTR_ALIAS
313319
#undef SIMPLE_DECL_ATTR

include/swift/Frontend/Frontend.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
#include "swift/Migrator/MigratorOptions.h"
3535
#include "swift/Parse/CodeCompletionCallbacks.h"
3636
#include "swift/Parse/Parser.h"
37-
#include "swift/SIL/SILModule.h"
3837
#include "swift/Sema/SourceLoader.h"
3938
#include "swift/Serialization/Validation.h"
4039
#include "swift/Subsystems.h"
@@ -49,6 +48,7 @@
4948
namespace swift {
5049

5150
class SerializedModuleLoader;
51+
class SILModule;
5252

5353
/// The abstract configuration of the compiler, including:
5454
/// - options for all stages of translation,
@@ -371,6 +371,15 @@ class CompilerInstance {
371371
void createSILModule();
372372

373373
public:
374+
// Out of line to avoid having to import SILModule.h.
375+
CompilerInstance();
376+
~CompilerInstance();
377+
378+
CompilerInstance(const CompilerInstance &) = delete;
379+
void operator=(const CompilerInstance &) = delete;
380+
CompilerInstance(CompilerInstance &&) = delete;
381+
void operator=(CompilerInstance &&) = delete;
382+
374383
SourceManager &getSourceMgr() { return SourceMgr; }
375384

376385
DiagnosticEngine &getDiags() { return Diagnostics; }
@@ -398,9 +407,7 @@ class CompilerInstance {
398407
/// Set the SIL module for this compilation instance.
399408
///
400409
/// The CompilerInstance takes ownership of the given SILModule object.
401-
void setSILModule(std::unique_ptr<SILModule> M) {
402-
TheSILModule = std::move(M);
403-
}
410+
void setSILModule(std::unique_ptr<SILModule> M);
404411

405412
SILModule *getSILModule() {
406413
return TheSILModule.get();

include/swift/IRGen/Linking.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,9 +733,12 @@ class LinkEntity {
733733
getSILGlobalVariable()->getDecl())
734734
return getSILGlobalVariable()->getDecl()->isWeakImported(module);
735735

736-
if (getKind() == Kind::SILFunction)
736+
if (getKind() == Kind::SILFunction) {
737737
if (auto clangOwner = getSILFunction()->getClangNodeOwner())
738738
return clangOwner->isWeakImported(module);
739+
if (getSILFunction()->isWeakLinked())
740+
return getSILFunction()->isAvailableExternally();
741+
}
739742

740743
if (!isDeclKind(getKind()))
741744
return false;

include/swift/SIL/SILFunction.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ class SILFunction
171171
/// would indicate.
172172
unsigned HasCReferences : 1;
173173

174+
/// Whether cross-module references to this function should use weak linking.
175+
unsigned IsWeakLinked : 1;
176+
174177
/// If != OptimizationMode::NotSet, the optimization mode specified with an
175178
/// function attribute.
176179
OptimizationMode OptMode;
@@ -450,6 +453,16 @@ class SILFunction
450453
bool hasCReferences() const { return HasCReferences; }
451454
void setHasCReferences(bool value) { HasCReferences = value; }
452455

456+
/// Returns whether this function's symbol must always be weakly referenced
457+
/// across module boundaries.
458+
bool isWeakLinked() const { return IsWeakLinked; }
459+
/// Forces IRGen to treat references to this function as weak across module
460+
/// boundaries (i.e. if it has external linkage).
461+
void setWeakLinked(bool value = true) {
462+
assert(!IsWeakLinked && "already set");
463+
IsWeakLinked = value;
464+
}
465+
453466
/// Get the DeclContext of this function. (Debug info only).
454467
DeclContext *getDeclContext() const {
455468
return getLocation().getAsDeclContext();

include/swift/Serialization/ModuleFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 398; // Private discriminators for type xrefs
57+
/// Don't worry about adhering to the 80-column limit for this line.
58+
const uint16_t VERSION_MINOR = 399; // Last change: @_weakLinked
5859

5960
using DeclIDField = BCFixed<31>;
6061

lib/AST/Attr.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -498,14 +498,6 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
498498
break;
499499
}
500500

501-
case DAK_StaticInitializeObjCMetadata:
502-
Printer.printAttrName("@_staticInitializeObjCMetadata");
503-
break;
504-
505-
case DAK_DowngradeExhaustivityCheck:
506-
Printer.printAttrName("@_downgrade_exhaustivity_check");
507-
break;
508-
509501
case DAK_ClangImporterSynthesizedType: {
510502
Printer.printAttrName("@_clangImporterSynthesizedType");
511503
auto *attr = cast<ClangImporterSynthesizedTypeAttr>(this);
@@ -517,8 +509,13 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
517509
case DAK_Count:
518510
llvm_unreachable("exceed declaration attribute kinds");
519511

512+
#define SIMPLE_DECL_ATTR(X, CLASS, ...) case DAK_##CLASS:
513+
#include "swift/AST/Attr.def"
514+
llvm_unreachable("handled above");
515+
520516
default:
521-
llvm_unreachable("handled before this switch");
517+
assert(DeclAttribute::isDeclModifier(getKind()) &&
518+
"handled above");
522519
}
523520

524521
return true;

lib/AST/Decl.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,14 @@ bool Decl::isWeakImported(ModuleDecl *fromModule) const {
482482
return clangDecl->isWeakImported();
483483
}
484484

485-
// FIXME: Implement using AvailableAttr::getVersionAvailability().
485+
auto *containingModule = getModuleContext();
486+
if (containingModule == fromModule)
487+
return false;
488+
489+
if (getAttrs().hasAttribute<WeakLinkedAttr>())
490+
return true;
491+
492+
// FIXME: Also check availability when containingModule is resilient.
486493
return false;
487494
}
488495

lib/Frontend/Frontend.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737

3838
using namespace swift;
3939

40+
CompilerInstance::CompilerInstance() = default;
41+
CompilerInstance::~CompilerInstance() = default;
42+
4043
std::string CompilerInvocation::getPCHHash() const {
4144
using llvm::hash_code;
4245
using llvm::hash_value;
@@ -76,6 +79,10 @@ void CompilerInstance::createSILModule() {
7679
Invocation.getFrontendOptions().InputsAndOutputs.isWholeModule());
7780
}
7881

82+
void CompilerInstance::setSILModule(std::unique_ptr<SILModule> M) {
83+
TheSILModule = std::move(M);
84+
}
85+
7986
void CompilerInstance::recordPrimaryInputBuffer(unsigned BufID) {
8087
PrimaryBufferIDs.insert(BufID);
8188
}

lib/ParseSIL/ParseSIL.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ static bool parseDeclSILOptional(bool *isTransparent,
882882
IsThunk_t *isThunk, bool *isGlobalInit,
883883
Inline_t *inlineStrategy,
884884
OptimizationMode *optimizationMode,
885-
bool *isLet,
885+
bool *isLet, bool *isWeakLinked,
886886
SmallVectorImpl<std::string> *Semantics,
887887
SmallVectorImpl<ParsedSpecAttr> *SpecAttrs,
888888
ValueDecl **ClangDecl,
@@ -909,6 +909,8 @@ static bool parseDeclSILOptional(bool *isTransparent,
909909
*isThunk = IsReabstractionThunk;
910910
else if (isGlobalInit && SP.P.Tok.getText() == "global_init")
911911
*isGlobalInit = true;
912+
else if (isWeakLinked && SP.P.Tok.getText() == "_weakLinked")
913+
*isWeakLinked = true;
912914
else if (inlineStrategy && SP.P.Tok.getText() == "noinline")
913915
*inlineStrategy = NoInline;
914916
else if (optimizationMode && SP.P.Tok.getText() == "Onone")
@@ -5089,7 +5091,7 @@ bool SILParserTUState::parseDeclSIL(Parser &P) {
50895091
bool isTransparent = false;
50905092
IsSerialized_t isSerialized = IsNotSerialized;
50915093
IsThunk_t isThunk = IsNotThunk;
5092-
bool isGlobalInit = false;
5094+
bool isGlobalInit = false, isWeakLinked = false;
50935095
Inline_t inlineStrategy = InlineDefault;
50945096
OptimizationMode optimizationMode = OptimizationMode::NotSet;
50955097
SmallVector<std::string, 1> Semantics;
@@ -5099,7 +5101,7 @@ bool SILParserTUState::parseDeclSIL(Parser &P) {
50995101
if (parseSILLinkage(FnLinkage, P) ||
51005102
parseDeclSILOptional(&isTransparent, &isSerialized, &isThunk, &isGlobalInit,
51015103
&inlineStrategy, &optimizationMode, nullptr,
5102-
&Semantics, &SpecAttrs,
5104+
&isWeakLinked, &Semantics, &SpecAttrs,
51035105
&ClangDecl, &MRK, FunctionState) ||
51045106
P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
51055107
P.parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) ||
@@ -5125,6 +5127,7 @@ bool SILParserTUState::parseDeclSIL(Parser &P) {
51255127
FunctionState.F->setSerialized(IsSerialized_t(isSerialized));
51265128
FunctionState.F->setThunk(IsThunk_t(isThunk));
51275129
FunctionState.F->setGlobalInit(isGlobalInit);
5130+
FunctionState.F->setWeakLinked(isWeakLinked);
51285131
FunctionState.F->setInlineStrategy(inlineStrategy);
51295132
FunctionState.F->setOptimizationMode(optimizationMode);
51305133
FunctionState.F->setEffectsKind(MRK);
@@ -5257,7 +5260,7 @@ bool SILParserTUState::parseSILGlobal(Parser &P) {
52575260
if (parseSILLinkage(GlobalLinkage, P) ||
52585261
parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
52595262
nullptr, nullptr, &isLet, nullptr, nullptr, nullptr,
5260-
nullptr, State) ||
5263+
nullptr, nullptr, State) ||
52615264
P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
52625265
P.parseIdentifier(GlobalName, NameLoc, diag::expected_sil_value_name) ||
52635266
P.parseToken(tok::colon, diag::expected_sil_type))
@@ -5300,7 +5303,7 @@ bool SILParserTUState::parseSILVTable(Parser &P) {
53005303
IsSerialized_t Serialized = IsNotSerialized;
53015304
if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr,
53025305
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
5303-
nullptr, VTableState))
5306+
nullptr, nullptr, VTableState))
53045307
return true;
53055308

53065309
// Parse the class name.
@@ -5650,7 +5653,7 @@ bool SILParserTUState::parseSILWitnessTable(Parser &P) {
56505653
IsSerialized_t isSerialized = IsNotSerialized;
56515654
if (parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
56525655
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
5653-
nullptr, WitnessState))
5656+
nullptr, nullptr, WitnessState))
56545657
return true;
56555658

56565659
Scope S(&P, ScopeKind::TopLevel);

lib/SIL/SILFunction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage, StringRef Name,
9898
Serialized(isSerialized), Thunk(isThunk),
9999
ClassSubclassScope(unsigned(classSubclassScope)), GlobalInitFlag(false),
100100
InlineStrategy(inlineStrategy), Linkage(unsigned(Linkage)),
101-
HasCReferences(false),
101+
HasCReferences(false), IsWeakLinked(false),
102102
OptMode(OptimizationMode::NotSet), EffectsKindAttr(E),
103103
EntryCount(entryCount) {
104104
if (InsertBefore)

lib/SIL/SILModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,9 @@ static void addFunctionAttributes(SILFunction *F, DeclAttributes &Attrs,
310310
if (Attrs.hasAttribute<SILGenNameAttr>() ||
311311
Attrs.hasAttribute<CDeclAttr>())
312312
F->setHasCReferences(true);
313+
314+
if (Attrs.hasAttribute<WeakLinkedAttr>())
315+
F->setWeakLinked();
313316
}
314317

315318
SILFunction *SILModule::getOrCreateFunction(SILLocation loc,

lib/SIL/SILPrinter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2280,7 +2280,9 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
22802280

22812281
if (isGlobalInit())
22822282
OS << "[global_init] ";
2283-
2283+
if (isWeakLinked())
2284+
OS << "[_weakLinked] ";
2285+
22842286
switch (getInlineStrategy()) {
22852287
case NoInline: OS << "[noinline] "; break;
22862288
case AlwaysInline: OS << "[always_inline] "; break;

lib/Sema/TypeCheckAttr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ class AttributeEarlyChecker : public AttributeVisitor<AttributeEarlyChecker> {
112112
IGNORED_ATTR(UIApplicationMain)
113113
IGNORED_ATTR(UnsafeNoObjCTaggedPointer)
114114
IGNORED_ATTR(Versioned)
115+
IGNORED_ATTR(WeakLinked)
115116
#undef IGNORED_ATTR
116117

117118
// @noreturn has been replaced with a 'Never' return type.
@@ -833,6 +834,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
833834
IGNORED_ATTR(Testable)
834835
IGNORED_ATTR(Transparent)
835836
IGNORED_ATTR(WarnUnqualifiedAccess)
837+
IGNORED_ATTR(WeakLinked)
836838
#undef IGNORED_ATTR
837839

838840
void visitAvailableAttr(AvailableAttr *attr);

lib/Sema/TypeCheckDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6527,6 +6527,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
65276527
UNINTERESTING_ATTR(DowngradeExhaustivityCheck)
65286528
UNINTERESTING_ATTR(ImplicitlyUnwrappedOptional)
65296529
UNINTERESTING_ATTR(ClangImporterSynthesizedType)
6530+
UNINTERESTING_ATTR(WeakLinked)
65306531
#undef UNINTERESTING_ATTR
65316532

65326533
void visitAvailableAttr(AvailableAttr *attr) {

lib/Serialization/DeserializeSIL.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -413,12 +413,12 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
413413
GenericEnvironmentID genericEnvID;
414414
unsigned rawLinkage, isTransparent, isSerialized, isThunk, isGlobal,
415415
inlineStrategy, optimizationMode, effect, numSpecAttrs,
416-
hasQualifiedOwnership;
416+
hasQualifiedOwnership, isWeakLinked;
417417
ArrayRef<uint64_t> SemanticsIDs;
418418
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
419419
isThunk, isGlobal, inlineStrategy,
420-
optimizationMode, effect,
421-
numSpecAttrs, hasQualifiedOwnership, funcTyID,
420+
optimizationMode, effect, numSpecAttrs,
421+
hasQualifiedOwnership, isWeakLinked, funcTyID,
422422
genericEnvID, clangNodeOwnerID, SemanticsIDs);
423423

424424
if (funcTyID == 0) {
@@ -498,6 +498,7 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
498498
fn->setGlobalInit(isGlobal == 1);
499499
fn->setEffectsKind((EffectsKind)effect);
500500
fn->setOptimizationMode((OptimizationMode)optimizationMode);
501+
fn->setWeakLinked(isWeakLinked);
501502
if (clangNodeOwner)
502503
fn->setClangNodeOwner(clangNodeOwner);
503504
for (auto ID : SemanticsIDs) {
@@ -2405,12 +2406,12 @@ bool SILDeserializer::hasSILFunction(StringRef Name,
24052406
GenericEnvironmentID genericEnvID;
24062407
unsigned rawLinkage, isTransparent, isSerialized, isThunk, isGlobal,
24072408
inlineStrategy, optimizationMode, effect, numSpecAttrs,
2408-
hasQualifiedOwnership;
2409+
hasQualifiedOwnership, isWeakLinked;
24092410
ArrayRef<uint64_t> SemanticsIDs;
24102411
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
24112412
isThunk, isGlobal, inlineStrategy,
2412-
optimizationMode, effect,
2413-
numSpecAttrs, hasQualifiedOwnership, funcTyID,
2413+
optimizationMode, effect, numSpecAttrs,
2414+
hasQualifiedOwnership, isWeakLinked, funcTyID,
24142415
genericEnvID, clangOwnerID, SemanticsIDs);
24152416
auto linkage = fromStableSILLinkage(rawLinkage);
24162417
if (!linkage) {

lib/Serialization/SILFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ namespace sil_block {
280280
BCFixed<2>, // side effect info.
281281
BCVBR<8>, // number of specialize attributes
282282
BCFixed<1>, // has qualified ownership
283+
BCFixed<1>, // must be weakly referenced
283284
TypeIDField, // SILFunctionType
284285
GenericEnvironmentIDField,
285286
DeclIDField, // ClangNode owner

lib/Serialization/SerializeSIL.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,8 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
379379
(unsigned)F.isThunk(), (unsigned)F.isGlobalInit(),
380380
(unsigned)F.getInlineStrategy(), (unsigned)F.getOptimizationMode(),
381381
(unsigned)F.getEffectsKind(),
382-
(unsigned)numSpecAttrs, (unsigned)F.hasQualifiedOwnership(), FnID,
383-
genericEnvID, clangNodeOwnerID, SemanticsIDs);
382+
(unsigned)numSpecAttrs, (unsigned)F.hasQualifiedOwnership(),
383+
F.isWeakLinked(), FnID, genericEnvID, clangNodeOwnerID, SemanticsIDs);
384384

385385
if (NoBody)
386386
return;

0 commit comments

Comments
 (0)