-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Preliminary support for _specialize(exported: true, ...)
#32657
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
Preliminary support for _specialize(exported: true, ...)
#32657
Conversation
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.
Cool! Can this eventually be used to generate SwiftOnoneSupport too?
@@ -221,6 +228,12 @@ bool SILDeclRef::isImplicit() const { | |||
} | |||
|
|||
SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const { | |||
|
|||
// Prespecializations are public. |
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.
Only specializations of public symbols though, right?
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.
Pre-specialization are intentionally always public.
For example, there is going to be a public entry point for the specialized version of:
@_alwaysEmitIntoClient
@_specialize(exported: true, where T == Int)
internal func testGeneric<T>(t: T) {
print(t)
}
include/swift/SIL/SILDeclRef.h
Outdated
@@ -151,6 +153,8 @@ struct SILDeclRef { | |||
/// The derivative function identifier. | |||
AutoDiffDerivativeFunctionIdentifier *derivativeFunctionIdentifier = nullptr; | |||
|
|||
GenericSignature specializedSignature; |
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.
Can we stick this in a union with derivativeFunctionIdentifier to save space?
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.
Good point.
@@ -631,9 +631,6 @@ bool Parser::parseSpecializeAttributeArguments( | |||
if (ParamLabel == "exported") { | |||
auto trueLoc = Tok.getLoc(); | |||
bool isTrue = consumeIf(tok::kw_true); | |||
if (isTrue) { | |||
diagnose(trueLoc, diag::attr_specialize_export_true_no_op); |
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 think you can remove this diagnostic now
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 did.
// use the same set of generic parameters, i.e. each generic | ||
// parameter should be mapped to itself. | ||
for (auto GP : CalleeGenericSig->getGenericParams()) { | ||
CalleeInterfaceToSpecializedInterfaceMapping[GP] = Type(GP); |
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.
Do you really need CalleeInterfaceToSpecializedInterfaceMapping at all then? The lookup() below can be replaced with just 'type' itself, no?
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.
Yes. Likely. I have copied this code from the FunctionSignaturePartialSpecializer and have not gone back to simplify it.
: TargetModule(targetModule), isWholeModule(isWholeModule), | ||
isPrespecialization(isPrespecialization) { | ||
Serialized = | ||
this->isPrespecialization ? IsNotSerialized : Callee->isSerialized(); |
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.
Why can't we serialize the pre-specialization if the original function is serialized?
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 intentional. Pre-specialization as implemented in this patch get their own symbol/mangling to make them easily identifiable for tooling. The intent of exported pre-specializations is to reduce code size. When using the pre-specializated symbol I don't want the code to be available in the client module for further optimization.
I think so. |
efb616e
to
76cd65a
Compare
ecc4510
to
5a39f76
Compare
e0a4d8f
to
f7c31a1
Compare
_specialize(exported: true, ...)
_specialize(exported: true, ...)
@swift-ci Please test |
Build failed |
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
``` @_specialize(exported: true, spi: SPIGroupName, where T == Int) public func myFunc() { } ``` The specialized entry point is only visible for modules that import using `_spi(SPIGroupName) import ModuleDefiningMyFunc `. rdar://64993425
4ec70aa
to
d6d79c6
Compare
Please test with following PR: @swift-ci Please test |
@swift-ci Please test source compatibility |
The compiler failure in the source compatibility run also occurs without this change in: https://ci.swift.org/job/swift-main-source-compat-suite/5513/artifact/swift-source-compat-suite/FAIL_swift-nio-ssl_5.0_BuildSwiftPackage.log |
Adds support for
_specialize(exported: true, ...)
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 typeInt
that clients of thelibrary can call.
Pre-specializations of internal
@inlinable
functions are allowed.There is syntax to pre-specialize a method from a different module.
Specially marked extensions allow for pre-specialization of internal
methods accross module boundries (respecting
@inlinable
and@usableFromInline
).Adds support for marking a _specialize attribute as SPI
The specialized entry point is only visible for modules that import
using
_spi(SPIGroupName) import ModuleDefiningMyFunc
.rdar://64993425