|
24 | 24 | #include "swift/Basic/Defer.h"
|
25 | 25 | #include "swift/Basic/Range.h"
|
26 | 26 | #include "swift/Basic/LLVM.h"
|
| 27 | +#include "swift/Runtime/ExistentialContainer.h" |
| 28 | +#include "swift/Runtime/HeapObject.h" |
27 | 29 | #include "swift/Runtime/Unreachable.h"
|
28 | 30 |
|
29 | 31 | #include <vector>
|
@@ -261,7 +263,64 @@ class MetadataReader {
|
261 | 263 |
|
262 | 264 | return start;
|
263 | 265 | }
|
264 |
| - |
| 266 | + |
| 267 | + /// Given a pointer to the metadata, attempt to read the value |
| 268 | + /// witness table. |
| 269 | + llvm::Optional<TargetValueWitnessTable<Runtime>> |
| 270 | + readValueWitnessTable(StoredPointer MetadataAddress) { |
| 271 | + // The value witness table pointer is at offset -1 from the metadata |
| 272 | + // pointer, that is, the pointer-sized word immediately before the |
| 273 | + // pointer's referenced address. |
| 274 | + TargetValueWitnessTable<Runtime> VWT; |
| 275 | + auto ValueWitnessTableAddrAddr = MetadataAddress - sizeof(StoredPointer); |
| 276 | + StoredPointer ValueWitnessTableAddr; |
| 277 | + if (!Reader->readInteger(RemoteAddress(ValueWitnessTableAddrAddr), |
| 278 | + &ValueWitnessTableAddr)) |
| 279 | + return llvm::None; |
| 280 | + if (!Reader->readBytes(RemoteAddress(ValueWitnessTableAddr), |
| 281 | + (uint8_t *)&VWT, sizeof(VWT))) |
| 282 | + return llvm::None; |
| 283 | + return VWT; |
| 284 | + } |
| 285 | + |
| 286 | + /// Given a known-opaque existential, attemp to discover the pointer to its |
| 287 | + /// metadata address and its value. |
| 288 | + llvm::Optional<std::pair<RemoteAddress, RemoteAddress>> |
| 289 | + readMetadataAndValueOpaqueExistential(RemoteAddress ExistentialAddress) { |
| 290 | + // OpaqueExistentialContainer is the layout of an opaque existential. |
| 291 | + // `Type` is the pointer to the metadata. |
| 292 | + TargetOpaqueExistentialContainer<Runtime> Container; |
| 293 | + if (!Reader->readBytes(RemoteAddress(ExistentialAddress), |
| 294 | + (uint8_t *)&Container, sizeof(Container))) |
| 295 | + return llvm::None; |
| 296 | + auto MetadataAddress = reinterpret_cast<StoredPointer>(Container.Type); |
| 297 | + auto Metadata = readMetadata(MetadataAddress); |
| 298 | + if (!Metadata) |
| 299 | + return llvm::None; |
| 300 | + |
| 301 | + auto VWT = readValueWitnessTable(MetadataAddress); |
| 302 | + if (!VWT) |
| 303 | + return llvm::None; |
| 304 | + |
| 305 | + // Inline representation (the value fits in the existential container). |
| 306 | + // So, the value starts at the first word of the container. |
| 307 | + if (VWT->isValueInline()) |
| 308 | + return llvm::Optional<std::pair<RemoteAddress, RemoteAddress>>( |
| 309 | + {RemoteAddress(MetadataAddress), ExistentialAddress}); |
| 310 | + |
| 311 | + // Non-inline (box'ed) representation. |
| 312 | + // The first word of the container stores the address to the box. |
| 313 | + StoredPointer BoxAddress; |
| 314 | + if (!Reader->readInteger(ExistentialAddress, &BoxAddress)) |
| 315 | + return llvm::None; |
| 316 | + |
| 317 | + auto AlignmentMask = VWT->getAlignmentMask(); |
| 318 | + auto Offset = (sizeof(HeapObject) + AlignmentMask) & ~AlignmentMask; |
| 319 | + auto StartOfValue = BoxAddress + Offset; |
| 320 | + return llvm::Optional<std::pair<RemoteAddress, RemoteAddress>>( |
| 321 | + {RemoteAddress(MetadataAddress), RemoteAddress(StartOfValue)}); |
| 322 | + } |
| 323 | + |
265 | 324 | /// Given a remote pointer to metadata, attempt to turn it into a type.
|
266 | 325 | BuiltType readTypeFromMetadata(StoredPointer MetadataAddress,
|
267 | 326 | bool skipArtificialSubclasses = false) {
|
|
0 commit comments