]> git.ipfire.org Git - thirdparty/gcc.git/blob - libcc1/context.cc
af5884b3db99c1cc86d948bbb5f6e7e29c937e4d
[thirdparty/gcc.git] / libcc1 / context.cc
1 /* Generic plugin context
2 Copyright (C) 2020-2025 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 #include "diagnostic-format-text.h"
43
44 #include "gcc-interface.h"
45
46 #include "context.hh"
47 #include "marshall.hh"
48
49 \f
50
51 #ifdef __GNUC__
52 #pragma GCC visibility push(default)
53 #endif
54 int plugin_is_GPL_compatible;
55 #ifdef __GNUC__
56 #pragma GCC visibility pop
57 #endif
58
59 cc1_plugin::plugin_context *cc1_plugin::current_context;
60
61 \f
62
63 // This is put into the lang hooks when the plugin starts.
64
65 static void
66 plugin_print_error_function (diagnostic_text_output_format &text_output,
67 const char *file,
68 const diagnostic_info *diagnostic)
69 {
70 if (current_function_decl != NULL_TREE
71 && DECL_NAME (current_function_decl) != NULL_TREE
72 && strcmp (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
73 GCC_FE_WRAPPER_FUNCTION) == 0)
74 return;
75 lhd_print_error_function (text_output, file, diagnostic);
76 }
77
78 \f
79
80 location_t
81 cc1_plugin::plugin_context::get_location_t (const char *filename,
82 unsigned int line_number)
83 {
84 if (filename == NULL)
85 return UNKNOWN_LOCATION;
86
87 filename = intern_filename (filename);
88 linemap_add (line_table, LC_ENTER, false, filename, line_number);
89 location_t loc = linemap_line_start (line_table, line_number, 0);
90 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
91 return loc;
92 }
93
94 // Add a file name to FILE_NAMES and return the canonical copy.
95 const char *
96 cc1_plugin::plugin_context::intern_filename (const char *filename)
97 {
98 const char **slot = file_names.find_slot (filename, INSERT);
99 if (*slot == NULL)
100 {
101 /* The file name must live as long as the line map, which
102 effectively means as long as this compilation. So, we copy
103 the string here but never free it. */
104 *slot = xstrdup (filename);
105 }
106 return *slot;
107 }
108
109 void
110 cc1_plugin::plugin_context::mark ()
111 {
112 for (const auto &item : address_map)
113 {
114 ggc_mark (item->decl);
115 ggc_mark (item->address);
116 }
117
118 for (const auto &item : preserved)
119 ggc_mark (&item);
120 }
121
122 \f
123
124 // Perform GC marking.
125
126 static void
127 gc_mark (void *, void *)
128 {
129 if (cc1_plugin::current_context != NULL)
130 cc1_plugin::current_context->mark ();
131 }
132
133 void
134 cc1_plugin::generic_plugin_init (struct plugin_name_args *plugin_info,
135 unsigned int version)
136 {
137 long fd = -1;
138 for (int i = 0; i < plugin_info->argc; ++i)
139 {
140 if (strcmp (plugin_info->argv[i].key, "fd") == 0)
141 {
142 char *tail;
143 errno = 0;
144 fd = strtol (plugin_info->argv[i].value, &tail, 0);
145 if (*tail != '\0' || errno != 0)
146 fatal_error (input_location,
147 "%s: invalid file descriptor argument to plugin",
148 plugin_info->base_name);
149 break;
150 }
151 }
152 if (fd == -1)
153 fatal_error (input_location,
154 "%s: required plugin argument %<fd%> is missing",
155 plugin_info->base_name);
156
157 current_context = new plugin_context (fd);
158
159 // Handshake.
160 cc1_plugin::protocol_int h_version;
161 if (!current_context->require ('H')
162 || ! ::cc1_plugin::unmarshall (current_context, &h_version))
163 fatal_error (input_location,
164 "%s: handshake failed", plugin_info->base_name);
165 if (h_version != version)
166 fatal_error (input_location,
167 "%s: unknown version in handshake", plugin_info->base_name);
168
169 register_callback (plugin_info->base_name, PLUGIN_GGC_MARKING,
170 gc_mark, NULL);
171
172 lang_hooks.print_error_function = plugin_print_error_function;
173 }