OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [plugin.c] - Blame information for rev 826

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 280 jeremybenn
/* Support for GCC plugin mechanism.
2
   Copyright (C) 2009 Free Software Foundation, Inc.
3
 
4
This file is part of GCC.
5
 
6
GCC is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 3, or (at your option)
9
any later version.
10
 
11
GCC is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GCC; see the file COPYING3.  If not see
18
<http://www.gnu.org/licenses/>.  */
19
 
20
/* This file contains the support for GCC plugin mechanism based on the
21
   APIs described in doc/plugin.texi.  */
22
 
23
#include "config.h"
24
#include "system.h"
25
 
26
/* If plugin support is not enabled, do not try to execute any code
27
   that may reference libdl.  The generic code is still compiled in to
28
   avoid including too many conditional compilation paths in the rest
29
   of the compiler.  */
30
#ifdef ENABLE_PLUGIN
31
#include <dlfcn.h>
32
#endif
33
 
34
#include "coretypes.h"
35
#include "toplev.h"
36
#include "tree.h"
37
#include "tree-pass.h"
38
#include "intl.h"
39
#include "plugin.h"
40
#include "timevar.h"
41
#include "ggc.h"
42
 
43
#ifdef ENABLE_PLUGIN
44
#include "plugin-version.h"
45
#endif
46
 
47
#define GCC_PLUGIN_STRINGIFY0(X) #X
48
#define GCC_PLUGIN_STRINGIFY1(X) GCC_PLUGIN_STRINGIFY0 (X)
49
 
50
/* Event names as strings.  Keep in sync with enum plugin_event.  */
51
static const char *plugin_event_name_init[] =
52
{
53
# define DEFEVENT(NAME) GCC_PLUGIN_STRINGIFY1 (NAME),
54
# include "plugin.def"
55
# undef DEFEVENT
56
};
57
 
58
/* A printf format large enough for the largest event above.  */
59
#define FMT_FOR_PLUGIN_EVENT "%-32s"
60
 
61
const char **plugin_event_name = plugin_event_name_init;
62
 
63
/* A hash table to map event names to the position of the names in the
64
   plugin_event_name table.  */
65
static htab_t event_tab;
66
 
67
/* Keep track of the limit of allocated events and space ready for
68
   allocating events.  */
69
static int event_last = PLUGIN_EVENT_FIRST_DYNAMIC;
70
static int event_horizon = PLUGIN_EVENT_FIRST_DYNAMIC;
71
 
72
/* Hash table for the plugin_name_args objects created during command-line
73
   parsing.  */
74
static htab_t plugin_name_args_tab = NULL;
75
 
76
/* List node for keeping track of plugin-registered callback.  */
77
struct callback_info
78
{
79
  const char *plugin_name;   /* Name of plugin that registers the callback.  */
80
  plugin_callback_func func; /* Callback to be called.  */
81
  void *user_data;           /* plugin-specified data.  */
82
  struct callback_info *next;
83
};
84
 
85
/* An array of lists of 'callback_info' objects indexed by the event id.  */
86
static struct callback_info *plugin_callbacks_init[PLUGIN_EVENT_FIRST_DYNAMIC];
87
static struct callback_info **plugin_callbacks = plugin_callbacks_init;
88
 
89
 
90
#ifdef ENABLE_PLUGIN
91
/* Each plugin should define an initialization function with exactly
92
   this name.  */
93
static const char *str_plugin_init_func_name = "plugin_init";
94
 
95
/* Each plugin should define this symbol to assert that it is
96
   distributed under a GPL-compatible license.  */
97
static const char *str_license = "plugin_is_GPL_compatible";
98
#endif
99
 
100
/* Helper function for the hash table that compares the base_name of the
101
   existing entry (S1) with the given string (S2).  */
102
 
103
static int
104
htab_str_eq (const void *s1, const void *s2)
105
{
106
  const struct plugin_name_args *plugin = (const struct plugin_name_args *) s1;
107
  return !strcmp (plugin->base_name, (const char *) s2);
108
}
109
 
110
 
111
/* Given a plugin's full-path name FULL_NAME, e.g. /pass/to/NAME.so,
112
   return NAME.  */
113
 
114
static char *
115
get_plugin_base_name (const char *full_name)
116
{
117
  /* First get the base name part of the full-path name, i.e. NAME.so.  */
118
  char *base_name = xstrdup (lbasename (full_name));
119
 
120
  /* Then get rid of '.so' part of the name.  */
121
  strip_off_ending (base_name, strlen (base_name));
122
 
123
  return base_name;
124
}
125
 
126
 
127
/* Create a plugin_name_args object for the give plugin and insert it to
128
   the hash table. This function is called when -fplugin=/path/to/NAME.so
129
   option is processed.  */
130
 
131
void
132
add_new_plugin (const char* plugin_name)
133
{
134
  struct plugin_name_args *plugin;
135
  void **slot;
136
  char *base_name = get_plugin_base_name (plugin_name);
137
 
138
  /* If this is the first -fplugin= option we encounter, create
139
     'plugin_name_args_tab' hash table.  */
140
  if (!plugin_name_args_tab)
141
    plugin_name_args_tab = htab_create (10, htab_hash_string, htab_str_eq,
142
                                        NULL);
143
 
144
  slot = htab_find_slot (plugin_name_args_tab, base_name, INSERT);
145
 
146
  /* If the same plugin (name) has been specified earlier, either emit an
147
     error or a warning message depending on if they have identical full
148
     (path) names.  */
149
  if (*slot)
150
    {
151
      plugin = (struct plugin_name_args *) *slot;
152
      if (strcmp (plugin->full_name, plugin_name))
153
        error ("Plugin %s was specified with different paths:\n%s\n%s",
154
               plugin->base_name, plugin->full_name, plugin_name);
155
      return;
156
    }
157
 
158
  plugin = XCNEW (struct plugin_name_args);
159
  plugin->base_name = base_name;
160
  plugin->full_name = plugin_name;
161
 
162
  *slot = plugin;
163
}
164
 
165
 
166
/* Parse the -fplugin-arg-<name>-<key>[=<value>] option and create a
167
   'plugin_argument' object for the parsed key-value pair. ARG is
168
   the <name>-<key>[=<value>] part of the option.  */
169
 
170
void
171
parse_plugin_arg_opt (const char *arg)
172
{
173
  size_t len = 0, name_len = 0, key_len = 0, value_len = 0;
174
  const char *ptr, *name_start = arg, *key_start = NULL, *value_start = NULL;
175
  char *name, *key, *value;
176
  void **slot;
177
  bool name_parsed = false, key_parsed = false;
178
 
179
  /* Iterate over the ARG string and identify the starting character position
180
     of 'name', 'key', and 'value' and their lengths.  */
181
  for (ptr = arg; *ptr; ++ptr)
182
    {
183
      /* Only the first '-' encountered is considered a separator between
184
         'name' and 'key'. All the subsequent '-'s are considered part of
185
         'key'. For example, given -fplugin-arg-foo-bar-primary-key=value,
186
         the plugin name is 'foo' and the key is 'bar-primary-key'.  */
187
      if (*ptr == '-' && !name_parsed)
188
        {
189
          name_len = len;
190
          len = 0;
191
          key_start = ptr + 1;
192
          name_parsed = true;
193
          continue;
194
        }
195
      else if (*ptr == '=')
196
        {
197
          if (key_parsed)
198
            {
199
              error ("Malformed option -fplugin-arg-%s (multiple '=' signs)",
200
                     arg);
201
              return;
202
            }
203
          key_len = len;
204
          len = 0;
205
          value_start = ptr + 1;
206
          key_parsed = true;
207
          continue;
208
        }
209
      else
210
        ++len;
211
    }
212
 
213
  if (!key_start)
214
    {
215
      error ("Malformed option -fplugin-arg-%s (missing -<key>[=<value>])",
216
             arg);
217
      return;
218
    }
219
 
220
  /* If the option doesn't contain the 'value' part, LEN is the KEY_LEN.
221
     Otherwise, it is the VALUE_LEN.  */
222
  if (!value_start)
223
    key_len = len;
224
  else
225
    value_len = len;
226
 
227
  name = XNEWVEC (char, name_len + 1);
228
  strncpy (name, name_start, name_len);
229
  name[name_len] = '\0';
230
 
231
  /* Check if the named plugin has already been specified earlier in the
232
     command-line.  */
233
  if (plugin_name_args_tab
234
      && ((slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT))
235
          != NULL))
236
    {
237
      struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
238
 
239
      key = XNEWVEC (char, key_len + 1);
240
      strncpy (key, key_start, key_len);
241
      key[key_len] = '\0';
242
      if (value_start)
243
        {
244
          value = XNEWVEC (char, value_len + 1);
245
          strncpy (value, value_start, value_len);
246
          value[value_len] = '\0';
247
        }
248
      else
249
        value = NULL;
250
 
251
      /* Create a plugin_argument object for the parsed key-value pair.
252
         If there are already arguments for this plugin, we will need to
253
         adjust the argument array size by creating a new array and deleting
254
         the old one. If the performance ever becomes an issue, we can
255
         change the code by pre-allocating a larger array first.  */
256
      if (plugin->argc > 0)
257
        {
258
          struct plugin_argument *args = XNEWVEC (struct plugin_argument,
259
                                                  plugin->argc + 1);
260
          memcpy (args, plugin->argv,
261
                  sizeof (struct plugin_argument) * plugin->argc);
262
          XDELETEVEC (plugin->argv);
263
          plugin->argv = args;
264
          ++plugin->argc;
265
        }
266
      else
267
        {
268
          gcc_assert (plugin->argv == NULL);
269
          plugin->argv = XNEWVEC (struct plugin_argument, 1);
270
          plugin->argc = 1;
271
        }
272
 
273
      plugin->argv[plugin->argc - 1].key = key;
274
      plugin->argv[plugin->argc - 1].value = value;
275
    }
276
  else
277
    error ("Plugin %s should be specified before -fplugin-arg-%s "
278
           "in the command line", name, arg);
279
 
280
  /* We don't need the plugin's name anymore. Just release it.  */
281
  XDELETEVEC (name);
282
}
283
 
284
/* Register additional plugin information. NAME is the name passed to
285
   plugin_init. INFO is the information that should be registered. */
286
 
287
static void
288
register_plugin_info (const char* name, struct plugin_info *info)
289
{
290
  void **slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT);
291
  struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
292
  plugin->version = info->version;
293
  plugin->help = info->help;
294
}
295
 
296
/* Helper function for the event hash table that compares the name of an
297
   existing entry (E1) with the given string (S2).  */
298
 
299
static int
300
htab_event_eq (const void *e1, const void *s2)
301
{
302
  const char *s1= *(const char * const *) e1;
303
  return !strcmp (s1, (const char *) s2);
304
}
305
 
306
/* Look up the event id for NAME.  If the name is not found, return -1
307
   if INSERT is NO_INSERT.  */
308
 
309
int
310
get_named_event_id (const char *name, enum insert_option insert)
311
{
312
  void **slot;
313
 
314
  if (!event_tab)
315
    {
316
      int i;
317
 
318
      event_tab = htab_create (150, htab_hash_string, htab_event_eq, NULL);
319
      for (i = 0; i < event_last; i++)
320
        {
321
          slot = htab_find_slot (event_tab, plugin_event_name[i], INSERT);
322
          gcc_assert (*slot == HTAB_EMPTY_ENTRY);
323
          *slot = &plugin_event_name[i];
324
        }
325
    }
326
  slot = htab_find_slot (event_tab, name, insert);
327
  if (slot == NULL)
328
    return -1;
329
  if (*slot != HTAB_EMPTY_ENTRY)
330
    return (const char **) *slot - &plugin_event_name[0];
331
 
332
  if (event_last >= event_horizon)
333
    {
334
      event_horizon = event_last * 2;
335
      if (plugin_event_name == plugin_event_name_init)
336
        {
337
          plugin_event_name = XNEWVEC (const char *, event_horizon);
338
          memcpy (plugin_event_name, plugin_event_name_init,
339
                  sizeof plugin_event_name_init);
340
          plugin_callbacks = XNEWVEC (struct callback_info *, event_horizon);
341
          memcpy (plugin_callbacks, plugin_callbacks_init,
342
                  sizeof plugin_callbacks_init);
343
        }
344
      else
345
        {
346
          plugin_event_name
347
            = XRESIZEVEC (const char *, plugin_event_name, event_horizon);
348
          plugin_callbacks = XRESIZEVEC (struct callback_info *,
349
                                         plugin_callbacks, event_horizon);
350
        }
351
      /* All the pointers in the hash table will need to be updated.  */
352
      htab_delete (event_tab);
353
      event_tab = NULL;
354
    }
355
  else
356
    *slot = &plugin_event_name[event_last];
357
  plugin_event_name[event_last] = name;
358
  return event_last++;
359
}
360
 
361
/* Called from the plugin's initialization code. Register a single callback.
362
   This function can be called multiple times.
363
 
364
   PLUGIN_NAME - display name for this plugin
365
   EVENT       - which event the callback is for
366
   CALLBACK    - the callback to be called at the event
367
   USER_DATA   - plugin-provided data   */
368
 
369
void
370
register_callback (const char *plugin_name,
371
                   int event,
372
                   plugin_callback_func callback,
373
                   void *user_data)
374
{
375
  switch (event)
376
    {
377
      case PLUGIN_PASS_MANAGER_SETUP:
378
        gcc_assert (!callback);
379
        register_pass ((struct register_pass_info *) user_data);
380
        break;
381
      case PLUGIN_INFO:
382
        gcc_assert (!callback);
383
        register_plugin_info (plugin_name, (struct plugin_info *) user_data);
384
        break;
385
      case PLUGIN_REGISTER_GGC_ROOTS:
386
        gcc_assert (!callback);
387
        ggc_register_root_tab ((const struct ggc_root_tab*) user_data);
388
        break;
389
      case PLUGIN_REGISTER_GGC_CACHES:
390
        gcc_assert (!callback);
391
        ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data);
392
        break;
393
      case PLUGIN_EVENT_FIRST_DYNAMIC:
394
      default:
395
        if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last)
396
          {
397
            error ("Unknown callback event registered by plugin %s",
398
                   plugin_name);
399
            return;
400
          }
401
      /* Fall through.  */
402
      case PLUGIN_FINISH_TYPE:
403
      case PLUGIN_START_UNIT:
404
      case PLUGIN_FINISH_UNIT:
405
      case PLUGIN_PRE_GENERICIZE:
406
      case PLUGIN_GGC_START:
407
      case PLUGIN_GGC_MARKING:
408
      case PLUGIN_GGC_END:
409
      case PLUGIN_ATTRIBUTES:
410
      case PLUGIN_PRAGMAS:
411
      case PLUGIN_FINISH:
412
      case PLUGIN_ALL_PASSES_START:
413
      case PLUGIN_ALL_PASSES_END:
414
      case PLUGIN_ALL_IPA_PASSES_START:
415
      case PLUGIN_ALL_IPA_PASSES_END:
416
      case PLUGIN_OVERRIDE_GATE:
417
      case PLUGIN_PASS_EXECUTION:
418
      case PLUGIN_EARLY_GIMPLE_PASSES_START:
419
      case PLUGIN_EARLY_GIMPLE_PASSES_END:
420
      case PLUGIN_NEW_PASS:
421
        {
422
          struct callback_info *new_callback;
423
          if (!callback)
424
            {
425
              error ("Plugin %s registered a null callback function "
426
                     "for event %s", plugin_name, plugin_event_name[event]);
427
              return;
428
            }
429
          new_callback = XNEW (struct callback_info);
430
          new_callback->plugin_name = plugin_name;
431
          new_callback->func = callback;
432
          new_callback->user_data = user_data;
433
          new_callback->next = plugin_callbacks[event];
434
          plugin_callbacks[event] = new_callback;
435
        }
436
        break;
437
    }
438
}
439
 
440
/* Remove a callback for EVENT which has been registered with for a plugin
441
   PLUGIN_NAME.  Return PLUGEVT_SUCCESS if a matching callback was
442
   found & removed, PLUGEVT_NO_CALLBACK if the event does not have a matching
443
   callback, and PLUGEVT_NO_SUCH_EVENT if EVENT is invalid.  */
444
int
445
unregister_callback (const char *plugin_name, int event)
446
{
447
  struct callback_info *callback, **cbp;
448
 
449
  if (event >= event_last)
450
    return PLUGEVT_NO_SUCH_EVENT;
451
 
452
  for (cbp = &plugin_callbacks[event]; (callback = *cbp); cbp = &callback->next)
453
    if (strcmp (callback->plugin_name, plugin_name) == 0)
454
      {
455
        *cbp = callback->next;
456
        return PLUGEVT_SUCCESS;
457
      }
458
  return PLUGEVT_NO_CALLBACK;
459
}
460
 
461
/* Called from inside GCC.  Invoke all plug-in callbacks registered with
462
   the specified event.
463
   Return PLUGEVT_SUCCESS if at least one callback was called,
464
   PLUGEVT_NO_CALLBACK if there was no callback.
465
 
466
   EVENT    - the event identifier
467
   GCC_DATA - event-specific data provided by the compiler  */
468
 
469
int
470
invoke_plugin_callbacks (int event, void *gcc_data)
471
{
472
  int retval = PLUGEVT_SUCCESS;
473
 
474
  timevar_push (TV_PLUGIN_RUN);
475
 
476
  switch (event)
477
    {
478
      case PLUGIN_EVENT_FIRST_DYNAMIC:
479
      default:
480
        gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC);
481
        gcc_assert (event < event_last);
482
      /* Fall through.  */
483
      case PLUGIN_FINISH_TYPE:
484
      case PLUGIN_START_UNIT:
485
      case PLUGIN_FINISH_UNIT:
486
      case PLUGIN_PRE_GENERICIZE:
487
      case PLUGIN_ATTRIBUTES:
488
      case PLUGIN_PRAGMAS:
489
      case PLUGIN_FINISH:
490
      case PLUGIN_GGC_START:
491
      case PLUGIN_GGC_MARKING:
492
      case PLUGIN_GGC_END:
493
      case PLUGIN_ALL_PASSES_START:
494
      case PLUGIN_ALL_PASSES_END:
495
      case PLUGIN_ALL_IPA_PASSES_START:
496
      case PLUGIN_ALL_IPA_PASSES_END:
497
      case PLUGIN_OVERRIDE_GATE:
498
      case PLUGIN_PASS_EXECUTION:
499
      case PLUGIN_EARLY_GIMPLE_PASSES_START:
500
      case PLUGIN_EARLY_GIMPLE_PASSES_END:
501
      case PLUGIN_NEW_PASS:
502
        {
503
          /* Iterate over every callback registered with this event and
504
             call it.  */
505
          struct callback_info *callback = plugin_callbacks[event];
506
 
507
          if (!callback)
508
            retval = PLUGEVT_NO_CALLBACK;
509
          for ( ; callback; callback = callback->next)
510
            (*callback->func) (gcc_data, callback->user_data);
511
        }
512
        break;
513
 
514
      case PLUGIN_PASS_MANAGER_SETUP:
515
      case PLUGIN_REGISTER_GGC_ROOTS:
516
      case PLUGIN_REGISTER_GGC_CACHES:
517
        gcc_assert (false);
518
    }
519
 
520
  timevar_pop (TV_PLUGIN_RUN);
521
  return retval;
522
}
523
 
524
#ifdef ENABLE_PLUGIN
525
/* We need a union to cast dlsym return value to a function pointer
526
   as ISO C forbids assignment between function pointer and 'void *'.
527
   Use explicit union instead of __extension__(<union_cast>) for
528
   portability.  */
529
#define PTR_UNION_TYPE(TOTYPE) union { void *_q; TOTYPE _nq; }
530
#define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
531
#define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
532
 
533
/* Try to initialize PLUGIN. Return true if successful. */
534
 
535
static bool
536
try_init_one_plugin (struct plugin_name_args *plugin)
537
{
538
  void *dl_handle;
539
  plugin_init_func plugin_init;
540
  const char *err;
541
  PTR_UNION_TYPE (plugin_init_func) plugin_init_union;
542
 
543
  /* We use RTLD_NOW to accelerate binding and detect any mismatch
544
     between the API expected by the plugin and the GCC API; we use
545
     RTLD_GLOBAL which is useful to plugins which themselves call
546
     dlopen.  */
547
  dl_handle = dlopen (plugin->full_name, RTLD_NOW | RTLD_GLOBAL);
548
  if (!dl_handle)
549
    {
550
      error ("Cannot load plugin %s\n%s", plugin->full_name, dlerror ());
551
      return false;
552
    }
553
 
554
  /* Clear any existing error.  */
555
  dlerror ();
556
 
557
  /* Check the plugin license.  */
558
  if (dlsym (dl_handle, str_license) == NULL)
559
    fatal_error ("plugin %s is not licensed under a GPL-compatible license\n"
560
                 "%s", plugin->full_name, dlerror ());
561
 
562
  PTR_UNION_AS_VOID_PTR (plugin_init_union) =
563
      dlsym (dl_handle, str_plugin_init_func_name);
564
  plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union);
565
 
566
  if ((err = dlerror ()) != NULL)
567
    {
568
      error ("Cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
569
             plugin->full_name, err);
570
      return false;
571
    }
572
 
573
  /* Call the plugin-provided initialization routine with the arguments.  */
574
  if ((*plugin_init) (plugin, &gcc_version))
575
    {
576
      error ("Fail to initialize plugin %s", plugin->full_name);
577
      return false;
578
    }
579
 
580
  return true;
581
}
582
 
583
 
584
/* Routine to dlopen and initialize one plugin. This function is passed to
585
   (and called by) the hash table traverse routine. Return 1 for the
586
   htab_traverse to continue scan, 0 to stop.
587
 
588
   SLOT - slot of the hash table element
589
   INFO - auxiliary pointer handed to hash table traverse routine
590
          (unused in this function)  */
591
 
592
static int
593
init_one_plugin (void **slot, void * ARG_UNUSED (info))
594
{
595
  struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
596
  bool ok = try_init_one_plugin (plugin);
597
  if (!ok)
598
    {
599
      htab_remove_elt (plugin_name_args_tab, plugin->base_name);
600
      XDELETE (plugin);
601
    }
602
  return 1;
603
}
604
 
605
#endif  /* ENABLE_PLUGIN  */
606
 
607
/* Main plugin initialization function.  Called from compile_file() in
608
   toplev.c.  */
609
 
610
void
611
initialize_plugins (void)
612
{
613
  /* If no plugin was specified in the command-line, simply return.  */
614
  if (!plugin_name_args_tab)
615
    return;
616
 
617
  timevar_push (TV_PLUGIN_INIT);
618
 
619
#ifdef ENABLE_PLUGIN
620
  /* Traverse and initialize each plugin specified in the command-line.  */
621
  htab_traverse_noresize (plugin_name_args_tab, init_one_plugin, NULL);
622
#endif
623
 
624
  timevar_pop (TV_PLUGIN_INIT);
625
}
626
 
627
/* Release memory used by one plugin. */
628
 
629
static int
630
finalize_one_plugin (void **slot, void * ARG_UNUSED (info))
631
{
632
  struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
633
  XDELETE (plugin);
634
  return 1;
635
}
636
 
637
/* Free memory allocated by the plugin system. */
638
 
639
void
640
finalize_plugins (void)
641
{
642
  if (!plugin_name_args_tab)
643
    return;
644
 
645
  /* We can now delete the plugin_name_args object as it will no longer
646
     be used. Note that base_name and argv fields (both of which were also
647
     dynamically allocated) are not freed as they could still be used by
648
     the plugin code.  */
649
 
650
  htab_traverse_noresize (plugin_name_args_tab, finalize_one_plugin, NULL);
651
 
652
  /* PLUGIN_NAME_ARGS_TAB is no longer needed, just delete it.  */
653
  htab_delete (plugin_name_args_tab);
654
  plugin_name_args_tab = NULL;
655
}
656
 
657
/* Used to pass options to htab_traverse callbacks. */
658
 
659
struct print_options
660
{
661
  FILE *file;
662
  const char *indent;
663
};
664
 
665
/* Print the version of one plugin. */
666
 
667
static int
668
print_version_one_plugin (void **slot, void *data)
669
{
670
  struct print_options *opt = (struct print_options *) data;
671
  struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
672
  const char *version = plugin->version ? plugin->version : "Unknown version.";
673
 
674
  fprintf (opt->file, " %s%s: %s\n", opt->indent, plugin->base_name, version);
675
  return 1;
676
}
677
 
678
/* Print the version of each plugin. */
679
 
680
void
681
print_plugins_versions (FILE *file, const char *indent)
682
{
683
  struct print_options opt;
684
  opt.file = file;
685
  opt.indent = indent;
686
  if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
687
    return;
688
 
689
  fprintf (file, "%sVersions of loaded plugins:\n", indent);
690
  htab_traverse_noresize (plugin_name_args_tab, print_version_one_plugin, &opt);
691
}
692
 
693
/* Print help for one plugin. SLOT is the hash table slot. DATA is the
694
   argument to htab_traverse_noresize. */
695
 
696
static int
697
print_help_one_plugin (void **slot, void *data)
698
{
699
  struct print_options *opt = (struct print_options *) data;
700
  struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
701
  const char *help = plugin->help ? plugin->help : "No help available .";
702
 
703
  char *dup = xstrdup (help);
704
  char *p, *nl;
705
  fprintf (opt->file, " %s%s:\n", opt->indent, plugin->base_name);
706
 
707
  for (p = nl = dup; nl; p = nl)
708
    {
709
      nl = strchr (nl, '\n');
710
      if (nl)
711
        {
712
          *nl = '\0';
713
          nl++;
714
        }
715
      fprintf (opt->file, "   %s %s\n", opt->indent, p);
716
    }
717
 
718
  free (dup);
719
  return 1;
720
}
721
 
722
/* Print help for each plugin. The output goes to FILE and every line starts
723
   with INDENT. */
724
 
725
void
726
print_plugins_help (FILE *file, const char *indent)
727
{
728
  struct print_options opt;
729
  opt.file = file;
730
  opt.indent = indent;
731
  if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
732
    return;
733
 
734
  fprintf (file, "%sHelp for the loaded plugins:\n", indent);
735
  htab_traverse_noresize (plugin_name_args_tab, print_help_one_plugin, &opt);
736
}
737
 
738
 
739
/* Return true if plugins have been loaded.  */
740
 
741
bool
742
plugins_active_p (void)
743
{
744
  int event;
745
 
746
  for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
747
    if (plugin_callbacks[event])
748
      return true;
749
 
750
  return false;
751
}
752
 
753
 
754
/* Dump to FILE the names and associated events for all the active
755
   plugins.  */
756
 
757
void
758
dump_active_plugins (FILE *file)
759
{
760
  int event;
761
 
762
  if (!plugins_active_p ())
763
    return;
764
 
765
  fprintf (file, FMT_FOR_PLUGIN_EVENT " | %s\n", _("Event"), _("Plugins"));
766
  for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
767
    if (plugin_callbacks[event])
768
      {
769
        struct callback_info *ci;
770
 
771
        fprintf (file, FMT_FOR_PLUGIN_EVENT " |", plugin_event_name[event]);
772
 
773
        for (ci = plugin_callbacks[event]; ci; ci = ci->next)
774
          fprintf (file, " %s", ci->plugin_name);
775
 
776
        putc('\n', file);
777
      }
778
}
779
 
780
 
781
/* Dump active plugins to stderr.  */
782
 
783
void
784
debug_active_plugins (void)
785
{
786
  dump_active_plugins (stderr);
787
}
788
 
789
/* The default version check. Compares every field in VERSION. */
790
 
791
bool
792
plugin_default_version_check (struct plugin_gcc_version *gcc_version,
793
                              struct plugin_gcc_version *plugin_version)
794
{
795
  if (!gcc_version || !plugin_version)
796
    return false;
797
 
798
  if (strcmp (gcc_version->basever, plugin_version->basever))
799
    return false;
800
  if (strcmp (gcc_version->datestamp, plugin_version->datestamp))
801
    return false;
802
  if (strcmp (gcc_version->devphase, plugin_version->devphase))
803
    return false;
804
  if (strcmp (gcc_version->revision, plugin_version->revision))
805
    return false;
806
  if (strcmp (gcc_version->configuration_arguments,
807
              plugin_version->configuration_arguments))
808
    return false;
809
  return true;
810
}
811
 
812
/* Return the current value of event_last, so that plugins which provide
813
   additional functionality for events for the benefit of high-level plugins
814
   know how many valid entries plugin_event_name holds.  */
815
 
816
int
817
get_event_last (void)
818
{
819
  return event_last;
820
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.