Hi Austin, > On Jan 1, 2016, at 10:58 PM, Austin Zheng via swift-dev <swift-dev@swift.org> > 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. > > 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.
The three arguments together form the 'self' value of the call. That is, an EnumMirror is a struct containing a pointer to the owner object, a pointer to the value being reflected, and runtime type information for the value. You can see this if you look at how the _MagicMirrorData struct is defined on the swift side. > 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. Right. > > * 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. The value should indeed be a pointer to the enum value itself. Not sure why it's not working for you, maybe you can share more code? > 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. The value witness table is a member of the type metadata. It contains entry points for runtime manipulation of values of that type. The value witness table is used for runtime generics (when I have a generic parameter 'T' and a value of type 'T', the value witness functions are used for copying/moving/destroying/etc values of type 'T'). They are also used for reflection. They're not really documented anywhere except for in the source code itself -- see here: include/swift/Runtime/Metadata.h lib/IRGen/ValueWitness.h Slava > > Thanks a lot for your time. > > Best, > Austin > > _______________________________________________ > swift-dev mailing list > swift-dev@swift.org > https://lists.swift.org/mailman/listinfo/swift-dev _______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev