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

Reply via email to