This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Defining a common plugin machinery


Cupertino Miranda wrote:
Hi all,

As Grigori says, and well, the project is frozen (for around one year) since there was no expectations on it, specially since future of plugins by that time was really unclear.
In fact the idea by the time I stopped working in it was to extend gengtype (Garbage Collector's structure parser) to store meta-information of the structures so that having a root node to a structure with all the important data would allow to externally traverse / modify GCC data without having to include all the header files from GCC.
The reason for that wasn't to avoid the usage of GCC header files but instead to allow data serialization and perform plugins in other languages.
My GTY patch in http://gcc.gnu.org/ml/gcc-patches/2008-07/msg01607.html accomplishes this so treehydra JavaScript scripts can access GIMPLE.
http://developer.mozilla.org/en/docs/Treehydra


Great to see that others independantly identified need for the same functionality. Hopefully the patch will go into the next development cycle.

Taras

Cheers, Cupertino

On Oct 10, 2008, at 4:14 PM, Grigori Fursin wrote:

I currently don't have any preference for a specific way to deal with data marshaling
since currently it's enough for the MILEPOST project just to return void* pointer,
but just wanted to mention that last year Cupertino Miranda tried to introduce
an intermediate data layer to ICI to separate program analysis from transformations
and potentially simplify dealing with external optimization plugins. I think the
project has been frozen or Cupertino can comment on that if he follows this thread ;),
but I thought to give a link to the tech. report Cupertino presented last year,
if anyone is interested:


http://gcc-ici.sourceforge.net/papers/mfpp2007.pdf

By the way, if I am correct, GCC MELT (developed by Basile)
also attempts to address some of these issues with data marshaling
to modularize GCC ...

Cheers,
Grigori



-----Original Message-----
From: Brendon Costa [mailto:bcosta@avdat.com.au]
Sent: Friday, October 10, 2008 2:33 AM
To: Dave Korn
Cc: 'Taras Glek'; 'Grigori Fursin'; 'Hugh Leather'; 'Basile STARYNKEVITCH'; gcc@gcc.gnu.org;
'Sean Callanan'; 'Cupertino Miranda'; clattner@apple.com; iant@google.com; 'Taras Glek';
'Diego Novillo'; 'Mike O'Boyle'
Subject: Re: Defining a common plugin machinery



Sounds like you're almost in need of a generic data marshalling interface
here.


Why do we need the complication of data marshaling?

I don't see why we need to define that all plugin hooks have the same
function interface as currently proposed. I.e. a single void*. This
makes a lot of work marshaling data both as parameters and from return
values. This is already done for us by the language (Though i may have
mis-understood the train of thought here).

I will propose the start of a new idea. This needs to be fleshed out a
lot but it would be good to get some feedback.

I will use the following terminology borrowed from QT:
signal: Is a uniquely identified "hook" to which zero or more slots are
added. (I.e. Caller)
slot: Is a function implementation say in a plugin. This is added to a
linked list for the specified signal. (I.e. Callee)

The main concepts in this plugin hook definition are:
* Signals can define any type of function pointer so can return values
and accept any parameters without special data marshaling
* Each signal is uniquely identified as a member variable in a struct
called Hooks
* A signal is implemented as a linked list where each node has a
reference to a slot that has been connected to the signal
* A slot is a function pointer and a unique string identifier

This differs a bit from the QT definition but i find it helpful to
describe the entities.

Important things to note:
Multiple plugins are "chained" one after the other. I.e. It is the
responsibility of the plugin author to call any plugins that follow it
in the list. This gives the plugin authors a bit more control over how
their plugins inter-operate with other plugins, however it would be
STRONGLY recommended that they follow a standard procedure and just call
the next plugin after they have done their work.


Basically, the idea is to provide the following structure and then most
of the work will involve manipulation of the linked lists. I.e. Querying
existing items in the LL, inserting new items before/after existing
items, removing items from the LL.


This is not a proposed end product. It is just to propose an idea. There
are a few disadvantages with the way it is implemented right now:
* Too much boilerplate code for each signal definition
* The idea of chaining calls means the responsibility of calling the
next plugin ends up with the plugin developer which could be bad if a
plugin developer does not take due care, however it also provides them
with more flexibility (not sure if that is necessary).


Now, i have NO experience with the current pass manager in GCC, but
would the passes be able to be managed using this same framework
assuming that each pass is given a unique identifier?

Thanks,
Brendon.

#include <stdio.h>
#include <stdlib.h>

/* GCC : Code */
struct Hooks
{
  /* Define the blah signal. */
  struct BlahFPWrap
  {
     const char* name;
     int (*fp)(struct BlahFPWrap* self, int i, char c, float f);
     void* data;

     struct BlahFPWrap* next;
     struct BlahFPWrap* prev;
  }* blah;

  struct FooFPWrap
  {
     const char* name;
     void (*fp)(struct FooFPWrap* self);
     void* data;

     struct FooFPWrap* next;
     struct FooFPWrap* prev;
  }* foo;
};

/* Initialised by main */
struct Hooks hooks;

void SomeFunc1(void)
{
  /* Call plugin hook: blah */
  int result = (!hooks.blah ? 0 : hooks.blah->fp(hooks.blah, 3, 'c',
2.0f));
  /* ... do stuff with result ... */
  (void)result;
}

void SomeFunc2(void)
{
  /* Call plugin hook: foo */
  if (hooks.foo) hooks.foo->fp(hooks.foo);
}

void PlgInit(struct Hooks* h);

int main()
{
  hooks.blah = NULL;
  hooks.foo = NULL;

  PlgInit(&hooks);
  return 0;
}


/* Writeme... */
#define PLUGIN_INSERT_BEFORE(Hooks, Struct, Hook, FuncPtr, Before, SlotName)



/* In plugin */ #define PLUGIN_NAME "myplg"

static void MyFoo(struct FooFPWrap* self)
{
  printf("MyFoo\n");
  if (self->next) self->next->fp(self->next);
}

static void MyBlah(struct BlahFPWrap* self, int i, char c, float f)
{
  printf("MyBlah\n");
  if (self->next) self->next->fp(self->next, i, c, f);
}

void PlgInit(struct Hooks* h)
{
  PLUGIN_INSERT_BEFORE(h, struct BlahFPWrap, blah, &MyBlah, NULL,
PLUGIN_NAME "_MyBlah");
  PLUGIN_INSERT_BEFORE(h, struct FooFPWrap, foo, &MyFoo, NULL,
PLUGIN_NAME "_MyFoo");
}

void PlgShut(struct Hooks* h)
{
  PLUGIN_REMOVE(h, PLUGIN_NAME "_MyBlah");
  PLUGIN_REMOVE(h, PLUGIN_NAME "_MyFoo");
}



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]