-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Embedded] Introduce a new linkage model for embedded Swift #83432
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
if (F->getModule().getASTContext().LangOpts.hasFeature( | ||
Feature::EmbeddedLinkageModel) && | ||
F->getDeclRef().isEmittedToObjectFile()) | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is bypassing the SIL serialization model. Instead, can you just set the SILFunction's SerializedKind
accordingly? Then, e.g. SIL verification can catch problems, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can certainly do that in addition, but I can't do it instead because it'll immediately be overridden by the -sil-serialize-all
just below.
Umbrella: #83433 |
17dcafe
to
89ae741
Compare
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 the existing linkage model for Embedded Swift (which emits everying as a non-mergeable symbol, so it doesn't work for static libraries), the "mergeable symbols" experimental feature that's the existing model but with "weak_odr" LLVM linkage, and the "-emit-empty-object-file" flag (which emits nothing to the object file, and only works for libraries but has no control).
89ae741
to
14330e7
Compare
Put the use of this attribute behind the `AlwaysEmitIntoObjectFile` experimental feature for the moment.
EmbeddedLeafLibrary infers @alwaysEmitInObjectFile for all public and open entities in the module to which it is applied. Anything else will retain linkonce_odr (mergeable) semantics. This allows the module to "seal off" the Swift code such that the resulting object file can be linked along with normal C code. With this are a number of important bug fixes to the core of the new Embedded Swift linkages model, including: * Definitions from imported modules always get linkonce_odr linkage, because they're likely to end up being duplicated by different clients of the imported module file. * Global variables also get linkonce_odr linkage unless they are @alwaysEmitInObjectFile. Now, building a library with the new embedded linkage model, by default, produces effectively no symbols in the object file other than linkonce_odr global variables. Symbols that are marked with @alwaysEmitInObjectFile, or that have it inferred via EmbeddedLeafLibrary, have strong definitions. Everything they depend on is pulled in as a linkonce_odr symbol.
The main entry point cannot be discarded. Always emit it as a non-weak symbol.
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 the existing
linkage model for Embedded Swift (which emits everying as a
non-mergeable symbol, so it doesn't work for static libraries), the
"mergeable symbols" experimental feature that's the existing model but
with "weak_odr" LLVM linkage, and the "-emit-empty-object-file" flag
(which emits nothing to the object file, and only works for libraries
but has no control).