Skip to content

Commit 489508f

Browse files
authored
Merge pull request #59511 from CodaFi/strato-caster
2 parents 596fd9d + c35e122 commit 489508f

File tree

9 files changed

+398
-22
lines changed

9 files changed

+398
-22
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,7 @@ class ExtendedExistentialTypeShapeFlags {
899899
SpecialKind getSpecialKind() const {
900900
return SpecialKind((Data & SpecialKindMask) >> SpecialKindShift);
901901
}
902+
bool isOpaque() const { return getSpecialKind() == SpecialKind::None; }
902903
bool isClassConstrained() const {
903904
return getSpecialKind() == SpecialKind::Class;
904905
}

lib/IRGen/GenCast.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ void irgen::emitScalarExistentialDowncast(IRGenFunction &IGF,
848848
/// that the actual value isn't changed in any way, thus preserving its
849849
/// reference identity.
850850
///
851-
/// These restrictions are set by canUseScalarCheckedCastInstructions.
851+
/// These restrictions are set by \c canSILUseScalarCheckedCastInstructions.
852852
/// Essentially, both the source and target types must be one of:
853853
/// - a (possibly generic) concrete class type,
854854
/// - a class-bounded archetype,

lib/SIL/Utils/DynamicCasts.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,6 +1311,14 @@ bool swift::canSILUseScalarCheckedCastInstructions(SILModule &M,
13111311
bool swift::canIRGenUseScalarCheckedCastInstructions(SILModule &M,
13121312
CanType sourceFormalType,
13131313
CanType targetFormalType) {
1314+
// If the cast involves any kind of generalized existential we
1315+
// need to use the indirect-cast path to handle checking the extra
1316+
// constraints there as the scalar path does not (yet) know how to do it.
1317+
if (sourceFormalType->hasParameterizedExistential() ||
1318+
targetFormalType->hasParameterizedExistential()) {
1319+
return false;
1320+
}
1321+
13141322
// Look through one level of optionality on the source.
13151323
auto objectType = sourceFormalType;
13161324
if (auto type = objectType.getOptionalObjectType())

stdlib/public/runtime/Demangle.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,13 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
443443
// Just a simple composition of protocols.
444444
return proto_list;
445445
}
446+
case MetadataKind::ExtendedExistential: {
447+
// FIXME: Implement this by demangling the extended existential and
448+
// substituting the generalization arguments into the demangle tree.
449+
// For now, unconditional casts will report '<<< invalid type >>>' when
450+
// they fail.
451+
return nullptr;
452+
}
446453
case MetadataKind::ExistentialMetatype: {
447454
auto metatype = static_cast<const ExistentialMetatypeMetadata *>(type);
448455
auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType,

stdlib/public/runtime/DynamicCast.cpp

Lines changed: 189 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,10 +1695,56 @@ tryCastUnwrappingExistentialSource(
16951695
return tryCast(destLocation, destType,
16961696
srcInnerValue, srcInnerType,
16971697
destFailureType, srcFailureType,
1698-
takeOnSuccess & (srcInnerValue == srcValue),
1698+
takeOnSuccess && (srcInnerValue == srcValue),
16991699
mayDeferChecks);
17001700
}
17011701

1702+
static DynamicCastResult tryCastUnwrappingExtendedExistentialSource(
1703+
OpaqueValue *destLocation, const Metadata *destType, OpaqueValue *srcValue,
1704+
const Metadata *srcType, const Metadata *&destFailureType,
1705+
const Metadata *&srcFailureType, bool takeOnSuccess, bool mayDeferChecks) {
1706+
assert(srcType != destType);
1707+
assert(srcType->getKind() == MetadataKind::ExtendedExistential);
1708+
1709+
auto srcExistentialType = cast<ExtendedExistentialTypeMetadata>(srcType);
1710+
1711+
// Unpack the existential content
1712+
const Metadata *srcInnerType = nullptr;
1713+
OpaqueValue *srcInnerValue = nullptr;
1714+
switch (srcExistentialType->Shape->Flags.getSpecialKind()) {
1715+
case ExtendedExistentialTypeShape::SpecialKind::None: {
1716+
auto opaqueContainer =
1717+
reinterpret_cast<OpaqueExistentialContainer *>(srcValue);
1718+
srcInnerType = opaqueContainer->Type;
1719+
srcInnerValue = const_cast<OpaqueValue *>(opaqueContainer->projectValue());
1720+
break;
1721+
}
1722+
case ExtendedExistentialTypeShape::SpecialKind::Class: {
1723+
auto classContainer =
1724+
reinterpret_cast<ClassExistentialContainer *>(srcValue);
1725+
srcInnerType = swift_getObjectType((HeapObject *)classContainer->Value);
1726+
srcInnerValue = reinterpret_cast<OpaqueValue *>(&classContainer->Value);
1727+
break;
1728+
}
1729+
case ExtendedExistentialTypeShape::SpecialKind::Metatype: {
1730+
auto srcExistentialContainer =
1731+
reinterpret_cast<ExistentialMetatypeContainer *>(srcValue);
1732+
srcInnerType = swift_getMetatypeMetadata(srcExistentialContainer->Value);
1733+
srcInnerValue = reinterpret_cast<OpaqueValue *>(&srcExistentialContainer->Value);
1734+
break;
1735+
}
1736+
case ExtendedExistentialTypeShape::SpecialKind::ExplicitLayout: {
1737+
swift_unreachable("Explicit layout not yet implemented");
1738+
break;
1739+
}
1740+
}
1741+
1742+
srcFailureType = srcInnerType;
1743+
return tryCast(destLocation, destType, srcInnerValue, srcInnerType,
1744+
destFailureType, srcFailureType,
1745+
takeOnSuccess & (srcInnerValue == srcValue), mayDeferChecks);
1746+
}
1747+
17021748
static DynamicCastResult
17031749
tryCastUnwrappingExistentialMetatypeSource(
17041750
OpaqueValue *destLocation, const Metadata *destType,
@@ -1722,6 +1768,134 @@ tryCastUnwrappingExistentialMetatypeSource(
17221768
mayDeferChecks);
17231769
}
17241770

1771+
1772+
static DynamicCastResult tryCastToExtendedExistential(
1773+
OpaqueValue *destLocation, const Metadata *destType, OpaqueValue *srcValue,
1774+
const Metadata *srcType, const Metadata *&destFailureType,
1775+
const Metadata *&srcFailureType, bool takeOnSuccess, bool mayDeferChecks) {
1776+
assert(srcType != destType);
1777+
assert(destType->getKind() == MetadataKind::ExtendedExistential);
1778+
1779+
auto destExistentialType = cast<ExtendedExistentialTypeMetadata>(destType);
1780+
auto *destExistentialShape = destExistentialType->Shape;
1781+
const unsigned shapeArgumentCount =
1782+
destExistentialShape->getGenSigArgumentLayoutSizeInWords();
1783+
const Metadata *selfType = srcType;
1784+
1785+
// If we have a type expression to look into, unwrap as much metatype
1786+
// structure as possible so we can reach the type metadata for the 'Self'
1787+
// parameter.
1788+
if (destExistentialShape->Flags.hasTypeExpression()) {
1789+
Demangler dem;
1790+
auto *node = dem.demangleType(destExistentialShape->getTypeExpression()->name.get());
1791+
if (!node)
1792+
return DynamicCastResult::Failure;
1793+
1794+
while (node->getKind() == Demangle::Node::Kind::Type &&
1795+
node->getNumChildren() &&
1796+
node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype &&
1797+
node->getChild(0)->getNumChildren()) {
1798+
auto *metatypeMetadata = dyn_cast<MetatypeMetadata>(selfType);
1799+
if (!metatypeMetadata)
1800+
return DynamicCastResult::Failure;
1801+
1802+
selfType = metatypeMetadata->InstanceType;
1803+
node = node->getChild(0)->getChild(0);
1804+
}
1805+
1806+
// Make sure the thing we've pulled out at the end is a dependent
1807+
// generic parameter.
1808+
if (!(node->getKind() == Demangle::Node::Kind::Type &&
1809+
node->getNumChildren() &&
1810+
node->getChild(0)->getKind() ==
1811+
Demangle::Node::Kind::DependentGenericParamType))
1812+
return DynamicCastResult::Failure;
1813+
}
1814+
1815+
llvm::SmallVector<const void *, 8> allGenericArgsVec;
1816+
unsigned witnessesMark = 0;
1817+
{
1818+
// Line up the arguments to the requirement signature.
1819+
auto genArgs = destExistentialType->getGeneralizationArguments();
1820+
allGenericArgsVec.append(genArgs, genArgs + shapeArgumentCount);
1821+
// Tack on the `Self` argument.
1822+
allGenericArgsVec.push_back((const void *)selfType);
1823+
// Mark the point where the generic arguments end.
1824+
// _checkGenericRequirements is going to fill in a set of witness tables
1825+
// after that.
1826+
witnessesMark = allGenericArgsVec.size();
1827+
1828+
SubstGenericParametersFromMetadata substitutions(destExistentialShape,
1829+
allGenericArgsVec.data());
1830+
// Verify the requirements in the requirement signature against the
1831+
// arguments from the source value.
1832+
auto error = swift::_checkGenericRequirements(
1833+
destExistentialShape->getRequirementSignature().getRequirements(),
1834+
allGenericArgsVec,
1835+
[&substitutions](unsigned depth, unsigned index) {
1836+
return substitutions.getMetadata(depth, index);
1837+
},
1838+
[](const Metadata *type, unsigned index) -> const WitnessTable * {
1839+
swift_unreachable("Resolution of witness tables is not supported");
1840+
});
1841+
if (error)
1842+
return DynamicCastResult::Failure;
1843+
}
1844+
1845+
OpaqueValue *destBox = nullptr;
1846+
const WitnessTable **destWitnesses = nullptr;
1847+
switch (destExistentialShape->Flags.getSpecialKind()) {
1848+
case ExtendedExistentialTypeShape::SpecialKind::None: {
1849+
auto destExistential =
1850+
reinterpret_cast<OpaqueExistentialContainer *>(destLocation);
1851+
1852+
// Allocate a box and fill in the type information.
1853+
destExistential->Type = srcType;
1854+
destBox = srcType->allocateBoxForExistentialIn(&destExistential->Buffer);
1855+
destWitnesses = destExistential->getWitnessTables();
1856+
break;
1857+
}
1858+
case ExtendedExistentialTypeShape::SpecialKind::Class: {
1859+
auto destExistential =
1860+
reinterpret_cast<ClassExistentialContainer *>(destLocation);
1861+
destBox = reinterpret_cast<OpaqueValue *>(&destExistential->Value);
1862+
destWitnesses = destExistential->getWitnessTables();
1863+
break;
1864+
}
1865+
case ExtendedExistentialTypeShape::SpecialKind::Metatype: {
1866+
auto destExistential =
1867+
reinterpret_cast<ExistentialMetatypeContainer *>(destLocation);
1868+
destBox = reinterpret_cast<OpaqueValue *>(&destExistential->Value);
1869+
destWitnesses = destExistential->getWitnessTables();
1870+
break;
1871+
}
1872+
case ExtendedExistentialTypeShape::SpecialKind::ExplicitLayout:
1873+
swift_unreachable("Witnesses for explicit layout not yet implemented");
1874+
}
1875+
1876+
// Fill in the trailing set of witness tables.
1877+
const unsigned numWitnessTables = allGenericArgsVec.size() - witnessesMark;
1878+
assert(numWitnessTables ==
1879+
llvm::count_if(destExistentialShape->getRequirementSignature().getRequirements(),
1880+
[](const auto &req) -> bool {
1881+
return req.getKind() ==
1882+
GenericRequirementKind::Protocol;
1883+
}));
1884+
for (unsigned i = 0; i < numWitnessTables; ++i) {
1885+
const auto witness = i + witnessesMark;
1886+
destWitnesses[i] =
1887+
reinterpret_cast<const WitnessTable *>(allGenericArgsVec[witness]);
1888+
}
1889+
1890+
if (takeOnSuccess) {
1891+
srcType->vw_initializeWithTake(destBox, srcValue);
1892+
return DynamicCastResult::SuccessViaTake;
1893+
} else {
1894+
srcType->vw_initializeWithCopy(destBox, srcValue);
1895+
return DynamicCastResult::SuccessViaCopy;
1896+
}
1897+
}
1898+
17251899
/******************************************************************************/
17261900
/**************************** Opaque Destination ******************************/
17271901
/******************************************************************************/
@@ -2006,12 +2180,14 @@ static tryCastFunctionType *selectCasterForDest(const Metadata *destType) {
20062180
swift_unreachable(
20072181
"Unknown existential type representation in dynamic cast dispatch");
20082182
}
2183+
case MetadataKind::ExtendedExistential:
2184+
return tryCastToExtendedExistential;
20092185
case MetadataKind::Metatype:
2010-
return tryCastToMetatype;
2011-
case MetadataKind::ObjCClassWrapper:
2186+
return tryCastToMetatype;
2187+
case MetadataKind::ObjCClassWrapper:
20122188
return tryCastToObjectiveCClass;
20132189
case MetadataKind::ExistentialMetatype:
2014-
return tryCastToExistentialMetatype;
2190+
return tryCastToExistentialMetatype;
20152191
case MetadataKind::HeapLocalVariable:
20162192
case MetadataKind::HeapGenericLocalVariable:
20172193
case MetadataKind::ErrorObject:
@@ -2169,6 +2345,15 @@ tryCast(
21692345
break;
21702346
}
21712347

2348+
case MetadataKind::ExtendedExistential: {
2349+
auto subcastResult = tryCastUnwrappingExtendedExistentialSource(
2350+
destLocation, destType, srcValue, srcType, destFailureType,
2351+
srcFailureType, takeOnSuccess, mayDeferChecks);
2352+
if (isSuccess(subcastResult)) {
2353+
return subcastResult;
2354+
}
2355+
break;
2356+
}
21722357
default:
21732358
break;
21742359
}

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2269,7 +2269,7 @@ static void installGetClassHook() {
22692269
unsigned SubstGenericParametersFromMetadata::
22702270
buildDescriptorPath(const ContextDescriptor *context,
22712271
Demangler &borrowFrom) const {
2272-
assert(sourceIsMetadata);
2272+
assert(sourceKind == SourceKind::Metadata);
22732273

22742274
// Terminating condition: we don't have a context.
22752275
if (!context)
@@ -2360,20 +2360,59 @@ buildEnvironmentPath(
23602360
return totalKeyParamCount;
23612361
}
23622362

2363+
unsigned SubstGenericParametersFromMetadata::buildShapePath(
2364+
const TargetExtendedExistentialTypeShape<InProcess> *shape) const {
2365+
unsigned totalParamCount = 0;
2366+
2367+
auto genSig = shape->getGeneralizationSignature();
2368+
if (!genSig.getParams().empty()) {
2369+
totalParamCount += genSig.getParams().size();
2370+
descriptorPath.push_back(PathElement{genSig.getParams(),
2371+
totalParamCount,
2372+
/*numKeyGenericParamsInParent*/ 0,
2373+
(unsigned)genSig.getParams().size(),
2374+
/*hasNonKeyGenericParams*/ false});
2375+
}
2376+
2377+
const unsigned genSigParamCount = genSig.getParams().size();
2378+
auto reqSig = shape->getRequirementSignature();
2379+
assert(reqSig.getParams().size() > genSig.getParams().size());
2380+
{
2381+
auto remainingParams = reqSig.getParams().drop_front(genSig.getParams().size());
2382+
totalParamCount += remainingParams.size();
2383+
descriptorPath.push_back(PathElement{remainingParams,
2384+
totalParamCount,
2385+
genSigParamCount,
2386+
(unsigned)remainingParams.size(),
2387+
/*hasNonKeyGenericParams*/ false});
2388+
}
2389+
2390+
// All parameters in this signature are key parameters.
2391+
return totalParamCount;
2392+
}
2393+
23632394
void SubstGenericParametersFromMetadata::setup() const {
23642395
if (!descriptorPath.empty())
23652396
return;
23662397

2367-
if (sourceIsMetadata && baseContext) {
2398+
switch (sourceKind) {
2399+
case SourceKind::Metadata: {
2400+
assert(baseContext);
23682401
DemanglerForRuntimeTypeResolution<StackAllocatedDemangler<2048>> demangler;
23692402
numKeyGenericParameters = buildDescriptorPath(baseContext, demangler);
23702403
return;
23712404
}
2372-
2373-
if (!sourceIsMetadata && environment) {
2405+
case SourceKind::Environment: {
2406+
assert(environment);
23742407
numKeyGenericParameters = buildEnvironmentPath(environment);
23752408
return;
23762409
}
2410+
case SourceKind::Shape: {
2411+
assert(shape);
2412+
numKeyGenericParameters = buildShapePath(shape);
2413+
return;
2414+
}
2415+
}
23772416
}
23782417

23792418
const Metadata *

0 commit comments

Comments
 (0)