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

source code of libcc1/context.cc