[llvm-commits] [llvm-gcc-4.2] r86892 - /llvm-gcc-4.2/trunk/gcc/llvm-abi.h

Rafael Espindola espindola at google.com
Thu Dec 10 15:19:10 PST 2009


2009/12/2 Rafael Espindola <espindola at google.com>:
>> I'm hoping Dale will weigh in on this soon, but I'm tentatively planning to add the byval support as soon as I get a chance (which may be a while).
>
> I have a small preference for expanding it early, but if most prefer
> the byval solution I can give it a try. Not the highest priority item
> for me right now, but might be able to help.

Attached is a patch that makes llvm-gcc produce

void @f(i32)
and
void @g(i32, i32, i32, i32, i16, i8)

When given

-----------------
struct foo {
char[3] a;
};

void f(struct foo x);
void g(int a, int b, int c, int d, struct foo x);
----------------------

It is obviously wrong in that that it has the number of argument
registers hardcoded. What is the best place to get that information in
llvm-gcc? What gcc does is handle this in a target dependent location.
I could also just add a #define to the different configs headers.
arm.h already has a NUM_ARG_REGS...

I think I would need the same information to implement the byval
alternative. byval is normally used for things copied on the stack, so
for function f above we would have to know that the struct would go in
registers.  In more complicated cases we have to split the structure.

I will try to figure out how to run the testsuite with qemu this weekend.

In a more long term note, I find the way we handle stacks very hard to
understand :-(

In the current way llvm-gcc is reverse engineering what llvm will do.
It knows what will be in each register and the stack layout. It uses
that information to map it to a llvm function signature that will be
expanded again by the code generator.  This is particularly bad for
x86 that uses both byval and first class aggregates.

What I would propose is making the argument placement explicit at the
LLVM IL level. A case like

struct foo {char a[5];};
void f(int a, int b, int c, foo d);

would compile to
%struct.f_stack_args = { i8 }
declare arm_explicit void @f(i32, i32, i32, i32, %struct.f_stack_args)

And a function like

void g(void) {
  struct foo x = {5, 6, 7, 8, 9};
  f(1, 2, 3, x);
}

would be compiled to

define arm_explicit void @g() nounwind {
entry:
  tail call arm_explicit  void @g(i32 1, i32 2, i32 3, i32 134678021,
{i8 9}) nounwind
  ret void
}

In this way almost all the lowering would be done in llvm-gcc/clang
(preferably in a shared library). The backend would be a lot simpler
since now every function would have at most 4 i32 args corresponding
to each register and an argument representing the memory layout of the
remaining C arguments.

One thing I am not sure is where to put things like nocapture.

Cheers,
-- 
Rafael Ávila de Espíndola
-------------- next part --------------
A non-text attachment was scrubbed...
Name: arm.patch
Type: text/x-patch
Size: 1763 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20091210/d6f4068f/attachment.bin>


More information about the llvm-commits mailing list