Skip to content

Commit

Permalink
Merge pull request #76586 from tbkka/tbkka-enum-with-CF
Browse files Browse the repository at this point in the history
Better support CoreFoundation types in RemoteMirror
  • Loading branch information
tbkka authored Sep 20, 2024
2 parents 885d221 + 0251431 commit 5d5627a
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 33 deletions.
33 changes: 33 additions & 0 deletions stdlib/public/RemoteInspection/TypeLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2196,6 +2196,34 @@ class LowerType
TypeConverter &TC;
remote::TypeInfoProvider *ExternalTypeInfo;

const TypeInfo *CFRefTypeInfo(const TypeRef *TR) {
if (auto N = dyn_cast<NominalTypeRef>(TR)) {
Demangler Dem;
auto Node = N->getDemangling(Dem);
if (Node->getKind() == Node::Kind::Type && Node->getNumChildren() == 1) {
auto Alias = Node->getChild(0);
if (Alias->getKind() == Node::Kind::TypeAlias && Alias->getNumChildren() == 2) {
auto Module = Alias->getChild(0);
auto Name = Alias->getChild(1);
if (Module->getKind() == Node::Kind::Module
&& Module->hasText()
&& Module->getText() == "__C"
&& Name->getKind() == Node::Kind::Identifier
&& Name->hasText()) {
auto CName = Name->getText();
// Heuristic: Hopefully good enough.
if (CName.starts_with("CF") && CName.ends_with("Ref")) {
// A CF reference is essentially the same as a Strong ObjC reference
return TC.getReferenceTypeInfo(ReferenceKind::Strong,
ReferenceCounting::Unknown);
}
}
}
}
}
return nullptr;
}

public:
using TypeRefVisitor<LowerType, const TypeInfo *>::visit;

Expand Down Expand Up @@ -2265,6 +2293,11 @@ class LowerType
if (auto External = QueryExternalTypeInfoProvider())
return External;

// CoreFoundation types require some special handling
if (auto CFTypeInfo = CFRefTypeInfo(TR))
return CFTypeInfo;


// If the external provider also fails we're out of luck.
DEBUG_LOG(fprintf(stderr, "No TypeInfo for nominal type: "); TR->dump());
return nullptr;
Expand Down
105 changes: 105 additions & 0 deletions validation-test/Reflection/reflect_Enum_CF.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -lswiftSwiftReflectionTest %s -o %t/reflect_Enum_CF
// RUN: %target-codesign %t/reflect_Enum_CF

// RUN: %target-run %target-swift-reflection-test %t/reflect_Enum_CF | tee /dev/stderr | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK%target-ptrsize --dump-input=fail %add_num_extra_inhabitants

// REQUIRES: objc_interop
// REQUIRES: executable_test
// REQUIRES: reflection_test_support
// UNSUPPORTED: use_os_stdlib
// UNSUPPORTED: asan

import SwiftReflectionTest
import Foundation

enum MyPair<T,U> {
case a(T)
case b(U)
}

reflect(enum: MyPair<Void,CFNumber>.b(kCFNumberPositiveInfinity))

// CHECK: Reflecting an enum.
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-NEXT: Type reference:
// CHECK-NEXT: (bound_generic_enum reflect_Enum_CF.MyPair
// CHECK-NEXT: (tuple)
// CHECK-NEXT: (foreign name=So11CFNumberRefa))

// CHECK: Type info:
// CHECK64-NEXT: (multi_payload_enum size=9 alignment=8 stride=16 num_extra_inhabitants=254 bitwise_takable=1
// CHECK64-NEXT: (case name=a index=0 offset=0
// CHECK64-NEXT: (tuple size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
// CHECK64-NEXT: (case name=b index=1 offset=0
// CHECK64-NEXT: (reference kind=strong refcounting=unknown)))

// CHECK: Mangled name: $s15reflect_Enum_CF6MyPairOyytSo11CFNumberRefaG
// CHECK-NEXT: Demangled name: reflect_Enum_CF.MyPair<(), __C.CFNumberRef>

// CHECK: Enum value:
// CHECK-NEXT: (enum_value name=b index=1
// CHECK-NEXT: (foreign name=So11CFNumberRefa)
// CHECK-NEXT: )

struct StructA {
let field1 = MyPair<Void,CFNumber>.b(kCFNumberPositiveInfinity)
let field2 = 7
}

enum T {
case a
case b(MyPair<Void,CFNumber>)
}

reflect(enum: StructA().field1)

// CHECK: Reflecting an enum.
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-NEXT: Type reference:
// CHECK-NEXT: (bound_generic_enum reflect_Enum_CF.MyPair
// CHECK-NEXT: (tuple)
// CHECK-NEXT: (foreign name=So11CFNumberRefa))

// CHECK: Type info:
// CHECK64-NEXT: (multi_payload_enum size=9 alignment=8 stride=16 num_extra_inhabitants=254 bitwise_takable=1
// CHECK64-NEXT: (case name=a index=0 offset=0
// CHECK64-NEXT: (tuple size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
// CHECK64-NEXT: (case name=b index=1 offset=0
// CHECK64-NEXT: (reference kind=strong refcounting=unknown)))

// CHECK: Mangled name: $s15reflect_Enum_CF6MyPairOyytSo11CFNumberRefaG
// CHECK-NEXT: Demangled name: reflect_Enum_CF.MyPair<(), __C.CFNumberRef>

// CHECK: Enum value:
// CHECK-NEXT: (enum_value name=b index=1
// CHECK-NEXT: (foreign name=So11CFNumberRefa)
// CHECK-NEXT: )

reflect(enum: T.a)

// CHECK: Reflecting an enum.
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-NEXT: Type reference:
// CHECK-NEXT: (enum reflect_Enum_CF.T)

// CHECK: Type info:
// CHECK64-NEXT: (single_payload_enum size=9 alignment=8 stride=16 num_extra_inhabitants=253 bitwise_takable=1
// CHECK64-NEXT: (case name=b index=0 offset=0
// CHECK64-NEXT: (multi_payload_enum size=9 alignment=8 stride=16 num_extra_inhabitants=254 bitwise_takable=1
// CHECK64-NEXT: (case name=a index=0 offset=0
// CHECK64-NEXT: (tuple size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
// CHECK64-NEXT: (case name=b index=1 offset=0
// CHECK64-NEXT: (reference kind=strong refcounting=unknown))))
// CHECK64-NEXT: (case name=a index=1))

// CHECK: Mangled name: $s15reflect_Enum_CF1TO
// CHECK-NEXT: Demangled name: reflect_Enum_CF.T

// CHECK: Enum value:
// CHECK-NEXT: (enum_value name=a index=1)

doneReflecting()

// CHECKALL: Done.

65 changes: 32 additions & 33 deletions validation-test/Reflection/reflect_Enum_SingleCaseCFPayload.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// RUN: %target-build-swift -g -lswiftSwiftReflectionTest %s -o %t/reflect_Enum_SingleCaseCFPayload
// RUN: %target-codesign %t/reflect_Enum_SingleCaseCFPayload

// RUN: %target-run %target-swift-reflection-test %t/reflect_Enum_SingleCaseCFPayload | %FileCheck %s --check-prefix=CHECK-%target-ptrsize
// RUN: %target-run %target-swift-reflection-test %t/reflect_Enum_SingleCaseCFPayload | %FileCheck %s --check-prefix=CHECK%target-ptrsize

// REQUIRES: reflection_test_support
// REQUIRES: executable_test
Expand All @@ -29,42 +29,41 @@ class ClassWithSingleCaseCFPayloadEnum {

reflect(object: ClassWithSingleCaseCFPayloadEnum())

// CHECK-64: Reflecting an object.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-64: Type reference:
// CHECK-64: (class reflect_Enum_SingleCaseCFPayload.ClassWithSingleCaseCFPayloadEnum)
// CHECK-64: Type info:
// CHECK-64: <null type info>
// CHECK: Reflecting an object.
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}

// CHECK-32: Reflecting an object.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (class reflect_Enum_SingleCaseCFPayload.ClassWithSingleCaseCFPayloadEnum)
// CHECK-32: Type info:
// CHECK-32: <null type info>
// CHECK: Type reference:
// CHECK-NEXT: (class reflect_Enum_SingleCaseCFPayload.ClassWithSingleCaseCFPayloadEnum)

// CHECK64: Type info:
// CHECK64-NEXT: (class_instance size=48 alignment=8 stride=48 num_extra_inhabitants=0 bitwise_takable=1
// CHECK64-NEXT: (field name=e1 offset=16
// CHECK64-NEXT: (single_payload_enum size=8 alignment=8 stride=8 num_extra_inhabitants=2147483646 bitwise_takable=1
// CHECK64-NEXT: (case name=some index=0 offset=0
// CHECK64-NEXT: (reference kind=strong refcounting=unknown))

// CHECK32: Type info:

reflect(enum: SingleCaseCFPayloadEnum.only(cfs1))

// CHECK-64: Reflecting an enum.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-64: Type reference:
// CHECK-64: (enum reflect_Enum_SingleCaseCFPayload.SingleCaseCFPayloadEnum)
// CHECK-64: Type info:
// CHECK-64: <null type info>
// CHECK-64: Enum value:
// CHECK-64: <null type info>

// CHECK-32: Reflecting an enum.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (enum reflect_Enum_SingleCaseCFPayload.SingleCaseCFPayloadEnum)
// CHECK-32: Type info:
// CHECK-32: <null type info>
// CHECK-32: Enum value:
// CHECK-32: <null type info>
// CHECK: Reflecting an enum.
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}

doneReflecting()
// CHECK: Type reference:
// CHECK-NEXT: (enum reflect_Enum_SingleCaseCFPayload.SingleCaseCFPayloadEnum)

// CHECK: Type info:
// CHECK-NEXT: (reference kind=strong refcounting=unknown)

// CHECK-64: Done.
// CHECK: Mangled name: $s32reflect_Enum_SingleCaseCFPayload0cdeB0O
// CHECK-NEXT: Demangled name: reflect_Enum_SingleCaseCFPayload.SingleCaseCFPayloadEnum

// CHECK: Enum value:
// CHECK-NEXT: (reference kind=strong refcounting=unknown)

// CHECK: Mangled name: $s32reflect_Enum_SingleCaseCFPayload0cdeB0O
// CHECK-NEXT: Demangled name: reflect_Enum_SingleCaseCFPayload.SingleCaseCFPayloadEnum

doneReflecting()

// CHECK-32: Done.
// CHECK: Done.

0 comments on commit 5d5627a

Please sign in to comment.