How to go about generating wrapper functions when a particular attribute is seen?

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

How to go about generating wrapper functions when a particular attribute is seen?

Robinson, Paul via cfe-dev
I am wondering what the best approach would be to generate a wrapper
function for functions with a particular attribute.  I.e.,

When the compiler sees

__attribute__ ((wrapthis)) int foo(args) {}

I want to generate foo as usual and also generate a function

int
foo_wrapper(args)
{
// do some stuff here
int result = foo(args);
// do some more stuff here
return result;
}

I am not sure where to generate the wrapper function, e.g., in clang,
in llvm?  And, what pass could I look at that might provide me with
some hints about how to go about this.  Any help would be appreciated.

Thanks,

seth



--------------
Seth Copen Goldstein
Carnegie Mellon University
Computer Science Dept
7111 GHC
412-268-3828

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: How to go about generating wrapper functions when a particular attribute is seen?

Robinson, Paul via cfe-dev

On Nov 15, 2017, at 10:32 PM, Seth Goldstein via cfe-dev <[hidden email]> wrote:

I am wondering what the best approach would be to generate a wrapper
function for functions with a particular attribute.  I.e.,

When the compiler sees

__attribute__ ((wrapthis)) int foo(args) {}

I want to generate foo as usual and also generate a function

int
foo_wrapper(args)
{
// do some stuff here
int result = foo(args);
// do some more stuff here
return result;
}

I am not sure where to generate the wrapper function, e.g., in clang,
in llvm?  And, what pass could I look at that might provide me with
some hints about how to go about this.  Any help would be appreciated.

A feature like this could be implemented in many different ways, so it's hard to answer
your question without more basic information.  How are you anticipating this wrapper
function being used?  Are all existing uses of the function re-routed to it?  Is it important
that "ignorant" translation units use the wrapper function?  Is it important that ignorant
translation units not use the wrapper function?  What's the basic goal here?

John.

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: How to go about generating wrapper functions when a particular attribute is seen?

Robinson, Paul via cfe-dev
The basic goal is the support low-cost parallelism when necessary.
The wrapper function provides some glue which allows the original
function to be invoked as a micro-thread.

So, either the original function or the wrapper function will be
called, depending on certain conditions.  There are no "ignorant"
translation units.  (In fact, as an extra, I would like the attribute
to be attached to both definitions and declarations so I can check the
use proper use of these functions.)



--------------
Seth Copen Goldstein
Carnegie Mellon University
Computer Science Dept
7111 GHC
412-268-3828

On Wed, Nov 15, 2017 at 11:14 PM, John McCall <[hidden email]> wrote:

On Nov 15, 2017, at 10:32 PM, Seth Goldstein via cfe-dev <[hidden email]> wrote:

I am wondering what the best approach would be to generate a wrapper
function for functions with a particular attribute.  I.e.,

When the compiler sees

__attribute__ ((wrapthis)) int foo(args) {}

I want to generate foo as usual and also generate a function

int
foo_wrapper(args)
{
// do some stuff here
int result = foo(args);
// do some more stuff here
return result;
}

I am not sure where to generate the wrapper function, e.g., in clang,
in llvm?  And, what pass could I look at that might provide me with
some hints about how to go about this.  Any help would be appreciated.

A feature like this could be implemented in many different ways, so it's hard to answer
your question without more basic information.  How are you anticipating this wrapper
function being used?  Are all existing uses of the function re-routed to it?  Is it important
that "ignorant" translation units use the wrapper function?  Is it important that ignorant
translation units not use the wrapper function?  What's the basic goal here?

John.


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: How to go about generating wrapper functions when a particular attribute is seen?

Robinson, Paul via cfe-dev

On Nov 16, 2017, at 1:02 PM, Seth Goldstein <[hidden email]> wrote:

The basic goal is the support low-cost parallelism when necessary.
The wrapper function provides some glue which allows the original
function to be invoked as a micro-thread.

So, either the original function or the wrapper function will be
called, depending on certain conditions.  There are no "ignorant"
translation units.

Can you elaborate on this?  Is it a dynamic decision or a static decision?  What
happens if we invoke the function as a micro-thread? — because presumably it
executes asynchronously to the caller, but since the function can have a return
value, and that return value can be used, we also presumably need to block on
the micro-thread.  Does that mean that the return value is actually a future?  How
far does the "future-ness" of the return value get propagated before we need to
force it?

My intuition is that, if the goal is for this:

// do some stuff here
int result = foo(args);
// do some more stuff here
return result;

to not join the micro-thread until the return statement, then you will need to at least
insert the join code in an LLVM pass, because Clang does not do reliable
cross-statement data-flow analysis itself.

Assuming that you don't really care about indirect calls — function pointers, C++
virtual functions, and so on — then it might be easiest overall to do almost all of
the work in an LLVM pass.  Clang would just do the semantic checking on the
attribute and then propagate that down to the LLVM function.  The LLVM function
would correspond to the normal, synchronously-executing version of the function.
Your pass would:

  1. for each function so annotated, create a new micro-thread-spawning function using
      some straightforward name-derivation scheme and

  2. for each direct call to such a function, potentially rewrite the call to use the
      micro-thread-spawning variant.

Unfortunately, doing this on an LLVM level does mean that you might have to
mess around with some ABI ugliness.  For example, if the synchronous function
has a return value that's returned indirectly, and the asynchronous variant just
returns a future, the attributes will need to be adjusted.  Of course, if this is just an
academic proof-of-concept, then you could reasonably just add a semantic condition
that the return type has to be simple in some way — e.g. void, integers, pointers, that
sort of thing — and basically just wish this whole problem away.

(In fact, as an extra, I would like the attribute
to be attached to both definitions and declarations so I can check the
use proper use of these functions.)

That's not the standard C rule, which is that attributes are inherited by redeclarations,
but it's certainly a reasonable enough goal — of course, the usual provisos of
cross-translation-unit semantic enforcement in C apply, but you can do your best.
To do this, you would want to make sure that it was not an InheritableAttr, and you'd
add some logic to Sema::mergeDeclAttributes.

John.




--------------
Seth Copen Goldstein
Carnegie Mellon University
Computer Science Dept
7111 GHC
412-268-3828

On Wed, Nov 15, 2017 at 11:14 PM, John McCall <[hidden email]> wrote:

On Nov 15, 2017, at 10:32 PM, Seth Goldstein via cfe-dev <[hidden email]> wrote:

I am wondering what the best approach would be to generate a wrapper
function for functions with a particular attribute.  I.e.,

When the compiler sees

__attribute__ ((wrapthis)) int foo(args) {}

I want to generate foo as usual and also generate a function

int
foo_wrapper(args)
{
// do some stuff here
int result = foo(args);
// do some more stuff here
return result;
}

I am not sure where to generate the wrapper function, e.g., in clang,
in llvm?  And, what pass could I look at that might provide me with
some hints about how to go about this.  Any help would be appreciated.

A feature like this could be implemented in many different ways, so it's hard to answer
your question without more basic information.  How are you anticipating this wrapper
function being used?  Are all existing uses of the function re-routed to it?  Is it important
that "ignorant" translation units use the wrapper function?  Is it important that ignorant
translation units not use the wrapper function?  What's the basic goal here?

John.



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev