> 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.
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 swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev