[PATCH] Add support for coldcc to clang

CC'ing llvmdev.

Okay, so per recent traffic on this thread, it sounds like this is not currently
required for the sanitizers. That leaves a few questions open:

1. Do we still care about exposing this CC to user code at all?
2. What ABI guarantees exactly are we making with this convention?
  - Is it worth asking LLVM to commit to a particular convention?
  - If not, what exactly is LLVM willing to guarantee?
    - Only calls to module-internal functions?
    - Calls to functions whose implementation is guaranteed to be compiled
      with this exact version of the compiler?
    - Some coarser degree of stability?
3. If we do publish this, what name do we use?
  - Does not putting LLVM in the name imply that this is some portable thing?
  - Should we put something like "unstable" in the name to encourage users
    to think twice about using this casually?
4. Is there a good reason to publicize only coldcc and not fastcc as well?
5. IIRC, coldcc is not just a calling convention — it's also interpreted as a hint
  that the code path performing that call is not frequently taken. Is that
  something we should document?

Note that *any* sort of cross-module ABI guarantee can bite us — .a library
distribution is not uncommon (indeed, on iOS, it's the only supported form
of user library).

John.

I'd certainly find it useful to expose the fastcc calling convention via an attribute.

I have project[1] where I generate functions that are JIT compiled with LLVM. I mark all these functions with the "fastcc" calling convention to guarantee efficient tail calls between them. At the moment I must also generate thunks so these functions can be called from non JIT'd code. With the the fastcc attribute I wouldn't need the thunks and I could call JIT'd functions directly after casting them to the right type. I could see a coldcc attribute being useful for similar reasons.

In regards to naming fastcc is easy to confuse with X86 fastcall calling convention. I think it would be sensible to add LLVM to the name when exposing it to users as this clearly implies that the calling convention is a non-portable, LLVM specific thing (e.g. llvm_fastcc).

[1] https://github.com/rlsosborne/tool_axe

http://llvm-reviews.chandlerc.com/D443

Are you sure we actually want to expose this to users?

I would like to mark the UBSan runtime handler functions as attribute((coldcc)), and I think that would make sense for other sanitizers too.

Are we now willing to commit to a fixed ABI for coldcc? I thought we hadn’t been.

Implementing attribute((coldcc)) does not necessarily imply fixing
the ABI, provided that we document the attribute as such. It should
be safe to use in compiler_rt once we modify its build system to use the
just-built clang.

I agree that we could certainly expose a calling convention with zero
binary-compatibility guarantees. I don’t know if that would work for what
Richard wants, though. Notably, you can’t stick that sort of thing in a
library that you haven’t rev-locked to the compiler.

CC’ing llvmdev.

Okay, so per recent traffic on this thread, it sounds like this is not currently
required for the sanitizers. That leaves a few questions open:

  1. Do we still care about exposing this CC to user code at all?
  2. What ABI guarantees exactly are we making with this convention?
  • Is it worth asking LLVM to commit to a particular convention?
  • If not, what exactly is LLVM willing to guarantee?
  • Only calls to module-internal functions?
  • Calls to functions whose implementation is guaranteed to be compiled
    with this exact version of the compiler?
  • Some coarser degree of stability?
  1. If we do publish this, what name do we use?
  • Does not putting LLVM in the name imply that this is some portable thing?
  • Should we put something like “unstable” in the name to encourage users
    to think twice about using this casually?
  1. Is there a good reason to publicize only coldcc and not fastcc as well?
  2. IIRC, coldcc is not just a calling convention — it’s also interpreted as a hint
    that the code path performing that call is not frequently taken. Is that
    something we should document?

Note that any sort of cross-module ABI guarantee can bite us — .a library
distribution is not uncommon (indeed, on iOS, it’s the only supported form
of user library).

John.

I’d certainly find it useful to expose the fastcc calling convention via an attribute.

I have project[1] where I generate functions that are JIT compiled with LLVM. I mark all these functions with the “fastcc” calling convention to guarantee efficient tail calls between them. At the moment I must also generate thunks so these functions can be called from non JIT’d code. With the the fastcc attribute I wouldn’t need the thunks and I could call JIT’d functions directly after casting them to the right type. I could see a coldcc attribute being useful for similar reasons.

LLVM’s overloading of “fastcc” for guaranteed tail calls is kind of a hack. For languages which need it, guaranteed tail calls aren’t just an optimization (make this run “fast”), they’re of course required for correctness. Consequently, overloading fastcc to cover both of these purposes means that both are unnecessarily constrained by the other’s problems. Guaranteed tail calls don’t need fastcc’s ABI volatility, while fastcc doesn’t need guaranteed tail call’s reservation of an extra register for the callee in some cases. It’s my impression that LLVM has lumped these two things together because it didn’t view them as important enough to have separate calling conventions. Perhaps it’s now a good time to re-evaluate that decision.

In regards to naming fastcc is easy to confuse with X86 fastcall calling convention. I think it would be sensible to add LLVM to the name when exposing it to users as this clearly implies that the calling convention is a non-portable, LLVM specific thing (e.g. llvm_fastcc).

It’s not an LLVM-specific thing. It’s a specific-version-of-LLVM-specific thing, because each version of LLVM could be different. It’s neither forward nor backward compatible. This is not a normal thing for C compilers to expose to users.

Dan