apple/swift
Serialization and module loading
Active contributors: jrose-apple, hamishknight, slavapestov
Purpose
lib/Serialization/ writes and reads the binary .swiftmodule format. A .swiftmodule captures everything the compiler needs to use a Swift module from a client: declarations, types, generic signatures, conformances, and (optionally) the SIL bodies that allow @inlinable cross-module inlining. The textual .swiftinterface complements it for ABI-stable distribution.
Directory layout
lib/Serialization/ (25 files)
├── Serialization.cpp # write a Swift module to disk
├── Deserialization.cpp # 9,661 lines — read decls/types/conformances
├── ModuleFile.cpp # the in-memory representation of a loaded .swiftmodule
├── ModuleFileSharedCore.cpp
├── SerializedModuleLoader.cpp # the FileUnit subclass for loaded modules
├── DeclTypeRecordNodes.def # the BCRecord-bytecodes used in .swiftmodule
├── SerializeSIL.cpp # SIL bodies inside .swiftmodule
├── DeserializeSIL.cpp
├── ScanningLoaders.cpp # used by lib/DependencyScan
└── ...
include/swift/Serialization/
├── Validation.h
└── SerializedModuleLoader.hKey abstractions
| Type | File | Description |
|---|---|---|
swift::ModuleFile |
include/swift/Serialization/ModuleFile.h |
A loaded .swiftmodule. |
swift::SerializedModuleLoader |
include/swift/Serialization/SerializedModuleLoader.h |
Finds and loads .swiftmodule files from import search paths. |
swift::serialization::Serializer |
lib/Serialization/Serialization.cpp |
Writes a .swiftmodule for a SourceFile. |
swift::serialization::ModuleFileSharedCore |
lib/Serialization/ModuleFileSharedCore.h |
Backing data shared between many ModuleFile instances. |
How it works
graph LR
SourceFile -->|"emit-module"| Serializer
Serializer --> SwiftModule[".swiftmodule"]
Serializer --> SwiftDoc[".swiftdoc"]
Serializer --> SwiftSourceInfo[".swiftsourceinfo"]
SwiftModule -->|"-import"| Loader[SerializedModuleLoader]
Loader --> ModuleFile
ModuleFile -->|lazy lookup| Decls[Swift Decls in ASTContext]Wire format
.swiftmodule is an LLVM Bitstream container with custom record types defined in DeclTypeRecordNodes.def. Each kind of AST node (struct, class, function, type alias, protocol, conformance, ...) has a record type. Serialization is lazy on read -- only the records actually accessed by the client are deserialized.
The associated files written together:
.swiftmodule-- decls + types + (optional) SIL..swiftdoc-- documentation comments..swiftsourceinfo-- source location data for IDE jump-to-definition..abi.json(when-abi-descriptoris on) -- ABI surface for diffing.
.swiftinterface
For ABI-stable libraries (and any library compiled with -enable-library-evolution), the compiler also emits a textual .swiftinterface. This is essentially Swift source containing only the public API. The advantage: it survives compiler upgrades because it can be re-typechecked by a newer compiler. See lib/Frontend/ModuleInterfaceLoader.cpp for the loader and lib/Frontend/PrintingDiagnosticConsumer.cpp for printing.
When a client imports such a module:
- Look for a
.swiftmodulenext to the interface that was built by this compiler. - If absent, type-check the
.swiftinterfaceinto a fresh.swiftmodule(in the cache) and proceed. - The
ModuleInterfaceLoaderhandles all this automatically.
Cross-module inlining
If a .swiftmodule was built with -emit-module-source-info and contains the SIL bodies of @inlinable / @_alwaysEmitIntoClient functions, the SIL deserializer (DeserializeSIL.cpp) can pull them in for cross-module inlining and specialization at the call site.
Dependency scanning
lib/DependencyScan/ builds a graph of module imports without fully type-checking. It uses ScanningLoaders.cpp to inspect .swiftmodule and .swiftinterface files and produce a JSON dependency graph for build systems (swift -scan-dependencies). Drives features like prebuilt module caches and explicit module builds.
Integration points
- Frontend (
lib/Frontend/) wires the loaders into theASTContextimport-search machinery. - Sema consumes deserialized decls as if they were locally type-checked.
- SILGen / IRGen sometimes deserialize SIL bodies for cross-module inlining.
- The build system treats
.swiftmoduleas an output artifact alongside.o. lib/APIDigester/consumes serialized modules to compare ABI/API surfaces between toolchains (swift-api-digester).
Entry points for modification
- Adding a new
Declkind: register a new record inDeclTypeRecordNodes.def, write a serializer inSerialization.cpp, write a deserializer inDeserialization.cpp. Bump the format version constant ininclude/swift/Serialization/ModuleFormat.h. - Investigating a deserialization crash: run with
-Xfrontend -dump-deserialized-modules. Many bugs are due to stale.swiftmodules; clean the module cache first. - Adding a
.swiftinterfaceflag: consider whether new APIs need@_alwaysEmitIntoClientto ship on older runtimes.
Related pages
- AST -- the data this module reads/writes.
- Frontend and driver -- where module loading is configured.
- ClangImporter -- another
ModuleLoaderpeer.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.