`@convention(thin)` function pointers

So there are a couple of calling convention variations I can think of that aren't entirely addressed by this:

  • Tuples may or may not be exploded into individual parameters or returns depending on the abstraction level. We could however say that, if you mark a tuple with explicit directness, then it's always treated as a single aggregate, and to match a convention that destructures the tuple, you can specify it as individual arguments.
  • Methods and closure invocation functions use the @convention(method) calling convention in SIL, which puts the self parameter in the special context register and preserves it across calls. It could be useful to expose @convention(method) as a surface-language-level convention too, perhaps, in order to allow for things like dynamically constructing protocol conformances, splitting a closure into separate context reference and invocation function values, and so on.

Yeah, we'd have to formalize the rules for what subset of types are allowed to be passed direct. That would at least include:

  • a struct or enum that's either @frozen or in the same module, and whose elements are all either indirect or can themselves be passed directly
  • an object reference of class type
  • a generic type or existential with an AnyObject constraint (either directly or implied)

At the risk of tying the feature to a boat anchor, maybe symbolName could take on the responsibliity for manually specifying both C and Swift symbol names, since a lot of the additional modifiers such a feature might need, like visibility, section, usedness, and so on, could apply independently to the Swift and C entry points. So you could end up writing something like

@symbolName(swift: "swift_foo", visibility: internal)
@symbolName(c: "c_foo", visibility: public, section: "__TEXT,__fooplugn", used)
func foo(...)

if you wanted to export a Swift entry point internally for some other Swift code to indirectly link against, while exporting the C entry point to be consumed by some plugin or other interface that needs it.

Maybe we could have a way to still semi-mangle the name to include the expected function type of the entry point, so that if you try to look it up with a different type, the lookup still fails.

1 Like