@@ -140,6 +140,10 @@ template <class T> struct FullMetadata : T::HeaderType, T {
140140 FullMetadata () = default ;
141141 constexpr FullMetadata (const HeaderType &header, const T &metadata)
142142 : 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)...) {}
143147};
144148
145149// / Given a canonical metadata pointer, produce the adjusted metadata pointer.
@@ -1571,7 +1575,14 @@ enum class ExistentialTypeRepresentation {
15711575 Error,
15721576};
15731577
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.
15751586template <typename Runtime>
15761587struct TargetExistentialTypeMetadata
15771588 : TargetMetadata<Runtime>,
@@ -1689,6 +1700,357 @@ struct TargetExistentialTypeMetadata
16891700using ExistentialTypeMetadata
16901701 = TargetExistentialTypeMetadata<InProcess>;
16911702
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+
16922054// / The basic layout of an existential metatype type.
16932055template <typename Runtime>
16942056struct TargetExistentialMetatypeContainer {
0 commit comments