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 theself
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
orenum
that's either@frozen
or in the same module, and whose elements are all eitherindirect
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.