[llvm-dev] [RFC] Introducing an explicit calling convention
Chris Lattner via llvm-dev
llvm-dev at lists.llvm.org
Thu Jan 17 22:29:35 PST 2019
On Jan 16, 2019, at 1:33 AM, David Chisnall via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> 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.
If anyone would like to organize a round table at EuroLLVM to talk about this topic, I’d love to participate. I have lots of thoughts and opinions here (but can’t really explain it all without a whiteboard) and they may be interesting to discuss.
More information about the llvm-dev