[cfe-dev] [llvm-dev] RFC: Implementing the Swift calling convention in LLVM and Clang
David Chisnall via cfe-dev
cfe-dev at lists.llvm.org
Fri Mar 4 00:54:01 PST 2016
On 2 Mar 2016, at 19:46, John McCall <rjmccall at apple.com> wrote:
> I have to say that, while I completely agree with you, I also deliberately made an effort in the design of our lowering to avoid as many of those existing complexities as I could. :) So I’m not sure we’d be an ideal vehicle for cleaning up the C lowering model. I’m also wary about turning this project — already somewhat complex — into a massive undertaking, which I’m afraid that changing general CC lowering rules would be. Furthermore, I’m concerned that anything we did here would just turn into an *extra* dimension of complexity for the backend, rather than replacing the current complexity, because it’s not obvious that targets would be able to simply drop their existing ad-hoc interpretation rules. But if you have concrete ideas about this, maybe we can find a way to work them in.
> The basic tension in CC lowering is between wanting simple cases to just work without further annotations and the need to cover the full gamut of special-case ABI rules. If we didn’t care about the former, we could just require every call and the function to completely describe the ABI to use — "argument 1 is in R0, argument 2 is in R12, argument 3 is at offset 48 on the stack, and we need 64 bytes on the stack and it has to be 16-byte-aligned at the call”. But dealing with that level of generality at every single call boundary would be a huge pain for backends, and we’d still need special code for things like varargs. So instead we’ve evolved all these informal protocols between frontends and backends. The informal protocols are… annoying, but I think the bigger problem is that they’re undocumented, and it’s unclear to everybody involved what’s supposed to happen when you go outside them. So the first step, I think, would just be to document as many of those informal, target-specific protocols as we can, and then from there maybe we can find commonalities that can be usefully generalized.
To be absolutely clear: I’m not suggesting that merging the Swift CC should be conditional on Apple fixing all of the associated ugliness in all of the calling convention logic. I support merging the Swift CC, but I also think that it is going to add some complexity to an already complex part of LLVM and think that it would be good if it could come along with a plan for reducing that complexity.
For the current logic, there are two interrelated issues:
- The C ABI defines how to map things to registers / stack slots.
- Other language ABI documents (including C++) are typically defined in terms of lowering to the platform’s C calling convention. Even when the core language is not, the C FFI usually is.
There are a few smaller issues, such as the complexity required for each pass to work out what the return value of a call / invoke instruction is (is it the return value, is it a load of some alloca that is passed via an sret argument?).
There are two separable parts of this problem:
- What does the representation of a call with a known set of C types look like in LLVM?
- What are the APIs that we use for constructing a function that has these calls?
Clang already has APIs to abstract a lot of this. Given a C type and a set of LLVM values that represent these C values, it can deconstruct the values into the relevant LLVM types and, on the callee side, reassemble LLVM values that correspond to the C types. It’s been proposed a few times before to have some kind of ABIBuilder class that would encapsulate this behaviour, probably pulling some code out of clang. It would then be the responsibility of backend maintainers to ensure that the ABIBuilder is kept in sync with any changes to how they represent their ABI in IR. It would probably also help to have some introspection APIs of the same form (e.g. for getting the return value).
More information about the cfe-dev