-
Notifications
You must be signed in to change notification settings - Fork 206
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SwiftBindings] Added TypeMetadata, removed SwiftTypeInfo #2804
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,199 @@ | ||||||||||||||||||||||||||||||||||||||
// Copyright (c) Microsoft Corporation. | ||||||||||||||||||||||||||||||||||||||
// Licensed under the MIT License. | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
using System.Collections.Generic; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
namespace Swift.Runtime; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// Flags used to describe types | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
[Flags] | ||||||||||||||||||||||||||||||||||||||
public enum TypeMetadataFlags { | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make sense to add a |
||||||||||||||||||||||||||||||||||||||
/// The metadata is not an actual type | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
MetadataKindIsNonType = 0x400, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata doesn't live on the heap | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
MetadataKindIsNonHeap = 0x200, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The type is private to the runtime | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
MetadataKindIsRuntimePrivate = 0x100, | ||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is
Suggested change
|
||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The type represented by the metadata | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
public enum TypeMetadataKind { | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// None - errror | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
None = 0, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents a struct | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
Struct = 0 | TypeMetadataFlags.MetadataKindIsNonHeap, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents an enum | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
Enum = 1 | TypeMetadataFlags.MetadataKindIsNonHeap, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents an optional type | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
Optional = 2 | TypeMetadataFlags.MetadataKindIsNonHeap, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents an non-swift class | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
ForeignClass = 3 | TypeMetadataFlags.MetadataKindIsNonHeap, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents an opaque type | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
Opaque = 0 | TypeMetadataFlags.MetadataKindIsRuntimePrivate | TypeMetadataFlags.MetadataKindIsNonHeap, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents a tuple | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
Tuple = 1 | TypeMetadataFlags.MetadataKindIsRuntimePrivate | TypeMetadataFlags.MetadataKindIsNonHeap, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents a closure/function | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
Function = 2 | TypeMetadataFlags.MetadataKindIsRuntimePrivate | TypeMetadataFlags.MetadataKindIsNonHeap, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents a protocol | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
Protocol = 3 | TypeMetadataFlags.MetadataKindIsRuntimePrivate | TypeMetadataFlags.MetadataKindIsNonHeap, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents a type of a TypeMetadata type | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
Metatype = 4 | TypeMetadataFlags.MetadataKindIsRuntimePrivate | TypeMetadataFlags.MetadataKindIsNonHeap, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents an Objective C wrapper | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
ObjCClassWrapper = 5 | TypeMetadataFlags.MetadataKindIsRuntimePrivate | TypeMetadataFlags.MetadataKindIsNonHeap, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents a type of an existential container | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
ExistentialMetatype = 6 | TypeMetadataFlags.MetadataKindIsRuntimePrivate | TypeMetadataFlags.MetadataKindIsNonHeap, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents a heap local variable | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
HeapLocalVariable = 0 | TypeMetadataFlags.MetadataKindIsNonType, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents a generic heap local variable | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
HeapGenericLocalVariable = 0 | TypeMetadataFlags.MetadataKindIsNonType | TypeMetadataFlags.MetadataKindIsRuntimePrivate, | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents an error | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
ErrorObject = 1 | TypeMetadataFlags.MetadataKindIsNonType | TypeMetadataFlags.MetadataKindIsRuntimePrivate, | ||||||||||||||||||||||||||||||||||||||
// Swift source code says that for fixed values, this will never exceed 0x7ff, | ||||||||||||||||||||||||||||||||||||||
// but all class types will be 0x800 and above | ||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// The metadata represents a class | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
Class = 0x800 | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// Represents the type metadata for a Swift type | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
public readonly struct TypeMetadata : IEquatable<TypeMetadata> { | ||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How this correlates with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SwiftMetadata is based off the same type, but the difference here is that I'm not trying to define it as a ref struct but an struct with an opaque pointer so that it's easy to manipulate, compare, hash, and pass to and from p/invokes (the most common operations by far) and because it is going to escape the stack. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this might be relevant #2796 (comment). tldr: we need to check There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not really relevant since we can't know unbound generic type sizes at compile time ever. Having the Size at compile time is only beneficial for frozen structs and frozen enums. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did not mean generics, but having an explicit size value in the |
||||||||||||||||||||||||||||||||||||||
readonly IntPtr handle; | ||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will this become There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a great question - since this is a private member and we should never (1) need to access this outside of the TypeMetadata (and I don't think we ever would) and (2) get this type from any other place that as an implicit argument passed to us from Swift or as a return from an explicit call, it's fine to leave it as an IntPtr. |
||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// An empty/invalid TypeMetadata object | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
public readonly static TypeMetadata Zero = default (TypeMetadata); | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// Construct a TypeMetadata object | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
/// <param name="handle">The handle for the type</param> | ||||||||||||||||||||||||||||||||||||||
TypeMetadata (IntPtr handle) | ||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||
this.handle = handle; | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// Returns true if and only if the TypeMetadata is valid. | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
public bool IsValid => handle != IntPtr.Zero; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// Throws a NotSupportedException if the TypeMetadata is invalid | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
/// <exception cref="NotSupportedException"></exception> | ||||||||||||||||||||||||||||||||||||||
void ThrowOnInvalid () | ||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||
if (!IsValid) | ||||||||||||||||||||||||||||||||||||||
throw new NotSupportedException (); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
// This comes from the Swift ABI documentation - https://github.com/swiftlang/swift/blob/23e3f5f5de2ed046f3183264589be1f9a54f7e1e/include/swift/ABI/MetadataValues.h#L117 | ||||||||||||||||||||||||||||||||||||||
const long kMaxDiscriminator = 0x7ff; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// Returns the kind of this TypeMetadata | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
public TypeMetadataKind Kind { | ||||||||||||||||||||||||||||||||||||||
get { | ||||||||||||||||||||||||||||||||||||||
ThrowOnInvalid (); | ||||||||||||||||||||||||||||||||||||||
long val = ReadPointerSizedInt (handle); | ||||||||||||||||||||||||||||||||||||||
if (val == 0) | ||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like there's a mix of spaces and tabs here. |
||||||||||||||||||||||||||||||||||||||
return TypeMetadataKind.None; | ||||||||||||||||||||||||||||||||||||||
if (val > kMaxDiscriminator) | ||||||||||||||||||||||||||||||||||||||
return TypeMetadataKind.Class; | ||||||||||||||||||||||||||||||||||||||
return (TypeMetadataKind)val; | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// Reads a pointer sized integer from the location supplied | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
/// <param name="p">a pointer to memory</param> | ||||||||||||||||||||||||||||||||||||||
/// <returns></returns> | ||||||||||||||||||||||||||||||||||||||
unsafe static nint ReadPointerSizedInt (IntPtr p) | ||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||
// Check for debug only. This calling code should always do the null | ||||||||||||||||||||||||||||||||||||||
// checking. | ||||||||||||||||||||||||||||||||||||||
#if DEBUG | ||||||||||||||||||||||||||||||||||||||
if (p == IntPtr.Zero) | ||||||||||||||||||||||||||||||||||||||
throw new ArgumentOutOfRangeException (nameof (p)); | ||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||
return *((nint*)p); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// Returns true if other is the same as this | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
/// <param name="other">a TypeMetadata object to compare</param> | ||||||||||||||||||||||||||||||||||||||
/// <returns>true if the other is the same, false otherwise</returns> | ||||||||||||||||||||||||||||||||||||||
public bool Equals(TypeMetadata other) | ||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||
return other.handle == handle; | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// Returns true if and only if o is a TypeMetadata object and is equal to this | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
/// <param name="o">an object to compare</param> | ||||||||||||||||||||||||||||||||||||||
/// <returns>true if the other is the same, false otherwise</returns> | ||||||||||||||||||||||||||||||||||||||
public override bool Equals (object? o) | ||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||
if (o is TypeMetadata tm) | ||||||||||||||||||||||||||||||||||||||
return tm.handle == this.handle; | ||||||||||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
/// <summary> | ||||||||||||||||||||||||||||||||||||||
/// Returns a hashcode for this TypeMetadata object | ||||||||||||||||||||||||||||||||||||||
/// </summary> | ||||||||||||||||||||||||||||||||||||||
/// <returns>A hashcode for this TypeMetadata object</returns> | ||||||||||||||||||||||||||||||||||||||
public override int GetHashCode () | ||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||
return handle.GetHashCode (); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look intentional? Unindent by one space?