While the comment is correct to state that this won't enable any
new optimizations with -Onone, it does enable IRGen's lazy
function emission, which is important for 'reasync' functions,
which we don't want to emit at all even at -Onone.
This fixes debug stdlib builds with the new reasync versions
of the &&, || and ?? operators.
In case a function is only referenced from a global without a declaration (e.g. an outlined global), we could end up with a null IRGenModule for the function (with multithreaded compilation). In this case, just use the primary IGM.
This fixes a IRGen crash, introduced with https://github.com/apple/swift/pull/35780
rdar://74358251
If a function uses a type imported as implementationOnly (or similar), it cannot be serialized.
I added a new API in ModuleDecl (canBeUsedForCrossModuleOptimization), which performs this check.
rdar://72864719
If the specialized function has a re-abstracted (= converted from indirect to direct) resilient argument or return types, use an alternative mangling: "TB" instead of "Tg".
Resilient parameters/returns can be converted from indirect to direct if the specialization is created within the type's resilience domain, i.e. in its module (where the type is loadable).
In this case we need to generate a different mangled name for the specialized function to distinguish it from specializations in other modules, which cannot re-abstract this resilient type.
This fixes a miscompile resulting from ODR-linking specializations from different modules, which in fact have different function signatures.
https://bugs.swift.org/browse/SR-13900
rdar://71914016
This attribute allows to define a pre-specialized entry point of a
generic function in a library.
The following definition provides a pre-specialized entry point for
`genericFunc(_:)` for the parameter type `Int` that clients of the
library can call.
```
@_specialize(exported: true, where T == Int)
public func genericFunc<T>(_ t: T) { ... }
```
Pre-specializations of internal `@inlinable` functions are allowed.
```
@usableFromInline
internal struct GenericThing<T> {
@_specialize(exported: true, where T == Int)
@inlinable
internal func genericMethod(_ t: T) {
}
}
```
There is syntax to pre-specialize a method from a different module.
```
import ModuleDefiningGenericFunc
@_specialize(exported: true, target: genericFunc(_:), where T == Double)
func prespecialize_genericFunc(_ t: T) { fatalError("dont call") }
```
Specially marked extensions allow for pre-specialization of internal
methods accross module boundries (respecting `@inlinable` and
`@usableFromInline`).
```
import ModuleDefiningGenericThing
public struct Something {}
@_specializeExtension
extension GenericThing {
@_specialize(exported: true, target: genericMethod(_:), where T == Something)
func prespecialize_genericMethod(_ t: T) { fatalError("dont call") }
}
```
rdar://64993425
The compiler stubs for testing the OSLog implementation are in need of an update. This change updates the stubs to be consistent with the current OSLog implementation, updates the existing tests, and adds new tests for String and metatype interpolations.
rdar://69719729
When a subclass inherits from a superclass that declares a no-args
desginated initializer and no other visible inits, the subclass may
elide calls to 'super.init()'. The way this was enforced was by looking
into the superclass *from the subclass' init*, not from the subclass.
This ensured that not only would we get results for initializers, we'd
get results for initializers that were actually _callable_ from the
subclass.
The changes in apple/swift#33515 accidentally swapped the decl context
here, which caused this lookup to start returning additional results.
In that case, we consider it ambiguous as to which designated
initializer we should synthesize, and so we bail.
The net result is DI errors where there previously were none. Let's put
this back in order.
rdar://67560590, rdar://67686660, rdar://67690116, SR-13427
…and modify resolveFileIDConflicts() to diagnose any such violations instead of asserting.
Swift does not allow any two files in the same module to have the same filename, even if they are in different directories. However, this is enforced in the driver, so tests that invoke the frontend directly can violate it. Turns out that a couple of those snuck into the test suite at various points.
This commit updates those tests. It also causes the frontend to diagnose the duplicate filename error just as the driver would have, which should help us understand what happened more easily if this crops up again in the future.
NFC, since invoking the frontend directly is unsupported.
This reinstates commit d7d829c059 with a fix for C tail-allocated arrays.
Replace a call of the getter of AnyKeyPath._storedInlineOffset with a "constant" offset, in case of a keypath literal.
"Constant" offset means a series of struct_element_addr and tuple_element_addr instructions with a 0-pointer as base address.
These instructions can then be lowered to "real" constants in IRGen for concrete types, or to metatype offset lookups for generic or resilient types.
Replace:
%kp = keypath ...
%offset = apply %_storedInlineOffset_method(%kp)
with:
%zero = integer_literal $Builtin.Word, 0
%null_ptr = unchecked_trivial_bit_cast %zero to $Builtin.RawPointer
%null_addr = pointer_to_address %null_ptr
%projected_addr = struct_element_addr %null_addr
... // other address projections
%offset_ptr = address_to_pointer %projected_addr
%offset_builtin_int = unchecked_trivial_bit_cast %offset_ptr
%offset_int = struct $Int (%offset_builtin_int)
%offset = enum $Optional<Int>, #Optional.some!enumelt, %offset_int
rdar://problem/53309403
Replace a call of the getter of AnyKeyPath._storedInlineOffset with a "constant" offset, in case of a keypath literal.
"Constant" offset means a series of struct_element_addr and tuple_element_addr instructions with a 0-pointer as base address.
These instructions can then be lowered to "real" constants in IRGen for concrete types, or to metatype offset lookups for generic or resilient types.
Replace:
%kp = keypath ...
%offset = apply %_storedInlineOffset_method(%kp)
with:
%zero = integer_literal $Builtin.Word, 0
%null_ptr = unchecked_trivial_bit_cast %zero to $Builtin.RawPointer
%null_addr = pointer_to_address %null_ptr
%projected_addr = struct_element_addr %null_addr
... // other address projections
%offset_ptr = address_to_pointer %projected_addr
%offset_builtin_int = unchecked_trivial_bit_cast %offset_ptr
%offset_int = struct $Int (%offset_builtin_int)
%offset = enum $Optional<Int>, #Optional.some!enumelt, %offset_int
rdar://problem/53309403
* Include small non-generic functions for serializaion
* serialize initializer of global variables: so that global let variables can be constant propagated across modules
rdar://problem/60696510
Re-name the file "foo.h" in the SILOptimizer inputs to "TypesWithUserProvidedDestructor.h" which better describes its purpose (to define types with user provided destructors).
* Fixes loadable edge case for address-only types.
* Re-work, generalize, and simplify by using projections.
* Support `-enable-cxx-interop` in sil-opt.
This became necessary after recent function type changes that keep
substituted generic function types abstract even after substitution to
correctly handle automatic opaque result type substitution.
Instead of performing the opaque result type substitution as part of
substituting the generic args the underlying type will now be reified as
part of looking at the parameter/return types which happens as part of
the function convention apis.
rdar://62560867
Global variables with resilient types might be allocated into a buffer and not statically in the data segment.
In this case, the global_addr depends on alloc_global being executed first.
We model this by letting global_addr have a side effect.
It prevents e.g. LICM to move a global_addr out of a loop while keeping the alloc_global inside the loop.
rdar://problem/61602640
In case an unchecked_addr_cast is used to convert between pointer and non-pointer, we missed some escaping values.
This can be the case when using C unions.
https://bugs.swift.org/browse/SR-12427
rdar://problem/60983997
Otherwise it can happen that e.g. specialization runs between CrossModuleSerializationSetup and serialization, resulting that an inlinable function references a shared function (which doesn't have a public linkage).
The solution is to move serialization right after CrossModuleSerializationSetup. But only do that if cross-module-optimization is enabled (it would be a disruptive change to move serialization in general).
This is a first version of cross module optimization (CMO).
The basic idea for CMO is to use the existing library evolution compiler features, but in an automated way. A new SIL module pass "annotates" functions and types with @inlinable and @usableFromInline. This results in functions being serialized into the swiftmodule file and thus available for optimizations in client modules.
The annotation is done with a worklist-algorithm, starting from public functions and continuing with entities which are used from already selected functions. A heuristic performs a preselection on which functions to consider - currently just generic functions are selected.
The serializer then writes annotated functions (including function bodies) into the swiftmodule file of the compiled module. Client modules are able to de-serialize such functions from their imported modules and use them for optimiations, like generic specialization.
The optimization is gated by a new compiler option -cross-module-optimization (also available in the swift driver).
By default this option is off. Without turning the option on, this change is (almost) a NFC.
rdar://problem/22591518
...not the one they came from. This is important when specializing an
inlinable function that takes an opaque type as a generic argument:
that opaque type should still be considered opaque even if it came
from the same module as the inlinable function.
rdar://problem/56410009
If a type is trivial in its own module but resilient outside, then we
fail to propagate the 'is resilient' bit to the outer type's lowering.
As a result, if the first time the type is lowered with the Maximal
expansion, we don't re-compute the lowering when it is again lowered
with the Minimal expansion.
This can produce invalid SIL and trigger assertions.
Fixes <rdar://problem/52270675>.
In the statement
optional1?.objc_setter = optional2?.objc_getter?.objc_getter
we can eliminate all optional switches expect for the first switch on
optional1. We must only execute the setter if optional1 has some value.
We can simplify the following switch_enum with a branch as long all
sideffecting instructions in someBB are objc_method calls on the
optional payload or on another objc_method call that transitively uses
the payload.
switch_enum %optionalValue, case #Optional.some!enumelt.1: someBB,
case #Optional.none: noneBB
someBB(%optionalPayload):
%1 = objc_method %optionalPayload
%2 = apply %1(..., %optionalPayload) // self position
br mergeBB(%2)
noneBB:
%4 = enum #Optional.none
br mergeBB(%4)
rdar://48007302
In this commit I added a more convenient API for doing this sort of operation.
Specifically: SILBuilder::emitScopedBorrowOperation. This performs either a
load_borrow or begin_borrow, then calls a user provided closure, and finally
inserts the end_borrow after the scope has closed.
rdar://43398898
Constructors and methods had two parameter lists, one for self and one
for the formal parameters. Destructors only had one parameter list,
which introduced an annoying corner case.