making a copy of a byval aggregate on the callee's frame

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

making a copy of a byval aggregate on the callee's frame

Robert Lytton
Hi - help!

I have read through previous threads on the subject of 'byval'  e.g.
    https://groups.google.com/forum/#!topicsearchin/llvm-dev/Exact$20meaning$20of$20byval/llvm-dev/cyRZyXcMCNI
    https://groups.google.com/forum/#!topicsearchin/llvm-dev/$20byval/llvm-dev/uk4uiK93jeM
    https://groups.google.com/forum/#!topicsearchin/llvm-dev/byval/llvm-dev/46Tv0lSRwBg
and read through code (as best I can) but I am no wiser.

I am using the XCore target where the pointee data needs to be copied by the callee (not the caller).
So:
        > I am not sure what this means though - when I generate code
        > from the LLVM assembly, do I need to do anything with byval?

        yes, the pointee needs to be passed by-copy, which usually means on the
        stack but could mean in a bunch of registers.

        > Either in the calling location or in the called function?

        The caller does the copy IIRC.  If you look at the .s file you should see
        it happening.

unfortunately does not help me.


There seems to be some disagreement if it should be done in clang or llvm.
Indeed I have hacked clang's CodeGenFunction::EmitFunctionProlog() and it works - but it is not nice.
BUT it seems most believe that it should be done within llvm using 'byVal'.

I have tried to follow the the 'byval' flag but am too ignorant to make any meaningful headway viz:
I tried adding t
o the XCoreCallingConv.td:
    CCIfByVal<CCPassByVal<0,4>>        // pushes pointer to the stack
and
    CCIfByVal<CCCustom<"XCoreCC_CustomByVal">>
But Have got stuck knowing if I can add the copy at this stage.
Is the pointee's details available or only the pointer's?
(Sorry if I have not dug deep enough to trace from pointer to pointee)

I also started to looked at the XCoreFrameLowering::emitPrologue()

Unfortunately, whilst stumbling around in the code is an interesting way to see the scenery, I am losing any sense of direction I may have had to start with!

Any input gratefully recieved - including key source files or the order in which things happen.
I'll try tracing through the calls (will -debug be enough) tomorrow.

thank you

robert



_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: making a copy of a byval aggregate on the callee's frame

Tim Northover-2
Hi Robert,

> I tried adding to the XCoreCallingConv.td:
>     CCIfByVal<CCPassByVal<0,4>>        // pushes pointer to the stack

This looks sensible to me. After that it comes down to cooperation
between XCoreISelLowering's LowerFormalArguments and LowerCall
functions. LowerFormalArguments is at the beginning of a function and
is responsible for taking arguments out of registers and putting them
into sensible places for the rest of the function to use. LowerCall is
responsible for putting call arguments where callees will expect them
and making the call.

On most targets, for byval, LowerCall would store the argument by
value on the stack (likely with a memcpy equivalent from the actual
pointer that's being passed); and LowerFormalArguments would create a
fixed FrameIndex pointing there and record that as the address for use
by everything else.

You'll want to do basically the reverse: LowerCall will just put the
pointer it's given on the stack; LowerFormalArguments will do the
memcpy like operation into a local variable created for the purpose
(also a FrameIndex, but of a different kind), then it'll record that
frame-index as the address for everything else to use.

Hope this helps; come back if there's still stuff you don't understand.

Cheers.

Tim.
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: making a copy of a byval aggregate on the callee's frame

Robert Lytton
Hi Tim,

Thank you for the input.
I think I follow you.

I believe the LowerCall is doing what it needs to do - passing pointer either on the stack or in register as per ABI.

The LowerFormalArguments() is where I am stuck.
LowerFormalArguments () calls CCInfo.AnalyzeFormalArguments(Ins, CC_XCore), which calls the CC_XCore().
This is where I placed the CCIfByVal<CCPassByVal<0,4>> which only pushed the pointer to the stack.
However, I don't want to push the pointer to the stack but COPY the pointee.
Indeed, I want to keep the pointer where it is BUT re-point it to a new object copied onto the callee's stack.
Hmmm
What I really want it something like:

static bool CC_XCore(...) {
  if (ArgFlags.isByVal()) {  // a 'CCCustom' function
    Size = ValNo.pointee.size;                     // where do I get the pointee's info from?
    NewVal = State.AllocateStack( Size, 4);  // how do I create space on the callee stack?
    memcpy(NewVal, ValNo.pointee, Size);  // how do I copy from caller's stack to callee's stack?
    ValNo.pointee=NewVal;                        // how re-point the pointer at the callee's stack (rather than caller's data)?
  }

If this is the correct way to do it, I will continue to plough ahead.
As you can see, I have no idea what api functions I should be using :-)

Thank you
robert

________________________________________
From: Tim Northover [[hidden email]]
Sent: 04 July 2013 20:24
To: Robert Lytton
Cc: <[hidden email]>
Subject: Re: [LLVMdev] making a copy of a byval aggregate on the callee's frame

Hi Robert,

> I tried adding to the XCoreCallingConv.td:
>     CCIfByVal<CCPassByVal<0,4>>        // pushes pointer to the stack

This looks sensible to me. After that it comes down to cooperation
between XCoreISelLowering's LowerFormalArguments and LowerCall
functions. LowerFormalArguments is at the beginning of a function and
is responsible for taking arguments out of registers and putting them
into sensible places for the rest of the function to use. LowerCall is
responsible for putting call arguments where callees will expect them
and making the call.

On most targets, for byval, LowerCall would store the argument by
value on the stack (likely with a memcpy equivalent from the actual
pointer that's being passed); and LowerFormalArguments would create a
fixed FrameIndex pointing there and record that as the address for use
by everything else.

You'll want to do basically the reverse: LowerCall will just put the
pointer it's given on the stack; LowerFormalArguments will do the
memcpy like operation into a local variable created for the purpose
(also a FrameIndex, but of a different kind), then it'll record that
frame-index as the address for everything else to use.

Hope this helps; come back if there's still stuff you don't understand.

Cheers.

Tim.

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: making a copy of a byval aggregate on the callee's frame

Tim Northover-2
Hi,

> I believe the LowerCall is doing what it needs to do - passing pointer either on the stack or in register as per ABI.

From very quick test-cases with no understanding of XCore, that looks plausible.

> LowerFormalArguments () calls CCInfo.AnalyzeFormalArguments(Ins, CC_XCore), which calls the CC_XCore().
> This is where I placed the CCIfByVal<CCPassByVal<0,4>> which only pushed the pointer to the stack.

Really, all it did was ask LowerCall and LowerFormalArguments to pass
the pointer on the stack (well, strictly "ByVal") as they see fit.

> static bool CC_XCore(...) {
>     <does weird and wonderful stuff>
> }

I think you're misinterpreting the purpose of these CC_* functions.
They don't actually do any of the work themselves. Their job is to
decide in broad terms where an argument goes and to record that
decision for the LowerWhatever functions. In fact, they don't have
access to any of the CodeGen or SelectionDAG machinery necessary to do
the job themselves.

The idea is that the DAG nodes we need to produce are actually
different in caller and callee, but whether some argument goes in R0
or R1 (or a stack slot) should hopefully be the same.

So the CC_* functions (& TableGen) take care of the first bit and then
the Lower* functions interpret those results in a target-specific way
(often). There are usually special checks for byval in those functions
which make copies at the appropriate points.

> As you can see, I have no idea what api functions I should be using :-)

I *think* you'll be fine with using CCPassByVal and won't need a
custom handler from what I've heard. At the very least you should be
focussing your attention on these Lower* functions for now. They're
horribly complicated, but I'm afraid that's something you just have to
deal with. They're where the real meaning of "byval" is decided.

Cheers.

Tim.
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: making a copy of a byval aggregate on the callee's frame

Robert Lytton
Hi Tim,

I may be missing something but using CCPassByVal is moving the pointer onto the stack - not what I'm after.
I need to add an operation to the function prolog that actually makes a copy of the pointed to data.
It is the responsibility of the callee to make the copy, not the caller - hence my trouble.
(currently the callee can corrupt the original data viz pass-by-reference!)

This should ideally be done early on in the IR in my thinking - to allow optimisation if the data is only ever read.

FYI, the clang hack is - notice the "CreateMemCpy":
      CodeGenFunction::EmitFunctionProlog(){
        ...
        if (ArgI.getIndirectByVal()) {
          llvm::AllocaInst *ByValue = CreateMemTemp(Ty, V->getName() + "agg.tmp");
          llvm::ConstantInt * size = llvm::ConstantInt::get(IntPtrTy,
                        getContext().getTypeSizeInChars(Ty).getQuantity());
          Builder.CreateMemCpy(ByValue, V, size, 4 );
          V = ByValue;   // and point the pointer to the new pointee!
        }

So, can it be done in the llvm?
Should it be done in the llvm?
I probably need to go away and read up on the llvm AST handling (is that the right name?).

robert

_______________________________________
From: Tim Northover [[hidden email]]
Sent: 04 July 2013 22:25
To: Robert Lytton
Cc: <[hidden email]>
Subject: Re: [LLVMdev] making a copy of a byval aggregate on the callee's frame

Hi,

> I believe the LowerCall is doing what it needs to do - passing pointer either on the stack or in register as per ABI.

From very quick test-cases with no understanding of XCore, that looks plausible.

> LowerFormalArguments () calls CCInfo.AnalyzeFormalArguments(Ins, CC_XCore), which calls the CC_XCore().
> This is where I placed the CCIfByVal<CCPassByVal<0,4>> which only pushed the pointer to the stack.

Really, all it did was ask LowerCall and LowerFormalArguments to pass
the pointer on the stack (well, strictly "ByVal") as they see fit.

> static bool CC_XCore(...) {
>     <does weird and wonderful stuff>
> }

I think you're misinterpreting the purpose of these CC_* functions.
They don't actually do any of the work themselves. Their job is to
decide in broad terms where an argument goes and to record that
decision for the LowerWhatever functions. In fact, they don't have
access to any of the CodeGen or SelectionDAG machinery necessary to do
the job themselves.

The idea is that the DAG nodes we need to produce are actually
different in caller and callee, but whether some argument goes in R0
or R1 (or a stack slot) should hopefully be the same.

So the CC_* functions (& TableGen) take care of the first bit and then
the Lower* functions interpret those results in a target-specific way
(often). There are usually special checks for byval in those functions
which make copies at the appropriate points.

> As you can see, I have no idea what api functions I should be using :-)

I *think* you'll be fine with using CCPassByVal and won't need a
custom handler from what I've heard. At the very least you should be
focussing your attention on these Lower* functions for now. They're
horribly complicated, but I'm afraid that's something you just have to
deal with. They're where the real meaning of "byval" is decided.

Cheers.

Tim.

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: making a copy of a byval aggregate on the callee's frame

Tim Northover-2
Hi Robert,

> This should ideally be done early on in the IR in my thinking - to allow optimisation if the data is only ever read.

I've thought that once or twice when dealing with ABIs myself. That's
certainly another possibility in your case. You could create a
separate FunctionPass that gets executed early on and replaces all
byval calls and functions with the correct memcpys.

It wouldn't work for other targets because they need more control over
just where the copy ends up, but it sounds like you shouldn't have an
issue.

> So, can it be done in the llvm?

Yes, in multiple ways.

> Should it be done in the llvm?

I think so, one way or the other.

Tim.
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: making a copy of a byval aggregate on the callee's frame

Robert Lytton
Hi Tim,

Thought about it last night and was coming to the same conclusion.
1. it cant be done at the end during lowering (target backend).
2. it should be part of llvm as the byVal needs to be handled.

As a twist, I have been told that llvm-gcc can lower byVal into memcpy in the callee.
I may take a look at this.
I wonder if it ever emits 'byVal'...

I still feel I don't understand enough about where byVal is used or what it means.
Is it *only* used as an attribute of an argument pointer to argument data that is pending a copy?
Once the memcpy is made, I assume the byVal is removed viz the arg pointer is replaced with a new arg pointer to the copied data.
Thus, must *all* byVal attributes be replaced in the IR?
I need to do more reading about other attributes and get more familiar with the IR in general...

robert

________________________________________
From: Tim Northover [[hidden email]]
Sent: 05 July 2013 07:43
To: Robert Lytton
Cc: <[hidden email]>
Subject: Re: [LLVMdev] making a copy of a byval aggregate on the callee's frame

Hi Robert,

> This should ideally be done early on in the IR in my thinking - to allow optimisation if the data is only ever read.

I've thought that once or twice when dealing with ABIs myself. That's
certainly another possibility in your case. You could create a
separate FunctionPass that gets executed early on and replaces all
byval calls and functions with the correct memcpys.

It wouldn't work for other targets because they need more control over
just where the copy ends up, but it sounds like you shouldn't have an
issue.

> So, can it be done in the llvm?

Yes, in multiple ways.

> Should it be done in the llvm?

I think so, one way or the other.

Tim.

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: making a copy of a byval aggregate on the callee's frame

Duncan Sands
Hi Robert, suppose you have a "byval" argument with type T*, and the caller
passes a T* called %X for it, while in the callee the argument is called %Y.

The IR level semantics are:
   (1) a copy should be made of *%X.  Whether the callee or the caller makes the
copy depends on the platform ABI.
   (2) in the callee, %Y refers to the address of this copy.

There are many ways (1) can be codegened, it all depends on what the platform
ABI says.  Examples:
   - the caller allocates memory on the stack, copies *%X to it, then passes a
pointer to the stack memory to the callee as %Y.
   - the caller passes %X to the callee, the callee allocates memory on the
stack, copies *%X to it, then places the address of the copy in %Y
   - the caller loads *%X into a bunch of registers and passes the registers to
the callee.  The callee allocates memory on the stack, writes the contents of
the registers to it (thus reconstructing *%X), and places the address of the
memory in %Y.

Which method is used should be specified by the platform ABI.  For example,
what does GCC do?

Ciao, Duncan.

On 05/07/13 09:52, Robert Lytton wrote:

> Hi Tim,
>
> Thought about it last night and was coming to the same conclusion.
> 1. it cant be done at the end during lowering (target backend).
> 2. it should be part of llvm as the byVal needs to be handled.
>
> As a twist, I have been told that llvm-gcc can lower byVal into memcpy in the callee.
> I may take a look at this.
> I wonder if it ever emits 'byVal'...
>
> I still feel I don't understand enough about where byVal is used or what it means.
> Is it *only* used as an attribute of an argument pointer to argument data that is pending a copy?
> Once the memcpy is made, I assume the byVal is removed viz the arg pointer is replaced with a new arg pointer to the copied data.
> Thus, must *all* byVal attributes be replaced in the IR?
> I need to do more reading about other attributes and get more familiar with the IR in general...
>
> robert
>
> ________________________________________
> From: Tim Northover [[hidden email]]
> Sent: 05 July 2013 07:43
> To: Robert Lytton
> Cc: <[hidden email]>
> Subject: Re: [LLVMdev] making a copy of a byval aggregate on the callee's frame
>
> Hi Robert,
>
>> This should ideally be done early on in the IR in my thinking - to allow optimisation if the data is only ever read.
>
> I've thought that once or twice when dealing with ABIs myself. That's
> certainly another possibility in your case. You could create a
> separate FunctionPass that gets executed early on and replaces all
> byval calls and functions with the correct memcpys.
>
> It wouldn't work for other targets because they need more control over
> just where the copy ends up, but it sounds like you shouldn't have an
> issue.
>
>> So, can it be done in the llvm?
>
> Yes, in multiple ways.
>
>> Should it be done in the llvm?
>
> I think so, one way or the other.
>
> Tim.
>
> _______________________________________________
> LLVM Developers mailing list
> [hidden email]         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: making a copy of a byval aggregate on the callee's frame

Robert Lytton
In reply to this post by Robert Lytton
Hi Tim,

Correction to my last email.

What I should have said is that the new pointer is used by the callee rather than the original byVal pointer arg.
(the byVal pointer arg remains but is not used by the callee).
viz:
define void @f1(%struct.tag* byval) {
entry:
  %st = alloca %struct.tag, align 4
  %1 = bitcast %struct.tag* %st to i8*
  %2 = bitcast %struct.tag* %0 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %1, i8* %2, i32 88, i32 4, i1 false)
  ; from now on %0 is not used
  ; callee uses the copy %st instead


Also, LowerFormalArguments() is not that late!
I just need to understand the process better :-/
 

As an aside, the Lang Ref states "The copy is considered to belong to the caller not the callee".
I guess this has to do with permission rather than location in memory or in time the copy happens.
Hence the copy can be made by the callee onto the callee's frame on behalf of the caller!

robert

________________________________________
From: [hidden email] [[hidden email]] on behalf of Robert Lytton [[hidden email]]
Sent: 05 July 2013 08:52
To: Tim Northover
Cc: <[hidden email]>
Subject: Re: [LLVMdev] making a copy of a byval aggregate on the callee's frame

Hi Tim,

Thought about it last night and was coming to the same conclusion.
1. it cant be done at the end during lowering (target backend).
2. it should be part of llvm as the byVal needs to be handled.

As a twist, I have been told that llvm-gcc can lower byVal into memcpy in the callee.
I may take a look at this.
I wonder if it ever emits 'byVal'...

I still feel I don't understand enough about where byVal is used or what it means.
Is it *only* used as an attribute of an argument pointer to argument data that is pending a copy?
Once the memcpy is made, I assume the byVal is removed viz the arg pointer is replaced with a new arg pointer to the copied data.
Thus, must *all* byVal attributes be replaced in the IR?
I need to do more reading about other attributes and get more familiar with the IR in general...

robert

________________________________________
From: Tim Northover [[hidden email]]
Sent: 05 July 2013 07:43
To: Robert Lytton
Cc: <[hidden email]>
Subject: Re: [LLVMdev] making a copy of a byval aggregate on the callee's frame

Hi Robert,

> This should ideally be done early on in the IR in my thinking - to allow optimisation if the data is only ever read.

I've thought that once or twice when dealing with ABIs myself. That's
certainly another possibility in your case. You could create a
separate FunctionPass that gets executed early on and replaces all
byval calls and functions with the correct memcpys.

It wouldn't work for other targets because they need more control over
just where the copy ends up, but it sounds like you shouldn't have an
issue.

> So, can it be done in the llvm?

Yes, in multiple ways.

> Should it be done in the llvm?

I think so, one way or the other.

Tim.

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: making a copy of a byval aggregate on the callee's frame

Tim Northover-2
> What I should have said is that the new pointer is used by the callee rather than the original byVal pointer arg.

Probably, I thought it looked a bit odd. Your code sequence looks
reasonable (apart from byval still being present in the argument list;
as you said before, lowering should probably remove that).

> Also, LowerFormalArguments() is not that late!

It's part of the LLVM IR to DAG conversion and target-specific. In
LLVM terms that is late. All of the opt passes have run by this point,
and they are the ones likely to make use of the extra freedom
provided.

Cheers.

Tim.
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: making a copy of a byval aggregate on the callee's frame

Robert Lytton
In reply to this post by Duncan Sands
Hi Duncan,
Thank you, that is helpful.
I need the 2nd example for doing (1)
I now have a better understanding of the SelectionDAG and LowerFormalArguments() so will see how far I get.
(so much to know, so many ways to get lost)
Robert
________________________________________
From: [hidden email] [[hidden email]] on behalf of Duncan Sands [[hidden email]]
Sent: 05 July 2013 10:19
To: [hidden email]
Subject: Re: [LLVMdev] making a copy of a byval aggregate on the callee's frame

Hi Robert, suppose you have a "byval" argument with type T*, and the caller
passes a T* called %X for it, while in the callee the argument is called %Y.

The IR level semantics are:
   (1) a copy should be made of *%X.  Whether the callee or the caller makes the
copy depends on the platform ABI.
   (2) in the callee, %Y refers to the address of this copy.

There are many ways (1) can be codegened, it all depends on what the platform
ABI says.  Examples:
   - the caller allocates memory on the stack, copies *%X to it, then passes a
pointer to the stack memory to the callee as %Y.
   - the caller passes %X to the callee, the callee allocates memory on the
stack, copies *%X to it, then places the address of the copy in %Y
   - the caller loads *%X into a bunch of registers and passes the registers to
the callee.  The callee allocates memory on the stack, writes the contents of
the registers to it (thus reconstructing *%X), and places the address of the
memory in %Y.

Which method is used should be specified by the platform ABI.  For example,
what does GCC do?

Ciao, Duncan.

On 05/07/13 09:52, Robert Lytton wrote:

> Hi Tim,
>
> Thought about it last night and was coming to the same conclusion.
> 1. it cant be done at the end during lowering (target backend).
> 2. it should be part of llvm as the byVal needs to be handled.
>
> As a twist, I have been told that llvm-gcc can lower byVal into memcpy in the callee.
> I may take a look at this.
> I wonder if it ever emits 'byVal'...
>
> I still feel I don't understand enough about where byVal is used or what it means.
> Is it *only* used as an attribute of an argument pointer to argument data that is pending a copy?
> Once the memcpy is made, I assume the byVal is removed viz the arg pointer is replaced with a new arg pointer to the copied data.
> Thus, must *all* byVal attributes be replaced in the IR?
> I need to do more reading about other attributes and get more familiar with the IR in general...
>
> robert
>
> ________________________________________
> From: Tim Northover [[hidden email]]
> Sent: 05 July 2013 07:43
> To: Robert Lytton
> Cc: <[hidden email]>
> Subject: Re: [LLVMdev] making a copy of a byval aggregate on the callee's frame
>
> Hi Robert,
>
>> This should ideally be done early on in the IR in my thinking - to allow optimisation if the data is only ever read.
>
> I've thought that once or twice when dealing with ABIs myself. That's
> certainly another possibility in your case. You could create a
> separate FunctionPass that gets executed early on and replaces all
> byval calls and functions with the correct memcpys.
>
> It wouldn't work for other targets because they need more control over
> just where the copy ends up, but it sounds like you shouldn't have an
> issue.
>
>> So, can it be done in the llvm?
>
> Yes, in multiple ways.
>
>> Should it be done in the llvm?
>
> I think so, one way or the other.
>
> Tim.
>
> _______________________________________________
> LLVM Developers mailing list
> [hidden email]         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev