Skip to content

Commit 34445a0

Browse files
authored
Merge pull request #59455 from CodaFi/dyno-saur
Implement Casting For Extended Existentials
2 parents d0b2f41 + 9e4670a commit 34445a0

File tree

7 files changed

+356
-21
lines changed

7 files changed

+356
-21
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
}

stdlib/public/runtime/Demangle.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,9 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
443443
// Just a simple composition of protocols.
444444
return proto_list;
445445
}
446+
case MetadataKind::ExtendedExistential: {
447+
swift_unreachable("Extended existentials not supported");
448+
}
446449
case MetadataKind::ExistentialMetatype: {
447450
auto metatype = static_cast<const ExistentialMetatypeMetadata *>(type);
448451
auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType,

stdlib/public/runtime/DynamicCast.cpp

Lines changed: 158 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,10 +1696,56 @@ tryCastUnwrappingExistentialSource(
16961696
return tryCast(destLocation, destType,
16971697
srcInnerValue, srcInnerType,
16981698
destFailureType, srcFailureType,
1699-
takeOnSuccess & (srcInnerValue == srcValue),
1699+
takeOnSuccess && (srcInnerValue == srcValue),
17001700
mayDeferChecks);
17011701
}
17021702

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

1772+
1773+
static DynamicCastResult tryCastToExtendedExistential(
1774+
OpaqueValue *destLocation, const Metadata *destType, OpaqueValue *srcValue,
1775+
const Metadata *srcType, const Metadata *&destFailureType,
1776+
const Metadata *&srcFailureType, bool takeOnSuccess, bool mayDeferChecks) {
1777+
assert(srcType != destType);
1778+
assert(destType->getKind() == MetadataKind::ExtendedExistential);
1779+
1780+
auto destExistentialType = cast<ExtendedExistentialTypeMetadata>(destType);
1781+
auto *destExistentialShape = destExistentialType->Shape;
1782+
const unsigned shapeArgumentCount =
1783+
destExistentialShape->getGenSigArgumentLayoutSizeInWords();
1784+
1785+
llvm::SmallVector<const void *, 8> allGenericArgsVec;
1786+
unsigned witnessesMark = 0;
1787+
{
1788+
// Line up the arguments to the requirement signature.
1789+
auto genArgs = destExistentialType->getGeneralizationArguments();
1790+
allGenericArgsVec.append(genArgs, genArgs + shapeArgumentCount);
1791+
// Tack on the `Self` argument.
1792+
allGenericArgsVec.push_back((const void *)srcType);
1793+
// Mark the point where the generic arguments end.
1794+
// _checkGenericRequirements is going to fill in a set of witness tables
1795+
// after that.
1796+
witnessesMark = allGenericArgsVec.size();
1797+
1798+
SubstGenericParametersFromMetadata substitutions(destExistentialShape,
1799+
allGenericArgsVec.data());
1800+
// Verify the requirements in the requirement signature against the
1801+
// arguments from the source value.
1802+
auto error = swift::_checkGenericRequirements(
1803+
destExistentialShape->getRequirementSignature().getRequirements(),
1804+
allGenericArgsVec,
1805+
[&substitutions](unsigned depth, unsigned index) {
1806+
return substitutions.getMetadata(depth, index);
1807+
},
1808+
[](const Metadata *type, unsigned index) -> const WitnessTable * {
1809+
swift_unreachable("Resolution of witness tables is not supported");
1810+
});
1811+
if (error)
1812+
return DynamicCastResult::Failure;
1813+
}
1814+
1815+
OpaqueValue *destBox = nullptr;
1816+
const WitnessTable **destWitnesses = nullptr;
1817+
switch (destExistentialShape->Flags.getSpecialKind()) {
1818+
case ExtendedExistentialTypeShape::SpecialKind::None: {
1819+
auto destExistential =
1820+
reinterpret_cast<OpaqueExistentialContainer *>(destLocation);
1821+
1822+
// Allocate a box and fill in the type information.
1823+
destExistential->Type = srcType;
1824+
destBox = srcType->allocateBoxForExistentialIn(&destExistential->Buffer);
1825+
destWitnesses = destExistential->getWitnessTables();
1826+
break;
1827+
}
1828+
case ExtendedExistentialTypeShape::SpecialKind::Class: {
1829+
auto destExistential =
1830+
reinterpret_cast<ClassExistentialContainer *>(destLocation);
1831+
destBox = reinterpret_cast<OpaqueValue *>(&destExistential->Value);
1832+
destWitnesses = destExistential->getWitnessTables();
1833+
break;
1834+
}
1835+
case ExtendedExistentialTypeShape::SpecialKind::Metatype: {
1836+
auto destExistential =
1837+
reinterpret_cast<ExistentialMetatypeContainer *>(destLocation);
1838+
destBox = reinterpret_cast<OpaqueValue *>(&destExistential->Value);
1839+
destWitnesses = destExistential->getWitnessTables();
1840+
break;
1841+
}
1842+
case ExtendedExistentialTypeShape::SpecialKind::ExplicitLayout:
1843+
swift_unreachable("Witnesses for explicit layout not yet implemented");
1844+
}
1845+
1846+
// Fill in the trailing set of witness tables.
1847+
const unsigned numWitnessTables = allGenericArgsVec.size() - witnessesMark;
1848+
assert(numWitnessTables ==
1849+
llvm::count_if(destExistentialShape->getRequirementSignature().getRequirements(),
1850+
[](const auto &req) -> bool {
1851+
return req.getKind() ==
1852+
GenericRequirementKind::Protocol;
1853+
}));
1854+
for (unsigned i = 0; i < numWitnessTables; ++i) {
1855+
const auto witness = i + witnessesMark;
1856+
destWitnesses[i] =
1857+
reinterpret_cast<const WitnessTable *>(allGenericArgsVec[witness]);
1858+
}
1859+
1860+
if (takeOnSuccess) {
1861+
srcType->vw_initializeWithTake(destBox, srcValue);
1862+
return DynamicCastResult::SuccessViaTake;
1863+
} else {
1864+
srcType->vw_initializeWithCopy(destBox, srcValue);
1865+
return DynamicCastResult::SuccessViaCopy;
1866+
}
1867+
}
1868+
17261869
/******************************************************************************/
17271870
/**************************** Opaque Destination ******************************/
17281871
/******************************************************************************/
@@ -2007,12 +2150,14 @@ static tryCastFunctionType *selectCasterForDest(const Metadata *destType) {
20072150
swift_unreachable(
20082151
"Unknown existential type representation in dynamic cast dispatch");
20092152
}
2153+
case MetadataKind::ExtendedExistential:
2154+
return tryCastToExtendedExistential;
20102155
case MetadataKind::Metatype:
2011-
return tryCastToMetatype;
2012-
case MetadataKind::ObjCClassWrapper:
2156+
return tryCastToMetatype;
2157+
case MetadataKind::ObjCClassWrapper:
20132158
return tryCastToObjectiveCClass;
20142159
case MetadataKind::ExistentialMetatype:
2015-
return tryCastToExistentialMetatype;
2160+
return tryCastToExistentialMetatype;
20162161
case MetadataKind::HeapLocalVariable:
20172162
case MetadataKind::HeapGenericLocalVariable:
20182163
case MetadataKind::ErrorObject:
@@ -2170,6 +2315,15 @@ tryCast(
21702315
break;
21712316
}
21722317

2318+
case MetadataKind::ExtendedExistential: {
2319+
auto subcastResult = tryCastUnwrappingExtendedExistentialSource(
2320+
destLocation, destType, srcValue, srcType, destFailureType,
2321+
srcFailureType, takeOnSuccess, mayDeferChecks);
2322+
if (isSuccess(subcastResult)) {
2323+
return subcastResult;
2324+
}
2325+
break;
2326+
}
21732327
default:
21742328
break;
21752329
}

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2280,7 +2280,7 @@ static void installGetClassHook() {
22802280
unsigned SubstGenericParametersFromMetadata::
22812281
buildDescriptorPath(const ContextDescriptor *context,
22822282
Demangler &borrowFrom) const {
2283-
assert(sourceIsMetadata);
2283+
assert(sourceKind == SourceKind::Metadata);
22842284

22852285
// Terminating condition: we don't have a context.
22862286
if (!context)
@@ -2371,20 +2371,59 @@ buildEnvironmentPath(
23712371
return totalKeyParamCount;
23722372
}
23732373

2374+
unsigned SubstGenericParametersFromMetadata::buildShapePath(
2375+
const TargetExtendedExistentialTypeShape<InProcess> *shape) const {
2376+
unsigned totalParamCount = 0;
2377+
2378+
auto genSig = shape->getGeneralizationSignature();
2379+
if (!genSig.getParams().empty()) {
2380+
totalParamCount += genSig.getParams().size();
2381+
descriptorPath.push_back(PathElement{genSig.getParams(),
2382+
totalParamCount,
2383+
/*numKeyGenericParamsInParent*/ 0,
2384+
(unsigned)genSig.getParams().size(),
2385+
/*hasNonKeyGenericParams*/ false});
2386+
}
2387+
2388+
const unsigned genSigParamCount = genSig.getParams().size();
2389+
auto reqSig = shape->getRequirementSignature();
2390+
assert(reqSig.getParams().size() > genSig.getParams().size());
2391+
{
2392+
auto remainingParams = reqSig.getParams().drop_front(genSig.getParams().size());
2393+
totalParamCount += remainingParams.size();
2394+
descriptorPath.push_back(PathElement{remainingParams,
2395+
totalParamCount,
2396+
genSigParamCount,
2397+
(unsigned)remainingParams.size(),
2398+
/*hasNonKeyGenericParams*/ false});
2399+
}
2400+
2401+
// All parameters in this signature are key parameters.
2402+
return totalParamCount;
2403+
}
2404+
23742405
void SubstGenericParametersFromMetadata::setup() const {
23752406
if (!descriptorPath.empty())
23762407
return;
23772408

2378-
if (sourceIsMetadata && baseContext) {
2409+
switch (sourceKind) {
2410+
case SourceKind::Metadata: {
2411+
assert(baseContext);
23792412
DemanglerForRuntimeTypeResolution<StackAllocatedDemangler<2048>> demangler;
23802413
numKeyGenericParameters = buildDescriptorPath(baseContext, demangler);
23812414
return;
23822415
}
2383-
2384-
if (!sourceIsMetadata && environment) {
2416+
case SourceKind::Environment: {
2417+
assert(environment);
23852418
numKeyGenericParameters = buildEnvironmentPath(environment);
23862419
return;
23872420
}
2421+
case SourceKind::Shape: {
2422+
assert(shape);
2423+
numKeyGenericParameters = buildShapePath(shape);
2424+
return;
2425+
}
2426+
}
23882427
}
23892428

23902429
const Metadata *

stdlib/public/runtime/Private.h

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -298,11 +298,17 @@ class TypeInfo {
298298
/// types.
299299
class SWIFT_RUNTIME_LIBRARY_VISIBILITY SubstGenericParametersFromMetadata {
300300
/// Whether the source is metadata (vs. a generic environment);
301-
const bool sourceIsMetadata;
301+
enum class SourceKind {
302+
Metadata,
303+
Environment,
304+
Shape,
305+
};
306+
const SourceKind sourceKind;
302307

303308
union {
304309
const TargetContextDescriptor<InProcess> *baseContext;
305310
const TargetGenericEnvironment<InProcess> *environment;
311+
const TargetExtendedExistentialTypeShape<InProcess> *shape;
306312
};
307313

308314
/// The generic arguments.
@@ -344,31 +350,40 @@ class TypeInfo {
344350
unsigned buildEnvironmentPath(
345351
const TargetGenericEnvironment<InProcess> *environment) const;
346352

353+
unsigned buildShapePath(
354+
const TargetExtendedExistentialTypeShape<InProcess> *shape) const;
355+
347356
// Set up the state we need to compute substitutions.
348357
void setup() const;
349358

350359
public:
351360
/// Produce substitutions entirely from the given metadata.
352361
explicit SubstGenericParametersFromMetadata(const Metadata *base)
353-
: sourceIsMetadata(true), baseContext(base->getTypeContextDescriptor()),
354-
genericArgs(base ? (const void * const *)base->getGenericArgs()
355-
: nullptr) { }
356-
362+
: sourceKind(SourceKind::Metadata),
363+
baseContext(base->getTypeContextDescriptor()),
364+
genericArgs(base ? (const void *const *)base->getGenericArgs()
365+
: nullptr) {}
366+
357367
/// Produce substitutions from the given instantiation arguments for the
358368
/// given context.
359369
explicit SubstGenericParametersFromMetadata(const ContextDescriptor *base,
360-
const void * const *args)
361-
: sourceIsMetadata(true), baseContext(base), genericArgs(args)
362-
{}
370+
const void *const *args)
371+
: sourceKind(SourceKind::Metadata), baseContext(base),
372+
genericArgs(args) {}
363373

364374
/// Produce substitutions from the given instantiation arguments for the
365375
/// given generic environment.
366376
explicit SubstGenericParametersFromMetadata(
367-
const TargetGenericEnvironment<InProcess> *environment,
368-
const void * const *arguments)
369-
: sourceIsMetadata(false), environment(environment),
370-
genericArgs(arguments) { }
371-
377+
const TargetGenericEnvironment<InProcess> *environment,
378+
const void *const *arguments)
379+
: sourceKind(SourceKind::Environment), environment(environment),
380+
genericArgs(arguments) {}
381+
382+
explicit SubstGenericParametersFromMetadata(
383+
const TargetExtendedExistentialTypeShape<InProcess> *shape,
384+
const void *const *arguments)
385+
: sourceKind(SourceKind::Shape), shape(shape), genericArgs(arguments) {}
386+
372387
const void * const *getGenericArgs() const { return genericArgs; }
373388

374389
const Metadata *getMetadata(unsigned depth, unsigned index) const;

0 commit comments

Comments
 (0)