@@ -140,6 +140,10 @@ template <class T> struct FullMetadata : T::HeaderType, T {
140
140
FullMetadata () = default ;
141
141
constexpr FullMetadata (const HeaderType &header, const T &metadata)
142
142
: HeaderType(header), T(metadata) {}
143
+
144
+ template <class ... Args>
145
+ constexpr FullMetadata (const HeaderType &header, Args &&...metadataArgs)
146
+ : HeaderType(header), T(std::forward<Args>(metadataArgs)...) {}
143
147
};
144
148
145
149
// / Given a canonical metadata pointer, produce the adjusted metadata pointer.
@@ -1571,7 +1575,14 @@ enum class ExistentialTypeRepresentation {
1571
1575
Error,
1572
1576
};
1573
1577
1574
- // / The structure of existential type metadata.
1578
+ // / The structure of type metadata for simple existential types which
1579
+ // / don't require an extended existential descriptor:
1580
+ // /
1581
+ // / - They are existential over a single type T.
1582
+ // / - Their head type is that type T.
1583
+ // / - Their existential constraints are a composition of protocol
1584
+ // / requirements, superclass constraints, and possibly a class
1585
+ // / layout constraint on T.
1575
1586
template <typename Runtime>
1576
1587
struct TargetExistentialTypeMetadata
1577
1588
: TargetMetadata<Runtime>,
@@ -1689,6 +1700,357 @@ struct TargetExistentialTypeMetadata
1689
1700
using ExistentialTypeMetadata
1690
1701
= TargetExistentialTypeMetadata<InProcess>;
1691
1702
1703
+ // / A description of the shape of an existential type.
1704
+ // /
1705
+ // / An existential type has the general form:
1706
+ // / \exists <signature> . <type>
1707
+ // /
1708
+ // / The signature is called the requirement signature. In the most
1709
+ // / common case (the only one Swift currently supports), it has exactly
1710
+ // / one type parameter. The types and conformances required by this
1711
+ // / signature must be stored in the existential container at runtime.
1712
+ // /
1713
+ // / The type is called the type (sub)expression, and it is expressed
1714
+ // / in terms of the type parameters introduced by the requirement
1715
+ // / signature. It is required to name each of the type parameters in
1716
+ // / an identity position (outside of the base type of a member type
1717
+ // / expression). In the most common case, it is the unique type
1718
+ // / parameter type. Swift currently only supports existential
1719
+ // / subexpressions that are either the (unique) type parameter or
1720
+ // / a metatype thereof (possibly multiply-derived).
1721
+ // /
1722
+ // / In order to efficiently support generic substitution of the
1723
+ // / constraints of existential types, extended existential type
1724
+ // / descriptors represent a generalizable form of the existential:
1725
+ // / \forall <gen sig> . \exists <req sig> . <type>
1726
+ // /
1727
+ // / The new signature is called the generalization signature of the
1728
+ // / shape. All concrete references to types within the requirement
1729
+ // / signature and head type which are not expressed in terms of
1730
+ // / the requirement signature are replaced with type parameters freshly
1731
+ // / added to the generalization signature. Any given existential type
1732
+ // / is then a specialization of this generalization.
1733
+ // /
1734
+ // / For example, the existential type
1735
+ // / \exists <T: Collection where T.Element == Int> . T
1736
+ // / is generalized as
1737
+ // / \forall <U> . \exists <T: Collection where T.Element == U> . T
1738
+ // / and is the application of this generalization at <Int>.
1739
+ // /
1740
+ // / The soundness condition on this is that the generalization
1741
+ // / signatures, requirement signatures, and head types must be
1742
+ // / identical for any two existential types for which a generic
1743
+ // / substitution can carry one to the other.
1744
+ // /
1745
+ // / Only particularly complex existential types are represented with
1746
+ // / an explicit existential shape. Types which are a simple composition
1747
+ // / of layout, superclass, and unconstrained protocol constraints on
1748
+ // / an opaque or (metatype-of)+-opaque are represented with
1749
+ // / ExistentialTypeMetadata or ExistentialMetatypeMetadata.
1750
+ // / Types which *can* be represented with those classes *must*
1751
+ // / be represented with them.
1752
+ template <typename Runtime>
1753
+ struct TargetExtendedExistentialTypeShape
1754
+ : swift::ABI::TrailingObjects<
1755
+ TargetExtendedExistentialTypeShape<Runtime>,
1756
+ // Optional generalization signature header
1757
+ TargetGenericContextDescriptorHeader<Runtime>,
1758
+ // Optional type subexpression
1759
+ TargetRelativeDirectPointer<Runtime, const char , /* nullable*/ false >,
1760
+ // Optional suggested value witnesses
1761
+ TargetRelativeIndirectablePointer<Runtime, const TargetValueWitnessTable<Runtime>,
1762
+ /* nullable*/ false >,
1763
+ // Parameters for requirement signature, followed by parameters
1764
+ // for generalization signature
1765
+ GenericParamDescriptor,
1766
+ // Requirements for requirement signature, followed by requirements
1767
+ // for generalization signature
1768
+ TargetGenericRequirementDescriptor<Runtime>> {
1769
+ private:
1770
+ using RelativeStringPointer =
1771
+ TargetRelativeDirectPointer<Runtime, const char , /* nullable*/ false >;
1772
+ using RelativeValueWitnessTablePointer =
1773
+ TargetRelativeIndirectablePointer<Runtime,
1774
+ const TargetValueWitnessTable<Runtime>,
1775
+ /* nullable*/ false >;
1776
+ using TrailingObjects =
1777
+ swift::ABI::TrailingObjects<
1778
+ TargetExtendedExistentialTypeShape<Runtime>,
1779
+ TargetGenericContextDescriptorHeader<Runtime>,
1780
+ RelativeStringPointer,
1781
+ RelativeValueWitnessTablePointer,
1782
+ GenericParamDescriptor,
1783
+ TargetGenericRequirementDescriptor<Runtime>>;
1784
+ friend TrailingObjects;
1785
+
1786
+ template <typename T>
1787
+ using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
1788
+
1789
+ size_t numTrailingObjects (OverloadToken<TargetGenericContextDescriptorHeader<Runtime>>) const {
1790
+ return Flags.hasGeneralizationSignature ();
1791
+ }
1792
+
1793
+ size_t numTrailingObjects (OverloadToken<RelativeStringPointer>) const {
1794
+ return Flags.hasTypeExpression ();
1795
+ }
1796
+
1797
+ size_t numTrailingObjects (OverloadToken<RelativeValueWitnessTablePointer>) const {
1798
+ return Flags.hasSuggestedValueWitnesses ();
1799
+ }
1800
+
1801
+ size_t numTrailingObjects (OverloadToken<GenericParamDescriptor>) const {
1802
+ return (Flags.hasImplicitReqSigParams () ? 0 : getNumReqSigParams ())
1803
+ + (Flags.hasImplicitGenSigParams () ? 0 : getNumGenSigParams ());
1804
+ }
1805
+
1806
+ size_t numTrailingObjects (OverloadToken<GenericRequirementDescriptor>) const {
1807
+ return getNumGenSigRequirements () + getNumReqSigRequirements ();
1808
+ }
1809
+
1810
+ const TargetGenericContextDescriptorHeader<Runtime> *
1811
+ getGenSigHeader () const {
1812
+ assert (hasGeneralizationSignature ());
1813
+ return this ->template getTrailingObjects <
1814
+ TargetGenericContextDescriptorHeader<Runtime>>();
1815
+ }
1816
+
1817
+ public:
1818
+ using SpecialKind = ExtendedExistentialTypeShapeFlags::SpecialKind;
1819
+
1820
+ // / Flags for the existential shape.
1821
+ ExtendedExistentialTypeShapeFlags Flags;
1822
+
1823
+ // / The header describing the requirement signature of the existential.
1824
+ TargetGenericContextDescriptorHeader<Runtime> ReqSigHeader;
1825
+
1826
+ RuntimeGenericSignature getRequirementSignature () const {
1827
+ return {ReqSigHeader, getReqSigParams (), getReqSigRequirements ()};
1828
+ }
1829
+
1830
+ unsigned getNumReqSigParams () const {
1831
+ return ReqSigHeader.NumParams ;
1832
+ }
1833
+
1834
+ const GenericParamDescriptor *getReqSigParams () const {
1835
+ return Flags.hasImplicitReqSigParams ()
1836
+ ? ImplicitGenericParamDescriptors
1837
+ : this ->template getTrailingObjects <GenericParamDescriptor>();
1838
+ }
1839
+
1840
+ unsigned getNumReqSigRequirements () const {
1841
+ return ReqSigHeader.NumRequirements ;
1842
+ }
1843
+
1844
+ const TargetGenericRequirementDescriptor<Runtime> *
1845
+ getReqSigRequirements () const {
1846
+ return this ->template getTrailingObjects <
1847
+ TargetGenericRequirementDescriptor<Runtime>>();
1848
+ }
1849
+
1850
+ // / The type expression of the existential, as a symbolic mangled type
1851
+ // / string. Must be null if the header is just the (single)
1852
+ // / requirement type parameter.
1853
+ TargetPointer<Runtime, const char > getTypeExpression () const {
1854
+ return Flags.hasTypeExpression ()
1855
+ ? this ->template getTrailingObjects <RelativeStringPointer>()->get ()
1856
+ : nullptr ;
1857
+ }
1858
+
1859
+ bool isTypeExpressionOpaque () const {
1860
+ return !Flags.hasTypeExpression ();
1861
+ }
1862
+
1863
+ // / The suggested value witness table for the existential.
1864
+ // / Required if:
1865
+ // / - the special kind is SpecialKind::ExplicitLayout
1866
+ // / - the special kind is SpecialKind::None and the type head
1867
+ // / isn't opaque
1868
+ TargetPointer<Runtime, const TargetValueWitnessTable<Runtime>>
1869
+ getSuggestedValueWitnesses () const {
1870
+ return Flags.hasSuggestedValueWitnesses ()
1871
+ ? this ->template getTrailingObjects <
1872
+ RelativeValueWitnessTablePointer>()->get ()
1873
+ : nullptr ;
1874
+ }
1875
+
1876
+ // / Return the amount of space used in the existential container
1877
+ // / for storing the existential arguments (including both the
1878
+ // / type metadata and the conformances).
1879
+ unsigned getContainerSignatureLayoutSizeInWords () const {
1880
+ unsigned rawSize = ReqSigHeader.getArgumentLayoutSizeInWords ();
1881
+ switch (Flags.getSpecialKind ()) {
1882
+ // The default and explicitly-sized-value-layout cases don't optimize
1883
+ // the storage of the signature.
1884
+ case SpecialKind::None:
1885
+ case SpecialKind::ExplicitLayout:
1886
+ return rawSize;
1887
+
1888
+ // The class and metadata cases don't store type metadata.
1889
+ case SpecialKind::Class:
1890
+ case SpecialKind::Metatype:
1891
+ // Requirement signatures won't have non-key parameters.
1892
+ return rawSize - ReqSigHeader.NumParams ;
1893
+ }
1894
+
1895
+ // Assume any future cases don't optimize metadata storage.
1896
+ return rawSize;
1897
+ }
1898
+
1899
+ bool hasGeneralizationSignature () const {
1900
+ return Flags.hasGeneralizationSignature ();
1901
+ }
1902
+
1903
+ RuntimeGenericSignature getGeneralizationSignature () const {
1904
+ if (!hasGeneralizationSignature ()) return RuntimeGenericSignature ();
1905
+ return {*getGenSigHeader (), getGenSigParams (), getGenSigRequirements ()};
1906
+ }
1907
+
1908
+ unsigned getNumGenSigParams () const {
1909
+ return hasGeneralizationSignature ()
1910
+ ? getGenSigHeader ()->NumParams : 0 ;
1911
+ }
1912
+
1913
+ const GenericParamDescriptor *getGenSigParams () const {
1914
+ assert (hasGeneralizationSignature ());
1915
+ if (Flags.hasImplicitGenSigParams ())
1916
+ return ImplicitGenericParamDescriptors;
1917
+ auto base = this ->template getTrailingObjects <GenericParamDescriptor>();
1918
+ if (!Flags.hasImplicitReqSigParams ())
1919
+ base += getNumReqSigParams ();
1920
+ return base;
1921
+ }
1922
+
1923
+ unsigned getNumGenSigRequirements () const {
1924
+ return hasGeneralizationSignature ()
1925
+ ? getGenSigHeader ()->NumRequirements : 0 ;
1926
+ }
1927
+
1928
+ const TargetGenericRequirementDescriptor<Runtime> *
1929
+ getGenSigRequirements () const {
1930
+ assert (hasGeneralizationSignature ());
1931
+ return getReqSigRequirements () + ReqSigHeader.NumRequirements ;
1932
+ }
1933
+
1934
+ // / Return the amount of space used in ExtendedExistentialTypeMetadata
1935
+ // / for this shape to store the generalization arguments.
1936
+ unsigned getGenSigArgumentLayoutSizeInWords () const {
1937
+ if (!hasGeneralizationSignature ()) return 0 ;
1938
+ return getGenSigHeader ()->getArgumentLayoutSizeInWords ();
1939
+ }
1940
+ };
1941
+ using ExtendedExistentialTypeShape
1942
+ = TargetExtendedExistentialTypeShape<InProcess>;
1943
+
1944
+ // / A hash which is guaranteed (ignoring a weakness in the
1945
+ // / selected cryptographic hash algorithm) to be unique for the
1946
+ // / source string. Cryptographic hashing is reasonable to use
1947
+ // / for certain kinds of complex uniquing performed by the
1948
+ // / runtime when the representation being uniqued would otherwise
1949
+ // / be prohibitively difficult to hash and compare, such as a
1950
+ // / generic signature.
1951
+ // /
1952
+ // / The hash is expected to be computed at compile time and simply
1953
+ // / trusted at runtime. We are therefore not concerned about
1954
+ // / malicious collisions: an attacker would have to control the
1955
+ // / program text, and there is nothing they can accomplish from a
1956
+ // / hash collision that they couldn't do more easily by just changing
1957
+ // / the program to do what they want. We just want a hash with
1958
+ // / minimal chance of a birthday-problem collision. As long as
1959
+ // / we use a cryptographic hash algorithm, even a 64-bit hash would
1960
+ // / probably do the trick just fine, since the number of objects
1961
+ // / being uniqued will be far less than 2^32. Still, to stay on the
1962
+ // / safe side, we use a 128-bit hash; the additional 8 bytes is
1963
+ // / fairly marginal compared to the size of (e.g.) even the smallest
1964
+ // / existential shape.
1965
+ // /
1966
+ // / We'd like to use BLAKE3 for this, but pending acceptance of
1967
+ // / that into LLVM, we're using SHA-256. We simply truncaate the
1968
+ // / hash to the desired length.
1969
+ struct UniqueHash {
1970
+ static_assert (NumBytes_UniqueHash % sizeof (uint32_t ) == 0 ,
1971
+ " NumBytes_UniqueHash not a multiple of 4" );
1972
+ enum { NumChunks = NumBytes_UniqueHash / sizeof (uint32_t ) };
1973
+
1974
+ uint32_t Data[NumChunks];
1975
+
1976
+ friend bool operator ==(const UniqueHash &lhs, const UniqueHash &rhs) {
1977
+ for (unsigned i = 0 ; i != NumChunks; ++i)
1978
+ if (lhs.Data [i] != rhs.Data [i])
1979
+ return false ;
1980
+ return true ;
1981
+ }
1982
+
1983
+ friend uint32_t hash_value (const UniqueHash &hash) {
1984
+ // It's a cryptographic hash, so there's no point in merging
1985
+ // hash data from multiple chunks.
1986
+ return hash.Data [0 ];
1987
+ }
1988
+ };
1989
+
1990
+ // / A descriptor for an extended existential type descriptor which
1991
+ // / needs to be uniqued at runtime.
1992
+ template <typename Runtime>
1993
+ struct TargetNonUniqueExtendedExistentialTypeShape {
1994
+ // / A reference to memory that can be used to cache a globally-unique
1995
+ // / descriptor for this existential shape.
1996
+ TargetRelativeDirectPointer<Runtime,
1997
+ std::atomic<ConstTargetMetadataPointer<Runtime,
1998
+ TargetExtendedExistentialTypeShape>>> UniqueCache;
1999
+
2000
+ // / A hash of the mangling of the existential shape.
2001
+ // /
2002
+ // / TODO: describe that mangling here
2003
+ UniqueHash Hash;
2004
+
2005
+ // / The local copy of the existential shape descriptor.
2006
+ TargetExtendedExistentialTypeShape<Runtime> LocalCopy;
2007
+ };
2008
+ using NonUniqueExtendedExistentialTypeShape
2009
+ = TargetNonUniqueExtendedExistentialTypeShape<InProcess>;
2010
+
2011
+ // / The structure of type metadata for existential types which require
2012
+ // / an extended existential descriptor.
2013
+ // /
2014
+ // / An extended existential type metadata is a concrete application of
2015
+ // / an extended existential descriptor to its generalization arguments,
2016
+ // / which there may be none of. See ExtendedExistentialDescriptor.
2017
+ template <typename Runtime>
2018
+ struct TargetExtendedExistentialTypeMetadata
2019
+ : TargetMetadata<Runtime>,
2020
+ swift::ABI::TrailingObjects<
2021
+ TargetExtendedExistentialTypeMetadata<Runtime>,
2022
+ ConstTargetPointer<Runtime, void >> {
2023
+ private:
2024
+ using TrailingObjects =
2025
+ swift::ABI::TrailingObjects<
2026
+ TargetExtendedExistentialTypeMetadata<Runtime>,
2027
+ ConstTargetPointer<Runtime, void >>;
2028
+ friend TrailingObjects;
2029
+
2030
+ template <typename T>
2031
+ using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
2032
+
2033
+ size_t numTrailingObjects (OverloadToken<ConstTargetPointer<Runtime, void >>) const {
2034
+ return Shape->getGenSigLayoutSizeInWords ();
2035
+ }
2036
+
2037
+ public:
2038
+ explicit constexpr
2039
+ TargetExtendedExistentialTypeMetadata (const ExtendedExistentialTypeShape *shape)
2040
+ : TargetMetadata<Runtime>(MetadataKind::ExtendedExistential),
2041
+ Shape (shape) {}
2042
+
2043
+ TargetSignedPointer<Runtime, const ExtendedExistentialTypeShape *
2044
+ __ptrauth_swift_nonunique_extended_existential_type_shape>
2045
+ Shape;
2046
+
2047
+ ConstTargetPointer<Runtime, void > const *getGeneralizationArguments () const {
2048
+ return this ->template getTrailingObjects <ConstTargetPointer<Runtime, void >>();
2049
+ }
2050
+ };
2051
+ using ExtendedExistentialTypeMetadata
2052
+ = TargetExtendedExistentialTypeMetadata<InProcess>;
2053
+
1692
2054
// / The basic layout of an existential metatype type.
1693
2055
template <typename Runtime>
1694
2056
struct TargetExistentialMetatypeContainer {
0 commit comments