[cfe-commits] [PATCH][CodeGen] Add padding to expanded struct function arguments if the ABI requires it.

Michael Spencer bigcheesegs at gmail.com
Sat Nov 13 23:34:02 PST 2010


On Sun, Nov 14, 2010 at 1:49 AM, John McCall <rjmccall at apple.com> wrote:
>
> On Nov 13, 2010, at 9:43 AM, Michael Spencer wrote:
>
>> On Sat, Nov 13, 2010 at 1:12 AM, John McCall <rjmccall at apple.com> wrote:
>>>
>>> On Nov 12, 2010, at 7:52 PM, Michael Spencer wrote:
>>>
>>>> On Fri, Nov 12, 2010 at 10:14 PM, John McCall <rjmccall at apple.com> wrote:
>>>>> On Oct 18, 2010, at 11:54 PM, Michael Spencer wrote:
>>>>>> The Microsoft ABI requires that structs passed by value as "expanded"
>>>>>> arguments maintain padding. This patch implements this and fixes
>>>>>> <http://llvm.org/bugs/show_bug.cgi?id=8398>.
>>>>>
>>>>> Sorry this has taken so long.  Can you explain how this approach is different from just not passing the struct as expanded at all, i.e. passing it byval?
>>>>>
>>>>> John.
>>>>
>>>> I thought byval was a pointer thing, would it work in this case?
>>>
>>> As I understand it, byval arguments are passed in memory by copying the pointed-to object into the appropriate position in the arguments, which is pretty much exactly what you want.  I think the pointer-is-secretly-a-struct thing is just a throwback to before we had first-class aggregates.
>>>
>>> I'm also pretty sure that expansion won't work because it screws up register-passing CCs, of which there are several we need to support on MS platforms.  For example:
>>>
>>>  struct A { int x; double d; };
>>>  void __fastcall foo(struct A, void *, void *);  // the pointers should be passed in registers, not the int and the padding pseudo-argument.
>>>
>>> John.
>>
>> OK, so the actual problem is in X86_32ABIInfo::classifyArgumentType.
>> It should not be expanding small structs with padding, or any struct
>> at all when using fastcc.
>
> _fastcall is x86_fastcall;  fastcc is a totally different beast.
>
> The way I read it, the Windows calling conventions *never* conceptually do struct expansion;  i.e. in no case do you ever pass a struct by breaking it into components and figuring out how to pass those individually.

Yep.

>  (In contrast, the standard Unix x86-64 CC will pass, e.g., struct { double d; void *p; } in an FP register and an integer register unless you're passing it as a vararg).  I think that's how the standard Unix x86 convention works, too.  That doesn't mean we never want to do struct expansion anyway — it generally produces cleaner IR and allows better optimization and codegen — but it does mean we have to be careful to only do it in cases where the backend will end up producing the right results.  That probably means a lot of experimentation, but that can happen later, since it's just QoI;  for now, never expanding for structs with padding sounds good.


Yeah, expanded argument code is much cleaner .

>
> The documentation for __fastcall that I've seen says that arguments are passed in registers when they're no larger than a pointer;  if that's true and small structs really are passed in a single register, then classifyArgumentType should return 'direct' with a coercion to the appropriate integer type.  It's probably okay to do this regardless of CC and clean it up later as QoI work, but however you see fit.
>
> Some useful test cases to investigate:
>
> void _fastcall foo(struct A { char a; short b; } var);
> void _fastcall foo(struct A { short a; short b; } var);
>
> John.

Thanks for the test cases. I also have quite a few other combinations
I am looking at. I agree that's it's good to expand when possible.
Expand with padding really is a different operation than just padding.
I will also end up with much better code.

- Michael Spencer




More information about the cfe-commits mailing list