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

Reid Kleckner via cfe-dev cfe-dev at lists.llvm.org
Wed Mar 2 12:00:57 PST 2016


On Tue, Mar 1, 2016 at 5:14 PM, John McCall via llvm-dev <
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.

  - 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?


>   - 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.


>   - 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. 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160302/b1ed20eb/attachment.html>


More information about the cfe-dev mailing list