1 /* A trivial (dumb) plugin example that shows how to use the GCC plugin
2    mechanism.  */
3 
4 #include "gcc-plugin.h"
5 #include <stdlib.h>
6 #include "config.h"
7 #include "system.h"
8 #include "coretypes.h"
9 #include "tree.h"
10 #include "tree-pass.h"
11 #include "intl.h"
12 #include "toplev.h"
13 #include "diagnostic.h"
14 #include "context.h"
15 
16 int plugin_is_GPL_compatible;
17 
18 /* Callback function to invoke after GCC finishes parsing a struct.  */
19 
20 void
handle_struct(void * event_data,void * data)21 handle_struct (void *event_data, void *data)
22 {
23   tree type = (tree) event_data;
24   warning (0, G_("Process struct %s"),
25            IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
26 }
27 
28 /* Callback function to invoke before the function body is genericized.  */
29 
30 void
handle_pre_generic(void * event_data,void * data)31 handle_pre_generic (void *event_data, void *data)
32 {
33   tree fndecl = (tree) event_data;
34   warning (0, G_("Before genericizing function %s"),
35            IDENTIFIER_POINTER (DECL_NAME (fndecl)));
36 }
37 
38 /* Callback function to invoke after GCC finishes the compilation unit.  */
39 
40 void
handle_end_of_compilation_unit(void * event_data,void * data)41 handle_end_of_compilation_unit (void *event_data, void *data)
42 {
43   warning (0, G_("End of compilation unit"));
44 }
45 
46 
47 namespace {
48 
49 const pass_data pass_data_dumb_plugin_example =
50 {
51   GIMPLE_PASS, /* type */
52   "dumb_plugin_example", /* name */
53   OPTGROUP_NONE, /* optinfo_flags */
54   TV_NONE, /* tv_id */
55   PROP_cfg, /* properties_required */
56   0, /* properties_provided */
57   0, /* properties_destroyed */
58   0, /* todo_flags_start */
59   0, /* todo_flags_finish */
60 };
61 
62 class pass_dumb_plugin_example : public gimple_opt_pass
63 {
64 public:
pass_dumb_plugin_example(gcc::context * ctxt)65   pass_dumb_plugin_example(gcc::context *ctxt)
66     : gimple_opt_pass(pass_data_dumb_plugin_example, ctxt)
67   {}
68 
69   /* opt_pass methods: */
70   virtual unsigned int execute (function *);
71 
72 }; // class pass_dumb_plugin_example
73 
74 unsigned int
execute(function *)75 pass_dumb_plugin_example::execute (function *)
76 {
77   warning (0, G_("Analyze function %s"),
78            IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
79   return 0;
80 }
81 
82 } // anon namespace
83 
84 static gimple_opt_pass *
make_pass_dumb_plugin_example(gcc::context * ctxt)85 make_pass_dumb_plugin_example (gcc::context *ctxt)
86 {
87   return new pass_dumb_plugin_example (ctxt);
88 }
89 
90 /* Initialization function that GCC calls. This plugin takes an argument
91    that specifies the name of the reference pass and an instance number,
92    both of which determine where the plugin pass should be inserted.  */
93 
94 int
plugin_init(struct plugin_name_args * plugin_info,struct plugin_gcc_version * version)95 plugin_init (struct plugin_name_args *plugin_info,
96              struct plugin_gcc_version *version)
97 {
98   struct register_pass_info pass_info;
99   const char *plugin_name = plugin_info->base_name;
100   int argc = plugin_info->argc;
101   struct plugin_argument *argv = plugin_info->argv;
102   char *ref_pass_name = NULL;
103   int ref_instance_number = 0;
104   int i;
105 
106   /* Process the plugin arguments. This plugin takes the following arguments:
107      ref-pass-name=<PASS_NAME> and ref-pass-instance-num=<NUM>.  */
108   for (i = 0; i < argc; ++i)
109     {
110       if (!strcmp (argv[i].key, "ref-pass-name"))
111         {
112           if (argv[i].value)
113             ref_pass_name = argv[i].value;
114           else
115             warning (0, G_("option '-fplugin-arg-%s-ref-pass-name'"
116                            " requires a pass name"), plugin_name);
117         }
118       else if (!strcmp (argv[i].key, "ref-pass-instance-num"))
119         {
120           if (argv[i].value)
121             ref_instance_number = strtol (argv[i].value, NULL, 0);
122           else
123             warning (0, G_("option '-fplugin-arg-%s-ref-pass-instance-num'"
124                            " requires an integer value"), plugin_name);
125         }
126       else
127         warning (0, G_("plugin %qs: unrecognized argument %qs ignored"),
128                  plugin_name, argv[i].key);
129     }
130 
131   if (!ref_pass_name)
132     {
133       error (G_("plugin %qs requires a reference pass name"), plugin_name);
134       return 1;
135     }
136 
137   pass_info.pass = make_pass_dumb_plugin_example (g);
138   pass_info.reference_pass_name = ref_pass_name;
139   pass_info.ref_pass_instance_number = ref_instance_number;
140   pass_info.pos_op = PASS_POS_INSERT_AFTER;
141 
142   register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
143 
144   register_callback (plugin_name, PLUGIN_FINISH_TYPE, handle_struct, NULL);
145 
146   register_callback (plugin_name, PLUGIN_PRE_GENERICIZE,
147                      handle_pre_generic, NULL);
148 
149   register_callback (plugin_name, PLUGIN_FINISH_UNIT,
150                      handle_end_of_compilation_unit, NULL);
151   return 0;
152 }
153