Skip to content

Commit 1424b9b

Browse files
committed
Introduce @specialized attribute
Implements SE-0460 -- the non-underscored version of @specialized. It allows to specify "internal" (not abi affecting) specializations. rdar://150033316
1 parent 55b29fe commit 1424b9b

39 files changed

+645
-188
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,6 +1396,15 @@ BridgedSpecializeAttr BridgedSpecializeAttr_createParsed(
13961396
BridgedDeclNameRef cTargetFunction, BridgedArrayRef cSPIGroups,
13971397
BridgedArrayRef cAvailableAttrs);
13981398

1399+
SWIFT_NAME("BridgedSpecializedAttr.createParsed(_:atLoc:range:whereClause:"
1400+
"exported:kind:taretFunction:spiGroups:availableAttrs:)")
1401+
BridgedSpecializedAttr BridgedSpecializedAttr_createParsed(
1402+
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
1403+
BridgedSourceRange cRange, BridgedNullableTrailingWhereClause cWhereClause,
1404+
bool exported, BridgedSpecializationKind cKind,
1405+
BridgedDeclNameRef cTargetFunction, BridgedArrayRef cSPIGroups,
1406+
BridgedArrayRef cAvailableAttrs);
1407+
13991408
SWIFT_NAME(
14001409
"BridgedSPIAccessControlAttr.createParsed(_:atLoc:range:spiGroupName:)")
14011410
BridgedSPIAccessControlAttr BridgedSPIAccessControlAttr_createParsed(

include/swift/AST/ASTScope.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class GenericParamList;
7575
class TrailingWhereClause;
7676
class ParameterList;
7777
class PatternBindingEntry;
78-
class SpecializeAttr;
78+
class AbstractSpecializeAttr;
7979
class GenericContext;
8080
class DeclName;
8181
class StmtConditionElement;
@@ -1241,10 +1241,10 @@ class TopLevelCodeScope final : public ASTScopeImpl {
12411241
/// The \c _@specialize attribute.
12421242
class SpecializeAttributeScope final : public ASTScopeImpl {
12431243
public:
1244-
SpecializeAttr *const specializeAttr;
1244+
AbstractSpecializeAttr *const specializeAttr;
12451245
AbstractFunctionDecl *const whatWasSpecialized;
12461246

1247-
SpecializeAttributeScope(SpecializeAttr *specializeAttr,
1247+
SpecializeAttributeScope(AbstractSpecializeAttr *specializeAttr,
12481248
AbstractFunctionDecl *whatWasSpecialized)
12491249
: ASTScopeImpl(ScopeKind::SpecializeAttribute),
12501250
specializeAttr(specializeAttr), whatWasSpecialized(whatWasSpecialized) {

include/swift/AST/Attr.h

Lines changed: 165 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
#ifndef SWIFT_ATTR_H
1818
#define SWIFT_ATTR_H
19-
2019
#include "swift/AST/ASTAllocated.h"
2120
#include "swift/AST/AttrKind.h"
2221
#include "swift/AST/AutoDiff.h"
@@ -203,7 +202,7 @@ class DeclAttribute : public AttributeBase {
203202
ownership : NumReferenceOwnershipBits
204203
);
205204

206-
SWIFT_INLINE_BITFIELD(SpecializeAttr, DeclAttribute, 1+1,
205+
SWIFT_INLINE_BITFIELD(AbstractSpecializeAttr, DeclAttribute, 1+1,
207206
exported : 1,
208207
kind : 1
209208
);
@@ -1730,15 +1729,17 @@ class SynthesizedProtocolAttr : public DeclAttribute {
17301729
}
17311730
};
17321731

1733-
/// The @_specialize attribute, which forces specialization on the specified
1734-
/// type list.
1735-
class SpecializeAttr final
1732+
/// The @_specialize/@specialize attribute, which forces specialization on the
1733+
/// specified type list.
1734+
template<typename Base, typename...AdditionalTrailingObjects>
1735+
using SpecializeAttrTrailingObjects = llvm::TrailingObjects<Base,
1736+
Identifier, AvailableAttr *, Type , AdditionalTrailingObjects...>;
1737+
1738+
class AbstractSpecializeAttr
17361739
: public DeclAttribute,
1737-
private llvm::TrailingObjects<SpecializeAttr, Identifier,
1738-
AvailableAttr *, Type> {
1740+
private llvm::trailing_objects_internal::TrailingObjectsBase {
17391741
friend class SpecializeAttrTargetDeclRequest;
17401742
friend class SerializeAttrGenericSignatureRequest;
1741-
friend TrailingObjects;
17421743

17431744
public:
17441745
// NOTE: When adding new kinds, you must update the inline bitfield macro.
@@ -1759,82 +1760,81 @@ class SpecializeAttr final
17591760
size_t numTypeErasedParams;
17601761
bool typeErasedParamsInitialized;
17611762

1762-
SpecializeAttr(SourceLoc atLoc, SourceRange Range,
1763-
TrailingWhereClause *clause, bool exported,
1763+
protected:
1764+
AbstractSpecializeAttr(DeclAttrKind DK, SourceLoc atLoc, SourceRange Range,
1765+
TrailingWhereClause *clause,
1766+
bool exported,
17641767
SpecializationKind kind, GenericSignature specializedSignature,
17651768
DeclNameRef targetFunctionName, ArrayRef<Identifier> spiGroups,
17661769
ArrayRef<AvailableAttr *> availabilityAttrs,
17671770
size_t typeErasedParamsCount);
17681771

17691772
public:
1770-
static SpecializeAttr *
1771-
create(ASTContext &Ctx, SourceLoc atLoc, SourceRange Range,
1772-
TrailingWhereClause *clause, bool exported, SpecializationKind kind,
1773-
DeclNameRef targetFunctionName, ArrayRef<Identifier> spiGroups,
1774-
ArrayRef<AvailableAttr *> availabilityAttrs,
1775-
GenericSignature specializedSignature = nullptr);
1776-
1777-
static SpecializeAttr *create(ASTContext &ctx, bool exported,
1778-
SpecializationKind kind,
1779-
ArrayRef<Identifier> spiGroups,
1780-
ArrayRef<AvailableAttr *> availabilityAttrs,
1781-
GenericSignature specializedSignature,
1782-
DeclNameRef replacedFunction);
1783-
1784-
static SpecializeAttr *create(ASTContext &ctx, bool exported,
1785-
SpecializationKind kind,
1786-
ArrayRef<Identifier> spiGroups,
1787-
ArrayRef<AvailableAttr *> availabilityAttrs,
1788-
ArrayRef<Type> typeErasedParams,
1789-
GenericSignature specializedSignature,
1790-
DeclNameRef replacedFunction,
1791-
LazyMemberLoader *resolver, uint64_t data);
1792-
17931773
size_t numTrailingObjects(OverloadToken<Identifier>) const {
17941774
return numSPIGroups;
17951775
}
17961776

17971777
size_t numTrailingObjects(OverloadToken<AvailableAttr *>) const {
17981778
return numAvailableAttrs;
17991779
}
1780+
// Helper to get the trailing objects of one of the subclasses.
1781+
template<typename Type>
1782+
const Type *getSubclassTrailingObjects() const;
1783+
1784+
template<typename Type>
1785+
Type *getSubclassTrailingObjects() {
1786+
const auto *constThis = this;
1787+
return const_cast<Type*>(constThis->getSubclassTrailingObjects<Type>());
1788+
}
1789+
18001790
/// Name of SPIs declared by the attribute.
18011791
///
18021792
/// Note: A single SPI name per attribute is currently supported but this
18031793
/// may change with the syntax change.
18041794
ArrayRef<Identifier> getSPIGroups() const {
1805-
return { this->template getTrailingObjects<Identifier>(),
1795+
return { getSubclassTrailingObjects<Identifier>(),
18061796
numSPIGroups };
18071797
}
18081798

18091799
ArrayRef<AvailableAttr *> getAvailableAttrs() const {
1810-
return {this->template getTrailingObjects<AvailableAttr *>(),
1800+
return {getSubclassTrailingObjects<AvailableAttr *>(),
18111801
numAvailableAttrs};
18121802
}
18131803

18141804
ArrayRef<Type> getTypeErasedParams() const {
18151805
if (!typeErasedParamsInitialized)
18161806
return {};
18171807

1818-
return {this->template getTrailingObjects<Type>(),
1808+
return {getSubclassTrailingObjects<Type>(),
18191809
numTypeErasedParams};
18201810
}
18211811

18221812
void setTypeErasedParams(const ArrayRef<Type> typeErasedParams) {
18231813
assert(typeErasedParams.size() == numTypeErasedParams);
18241814
if (!typeErasedParamsInitialized) {
1825-
std::uninitialized_copy(typeErasedParams.begin(), typeErasedParams.end(), getTrailingObjects<Type>());
1815+
std::uninitialized_copy(typeErasedParams.begin(), typeErasedParams.end(),
1816+
getSubclassTrailingObjects<Type>());
18261817
typeErasedParamsInitialized = true;
18271818
}
18281819
}
18291820

1821+
void setResolver(LazyMemberLoader *resolver, uint64_t resolverContextData) {
1822+
this->resolver = resolver;
1823+
this->resolverContextData = resolverContextData;
1824+
}
1825+
18301826
TrailingWhereClause *getTrailingWhereClause() const;
18311827

1828+
bool isPublic() const {
1829+
return getKind() == DeclAttrKind::Specialized;
1830+
}
1831+
18321832
bool isExported() const {
1833-
return Bits.SpecializeAttr.exported;
1833+
return Bits.AbstractSpecializeAttr.exported;
18341834
}
18351835

18361836
SpecializationKind getSpecializationKind() const {
1837-
return SpecializationKind(Bits.SpecializeAttr.kind);
1837+
return SpecializationKind(Bits.AbstractSpecializeAttr.kind);
18381838
}
18391839

18401840
bool isFullSpecialization() const {
@@ -1856,15 +1856,140 @@ class SpecializeAttr final
18561856
GenericSignature
18571857
getSpecializedSignature(const AbstractFunctionDecl *forDecl) const;
18581858

1859+
static bool classof(const DeclAttribute *DA) {
1860+
return DA->getKind() == DeclAttrKind::Specialize ||
1861+
DA->getKind() == DeclAttrKind::Specialized;
1862+
}
1863+
1864+
UNIMPLEMENTED_CLONE(AbstractSpecializeAttr)
1865+
1866+
bool isEquivalent(const AbstractSpecializeAttr *other, Decl *attachedTo) const;
1867+
};
1868+
1869+
/// The @_specialize attribute.
1870+
class SpecializeAttr final : public AbstractSpecializeAttr,
1871+
private SpecializeAttrTrailingObjects<SpecializeAttr> {
1872+
friend TrailingObjects;
1873+
friend AbstractSpecializeAttr;
1874+
1875+
// WARNING: Do not add storage here. The base class uses TrailingObjects.
1876+
private:
1877+
SpecializeAttr(SourceLoc atLoc, SourceRange Range,
1878+
TrailingWhereClause *clause,
1879+
bool exported,
1880+
SpecializationKind kind, GenericSignature specializedSignature,
1881+
DeclNameRef targetFunctionName, ArrayRef<Identifier> spiGroups,
1882+
ArrayRef<AvailableAttr *> availabilityAttrs,
1883+
size_t typeErasedParamsCount) :
1884+
AbstractSpecializeAttr(DeclAttrKind::Specialize, atLoc, Range, clause,
1885+
exported, kind, specializedSignature, targetFunctionName,
1886+
spiGroups, availabilityAttrs, typeErasedParamsCount) {}
1887+
1888+
public:
1889+
static SpecializeAttr *
1890+
create(ASTContext &Ctx, SourceLoc atLoc, SourceRange Range,
1891+
TrailingWhereClause *clause, bool exported,
1892+
SpecializationKind kind,
1893+
DeclNameRef targetFunctionName, ArrayRef<Identifier> spiGroups,
1894+
ArrayRef<AvailableAttr *> availabilityAttrs,
1895+
GenericSignature specializedSignature = nullptr);
1896+
1897+
static SpecializeAttr *create(ASTContext &ctx, bool exported,
1898+
SpecializationKind kind,
1899+
ArrayRef<Identifier> spiGroups,
1900+
ArrayRef<AvailableAttr *> availabilityAttrs,
1901+
GenericSignature specializedSignature,
1902+
DeclNameRef replacedFunction);
1903+
1904+
static SpecializeAttr *create(ASTContext &ctx, bool exported,
1905+
SpecializationKind kind,
1906+
ArrayRef<Identifier> spiGroups,
1907+
ArrayRef<AvailableAttr *> availabilityAttrs,
1908+
ArrayRef<Type> typeErasedParams,
1909+
GenericSignature specializedSignature,
1910+
DeclNameRef replacedFunction,
1911+
LazyMemberLoader *resolver, uint64_t data);
1912+
18591913
static bool classof(const DeclAttribute *DA) {
18601914
return DA->getKind() == DeclAttrKind::Specialize;
18611915
}
18621916

18631917
UNIMPLEMENTED_CLONE(SpecializeAttr)
18641918

1865-
bool isEquivalent(const SpecializeAttr *other, Decl *attachedTo) const;
1919+
bool isEquivalent(const SpecializeAttr *other, Decl *attachedTo) const {
1920+
return AbstractSpecializeAttr::isEquivalent(other, attachedTo);
1921+
}
18661922
};
18671923

1924+
/// The @specialized attribute.
1925+
class SpecializedAttr final : public AbstractSpecializeAttr ,
1926+
private SpecializeAttrTrailingObjects<SpecializeAttr> {
1927+
friend TrailingObjects;
1928+
friend AbstractSpecializeAttr;
1929+
1930+
// WARNING: Do not add storage here. The base class uses TrailingObjects.
1931+
private:
1932+
1933+
SpecializedAttr(SourceLoc atLoc, SourceRange Range,
1934+
TrailingWhereClause *clause,
1935+
bool exported,
1936+
SpecializationKind kind, GenericSignature specializedSignature,
1937+
DeclNameRef targetFunctionName, ArrayRef<Identifier> spiGroups,
1938+
ArrayRef<AvailableAttr *> availabilityAttrs,
1939+
size_t typeErasedParamsCount) :
1940+
AbstractSpecializeAttr(DeclAttrKind::Specialized, atLoc, Range, clause,
1941+
exported, kind, specializedSignature, targetFunctionName,
1942+
spiGroups, availabilityAttrs, typeErasedParamsCount) {}
1943+
1944+
public:
1945+
static SpecializedAttr *
1946+
create(ASTContext &Ctx, SourceLoc atLoc, SourceRange Range,
1947+
TrailingWhereClause *clause, bool exported,
1948+
SpecializationKind kind,
1949+
DeclNameRef targetFunctionName, ArrayRef<Identifier> spiGroups,
1950+
ArrayRef<AvailableAttr *> availabilityAttrs,
1951+
GenericSignature specializedSignature = nullptr);
1952+
1953+
static SpecializedAttr *create(ASTContext &ctx, bool exported,
1954+
SpecializationKind kind,
1955+
ArrayRef<Identifier> spiGroups,
1956+
ArrayRef<AvailableAttr *> availabilityAttrs,
1957+
GenericSignature specializedSignature,
1958+
DeclNameRef replacedFunction);
1959+
1960+
static SpecializedAttr *create(ASTContext &ctx, bool exported,
1961+
SpecializationKind kind,
1962+
ArrayRef<Identifier> spiGroups,
1963+
ArrayRef<AvailableAttr *> availabilityAttrs,
1964+
ArrayRef<Type> typeErasedParams,
1965+
GenericSignature specializedSignature,
1966+
DeclNameRef replacedFunction,
1967+
LazyMemberLoader *resolver, uint64_t data);
1968+
1969+
static bool classof(const DeclAttribute *DA) {
1970+
return DA->getKind() == DeclAttrKind::Specialized;
1971+
}
1972+
1973+
UNIMPLEMENTED_CLONE(SpecializedAttr)
1974+
1975+
bool isEquivalent(const SpecializedAttr *other, Decl *attachedTo) const {
1976+
return AbstractSpecializeAttr::isEquivalent(other, attachedTo);
1977+
}
1978+
};
1979+
1980+
template<typename Type>
1981+
const Type *AbstractSpecializeAttr::getSubclassTrailingObjects() const {
1982+
if (auto attr = dyn_cast<SpecializedAttr>(this)) {
1983+
return attr->getTrailingObjects<Type>();
1984+
}
1985+
if (auto attr = dyn_cast<SpecializeAttr>(this)) {
1986+
return attr->getTrailingObjects<Type>();
1987+
}
1988+
llvm_unreachable("unhandled AbstractSpecializeAttr subclass?");
1989+
}
1990+
1991+
1992+
18681993
class StorageRestrictionsAttr final
18691994
: public DeclAttribute,
18701995
private llvm::TrailingObjects<StorageRestrictionsAttr, Identifier> {

include/swift/AST/AvailabilityInference.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class AvailabilityInference {
5757
annotatedAvailableRange(const Decl *D);
5858

5959
static AvailabilityRange
60-
annotatedAvailableRangeForAttr(const Decl *D, const SpecializeAttr *attr,
60+
annotatedAvailableRangeForAttr(const Decl *D, const AbstractSpecializeAttr *attr,
6161
ASTContext &ctx);
6262

6363
/// For the attribute's introduction version, update the platform and version

include/swift/AST/DeclAttr.def

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -892,8 +892,13 @@ SIMPLE_DECL_ATTR(preEnumExtensibility, PreEnumExtensibility,
892892
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove | UnconstrainedInABIAttr,
893893
171)
894894
DECL_ATTR_FEATURE_REQUIREMENT(PreEnumExtensibility, ExtensibleAttribute)
895-
896-
LAST_DECL_ATTR(PreEnumExtensibility)
895+
896+
DECL_ATTR(specialized, Specialized,
897+
OnConstructor | OnFunc | OnAccessor,
898+
AllowMultipleAttributes | LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
899+
172)
900+
901+
LAST_DECL_ATTR(Specialized)
897902

898903
#undef DECL_ATTR_ALIAS
899904
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/DiagnosticsParse.def

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,22 +1746,26 @@ ERROR(attr_warn_unused_result_expected_rparen,none,
17461746

17471747
// _specialize
17481748
ERROR(attr_specialize_missing_colon,none,
1749-
"missing ':' after %0 in '_specialize' attribute", (StringRef))
1749+
"missing ':' after %0 in %select{'_specialize'|'specialized'}1 attribute", (StringRef, bool))
17501750

17511751
ERROR(attr_specialize_missing_comma,none,
1752-
"missing ',' in '_specialize' attribute", ())
1752+
"missing ',' in %select{'_specialize'|'specialized'}0 attribute", (bool))
17531753

17541754
ERROR(attr_specialize_unknown_parameter_name,none,
1755-
"unknown parameter %0 in '_specialize attribute'", (StringRef))
1755+
"unknown parameter %0 in %select{'_specialize'|'specialized'}1 attribute", (StringRef, bool))
1756+
ERROR(attr_specialize_unsupported_parameter_name,none,
1757+
"unsupported parameter %0 in 'specialized attribute'", (StringRef))
17561758

17571759
ERROR(attr_specialize_expected_bool_value,none,
1758-
"expected a boolean true or false value in '_specialize' attribute", ())
1760+
"expected a boolean true or false value in %select{'_specialize'|'specialized'}0 attribute", (bool))
17591761

17601762
ERROR(attr_specialize_missing_parameter_label_or_where_clause,none,
17611763
"expected a parameter label or a where clause in '_specialize' attribute", ())
1764+
ERROR(attr_specialized_missing_where_clause,none,
1765+
"expected a where clause in 'specialized' attribute", ())
17621766

17631767
ERROR(attr_specialize_parameter_already_defined,none,
1764-
"parameter '%0' was already defined in '_specialize' attribute", (StringRef))
1768+
"parameter '%0' was already defined in %select{'_specialize'|'specialized'}1 attribute", (StringRef, bool))
17651769

17661770
ERROR(attr_specialize_expected_partial_or_full,none,
17671771
"expected 'partial' or 'full' as values of the 'kind' parameter in '_specialize' attribute", ())

0 commit comments

Comments
 (0)