mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Implement projectExistentialAndUnwrapClass
Implement a version of projectExistential tailored for LLDB. There are 2
differences when projecting existentials for LLDB:
1 - When it comes to existentials, LLDB stores the address of the error
pointer, which must be dereferenced.
2 - When the existential wraps a class type, LLDB expects the address
returned is the class instance itself and not the address of the
reference.
This patch also adapts the swift reflection test machinery to test
projectExistentialAndUnwrapClass as well. This is done by exposing
the new functionality from swift reflection test. It is tested in
existentials.swift, and ensures that the typeref information is
exactly the same as what is expected from projectExistential,
except the out address.
(cherry picked from commit 55e971e06750c3ba29722d558cc5400298f6bdaf)
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let RequestInstanceKind = "k"
|
||||
let RequestShouldUnwrapClassExistential = "u"
|
||||
let RequestInstanceAddress = "i"
|
||||
let RequestReflectionInfos = "r"
|
||||
let RequestImages = "m"
|
||||
@@ -346,11 +347,15 @@ internal func sendPointerSize() {
|
||||
/// The parent sends a Done message to indicate that it's done
|
||||
/// looking at this instance. It will continue to ask for instances,
|
||||
/// so call doneReflecting() when you don't have any more instances.
|
||||
internal func reflect(instanceAddress: UInt, kind: InstanceKind) {
|
||||
internal func reflect(instanceAddress: UInt,
|
||||
kind: InstanceKind,
|
||||
shouldUnwrapClassExistential: Bool = false) {
|
||||
while let command = readLine(strippingNewline: true) {
|
||||
switch command {
|
||||
case String(validatingUTF8: RequestInstanceKind)!:
|
||||
sendValue(kind.rawValue)
|
||||
case String(validatingUTF8: RequestShouldUnwrapClassExistential)!:
|
||||
sendValue(shouldUnwrapClassExistential)
|
||||
case String(validatingUTF8: RequestInstanceAddress)!:
|
||||
sendValue(instanceAddress)
|
||||
case String(validatingUTF8: RequestReflectionInfos)!:
|
||||
@@ -437,12 +442,18 @@ public func reflect(object: AnyObject) {
|
||||
/// The test doesn't care about the witness tables - we only care
|
||||
/// about what's in the buffer, so we always put these values into
|
||||
/// an Any existential.
|
||||
public func reflect<T>(any: T, kind: InstanceKind = .Existential) {
|
||||
///
|
||||
/// If shouldUnwrapClassExistential is set to true, this exercises
|
||||
/// projectExistentialAndUnwrapClass instead of projectExistential.
|
||||
public func reflect<T>(any: T, kind: InstanceKind = .Existential,
|
||||
shouldUnwrapClassExistential: Bool = false) {
|
||||
let any: Any = any
|
||||
let anyPointer = UnsafeMutablePointer<Any>.allocate(capacity: MemoryLayout<Any>.size)
|
||||
anyPointer.initialize(to: any)
|
||||
let anyPointerValue = UInt(bitPattern: anyPointer)
|
||||
reflect(instanceAddress: anyPointerValue, kind: kind)
|
||||
reflect(instanceAddress: anyPointerValue,
|
||||
kind: kind,
|
||||
shouldUnwrapClassExistential: shouldUnwrapClassExistential)
|
||||
anyPointer.deallocate()
|
||||
}
|
||||
|
||||
@@ -474,6 +485,21 @@ public func reflect<T: Error>(error: T) {
|
||||
reflect(instanceAddress: errorPointerValue, kind: .ErrorExistential)
|
||||
}
|
||||
|
||||
// Like reflect<T: Error>(error: T), but calls projectExistentialAndUnwrapClass
|
||||
// instead of projectExistential and adds an extra level of indirection, which is
|
||||
// what projectExistentialAndUnwrapClass expects.
|
||||
public func reflectUnwrappingClassExistential<T: Error>(error: T) {
|
||||
let error: Error = error
|
||||
let errorPointerValue = unsafeBitCast(error, to: UInt.self)
|
||||
let anyPointer = UnsafeMutablePointer<Any>.allocate(capacity: MemoryLayout<Any>.size)
|
||||
anyPointer.initialize(to: errorPointerValue)
|
||||
let anyPointerValue = UInt(bitPattern: anyPointer)
|
||||
reflect(instanceAddress: anyPointerValue,
|
||||
kind: .ErrorExistential,
|
||||
shouldUnwrapClassExistential: true)
|
||||
anyPointer.deallocate()
|
||||
}
|
||||
|
||||
// Reflect an `Enum`
|
||||
//
|
||||
// These are handled like existentials, but
|
||||
|
||||
Reference in New Issue
Block a user