Skip to content

Commit 89ae741

Browse files
committed
[Embedded] Introduce a new linkage model for Embedded Swift
This linkage model gives symbols generated in Embedded Swift LLVM's linkonce_odr linkage (which allows the linker to merge duplicates) unless they specifically need to be emitted as strong symbols in the object. That fits better with creating and using static libraries with Embedded Swift, and essentially maps to the idea of "header-only" libraries in C and C++. Introduce the attribute @alwaysEmitIntoObjectFile that forces code for the symbol to be generated into the generated object file as a non-mergeable symbol. Anything it depends on will also be emitted into the object file, most of which will be via mergeable symbols based on the rule above. Again, as a C/C++ analogy, this is like putting the code into a ".c" or ".cpp" file, which will then include any header-only code it depends on as well. @alwaysEmitIntoObjectFile also suppresses SIL serialization for that symbol, completely hiding the definition of the function from clients of the module. This provides a rudimentary form of implementation hiding that is common in "Desktop" Swift but was not available in Embedded Swift. All of this is behind an experimental feature flag, EmbeddedLinkageModel, but is intended to subsume both the existing linkage model for Embedded Swift (which emits everying as a non-mergeable symbol, so it doesn't work for static libraries)
1 parent 2e7e884 commit 89ae741

File tree

18 files changed

+222
-10
lines changed

18 files changed

+222
-10
lines changed

include/swift/AST/Decl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,14 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
10671067
/// behaviors for it and, if it's an extension, its members.
10681068
bool isObjCImplementation() const;
10691069

1070+
/// True if this declaration *must* be emitted to an object file, overriding
1071+
/// other defaults that might delay emission, including Embedded mode and
1072+
/// Cross-Module Optimization.
1073+
///
1074+
/// As a user, this property can be indicated using
1075+
/// '@alwaysEmitIntoObjectFile'.
1076+
bool isEmittedToObjectFile() const;
1077+
10701078
using AuxiliaryDeclCallback = llvm::function_ref<void(Decl *)>;
10711079

10721080
/// Iterate over the auxiliary declarations for this declaration,

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/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 @alwaysEmitIntoObjectFile).
1859+
bool hasNonUniqueDefinition() const;
1860+
18531861
#undef LINKENTITY_GET_FIELD
18541862
#undef LINKENTITY_SET_FIELD
18551863

include/swift/SIL/SILDeclRef.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,14 @@ 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, overriding any
405+
/// defaults.
406+
bool isEmittedToObjectFile() const;
407+
408+
/// True if this function should have a non-unique definition based on the
409+
/// embedded linkage model.
410+
bool hasNonUniqueDefinition() const;
411+
404412
/// Return the expected linkage for a definition of this declaration.
405413
SILLinkage getDefinitionLinkage() const;
406414

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/Decl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2266,6 +2266,13 @@ bool Decl::isObjCImplementation() const {
22662266
return getAttrs().hasAttribute<ObjCImplementationAttr>(/*AllowInvalid=*/true);
22672267
}
22682268

2269+
bool Decl::isEmittedToObjectFile() const {
2270+
if (getSemanticAttrs().hasAttribute<AlwaysEmitIntoObjectFileAttr>())
2271+
return true;
2272+
2273+
return false;
2274+
}
2275+
22692276
PatternBindingDecl::PatternBindingDecl(SourceLoc StaticLoc,
22702277
StaticSpellingKind StaticSpelling,
22712278
SourceLoc VarLoc,

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,

0 commit comments

Comments
 (0)