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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [plugin.c] - Blame information for rev 804

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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