erichkeane added a comment. >> ! In D108643#3054443 <https://reviews.llvm.org/D108643#3054443>, @rjmccall >> wrote: >> >>> ! In D108643#3027473 <https://reviews.llvm.org/D108643#3027473>, >>> @erichkeane wrote: >>> >>>> ! In D108643#3026550 <https://reviews.llvm.org/D108643#3026550>, @rjmccall >>>> wrote: >>> >>> I think it would be better to provide a generic ABI specification that is >>> designed to "lower" `_BitInt` types into more basic concepts that ABIs >>> typically already have rules for. It would be appropriate to note at the >>> top that this is only a generic specification and that the rules for any >>> particular platform should be codified in a platform-specific ABI. But we >>> should make that easy so that platform owners who don't have strong >>> opinions about the ABI can just say "as described in version 1.4 of the >>> generic ABI at https://clang.llvm.org/..." >>> >>> Now, that is all independent of what we actually decide the ABI should be. >>> But I do think that if we're going to make this available on all targets, >>> we should strongly consider doing a "legalizing" lowering in the frontend: >>> at ABI-exposed points (call arguments/parameters and memory accesses), >>> `_BitInt` types should be translated into types that a naive backend can be >>> trusted to handle in a way that matches the documented ABI. Individual >>> targets can then opt in to using the natural lowerings if they promise to >>> match the ABI, but that becomes a decision that they make to enable better >>> optimization and code generation, not something that's necessary for >>> correctness. >> >> Don't we already have that? We work the same way a 'bool' does, that is, we >> zero/sign extend for parameters and return values? The backends then >> reliably up-scale these to the power-of-two/multiple-of-pointer. > > There's two levels of a "legalizing" lowering. > > On the specification level, we'd be formally saying that the ABI matches the > ABI of some other C construct. For example, we might say that a `signed > _BitInt(14)` argument is treated exactly as if the argument type was instead > `signed short` (with whatever restriction we do or do not impose on the > range). This is very nice on this level because, first, it's a rule that > works generically for all targets without needing to care about the details > of how arguments are assigned to registers or stack slots or whatever; and > second, it means you're never adding new cases to the ABI that e.g. libffi > would need to care about; and third, you can reliably match the ABI with > manually-lowered C code from a compiler that doesn't even support `_BitInt`s. > > On the implementation level, we'd have to actually emit IR which will turn > into code which matches that ABI. I think you are right that small integers > already reliably work that way in LLVM, so that if you pass an `i11 sext` > it'll get sign-extended to some width — what width exactly, I don't know, but > probably the same width that `i16 sext` would be. Larger integers, I'm not > sure. A legalizing lowering of big `_BitInt` argument would presumably say > either that it's exactly the same as a struct containing all the chunks or > that it's exactly the same as a series of arguments for each of the chunks. > Those are two very different rules! Most ABIs won't "straddle" a single > argument between registers and the stack, so e.g. if you'd need two registers > and you only have one left then you exhaust the registers and go fully on the > stack; but obviously you can get straddling if the lowering expands the > sequence. Similarly, some ABIs will go indirect if the struct gets big > enough, but you won't get that if the lowering expands. But on the other > hand, if the rule is really that it's like a struct, well, some ABIs don't > pass small structs in registers. Anyway, my point is that what exactly LLVM > targets do if you give them an `i117` might not match either of these > possibilities reliably across targets. In any case, since we currently have > to count registers in the frontend for the register-passing ABIs, we'll need > to actually know what the targets do.
Hmm... now that I think I understand the concern, I'm not sure we're able to take on this level of commitment. The Clang ABI code is a bit of a mess in general, plus each target has its own code, right (In CodeGen/TargetInfo.cpp)? Additionally, that would require breaking the Microsoft ABI again, and I thought we'd discussed trying not to make changes until Microsoft defined that ABI, right? I would like us to be able to find a way forward, and hope you can help make a suggestion on how to do so. We'd love to get Clang to support this C23 feature at least on some targets as there are a good amount of users of this feature already as `_ExtInt`, and we would really want to get them to the standards version ASAP. Do you have any suggestions on how we can move forward? PS: The current state of the things for the 4 platforms I deal with (and of course the most complicated ones) is: | | <32 bit | < 64 bit | < 128 bit | >128 bit | | Linux x86_64 | s/zext | always pass as a coerced i64 | Pass as 2 i64s 'coerced' while in registers, then Ptr to iN (byval) | Ptr to iN (Byval) | | Windows x86_64 | pass as iN | pass as iN | Ptr to iN | Ptr to iN | | Linux i386 | s/zext | pass as iN | Ptr to iN | Ptr to iN | | Windows i386 | s/zext | pass as iN | Ptr to iN | Ptr to iN | | + Your suggestion for ?all? as I understand it? | s/zext | s/zext | Split into i64s? | Split into i64s? | | Presumably there is a bit of issue because of register sizes too there, right? CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108643/new/ https://reviews.llvm.org/D108643 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits