xref: /netbsd-src/external/gpl3/gcc/dist/libcc1/context.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* Generic plugin context
2    Copyright (C) 2020-2022 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 it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 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 #include <cc1plugin-config.h>
21 
22 #undef PACKAGE_NAME
23 #undef PACKAGE_STRING
24 #undef PACKAGE_TARNAME
25 #undef PACKAGE_VERSION
26 
27 #include "../gcc/config.h"
28 
29 #undef PACKAGE_NAME
30 #undef PACKAGE_STRING
31 #undef PACKAGE_TARNAME
32 #undef PACKAGE_VERSION
33 
34 #include "gcc-plugin.h"
35 #include "system.h"
36 #include "coretypes.h"
37 #include "stringpool.h"
38 #include "hash-set.h"
39 #include "diagnostic.h"
40 #include "langhooks.h"
41 #include "langhooks-def.h"
42 
43 #include "gcc-interface.h"
44 
45 #include "context.hh"
46 #include "marshall.hh"
47 
48 
49 
50 #ifdef __GNUC__
51 #pragma GCC visibility push(default)
52 #endif
53 int plugin_is_GPL_compatible;
54 #ifdef __GNUC__
55 #pragma GCC visibility pop
56 #endif
57 
58 cc1_plugin::plugin_context *cc1_plugin::current_context;
59 
60 
61 
62 // This is put into the lang hooks when the plugin starts.
63 
64 static void
plugin_print_error_function(diagnostic_context * context,const char * file,diagnostic_info * diagnostic)65 plugin_print_error_function (diagnostic_context *context, const char *file,
66 			     diagnostic_info *diagnostic)
67 {
68   if (current_function_decl != NULL_TREE
69       && DECL_NAME (current_function_decl) != NULL_TREE
70       && strcmp (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
71 		 GCC_FE_WRAPPER_FUNCTION) == 0)
72     return;
73   lhd_print_error_function (context, file, diagnostic);
74 }
75 
76 
77 
78 location_t
get_location_t(const char * filename,unsigned int line_number)79 cc1_plugin::plugin_context::get_location_t (const char *filename,
80 					    unsigned int line_number)
81 {
82   if (filename == NULL)
83     return UNKNOWN_LOCATION;
84 
85   filename = intern_filename (filename);
86   linemap_add (line_table, LC_ENTER, false, filename, line_number);
87   location_t loc = linemap_line_start (line_table, line_number, 0);
88   linemap_add (line_table, LC_LEAVE, false, NULL, 0);
89   return loc;
90 }
91 
92 // Add a file name to FILE_NAMES and return the canonical copy.
93 const char *
intern_filename(const char * filename)94 cc1_plugin::plugin_context::intern_filename (const char *filename)
95 {
96   const char **slot = file_names.find_slot (filename, INSERT);
97   if (*slot == NULL)
98     {
99       /* The file name must live as long as the line map, which
100 	 effectively means as long as this compilation.  So, we copy
101 	 the string here but never free it.  */
102       *slot = xstrdup (filename);
103     }
104   return *slot;
105 }
106 
107 void
mark()108 cc1_plugin::plugin_context::mark ()
109 {
110   for (const auto &item : address_map)
111     {
112       ggc_mark (item->decl);
113       ggc_mark (item->address);
114     }
115 
116   for (const auto &item : preserved)
117     ggc_mark (&item);
118 }
119 
120 
121 
122 // Perform GC marking.
123 
124 static void
gc_mark(void *,void *)125 gc_mark (void *, void *)
126 {
127   if (cc1_plugin::current_context != NULL)
128     cc1_plugin::current_context->mark ();
129 }
130 
131 void
generic_plugin_init(struct plugin_name_args * plugin_info,unsigned int version)132 cc1_plugin::generic_plugin_init (struct plugin_name_args *plugin_info,
133 				 unsigned int version)
134 {
135   long fd = -1;
136   for (int i = 0; i < plugin_info->argc; ++i)
137     {
138       if (strcmp (plugin_info->argv[i].key, "fd") == 0)
139 	{
140 	  char *tail;
141 	  errno = 0;
142 	  fd = strtol (plugin_info->argv[i].value, &tail, 0);
143 	  if (*tail != '\0' || errno != 0)
144 	    fatal_error (input_location,
145 			 "%s: invalid file descriptor argument to plugin",
146 			 plugin_info->base_name);
147 	  break;
148 	}
149     }
150   if (fd == -1)
151     fatal_error (input_location,
152 		 "%s: required plugin argument %<fd%> is missing",
153 		 plugin_info->base_name);
154 
155   current_context = new plugin_context (fd);
156 
157   // Handshake.
158   cc1_plugin::protocol_int h_version;
159   if (!current_context->require ('H')
160       || ! ::cc1_plugin::unmarshall (current_context, &h_version))
161     fatal_error (input_location,
162 		 "%s: handshake failed", plugin_info->base_name);
163   if (h_version != version)
164     fatal_error (input_location,
165 		 "%s: unknown version in handshake", plugin_info->base_name);
166 
167   register_callback (plugin_info->base_name, PLUGIN_GGC_MARKING,
168 		     gc_mark, NULL);
169 
170   lang_hooks.print_error_function = plugin_print_error_function;
171 }
172