1/* Generic plugin context
2 Copyright (C) 2020-2024 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#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
53int plugin_is_GPL_compatible;
54#ifdef __GNUC__
55#pragma GCC visibility pop
56#endif
57
58cc1_plugin::plugin_context *cc1_plugin::current_context;
59
60
61
62// This is put into the lang hooks when the plugin starts.
63
64static void
65plugin_print_error_function (diagnostic_context *context, const char *file,
66 const 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
78location_t
79cc1_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, sysp: false, to_file: filename, to_line: line_number);
87 location_t loc = linemap_line_start (set: line_table, to_line: line_number, max_column_hint: 0);
88 linemap_add (line_table, LC_LEAVE, sysp: false, NULL, to_line: 0);
89 return loc;
90}
91
92// Add a file name to FILE_NAMES and return the canonical copy.
93const char *
94cc1_plugin::plugin_context::intern_filename (const char *filename)
95{
96 const char **slot = file_names.find_slot (value: filename, insert: 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
107void
108cc1_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
124static void
125gc_mark (void *, void *)
126{
127 if (cc1_plugin::current_context != NULL)
128 cc1_plugin::current_context->mark ();
129}
130
131void
132cc1_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 (s1: plugin_info->argv[i].key, s2: "fd") == 0)
139 {
140 char *tail;
141 errno = 0;
142 fd = strtol (nptr: plugin_info->argv[i].value, endptr: &tail, base: 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 (c: 'H')
160 || ! ::cc1_plugin::unmarshall (conn: current_context, scalar: &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_name: plugin_info->base_name, event: PLUGIN_GGC_MARKING,
168 callback: gc_mark, NULL);
169
170 lang_hooks.print_error_function = plugin_print_error_function;
171}
172

source code of libcc1/context.cc