[cfe-dev] [llvm-dev] RFC: Implementing the Swift calling convention in LLVM and Clang

John McCall via cfe-dev cfe-dev at lists.llvm.org
Wed Mar 2 12:10:18 PST 2016

> On Mar 2, 2016, at 12:00 PM, Reid Kleckner <rnk at google.com> wrote:
> On Tue, Mar 1, 2016 at 5:14 PM, John McCall via llvm-dev <llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>> wrote:
> There are four general points of deviation from the intermediary convention:
>   - We sometimes want to return more values in registers than the convention normally does, and we want to be able to use both integer and floating-point registers.  For example, we want to return a value of struct A, above, purely in registers.  For the most part, I don’t think this is a problem to layer on to an existing IR convention: C frontends will generally use explicit sret arguments when the convention requires them, and so the Swift lowering will produce result types that don’t have legal interpretations as direct results under the C convention.  But we can use a different IR convention if it’s necessary to disambiguate Swift’s desired treatment from the target's normal attempts to retroactively match the C convention.
> You're suggesting that backends shouldn't try to turn returns of {i32, float, i32} into sret automatically if the C ABI would require that struct to be returned indirectly. I know there are many users of LLVM out there that wish that LLVM would just follow the C ABI for them in "simple" cases like this, even though in general it's a lost cause. I think if you hide this new behavior under your own swiftcc then we can keep those people happy, ish.

Yes, that may be best.

>   - We sometimes have both direct results and indirect results.  It would be nice to take advantage of the sret convention even in the presence of direct results on targets that do use a different (profitable) ABI treatment for it.  I don’t know how well-supported this is in LLVM.
> LLVM insists that sret functions be void because the C convention requires the sret pointer to be returned in the normal return register. X86 Sys V requires this, though LLVM does not leverage it, and was non-conforming for most of its life. I don't see why Swift would need to use the 'sret' attribute for indirect results, though, if it doesn't need to conform to that part of the x86 convention. Am I missing something profitable about reusing our sret support?

For most platforms, it’s not profitable.  On some platforms, there’s a register reserved for the sret argument; it would be nice to take advantage of that for several reasons, including just being nicer to existing tools (debuggers, etc.) in common cases.

>   - We want a special “context” treatment for a certain argument.  A pointer-sized value is passed in an integer register; the same value should be present in that register after the call.  In some cases, the caller may pass a context argument to a function that doesn’t expect one, and this should not trigger undefined behavior.  Both of these rules suggest that the context argument be passed in a register which is normally callee-save.
> As discussed later, these arguments would come last. I thought it was already legal to call a C function with too many arguments without invoking UB, so I think we have to keep this working in LLVM anyway.

Formally, no, it’s UB to call (non-variadic, of course) C functions with extra arguments.  But you’re right, it does generally work at runtime, and LLVM doesn’t get in the way.
>   - The “error” treatment requires some way to (1) pass and receive the value in the caller and (2) receive and change the value in the callee.  The best way we could think of to represent this was to pretend that the argument is actually passed indirectly; the value is “passed” by storing to the pointer and “received” by loading from it.  To simplify backend lowering, we require the argument to be a special kind of swifterror alloca that can only be loaded, stored, and passed as a swifterror argument; in the callee, swifterror arguments have similar restrictions.  This ends up being fairly invasive in the backend, unfortunately.
> This seems unfortunate. I guess you've already rejected returning an FCA.

See one of my recent responses to Renato.  It’s really hard to make that work cleanly with the ability to call functions that lack the result.

> I wonder if we should ever go back to the world of "only calls can produce multiple values" as a special case, since that's what really happens at the MI level. I wonder if operand bundles or tokens could help solve this problem.
> ---
> In general, yes, I'm in favor of upstreaming this Swift CC support. The main awkwardness here to me is the error value which is in memory in the mid-level, but in registers in the backend. I feel like intrinsic/token/bundle/glue stuff might actually be better.

I agree that the error-result stuff is the most intrinsically awkward part of our current patch, and I would love to find alternatives.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160302/460a953f/attachment.html>

More information about the cfe-dev mailing list