Is there a way to know when value types are passed by reference at runtime?


This is a bit of an obscure question but I have some code GitHub - johnno1962/SwiftTrace: Trace Swift and Objective-C method invocations that allows you to intercept function calls for logging and is able to decorate the call signature with argument values using runtime metadata. The problem is some value types are passed by reference (a pointer to the struct) rather than the struct itself lowered into registers and it seems to be very difficult to know when this will happen. It seems to occur for "resilient types" which I'm told are value types where their module is compiled with "library evolution" as Foundation seems to be that are not @frozen, the icing on the cake being that even non-resilient user types that contain any of these types are passed by reference as their size is viewed as being potentially variable.

So, the question is. Is there any way at all to know, given an Any.Type whether it's values will be passed by reference or could such a thing be added to runtime metadata?



Unfortunately, it's not a uniform decision across all uses of a type. If the argument type's layout will be known across all callers, then it will (probably?) be passed directly; if the argument might be passed from a caller that does not know the layout, then it will definitely be passed indirectly. There are a bunch of other conditions as well, but this is the one (or at least one) you fundamentally can't do from type metadata. You'll have to go into debug info to be sure in all cases.

On the plus side, I bet it's very obvious from the debug info.


Can you hack up the compiler frontend to dump the relevant information about the types you’re interested in? What you’re referring to the compiler calls a “loadable” type. The information is easily obtained from type lowering.

Thanks Jordan, it's nice to know there is a solution in reserve even if I don't think I'll disappear down that very deep rabbit hole for now (I imagine the starting point would be the LLDB sources). I have a solution of sorts that works well enough judging by the number of issues people raise with the project.

1 Like