Add the module-format machinery that lets a Swift library record the
physical layout of hidden types (currently limited to C types imported via internal bridging header).
into binary modules, so downstream consumers can pull the layouts of these hidden types without
loading the internal dependency.
To test this, this change also added a frontend action to print hidden types' layouts
from both the module under compilation and all the modules being imported.
@_preInverseGenerics(except: <inverses>) is an extension of the existing
@_preInverseGenerics attribute that provides selective control over which
inverse requirements are mangled into a declaration's symbol name.
While the bare @_preInverseGenerics strips all inverse constraints
(~Copyable and ~Escapable) from mangling, the 'except:' form allows specific
inverses to be retained. This is needed when a type like Span already had
~Copyable mangled into its ABI-stable symbols and now needs to retroactively
adopt ~Escapable without changing those existing symbols. You can now express
that with `@_preInverseGenerics(except: ~Copyable)` to strip-out every inverse
except ~Copyable to preserve the pre-existing ~Copyable-containing symbols.
It requires the new experimental feature `PreInverseGenericsExcept`.
rdar://176395527
HiddenType is a new TypeBase subclass that carries a mangled name
without leaking the actual type definition. It serves as a type-slot
placeholder for stored-property types that have been elided from a
serialized binary module, so that the client side can either
(1) resolve this mangled name to the real type if the client has access to the owning module, or
(2) use the mangled name as a key to query abstract layout information also serialized in the binary module.
As an example — a library with a hidden field of a bridging-imported type:
```
// Utility.h (internal bridging header)
// typedef struct { int value; } Wrapper;
public struct S {
private var w: Wrapper
public var weight: Double
}
In the serialized module, the client's view reconstructs as:
public struct S {
private var w: @_hidden("$sSo7Wrappera")
public var weight: Double
}
```
Add a LAST_RECORD_KIND_MARKER sentinel at the end of the
options_block::RecordKind enum and a static_assert in writeHeader that
verifies the block's code width can encode every abbreviation the
writer may allocate. A future record kind that would overflow the
current code size now fails the build instead of producing a silent
malformed-module regression.
rdar://176522412
OPTIONS_BLOCK has historically been opened with a 4-bit abbreviation code size (BCBlockRAII(Out, OPTIONS_BLOCK_ID, 4) in Serializer::writeHeader), which permits at most 12 user-defined abbreviations (IDs 4–15, after the four reserved bitstream codes). New option records have been added incrementally, for certain flag combinations the writer now emits 13 or more abbreviations in OPTIONS_BLOCK, one past the 12-abbreviation ceiling that a 4-bit code size allows.
When that happens, the writer assigns the new abbreviation ID 16, which does not fit in 4 bits; BitstreamWriter::EmitCode silently truncates it to 0, which the reader interprets as END_BLOCK. OPTIONS_BLOCK is then popped prematurely, later records are reinterpreted as (invalid) content in the enclosing CONTROL_BLOCK, and the module fails to load with error: malformed compiled module. Widening the code size to 6 bits raises the cap to 60 user abbreviations (IDs 4–63), accommodates every currently-emitted record with substantial headroom.
rdar://176281964
We cannot use spare bits or other overlapping storage layout tricks with fundamentally
address-only enums, and we can take advantage of this to do borrowing switches or other
in-place projections without copying the value. However, for resilient enums, the
implementation may use spare bit packing, but the type must be handled address-only
outside of its defining module, and we didn't have a way to express that with
borrowing switch. Optimization passes have also been running into problems with the
complexity that we were using `unchecked_take_enum_data_addr` sometimes as a pure
operation. This patch splits the instruction into three:
- `unchecked_inplace_enum_data_addr` represents a nondestructive in-place enum
projection. It is only allowed for enums whose projection operation is
nondestructive.
- `unchecked_take_enum_data_addr` represents a destructive enum projection,
invalidating the enum and leaving the payload to be further consumed.
This matches the current instruction's semantics.
- `unchecked_borrow_enum_data_addr` represents a borrowing enum projection.
The instruction takes a second operand for "scratch" space, which the
enum representation may be copied into in order to avoid invalidating the
enum value, so the result is dependent on the lifetime of both the
original enum and the scratch buffer. This allows for borrowing switches
over resilient enums.
`unchecked_borrow_enum_data_addr` is implemented by taking advantage of the
"address-only enums can't do spare bit optimization" property at runtime.
We inspect the operand type's bitwise-borrowability from its metadata. If
the type is bitwise-borrowable, then we are allowed to bitwise-copy the
enum to the scratch space and apply the projection to the scratch space,
preserving the original value. If the type is not bitwise-borrowable, then
we cannot use spare bit optimization in its layout, so we apply the
projection in-place.
Fixes rdar://174952822.
The `@export(interface)` and `@export(implementation)` attributes
SE-0497 are queried directly on AST nodes in several places within the
SIL pipeline. However, they don't persist when SIL functions are
serialized, meaning that clients of the original module might make
different assumptions about the availability of a given function's
definition.
Represent these attributes in a SIL function (as an optional
CodeGenerationModel), (de-)serialize them into the module, and add a
textual representation as SIL function attributes `[export_interface]`
and `[export_implementation]`.
For a given function, we might end up emitting it's definition as
object code, serialized SIL, or both. The @export, @inlinable, and
@inline(always) attributes provide control of this behavior at the
declaration level.
Centralize the query function that will look for each of these
attributes and map down to a specific "code generation model", whose 3
options follow the naming from SE-0497: interface, inlinable, and
implementation. Use this one computation to back the queries for
"always emit into client", "never emit into client", and "inlinable"
so we can't get inconsistent results from places that are doing
one-off checks for these attributes.
Generalizes how isolation is stored for SILFunctionType and
makes it possible to store not just "erased" but any future
isolation we'd need to add as well.
Add a LIBRARY_LEVEL record to the .swiftmodule options block so the
declared -library-level value survives across compilations. Without
this, imported modules have to always fell back to a path heuristic
that could only distinguish API vs SPI and never returned IPI.
rdar://174255626
Conformance entries are used for fast conformance lookup, which doesn't need to query the runtime's conformance lookup table.
A conformance entry specifies if the class conforms or does not conform to a protocol.
At runtime, a type cast instruction to an existential can directly load the witness table pointer from the VTable.
If null, the class does not conform to the protocol.
When building the `OSLog` module, look for a variable named
`osLogStringSectionName`. It must have a string literal as its
initializer, which provides the section name where the log strings
should be emitted. The `OSLog` module should contain something like
this:
let osLogStringSectionName = "__TEXT,__logit"
When not present, the compiler will default to
`__TEXT,__oslogstring,cstring_literals`, which was previously the
hardcoded section name. Now, OSLog can customize the name.
Implements rdar://171571056
Currently only the top level dependencies get serialized in Swift modules. In
practice this is not enough information to fully replay a module import
sequence, especially when the dependencies include binary SDK modules that were
built elsewhere. In this case we cannot follow the links to its depenencies,
since they refer to paths on a different machine or unavailable CAS. During an
EBM build, the dependency scanner writes the complete list of dependencies into
a json file called the explicit Swift module map -- including the local
locations of the dependencies of binary SDK modules. Using this LLDB can replay
a module import with 100% accuracy.
rdar://170514919
The isFromAnnotation flag is set if and only if the lifetime originates from a
@lifetime or @_lifetime annotation in the source program.
isFromAnnotation==false means that the lifetime dependence checker would infer
the same lifetime if the Swift type or decl was printed without an annotation
for that dependency. More specifically, it means that the depenence was inferred
by the lifetime dependence checker.
Some dependencies on imported C/C++ decls are "inferred", but they either
correspond to explicit lifetime information in the source (smart pointers,
lifetimebound attribute) or are likely to differ from what the dependence
checker would infer. As such, we set the flag to true for all of them.
A protocol that's been reparented declares it
by writing `@reparented` in its inheirtance clause
for each new parent. You can introduce a `@reparented`
parent to a pre-existing ABI-stable protocol's
inheritance hierarchy.
Only protocols declared to be `@reparentable` can be
used to reparent other protocols. Adding or removing
the `@reparentable` attribute is ABI-breaking, as it
effects the type metadata layout. Thus, reparentable
protocols must be born as such to use them with
protocols that are already ABI-stable.
This set of changes does not include the actual
implementation of ABI-stable reparenting.
This new OSSA invariant simplifies many optimizations because they don't have to take care of the corner case of incomplete lifetimes in dead-end blocks.
The implementation basically consists of these changes:
* add the lifetime completion utility
* add a flag in SILFunction which tells optimization that they need to run the lifetime completion utility
* let all optimizations complete lifetimes if necessary
* enable the ownership verifier to check complete lifetimes
Introduce a new optional flag on the alloc_box SIL instruction to mark boxes as
inferred immutable, indicating that static analysis has proven they are never
written to despite having a mutable type.
The flag is preserved through serialization/deserialization and properly printed/parsed in textual SIL format.
I am doing this to prepare for treating these boxes as being Sendable when they
contain a sendable weak reference.
This updates a large number of internal symbols, function names,
and types to match the final approved terminology. Matching the
surface language terminology and the compiler internals should
make the code easier for people to understand into the future.
Store the original VarDecl in the same map we use for tracking the
original wrapper var for property wrappers. This will allow us to
use the same logic to determine the original var for both.
We need to serialize the underlying type substitution map for an
inlinable function. However, there is no reason to deserialize it
eagerly, since doing so can lead to cycles. It is better for
correctness and performance to only deserialize it when needed.
Technically this fixes a regression from #84299, but the actual
problem was there all along, it was just exposed by my change
on a specific project.
Fixes rdar://163301203.
Implement the @export(implementation) and @export(interface) attributes
to replace @_alwaysEmitIntoClient and @_neverEmitIntoClient. Provide a
warning + Fix-It to start staging out the very-new
@_neverEmitIntoClient. We'll hold off on pushing folks toward
@_alwaysEmitIntoClient for a little longer.
Whenever we have a reference to a foreign function/variable in SIL, use
a mangled name at the SIL level with the C name in the asmname
attribute. The expands the use of asmname to three kinds of cases that
it hadn't been used in yet:
* Declarations imported from C headers/modules
* @_cdecl @implementation of C headers/modules
* @_cdecl functions in general
Some code within the SIL pipeline makes assumptions that the C names of
various runtime functions are reflected at the SIL level. For example,
the linking of Embedded Swift runtime functions is done by-name, and
some of those names refer to C functions (like `swift_retain`) and
others refer to Swift functions that use `@_silgen_name` (like
`swift_getDefaultExecutor`). Extend the serialized module format to
include a table that maps from the asmname of functions/variables over
to their mangled names, so we can look up functions by asmname if we
want. These tables could also be used for checking for declarations
that conflict on their asmname in the future. Right now, we leave it
up to LLVM or the linker to do the checking.
`@_silgen_name` is not affected by these changes, nor should it be:
that hidden feature is specifically meant to affect the name at the
SIL level.
The vast majority of test changes are SIL tests where we had expected
to see the C/C++/Objective-C names in the tests for references to
foreign entities, and now we see Swift mangled names (ending in To).
The SIL declarations themselves will have a corresponding asmname.
Notably, the IRGen tests have *not* changed, because we generally the
same IR as before. It's only the modeling at the SIL lever that has
changed.
Another part of rdar://137014448.
This change just stages in a few new platform kinds, without fully adding
support for them yet.
- The `Swift` platform represents availability of the Swift runtime across all
platforms that support an ABI stable Swift runtime (see the pitch at
https://forums.swift.org/t/pitch-swift-runtime-availability/82742).
- The `anyAppleOS` platform is an experimental platform that represents all of
Apple's operating systems. This is intended to simplify writing availability
for Apple's platforms by taking advantage of the new unified OS versioning
system announced at WWDC 2025.
- The `DriverKit` platform corresponds to Apple DriverKit which is already
supported by LLVM.
For clients, such as the debugger, who do not have access the full
output of the dependency scanner, it is a huger performance and
correctness improvement if each explicitly built Swift module not just
serialized all its Clang .pcm dependencies (via the serialized Clang
compiler invocation) but also its direct Swift module dependencies.
This patch changes the Swift module format to store the absolute path
or cas cache key for each dependency in the INPUT block, and makes
sure the deserialization makes these available to the ESML.
rdar://150969755
This instruction converts Builtin.ImplicitActor to Optional<any Actor>. In the
process of doing so, it masks out the bits we may have stolen from the witness
table pointer of Builtin.ImplicitActor. The bits that we mask out are the bottom
two bits of the top nibble of the TBI space on platforms that support TBI (that
is bit 60,61 on arm64). On platforms that do not support TBI, we just use the
bottom two tagged pointer bits (0,1).
By using an instruction, we avoid having to represent the bitmasking that we are
performing at the SIL level and can instead just make the emission of the
bitmasking an IRGen detail. It also allows us to move detection if we are
compiling for AArch64 to be an IRGen flag instead of a LangOpts flag.
The instruction is a guaranteed forwarding instruction since we want to treat
its result as a borrowed projection from the Builtin.ImplicitActor.
The asmname attribute allows one to specify the name that will be used
when lowering a given SIL declaration to LLVM IR. It is not currently
exposed in the surface language.
Make sure this attribute round-trips through the parser and
serialization.
Part of rdar://137014448O.