|
From: Patrick J. L. <lop...@gm...> - 2012-08-23 16:29:59
|
Hi, Julian. Thank you for your reply.
On Thu, Aug 23, 2012 at 6:47 AM, Julian Seward <js...@ac...> wrote:
>
> Yes. I take it that the x86_64 ABI guarantees that all 128 bit
> values will be returned in RDX:RAX (yes?) so the above is always correct.
Short answer: Yes, for our purposes.
Long answer: Doubles are returned in %xmm0. So are SSE2 values
(__m128i). But integer aggregates -- including all arms of Valgrind's
V128 union -- are returned in RDX:RAX according to the ABI.
So, assuming dirty helpers are written in portable C (or "portable"
GCC), and that they only return integers or integer aggregates, then
yes, you can rely on the values being in RDX:RAX.
Of course, there is nothing in principle preventing dirty helpers from
being platform dependent, but I assume you want to avoid that (?)
On a related note, do you prefer portable C, or do you like GCC
extensions? In particular, GCC allows this:
typedef unsigned long V128 __attribute__ ((mode(TI)));
...and then you can say "V128 x = 37; ++x;" and GCC will actually
generate code to perform 128-bit arithmetic on 64- or 32-bit
platforms.
I assume you prefer portable C, especially since the above does not
extend to V256 and beyond, but I thought I would throw it out there.
> I would prefer that we work through some more of the details first,
> in order to be sure we have a good design. In particular I am concerned
> to arrive at something which also works for 256 bit return values,
> and for other architectures.
Well, an ABI is what it is, so there is not much to design if we want
to allow dirty helpers to return V128. The ABI determines this
convention; we just have to implement it for each platform.
In portable C, the representation for anything larger than 64 bits
will always be an aggregate. V128 is already an aggregate; V256 will
be another aggregate; V512 yet another; and so on. If we want helpers
to be able to return V128, V256, etc., we need to implement the ABI
for each platform, whatever it is. And on any platform, at some point
(256 bit return, 512 bit return, 1024 bit return, etc.), the
convention will become "pass a pointer to some stack space and let the
callee fill it in".
An alternative would to implement our own portable convention for
dirty helpers that want to return these types. So instead of:
V128 dirty_helper(ULong arg1, ULong arg2) { ... }
...we would write:
void dirty_helper(ULong arg1, ULong arg2, V128 *result) { ... }
The advantage of this approach is that it would be
platform-independent for arbitrary-size aggregates (V128, V256, etc).
The disadvantage is that it would require an entirely new dirty call
infrastructure, with the ability to marshall IExprs (or whatever)
across this call boundary, presumably via the stack (?).
So I guess my #1 question is this: Which one do you want? Implement
the platform-dependent ABI for each platform to allow helpers to
return V128? Or implement platform-independent marshalling to pass
"V128 *" to helpers?
> A simpler solution would be to state the
> return type of the helper to be Ity_V128 (after all, that is what it is,
> essentially) and change the back end to generate code to get the
> result value into a 128-bit vector class register:
>
>> + addInstr(env, mk_iMOVsd_RR(hregAMD64_RDX(),dstHi) );
>> + addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(),dstLo) );
>
> then push RAX and RDX on the stack and load into a vector register.
> Copy whatever is done for Iop_64HLtoV128.
I understand. But first I need to know the answer to my question,
especially if you want me to implement this for all platforms.
> Patches on bug reports are way better, since those on mailing lists
> tend to get lost. The mail list is good for kicking people into
> doing reviews, taking notice of patch updates, etc, though.
Once we agree on an approach and I have a patch in some kind of
reasonable state, I will attach it to a bug report.
Thanks again.
- Pat
|