1 /* This plugin recursively dumps the source-code location ranges of
2    expressions, at the pre-gimplification tree stage.  */
3 /* { dg-options "-O" } */
4 
5 #include "gcc-plugin.h"
6 #include "config.h"
7 #include "system.h"
8 #include "coretypes.h"
9 #include "tm.h"
10 #include "tree.h"
11 #include "stringpool.h"
12 #include "toplev.h"
13 #include "basic-block.h"
14 #include "hash-table.h"
15 #include "vec.h"
16 #include "ggc.h"
17 #include "basic-block.h"
18 #include "tree-ssa-alias.h"
19 #include "internal-fn.h"
20 #include "gimple-fold.h"
21 #include "tree-eh.h"
22 #include "gimple-expr.h"
23 #include "is-a.h"
24 #include "gimple.h"
25 #include "gimple-iterator.h"
26 #include "tree.h"
27 #include "tree-pass.h"
28 #include "intl.h"
29 #include "plugin-version.h"
30 #include "diagnostic.h"
31 #include "context.h"
32 #include "gcc-rich-location.h"
33 #include "print-tree.h"
34 
35 int plugin_is_GPL_compatible;
36 
37 static void
show_tree(tree node)38 show_tree (tree node)
39 {
40   if (!CAN_HAVE_RANGE_P (node))
41     return;
42 
43   gcc_rich_location richloc (EXPR_LOCATION (node));
44   richloc.add_expr (node, NULL);
45 
46   if (richloc.get_num_locations () < 2)
47     {
48       error_at (&richloc, "range not found");
49       return;
50     }
51 
52   enum tree_code code = TREE_CODE (node);
53 
54   location_range *range = richloc.get_range (1);
55   inform (&richloc, "%s", get_tree_code_name (code));
56 
57   /* Recurse.  */
58   int min_idx = 0;
59   int max_idx = TREE_OPERAND_LENGTH (node);
60   switch (code)
61     {
62     case CALL_EXPR:
63       min_idx = 3;
64       break;
65 
66     default:
67       break;
68     }
69 
70   for (int i = min_idx; i < max_idx; i++)
71     show_tree (TREE_OPERAND (node, i));
72 }
73 
74 tree
cb_walk_tree_fn(tree * tp,int * walk_subtrees,void * data ATTRIBUTE_UNUSED)75 cb_walk_tree_fn (tree * tp, int * walk_subtrees,
76 		 void * data ATTRIBUTE_UNUSED)
77 {
78   if (TREE_CODE (*tp) != CALL_EXPR)
79     return NULL_TREE;
80 
81   tree call_expr = *tp;
82   tree fn = CALL_EXPR_FN (call_expr);
83   if (TREE_CODE (fn) != ADDR_EXPR)
84     return NULL_TREE;
85   fn = TREE_OPERAND (fn, 0);
86   if (TREE_CODE (fn) != FUNCTION_DECL)
87     return NULL_TREE;
88   if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fn)), "__show_tree"))
89     return NULL_TREE;
90 
91   /* Get arg 1; print it! */
92   tree arg = CALL_EXPR_ARG (call_expr, 1);
93 
94   show_tree (arg);
95 
96   return NULL_TREE;
97 }
98 
99 static void
callback(void * gcc_data,void * user_data)100 callback (void *gcc_data, void *user_data)
101 {
102   tree fndecl = (tree)gcc_data;
103   walk_tree (&DECL_SAVED_TREE (fndecl), cb_walk_tree_fn, NULL, NULL);
104 }
105 
106 int
plugin_init(struct plugin_name_args * plugin_info,struct plugin_gcc_version * version)107 plugin_init (struct plugin_name_args *plugin_info,
108 	     struct plugin_gcc_version *version)
109 {
110   struct register_pass_info pass_info;
111   const char *plugin_name = plugin_info->base_name;
112   int argc = plugin_info->argc;
113   struct plugin_argument *argv = plugin_info->argv;
114 
115   if (!plugin_default_version_check (version, &gcc_version))
116     return 1;
117 
118   register_callback (plugin_name,
119 		     PLUGIN_PRE_GENERICIZE,
120 		     callback,
121 		     NULL);
122 
123   return 0;
124 }
125