Commit Graph

449 Commits

Author SHA1 Message Date
Doug Gregor 92dcbd17c6 [SIL] Explicitly keep the code generation model in SILGlobalVariable
Just like we do with SILFunction, allow a code generation model to be
specified on a SILGlobalVariable and maintain that through the printed
and serialized forms.
2026-05-20 08:35:22 -07:00
Emil Pedersen aa4de7a348 [DebugInfo] Add getOrCreateDebugReconstructionBlock function
This function is used by passes and salvages to facilitate adding
instructions to reconstruction blocks, even if no block exists on the
debug value yet.
2026-05-16 18:23:44 +01:00
Emil Pedersen b563de2da4 [DebugInfo] Rename debug basic blocks to reconstruction blocks 2026-05-15 16:42:53 +01:00
Emil Pedersen bf22a70c1b [DebugInfo] Add SIL printing and parsing support for debug basic blocks
Assisted-by: Claude
2026-05-13 16:03:45 +01:00
Kavon Farvardin 21b2ebff12 Sema: infer inverses in opaque return types
Opaque return types are special type declarations that have it
own nested generic signature. Thus, given this:
```
  protocol P<A> { associatedtype A: ~Copyable }
  func f<T: ~Copyable>() -> some P<T> {}
```
The generic signature for f is <T where T Escapable>, and
for the opaque return type, its nested signature ends up as
```
  <X where X: P, X.A == T>
```
With SE-503, we will now also expand a default for the suppressed
primary associated type, so the signature after expansion becomes
```
  <X where X: P, X.A == T, X.A: Copyable>
```
It would be smarter to effectively have this rule
```
  X.A == T, T: ~Copyable
  ----------------------
     X.A: ~Copyable
```
where we infer the inverse on X.A to cancel-out the
expanded default X.A: Copyable. We already do this for
two in-scope type parameters, and it would be better if
we did it if one side was out-of-scope, but that would
be source-breaking to do in general.

In the case of opaque return types, the fact that
it has a nested generic signature seems more an
artifact of the implementation. There also is little
risk of source break, as the only kinds of same-type
requirements that can appear are from parameterized
protocol type.

The experimental suppressed associated types prior to
SE-503 wouldn't be broken by this change, as they do
not infer defaults that need suppression, and we only
filter-out requirements from defaults expansion, rather
than explicitly-written ones.

rdar://175500824
2026-05-04 14:49:34 -07:00
Kavon Farvardin 6651cb6389 NFC: refactor the applyInverses bool
There's a need for more control over how default requirements
for conformance to Copyable/Escapable are expanded, and
subsequently how inverses are applied or inferred to cancel-out
those defaults.

The pattern of `/*applyInverses*/BOOL` is insufficient, so this
is a refactoring to grow that into a proper type that carries
an option that can be used in some future scenario about inferring
inverses for opaque return types.
2026-04-29 16:56:00 -07:00
Pavel Yaskevich edfc363e19 [SIL] Parser: Remove uses of SILFunction::setActorIsolation 2026-04-28 15:27:11 -07:00
Joe Groff 097b0d3400 SIL: Split unchecked_*_enum_data_addr according to ownership and effects.
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.
2026-04-27 15:40:37 -07:00
Doug Gregor f2eb7cb1a8 [SIL] Model @export(interface) and @export(implementation) on SIL functions
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]`.
2026-04-15 13:04:10 -07:00
Pavel Yaskevich c6cd4f42e9 [SIL] SILFunctionType: Add support for nonisolated(nonsending) isolation
Similarly to `@isolated(any)` it's sometimes necessary to check
whether a call is to a `nonisolated(nonsending)` function value
i.e. for hop elimination pass and without this isolation support
it has to go trying to figure out the isolation from a callee
which is not possible if it doesn't refer to a `SILFunction *`.
2026-04-10 09:35:30 -07:00
John McCall 9b6777ff59 Allow alloc_pack_metadata to be marked as [non_nested].
This is inserted by SIL passes and so may not always be properly nested
with respect to non-unreorderable allocations such as async lets.
2026-04-08 17:56:47 -04:00
Erik Eckstein 6d8aa71814 SIL: add conformance entries to SILVTable
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.
2026-04-03 07:49:33 +02:00
Michael Gottesman ee3db7cd63 [sil] Add support for properly parsing an explicit GlobalActor.
NOTE: This is just for testing. I am in the future going to add support for
serializing/handling actor instances. I messed with the serialization but I
found that b/c ActorInstances can take exprs and we generally do not serialize
exprs, we can't do this naively.

NOTE: We only do this for SIL parsed global actors so we do not have to update
code generated by SILGen. I want to do that at some point but a little later.
2026-03-26 16:10:14 -07:00
Konrad `ktoso` Malawski 791f0796e2 [Distributed] Prevent dead code elimination of distributed funcs, thunks, witnesses (#87901)
Dead code elimination is not aware of the fact that distributed function
accessors and witnesses are actually used by the runtime, and therefore
may remove them. 🧟

This seems to have flown under the radar however when whole module
optimization is enabled in release mode this can trigger reliably and
result in pointing at deleted witnesses.

This PR mades a few cleanups in the way we mark and handle distributed
accessors so they don't get optimized away.

This is an additional fix on top of
https://github.com/swiftlang/swift/pull/87453

Resolves rdar://168881945
2026-03-18 22:20:24 +09:00
John McCall d45af1c021 Allow alloc_ref and alloc_ref_dynamic to be marked [non_nested]
This hopefully unblocks fixing the stack nesting of the
concellation and priority escalation handler builtins.
2026-03-13 19:40:21 -04:00
John McCall 22fc7399a4 [NFC] Make isNested a parameter of createPartialApply
Erik already did this for the Swift sources, and Michael pointed out in
code review that it makes sense to do in C++, too.
2026-03-13 19:40:21 -04:00
John McCall 374e3d37f0 Allow partial_apply [on_stack] to be flagged [non_nested]. 2026-03-06 03:15:28 -05:00
Joe Groff 2f02c7cda3 SIL: Introduce instructions for forming and dereferencing Builtin.Borrow.
Since after address lowering, `Borrow` can remain loadable with a known-
layout address-only referent, we need instructions that handle three
forms:

- borrow and referent are both loadable values
- borrow is a value, but referent is address-only
- borrow and referent are both address-only
2026-01-23 08:02:01 -08:00
Erik Eckstein 18063707b5 Optimizer: enable complete OSSA lifetimes throughout the pass pipeline
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
2026-01-22 17:41:48 +01:00
Erik Eckstein 0f0aa0c17b Optimizer: require that there are no unreachable blocks and infinite loops in OSSA
These two new invariants eliminate corner cases which caused bugs if optimization didn't handle them.
Also, it will significantly simplify lifetime completion.

The implementation basically consists of these changes:
* add a flag in SILFunction which tells optimization if they need to take care of infinite loops
* add a utility to break infinite loops
* let all optimizations remove unreachable blocks and break infinite loops if necessary
* add verification to check the new SIL invariants

The new `breakIfniniteLoops` utility breaks infinite loops in the control flow by inserting an "artificial" loop exit to a new dead-end block with an `unreachable`.
It inserts a `cond_br` with a `builtin "infinite_loop_true_condition"`:
```
bb0:
  br bb1
bb1:
  br bb1              // back-end branch
```
->
```
bb0:
  br bb1
bb1:
  %1 = builtin "infinite_loop_true_condition"() // always true, but the compiler doesn't know
  cond_br %1, bb2, bb3
bb2:                  // new back-end block
  br bb1
bb3:                  // new dead-end block
  unreachable
```
2026-01-22 17:41:23 +01:00
Michael Gottesman 56d6b60c36 Merge pull request #86312 from gottesmm/rdar166081666
[rbi] Convert Sendable immutable weak var captures to weak let to fix RegionIsolation checking
2026-01-17 11:38:12 -08:00
Michael Gottesman 5d0f2e3d5e [sil] Add [inferred-immutable] flag to alloc_box instruction
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.
2026-01-16 09:09:47 -08:00
Michael Gottesman 581cfcd7b6 [sil] Add @inferredImmutable flag to SILFunctionArgument for captured boxes
Introduce a new optional inferred-immutable flag on SILFunctionArgument to mark
closure-captured box parameters that are never written to despite being mutable.

This flag will enable in future commits:

- Marking captured mutable boxes as immutable when interprocedural analysis
  proves they are never modified
- Treating these captures as Sendable when they contain Sendable types
- Improving region-based isolation analysis for concurrent code

This complements the inferred-immutable flag on alloc_box by allowing
immutability information to flow through closure boundaries.
2026-01-16 08:22:21 -08:00
Pavel Yaskevich c6ee92e5d2 [SILParser] Adjust ownership requirement for ImplicitActorToOpaqueIsolationCast
Similarly to SILVerifier condition, it has to use `isCompatibleWith`
to allow for "none" as well.
2026-01-15 11:03:23 -08:00
Tim Kientzle aa39e91372 Start staging SIL printing transition
For now, the SIL parser accepts both `!read2`/`!modify2` and
`!yielding_borrow`/`!yielding_mutate`.  But the SIL printer
still only prints the interim terms.
2026-01-04 08:57:25 -08:00
Tim Kientzle 8eabeeb8ca [SE-0474] Read2/Modify2 => YieldingBorrow/YieldingMutate
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.
2026-01-03 16:05:12 -08:00
Erik Eckstein ceafe65500 SILVerifier: print a readable error message when referencing an undefined SIL function
This error was not printed because the verifier complained before the error handling was done.
2025-12-19 17:44:01 +01:00
Michael Gottesman 29229a9410 [sil] Add basic SIL support for alloc_stack [non_nested].
This means I just added the flag and added support for
cloning/printing/serializing the bit on alloc_stack.
2025-11-21 11:21:14 -08:00
Slava Pestov 64f2d1acce AST: Rename mapConformanceOutOfContext() => mapConformanceOutOfEnvironment(), mapReplacementTypesOutOfContext() => subs.mapReplacementTypesOutOfEnvironment() 2025-11-12 14:48:19 -05:00
Slava Pestov 819738c83e AST: Rename mapTypeIntoContext() => mapTypeIntoEnvironment(), mapTypeOutOfContext() => mapTypeOutOfEnvironment() 2025-11-12 14:48:19 -05:00
Meghana Gupta 1dc5c9611c Intoduce unchecked_ownership instruction in raw SIL
This instruction can be used to disable ownership verification on it's result and
will be allowed only in raw SIL.

Sometimes SILGen can produce invalid ownership SSA, that cannot be resolved until
mandatory passes run. We have a few ways to piecewise disable verification.
With unchecked_ownership instruction we can provide a uniform way to disable ownership
verification for a value.
2025-10-23 05:19:08 -07:00
Meghana Gupta e116df3628 Introduce return_borrow instruction 2025-10-23 05:18:59 -07:00
Michael Gottesman fe9c21fd87 [sil] Add a new instruction cast_implicit_actor_to_optional_actor.
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.
2025-10-16 10:52:04 -07:00
Doug Gregor 081b5cd1e8 [SIL] Serialize section name correctly and model it on global variables
Fixes rdar://162549960.
2025-10-15 20:44:11 -07:00
Doug Gregor 3e1ea3c0f7 [SIL] Add asmname attribute to SIL functions and global variables
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.
2025-10-15 20:44:09 -07:00
Arnold Schwaighofer 25a071efc8 Add experimental feature @inline(always)
The intent for `@inline(always)` is to act as an optimization control.
The user can rely on inlining to happen or the compiler will emit an error
message.

Because function values can be dynamic (closures, protocol/class lookup)
this guarantee can only be upheld for direct function references.

In cases where the optimizer can resolve dynamic function values the
attribute shall be respected.

rdar://148608854
2025-09-30 08:36:26 -07:00
Kavon Farvardin 61fe8a9b8e introduce @_manualOwnership performance attribute
This attribute forces programmers to acknowledge every
copy that is required to happen in the body of the
function. Only those copies that make sense according
to Swift's ownership rules should be "required".

The way this is implemented as of now is to flag each
non-explicit copy in a function, coming from SILGen, as
an error through PerformanceDiagnostics.
2025-09-17 13:51:57 -07:00
Janat Baig 798c0f51a4 Merge branch 'main' into temp-branch 2025-08-23 11:11:04 -04:00
JanBaig 6f1ee54885 [SIL] Remove AssignByWrapper suport from SIL parsing and serialization 2025-08-22 23:17:54 -04:00
Doug Gregor c91a4822d3 Serialize the "markedAsUsed" bit for SILGlobalVariable 2025-08-17 15:25:50 -07:00
JanBaig 988a3dcf25 [SIL] Introduce new SILDeclRef 2025-07-29 21:16:11 -04:00
Anthony Latsis fec049e5e4 Address llvm::PointerUnion::{is,get} deprecations
These were deprecated in
https://github.com/llvm/llvm-project/pull/122623.
2025-07-29 18:37:48 +01:00
Michael Gottesman ee3027c2ca [sil] Add the ability to mark a function with isolation just so we can write more concurrency tests in SIL.
Specifically, we write a string out like:

sil [isolation "$REPRESENTATION OF ISOLATION"] @function : $@convention(thin) ...

The idea is that by using a string, we avoid parsing issues of the isolation and
have flexibility. I left in the way we put isolation into the comment above
functions so I did not break any tests that rely on it. I also made it so that
we only accept this with sil tests that pass in the flag
"sil-print-function-isolation-info". I am going to for the next release put in a
full real implementation of this that allows for actor isolation to become a
true first class citizen in SIL. But for now this at least lets us write tests
in the short term.

Since this is temporary and behind a flag, I did not add support for
serialization since this is just for writing textual SIL tests.
2025-07-15 13:19:26 -07:00
Allan Shortlidge c6dad96492 Make LayoutPrespecialization a baseline feature instead of experimental.
Since LayoutPrespecialization has been enabled by default in all compiler
invocations for quite some time, it doesn't make sense for it to be treated as
experimental feature. Make it a baseline feature and remove all the
checks for it from the compiler.
2025-07-10 11:25:28 -07:00
Doug Gregor bc4cf1236b [SIL] Generalize CastingIsolatedConformances to CheckedCastInstOptions
We are going to need to add more flags to the various checked cast
instructions. Generalize the CastingIsolatedConformances bit in all of
these SIL instructions to an "options" struct that's easier to extend.

Precursor to rdar://152335805.
2025-06-04 17:12:28 -07:00
Arnold Schwaighofer 13ff5abdb8 Introduce @specialized attribute
Implements SE-0460 -- the non-underscored version of @specialized.

It allows to specify "internal" (not abi affecting) specializations.

rdar://150033316
2025-05-23 13:12:47 -07:00
Erik Eckstein a38db6439a SIL: add the vector_base_addr instruction
It derives the address of the first element of a vector, i.e. a `Builtin.FixedArray`, from the address of the vector itself.
Addresses of other vector elements can then be derived with `index_addr`.
2025-05-12 19:24:31 +02:00
Meghana Gupta 3cad5c5924 Merge pull request #81043 from meg-gupta/fixcow
Insert end_cow_mutation_addr for lifetime dependent values dependent on mutable addresses
2025-05-01 07:26:28 -07:00
Meghana Gupta 35d62a4a36 Introduce end_cow_mutation_addr instruction 2025-04-30 13:39:45 -07:00
Slava Pestov 6ffa8fd489 AST: Change signature of LookupConformanceFn
Instead of passing in the substituted type, we pass in the
InFlightSubstitution. This allows the substituted type to be
recovered if needed, but we can now skip computing it for
the common case of LookUpConformanceInSubstitutionMap.
2025-04-30 13:42:20 -04:00