|
31 | 31 | #include "Private.h" |
32 | 32 | #include "../SwiftShims/RuntimeShims.h" |
33 | 33 | #include "stddef.h" |
| 34 | +#if SWIFT_OBJC_INTEROP |
| 35 | +#include "swift/Runtime/ObjCBridge.h" |
| 36 | +#include "SwiftValue.h" |
| 37 | +#endif |
34 | 38 |
|
35 | 39 | #include <cstring> |
36 | 40 | #include <type_traits> |
@@ -2094,6 +2098,65 @@ checkDynamicCastFromOptional(OpaqueValue *dest, |
2094 | 2098 | return {false, payloadType}; |
2095 | 2099 | } |
2096 | 2100 |
|
| 2101 | +#if SWIFT_OBJC_INTEROP |
| 2102 | +/// Try to unbox a SwiftValue box to perform a dynamic cast. |
| 2103 | +static bool tryDynamicCastBoxedSwiftValue(OpaqueValue *dest, |
| 2104 | + OpaqueValue *src, |
| 2105 | + const Metadata *srcType, |
| 2106 | + const Metadata *targetType, |
| 2107 | + DynamicCastFlags flags) { |
| 2108 | + // Swift type should be AnyObject or a class type. |
| 2109 | + if (!srcType->isAnyClass()) { |
| 2110 | + auto existential = dyn_cast<ExistentialTypeMetadata>(srcType); |
| 2111 | + if (!existential || |
| 2112 | + existential->Flags.getSpecialProtocol() |
| 2113 | + != SpecialProtocol::AnyObject) |
| 2114 | + return false; |
| 2115 | + } |
| 2116 | + |
| 2117 | + id srcObject; |
| 2118 | + memcpy(&srcObject, src, sizeof(id)); |
| 2119 | + |
| 2120 | + // Do we have a SwiftValue? |
| 2121 | + SwiftValue *srcSwiftValue = getAsSwiftValue(srcObject); |
| 2122 | + if (!srcSwiftValue) |
| 2123 | + return false; |
| 2124 | + |
| 2125 | + // If so, extract the boxed value and try to cast it. |
| 2126 | + const Metadata *boxedType; |
| 2127 | + const OpaqueValue *boxedValue; |
| 2128 | + std::tie(boxedType, boxedValue) |
| 2129 | + = getValueFromSwiftValue(srcSwiftValue); |
| 2130 | + |
| 2131 | + // We can't touch the value from the box because it may be |
| 2132 | + // multiply-referenced. |
| 2133 | + // TODO: Check for uniqueness and consume if box is unique? |
| 2134 | + |
| 2135 | + // Does the boxed type exactly match the target type we're looking for? |
| 2136 | + if (boxedType == targetType) { |
| 2137 | + targetType->vw_initializeWithCopy(dest, |
| 2138 | + const_cast<OpaqueValue*>(boxedValue)); |
| 2139 | + // Release the box if we need to. |
| 2140 | + if (flags & DynamicCastFlags::TakeOnSuccess) |
| 2141 | + objc_release((id)srcSwiftValue); |
| 2142 | + return true; |
| 2143 | + } |
| 2144 | + |
| 2145 | + // Maybe we can cast the boxed value to our destination type somehow. |
| 2146 | + auto innerFlags = flags - DynamicCastFlags::TakeOnSuccess |
| 2147 | + - DynamicCastFlags::DestroyOnFailure; |
| 2148 | + if (swift_dynamicCast(dest, const_cast<OpaqueValue*>(boxedValue), |
| 2149 | + boxedType, targetType, innerFlags)) { |
| 2150 | + // Release the box if we need to. |
| 2151 | + if (flags & DynamicCastFlags::TakeOnSuccess) |
| 2152 | + objc_release((id)srcSwiftValue); |
| 2153 | + return true; |
| 2154 | + } |
| 2155 | + |
| 2156 | + return false; |
| 2157 | +} |
| 2158 | +#endif |
| 2159 | + |
2097 | 2160 | /// Perform a dynamic cast to an arbitrary type. |
2098 | 2161 | SWIFT_RT_ENTRY_VISIBILITY |
2099 | 2162 | bool swift::swift_dynamicCast(OpaqueValue *dest, |
@@ -2238,14 +2301,24 @@ bool swift::swift_dynamicCast(OpaqueValue *dest, |
2238 | 2301 | if (tryDynamicCastNSErrorToValue(dest, src, srcType, targetType, flags)) { |
2239 | 2302 | return true; |
2240 | 2303 | } |
| 2304 | +#endif |
| 2305 | + SWIFT_FALLTHROUGH; |
| 2306 | + } |
| 2307 | + |
| 2308 | + case MetadataKind::Existential: { |
| 2309 | +#if SWIFT_OBJC_INTEROP |
| 2310 | + // A class or AnyObject reference may point at a boxed SwiftValue. |
| 2311 | + if (tryDynamicCastBoxedSwiftValue(dest, src, srcType, |
| 2312 | + targetType, flags)) { |
| 2313 | + return true; |
| 2314 | + } |
2241 | 2315 | #endif |
2242 | 2316 | break; |
2243 | 2317 | } |
2244 | 2318 |
|
| 2319 | + case MetadataKind::ExistentialMetatype: |
2245 | 2320 | case MetadataKind::Enum: |
2246 | 2321 | case MetadataKind::Optional: |
2247 | | - case MetadataKind::Existential: |
2248 | | - case MetadataKind::ExistentialMetatype: |
2249 | 2322 | case MetadataKind::Function: |
2250 | 2323 | case MetadataKind::HeapLocalVariable: |
2251 | 2324 | case MetadataKind::HeapGenericLocalVariable: |
@@ -2557,7 +2630,7 @@ static id bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src, |
2557 | 2630 | if (consume) { |
2558 | 2631 | if (canTake) { |
2559 | 2632 | if (isOutOfLine) { |
2560 | | - // Should only be true of opaque existentials. |
| 2633 | + // Should only be true of opaque existentials right now. |
2561 | 2634 | assert(srcExistentialTy->getRepresentation() |
2562 | 2635 | == ExistentialTypeRepresentation::Opaque); |
2563 | 2636 | auto container = reinterpret_cast<OpaqueExistentialContainer*>(src); |
@@ -2589,8 +2662,8 @@ static id bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src, |
2589 | 2662 | return (id)srcBridgedObject; |
2590 | 2663 | } |
2591 | 2664 |
|
2592 | | - // TODO: Fall back to boxing here. |
2593 | | - crash("unimplemented boxing bridge"); |
| 2665 | + // Fall back to boxing. |
| 2666 | + return (id)bridgeAnythingToSwiftValueObject(src, srcType, consume); |
2594 | 2667 | } |
2595 | 2668 |
|
2596 | 2669 | SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE |
|
0 commit comments