> On Jan 1, 2016, at 10:58 PM, Austin Zheng via swift-dev <[email protected]>
> wrote:
>
> Hello,
>
> I'm trying to better understand how calls are made between the Swift standard
> library code and the runtime entry points. I've read through most of the
> documentation in the repo but still have some questions.
The particular functions in question aren't so much runtime entry points as
Swift methods that happen to be written in C++, in a way that makes them
incidentally ABI-compatible with Swift methods.
> More specifically, here's an example: the '_EnumMirror' struct below
> represents a mirror reflecting a value whose type is an enum.
>
> ------
>
> struct _EnumMirror : _MirrorType {
> let data: _MagicMirrorData
> var value: Any { return data.value }
> var valueType: Any.Type { return data.valueType }
> // ... more stuff
>
> var caseName: UnsafePointer<CChar> {
> @_silgen_name("swift_EnumMirror_caseName")get
> }
> // ... (more stuff)
> }
>
> ------
>
> The 'caseName' property represents the name of the enum value's case (e.g.
> "FirstCase" in Foo.FirstCase) as a C string. This property's getter calls
> into a C++ runtime function named "swift_EnumMirror_caseName", which is
> reproduced below (from Reflection.mm):
>
> extern "C"
> const char *swift_EnumMirror_caseName(HeapObject *owner,
> const OpaqueValue *value,
> const Metadata *type) {
> if (!isEnumReflectable(type))
> return nullptr;
>
> const auto Enum = static_cast<const EnumMetadata *>(type);
> const auto &Description = Enum->Description->Enum;
>
> unsigned tag;
> getEnumMirrorInfo(value, type, &tag, nullptr, nullptr); // effectively,
> same as "tag = type->vw_getEnumTag(value);"
> return getFieldName(Description.CaseNames, tag);
> }
>
> Now, I had a few questions about exactly how this interoperation works,
> because I'd like to be able to get the name of an enum case using this entry
> point from a different context (not from within an _EnumMirror property).
>
> * swift_EnumMirror_caseName takes three arguments, but the Swift call site
> doesn't seem to specify what gets passed into the function. Is there a
> convention that is implicitly passing properties on _EnumMirror as arguments
> into the C++ function when it's being called? I did note that there were
> other runtime entry points (like "swift_MagicMirrorData_summary") where the
> number of arguments in the Swift function matched the number of arguments in
> the C++ function, but in those cases the Swift function was a free function
> and not a method.
Swift structs are (currently) passed by passing each stored property
individually. _EnumMirror is defined as a struct with owner/value/type fields,
and the 'self' parameter to its methods gets broken down this way.
> * What I really want to do is to get the tag of an enum. I wrote a different
> entry point that omits the unused "owner" property and simply calls
> swift_EnumMirror_caseName with nullptr as the first argument. This other C++
> function takes 'value' (an OpaqueValue*) and 'type' (a Metadata*). I've
> surmised that 'type' should be the Swift metatype of the enum instance (e.g.
> myEnum.dynamicType), and I do get the case names table. However, if I pass in
> the enum instance itself as 'value', my tag is always retrieved as 0. I
> noticed that there's some sort of indirection in the form of "vw_getEnumTag",
> which goes through something called the "value witness". Is there somewhere I
> can read up about the value witness concept? I assume the reason the
> 'original' code worked was because it was passing in a different object as
> 'value', maybe one that could serve as a value witness for the reflected-upon
> instance's type.
'value' is a pointer to the value in memory, not the value itself. Are you
passing the enum's literal representation by value instead of passing a pointer
to it?
-Joe
_______________________________________________
swift-dev mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-dev