Skip to content

Commit 17dcafe

Browse files
committed
[Embedded] Introduce a new linkage model for embedded Swift
1 parent 2e7e884 commit 17dcafe

File tree

13 files changed

+94
-7
lines changed

13 files changed

+94
-7
lines changed

include/swift/AST/DeclAttr.def

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,11 @@ SIMPLE_DECL_ATTR(requires_stored_property_inits, RequiresStoredPropertyInits,
201201
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr,
202202
27)
203203

204-
// Unused '28'
204+
SIMPLE_DECL_ATTR(alwaysEmitIntoObjectFile, AlwaysEmitIntoObjectFile,
205+
OnAbstractFunction| OnVar | OnSubscript,
206+
UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
207+
28)
208+
205209
// Unused '29'
206210

207211
SIMPLE_DECL_ATTR(nonobjc, NonObjC,

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,12 @@ ERROR(cannot_import_non_embedded_module,none,
10001000
(Identifier))
10011001
ERROR(volatile_is_experimental,none,
10021002
"importing _Volatile module requires '-enable-experimental-feature Volatile'", ())
1003+
ERROR(in_object_file_experimental,none,
1004+
"'@alwaysEmitIntoObjectFile' attribute requires '-enable-experimental-feature EmbeddedLinkageModel'", ())
1005+
ERROR(in_object_file_generic,none,
1006+
"'@alwaysEmitIntoObjectFile' cannot be used on a generic function", ())
1007+
ERROR(in_object_file_inlinable,none,
1008+
"'@alwaysEmitIntoObjectFile' cannot be used with inlinable attribute", ())
10031009

10041010
ERROR(need_cxx_interop_to_import_module,none,
10051011
"module %0 was built with C++ interoperability enabled, but "

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,9 @@ EXPERIMENTAL_FEATURE(RawLayout, true)
420420
/// Enables the "embedded" swift mode (no runtime).
421421
EXPERIMENTAL_FEATURE(Embedded, true)
422422

423+
/// Embedded linkage model.
424+
EXPERIMENTAL_FEATURE(EmbeddedLinkageModel, true)
425+
423426
/// Enables importing the Volatile module
424427
EXPERIMENTAL_FEATURE(Volatile, true)
425428

include/swift/SIL/SILDeclRef.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,10 @@ struct SILDeclRef {
401401
/// True if the function has the @backDeployed attribute.
402402
bool isBackDeployed() const;
403403

404+
/// True if this function must be emitted to an object file in embedded
405+
/// mode.
406+
bool isEmittedToObjectFile() const;
407+
404408
/// Return the expected linkage for a definition of this declaration.
405409
SILLinkage getDefinitionLinkage() const;
406410

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5055,6 +5055,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
50555055
TRIVIAL_ATTR_PRINTER(WeakLinked, weak_linked)
50565056
TRIVIAL_ATTR_PRINTER(Nonexhaustive, nonexhaustive)
50575057
TRIVIAL_ATTR_PRINTER(Concurrent, concurrent)
5058+
TRIVIAL_ATTR_PRINTER(AlwaysEmitIntoObjectFile, alwaysEmitIntoObjectFile)
50585059

50595060
#undef TRIVIAL_ATTR_PRINTER
50605061

lib/AST/FeatureSet.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ UNINTERESTING_FEATURE(DoExpressions)
118118
UNINTERESTING_FEATURE(ImplicitLastExprResults)
119119
UNINTERESTING_FEATURE(RawLayout)
120120
UNINTERESTING_FEATURE(Embedded)
121+
UNINTERESTING_FEATURE(EmbeddedLinkageModel)
121122
UNINTERESTING_FEATURE(Volatile)
122123
UNINTERESTING_FEATURE(SuppressedAssociatedTypes)
123124
UNINTERESTING_FEATURE(StructLetDestructuring)

lib/ASTGen/Sources/ASTGen/DeclAttrs.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ extension ASTGenVisitor {
261261
.ImplicitSelfCapture,
262262
.InheritsConvenienceInitializers,
263263
.Inlinable,
264+
.AlwaysEmitIntoObjectFile,
264265
.Isolated,
265266
.LexicalLifetimes,
266267
.LLDBDebuggerFunction,

lib/IRGen/GenDecl.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1157,8 +1157,15 @@ static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) {
11571157
return true;
11581158
}
11591159

1160-
if (f.isPossiblyUsedExternally())
1160+
if (f.isPossiblyUsedExternally()) {
1161+
// Under the embedded linkage model, if the declaration is not specifically
1162+
// emitted to the object file, it's lazy.
1163+
if (f.getASTContext().LangOpts.hasFeature(Feature::EmbeddedLinkageModel) &&
1164+
!f.getDeclRef().isEmittedToObjectFile())
1165+
return true;
1166+
11611167
return false;
1168+
}
11621169

11631170
if (f.getDynamicallyReplacedFunction())
11641171
return false;

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,15 +510,21 @@ static LinkageLimit getLinkageLimit(SILDeclRef constant) {
510510
case Kind::GlobalAccessor:
511511
// global unsafeMutableAddressor should be kept hidden if its decl
512512
// is resilient.
513-
return cast<VarDecl>(d)->isResilient() ? Limit::NeverPublic : Limit::None;
513+
if (cast<VarDecl>(d)->isResilient())
514+
return Limit::NeverPublic;
515+
516+
break;
514517

515518
case Kind::DefaultArgGenerator:
516519
// If the default argument is to be serialized, only use non-ABI public
517520
// linkage. If the argument is not to be serialized, don't use a limit.
518521
// This actually means that default arguments *can be ABI public* if
519522
// `isSerialized()` returns false and the effective access level is public,
520523
// which happens under `-enable-testing` with an internal decl.
521-
return constant.isSerialized() ? Limit::AlwaysEmitIntoClient : Limit::None;
524+
if (constant.isSerialized())
525+
return Limit::AlwaysEmitIntoClient;
526+
527+
break;
522528

523529
case Kind::PropertyWrapperBackingInitializer:
524530
case Kind::PropertyWrapperInitFromProjectedValue: {
@@ -528,9 +534,12 @@ static LinkageLimit getLinkageLimit(SILDeclRef constant) {
528534
// This actually means that it *can be ABI public* if `isSerialized()`
529535
// returns false and the effective access level is public, which happens
530536
// under `-enable-testing` with an internal decl.
531-
return constant.isSerialized() ? Limit::AlwaysEmitIntoClient
532-
: Limit::None;
537+
if (constant.isSerialized())
538+
return Limit::AlwaysEmitIntoClient;
539+
540+
break;
533541
}
542+
534543
// Otherwise, regular property wrapper backing initializers (for properties)
535544
// are treated just like stored property initializers.
536545
LLVM_FALLTHROUGH;
@@ -571,6 +580,14 @@ static LinkageLimit getLinkageLimit(SILDeclRef constant) {
571580
case Kind::AsyncEntryPoint:
572581
llvm_unreachable("Already handled");
573582
}
583+
584+
// When using the Embedded linkage model, any symbol not explicitly emitted
585+
// to the object file is considered on-demand
586+
if (d->getASTContext().LangOpts.hasFeature(Feature::EmbeddedLinkageModel) &&
587+
!constant.isSerialized() &&
588+
!constant.isEmittedToObjectFile())
589+
return Limit::OnDemand;
590+
574591
return Limit::None;
575592
}
576593

@@ -1089,6 +1106,18 @@ bool SILDeclRef::isBackDeployed() const {
10891106
return false;
10901107
}
10911108

1109+
bool SILDeclRef::isEmittedToObjectFile() const {
1110+
// Entry points are always emitted to the object file.
1111+
if (kind == Kind::EntryPoint)
1112+
return true;
1113+
1114+
auto decl = getDecl();
1115+
if (!decl)
1116+
return false;
1117+
1118+
return decl->getAttrs().hasAttribute<AlwaysEmitIntoObjectFileAttr>();
1119+
}
1120+
10921121
bool SILDeclRef::isForeignToNativeThunk() const {
10931122
// If this isn't a native entry-point, it's not a foreign-to-native thunk.
10941123
if (isForeign)

lib/SILOptimizer/IPO/CrossModuleOptimization.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,10 @@ void CrossModuleOptimization::keepMethodAlive(SILDeclRef method) {
10051005
void CrossModuleOptimization::makeFunctionUsableFromInline(SILFunction *function) {
10061006
assert(canUseFromInline(function));
10071007
if (!isAvailableExternally(function->getLinkage()) &&
1008-
!isPackageOrPublic(function->getLinkage())) {
1008+
!isPackageOrPublic(function->getLinkage()) &&
1009+
!(function->getLinkage() == SILLinkage::Shared &&
1010+
M.getSwiftModule()->getASTContext().LangOpts.hasFeature(
1011+
Feature::EmbeddedLinkageModel))) {
10091012
function->setLinkage(SILLinkage::Public);
10101013
}
10111014
}

0 commit comments

Comments
 (0)