1/* Generic plugin context 2 Copyright (C) 2020-2022 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 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, 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. 93const char * 94cc1_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 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 (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