<div dir="ltr">Hey Slava,<div><br></div><div>Thanks a lot for your detailed responses; it definitely helps to understand how structs are passed to the C++ function.</div><div><br></div><div>In a separate email, Joe Groff mentioned that there was a difference between passing the enum value and passing a pointer to it. I think that might be the root of my problem. I&#39;ll try a few things and send over a better code sample tonight, if there are still issues.</div><div><br></div><div>Best,</div><div>Austin</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 6, 2016 at 11:37 AM, Slava Pestov <span dir="ltr">&lt;<a href="mailto:spestov@apple.com" target="_blank">spestov@apple.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Austin,<br>
<div><div class="h5"><br>
&gt; On Jan 1, 2016, at 10:58 PM, Austin Zheng via swift-dev &lt;<a href="mailto:swift-dev@swift.org">swift-dev@swift.org</a>&gt; wrote:<br>
&gt;<br>
&gt; Hello,<br>
&gt;<br>
&gt; I&#39;m trying to better understand how calls are made between the Swift standard library code and the runtime entry points. I&#39;ve read through most of the documentation in the repo but still have some questions.<br>
&gt;<br>
&gt; More specifically, here&#39;s an example: the &#39;_EnumMirror&#39; struct below represents a mirror reflecting a value whose type is an enum.<br>
&gt;<br>
&gt; ------<br>
&gt;<br>
&gt; struct _EnumMirror : _MirrorType {<br>
&gt;  let data: _MagicMirrorData<br>
&gt;  var value: Any { return data.value }<br>
&gt;  var valueType: Any.Type { return data.valueType }<br>
&gt;  // ... more stuff<br>
&gt;<br>
&gt;  var caseName: UnsafePointer&lt;CChar&gt; {<br>
&gt;    @_silgen_name(&quot;swift_EnumMirror_caseName&quot;)get<br>
&gt;  }<br>
&gt;  // ... (more stuff)<br>
&gt; }<br>
&gt;<br>
&gt; ------<br>
&gt;<br>
&gt; The &#39;caseName&#39; property represents the name of the enum value&#39;s case (e.g. &quot;FirstCase&quot; in Foo.FirstCase) as a C string. This property&#39;s getter calls into a C++ runtime function named &quot;swift_EnumMirror_caseName&quot;, which is reproduced below (from Reflection.mm):<br>
&gt;<br>
&gt; extern &quot;C&quot;<br>
&gt; const char *swift_EnumMirror_caseName(HeapObject *owner,<br>
&gt;                                      const OpaqueValue *value,<br>
&gt;                                      const Metadata *type) {<br>
&gt;  if (!isEnumReflectable(type))<br>
&gt;    return nullptr;<br>
&gt;<br>
&gt;  const auto Enum = static_cast&lt;const EnumMetadata *&gt;(type);<br>
&gt;  const auto &amp;Description = Enum-&gt;Description-&gt;Enum;<br>
&gt;<br>
&gt;  unsigned tag;<br>
&gt;  getEnumMirrorInfo(value, type, &amp;tag, nullptr, nullptr);    // effectively, same as &quot;tag = type-&gt;vw_getEnumTag(value);&quot;<br>
&gt;  return getFieldName(Description.CaseNames, tag);<br>
&gt; }<br>
&gt;<br>
&gt; Now, I had a few questions about exactly how this interoperation works, because I&#39;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).<br>
&gt;<br>
&gt; * swift_EnumMirror_caseName takes three arguments, but the Swift call site doesn&#39;t seem to specify what gets passed into the function.<br>
<br>
</div></div>The three arguments together form the &#39;self&#39; 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.<br>
<span class=""><br>
&gt; Is there a convention that is implicitly passing properties on _EnumMirror as arguments into the C++ function when it&#39;s being called? I did note that there were other runtime entry points (like &quot;swift_MagicMirrorData_summary&quot;) 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.<br>
<br>
</span>Right.<br>
<span class=""><br>
&gt;<br>
&gt; * What I really want to do is to get the tag of an enum. I wrote a different entry point that omits the unused &quot;owner&quot; property and simply calls swift_EnumMirror_caseName with nullptr as the first argument. This other C++ function takes &#39;value&#39; (an OpaqueValue*) and &#39;type&#39; (a Metadata*). I&#39;ve surmised that &#39;type&#39; 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 &#39;value&#39;, my tag is always retrieved as 0.<br>
<br>
</span>The value should indeed be a pointer to the enum value itself. Not sure why it&#39;s not working for you, maybe you can share more code?<br>
<span class=""><br>
&gt; I noticed that there&#39;s some sort of indirection in the form of &quot;vw_getEnumTag&quot;, which goes through something called the &quot;value witness&quot;. Is there somewhere I can read up about the value witness concept? I assume the reason the &#39;original&#39; code worked was because it was passing in a different object as &#39;value&#39;, maybe one that could serve as a value witness for the reflected-upon instance&#39;s type.<br>
<br>
</span>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 &#39;T&#39; and a value of type &#39;T&#39;, the value witness functions are used for copying/moving/destroying/etc values of type &#39;T&#39;). They are also used for reflection.<br>
<br>
They&#39;re not really documented anywhere except for in the source code itself -- see here:<br>
<br>
include/swift/Runtime/Metadata.h<br>
lib/IRGen/ValueWitness.h<br>
<br>
Slava<br>
<span class=""><br>
&gt;<br>
&gt; Thanks a lot for your time.<br>
&gt;<br>
&gt; Best,<br>
&gt; Austin<br>
&gt;<br>
</span>&gt; _______________________________________________<br>
&gt; swift-dev mailing list<br>
&gt; <a href="mailto:swift-dev@swift.org">swift-dev@swift.org</a><br>
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-dev" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-dev</a><br>
<br>
</blockquote></div><br></div>