[llvm-dev] [RFC] Introducing an explicit calling convention

David Chisnall via llvm-dev llvm-dev at lists.llvm.org
Wed Jan 16 01:33:08 PST 2019


On 15/01/2019 21:56, Manuel Jacob via llvm-dev wrote:
> 
> Sometimes people complain that ABI handling in the frontend is hard and 
> that they have to duplicate (in their language’s frontend) what Clang 
> does.  However, I don’t think that pushing more of this complexity into 
> LLVM would be a good idea.  What I suggest is that there should be a 
> helper library for ABI lowering (ideally that library should be used by 
> Clang eventually).  What do you think?

I would love to see this and I was hoping that some of the Swift work 
would lead to a refactored clang library that allowed you to generate IR 
corresponding to C/C++ functions.

I think we have four use cases for front ends:

1. JIT'd language, minimal FFI.  This doesn't care what the calling 
convention is, doesn't care that it's stable, does care that it's 
efficient.  Except at well-defined external calls, is very happy for 
LLVM to pick a different calling convention for every function.

2. Language that has only an LLVM implementation, but does support 
static compilation and linking across different compiler versions. 
Doesn't care what the calling convention is, but it has to be stable. 
LLVM is free to pick a different calling convention for every type 
signature, but the convention must be stable and doesn't have to match 
the platform ABI.

3. Language that is adding a new LLVM implementation that is expected to 
interoperate with an existing implementation.  There are a lot of these 
out there and they all end up suffering.  Typically they either fork 
LLVM and add a custom calling convention, or they try to upstream a 
calling convention.  When they want to support a new architecture, then 
need to coordinate their releases with LLVM to get their calling 
conventions supported by the new back end.  They make live even harder 
for the next person to want to use their calling convention by adding 
more undocumented informal contracts between how the front end generates 
LLVM IR and how the back end maps this to register / stack layout.

4. Language that wants to interoperate with C/C++.  These sometimes 
embed a big chunk of clang.  This probably should be the preferred 
solution, because it will invariably miss corner cases (packed structs, 
for example) if it does anything simpler.  Unfortunately, clang isn't 
really designed for this kind of embedding and the APIs that consumers 
need change quite frequently.  Alternatively, they implement their own 
partial ABI support.  For the core C ABI (ignoring GNU extensions and 
C++), it is *much* easier to do this in a JIT that generates assembly 
directly than one that targets LLVM IR.  ABI specs describe a fairly 
simple (even amd64, though that's stretching it somewhat) set of rules 
for mapping C constructs to registers / stack offsets.  These are well 
defined and well documented.  The corresponding set of mappings from C 
constructs to IR constructs are undocumented outside of the code and the 
only way that you can reliably find them is to run clang and see what it 
emits (I have done this - it's not fun).  If you need only basic C 
interop, doing this for each platform that you support ought to be 
simpler than embedding clang, but it isn't.

Ideally, we'd have both a clean set of APIs for other front ends to 
embed clang (including a lot of what libclang exposes: parsing C 
headers, walking types, and then generating interoperable code), built 
on top of a clean way for the front end to either specify the exact ABI 
requirements or leave them entirely up to later optimisations or the 
back end.

David


More information about the llvm-dev mailing list