172 lines
4.2 KiB
C++
172 lines
4.2 KiB
C++
|
/* Generic plugin context
|
|||
|
Copyright (C) 2020 Free Software Foundation, Inc.
|
|||
|
|
|||
|
This file is part of GCC.
|
|||
|
|
|||
|
GCC is free software; you can redistribute it and/or modify it under
|
|||
|
the terms of the GNU General Public License as published by the Free
|
|||
|
Software Foundation; either version 3, or (at your option) any later
|
|||
|
version.
|
|||
|
|
|||
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|||
|
for more details.
|
|||
|
|
|||
|
You should have received a copy of the GNU General Public License
|
|||
|
along with GCC; see the file COPYING3. If not see
|
|||
|
<http://www.gnu.org/licenses/>. */
|
|||
|
|
|||
|
#include <cc1plugin-config.h>
|
|||
|
|
|||
|
#undef PACKAGE_NAME
|
|||
|
#undef PACKAGE_STRING
|
|||
|
#undef PACKAGE_TARNAME
|
|||
|
#undef PACKAGE_VERSION
|
|||
|
|
|||
|
#include "../gcc/config.h"
|
|||
|
|
|||
|
#undef PACKAGE_NAME
|
|||
|
#undef PACKAGE_STRING
|
|||
|
#undef PACKAGE_TARNAME
|
|||
|
#undef PACKAGE_VERSION
|
|||
|
|
|||
|
#include "gcc-plugin.h"
|
|||
|
#include "system.h"
|
|||
|
#include "coretypes.h"
|
|||
|
#include "stringpool.h"
|
|||
|
#include "hash-set.h"
|
|||
|
#include "diagnostic.h"
|
|||
|
#include "langhooks.h"
|
|||
|
#include "langhooks-def.h"
|
|||
|
|
|||
|
#include "gcc-interface.h"
|
|||
|
|
|||
|
#include "context.hh"
|
|||
|
#include "marshall.hh"
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#ifdef __GNUC__
|
|||
|
#pragma GCC visibility push(default)
|
|||
|
#endif
|
|||
|
int plugin_is_GPL_compatible;
|
|||
|
#ifdef __GNUC__
|
|||
|
#pragma GCC visibility pop
|
|||
|
#endif
|
|||
|
|
|||
|
cc1_plugin::plugin_context *cc1_plugin::current_context;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// This is put into the lang hooks when the plugin starts.
|
|||
|
|
|||
|
static void
|
|||
|
plugin_print_error_function (diagnostic_context *context, const char *file,
|
|||
|
diagnostic_info *diagnostic)
|
|||
|
{
|
|||
|
if (current_function_decl != NULL_TREE
|
|||
|
&& DECL_NAME (current_function_decl) != NULL_TREE
|
|||
|
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
|
|||
|
GCC_FE_WRAPPER_FUNCTION) == 0)
|
|||
|
return;
|
|||
|
lhd_print_error_function (context, file, diagnostic);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
location_t
|
|||
|
cc1_plugin::plugin_context::get_location_t (const char *filename,
|
|||
|
unsigned int line_number)
|
|||
|
{
|
|||
|
if (filename == NULL)
|
|||
|
return UNKNOWN_LOCATION;
|
|||
|
|
|||
|
filename = intern_filename (filename);
|
|||
|
linemap_add (line_table, LC_ENTER, false, filename, line_number);
|
|||
|
location_t loc = linemap_line_start (line_table, line_number, 0);
|
|||
|
linemap_add (line_table, LC_LEAVE, false, NULL, 0);
|
|||
|
return loc;
|
|||
|
}
|
|||
|
|
|||
|
// Add a file name to FILE_NAMES and return the canonical copy.
|
|||
|
const char *
|
|||
|
cc1_plugin::plugin_context::intern_filename (const char *filename)
|
|||
|
{
|
|||
|
const char **slot = file_names.find_slot (filename, INSERT);
|
|||
|
if (*slot == NULL)
|
|||
|
{
|
|||
|
/* The file name must live as long as the line map, which
|
|||
|
effectively means as long as this compilation. So, we copy
|
|||
|
the string here but never free it. */
|
|||
|
*slot = xstrdup (filename);
|
|||
|
}
|
|||
|
return *slot;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
cc1_plugin::plugin_context::mark ()
|
|||
|
{
|
|||
|
for (const auto &item : address_map)
|
|||
|
{
|
|||
|
ggc_mark (item->decl);
|
|||
|
ggc_mark (item->address);
|
|||
|
}
|
|||
|
|
|||
|
for (const auto &item : preserved)
|
|||
|
ggc_mark (&item);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// Perform GC marking.
|
|||
|
|
|||
|
static void
|
|||
|
gc_mark (void *, void *)
|
|||
|
{
|
|||
|
if (cc1_plugin::current_context != NULL)
|
|||
|
cc1_plugin::current_context->mark ();
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
cc1_plugin::generic_plugin_init (struct plugin_name_args *plugin_info,
|
|||
|
unsigned int version)
|
|||
|
{
|
|||
|
long fd = -1;
|
|||
|
for (int i = 0; i < plugin_info->argc; ++i)
|
|||
|
{
|
|||
|
if (strcmp (plugin_info->argv[i].key, "fd") == 0)
|
|||
|
{
|
|||
|
char *tail;
|
|||
|
errno = 0;
|
|||
|
fd = strtol (plugin_info->argv[i].value, &tail, 0);
|
|||
|
if (*tail != '\0' || errno != 0)
|
|||
|
fatal_error (input_location,
|
|||
|
"%s: invalid file descriptor argument to plugin",
|
|||
|
plugin_info->base_name);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (fd == -1)
|
|||
|
fatal_error (input_location,
|
|||
|
"%s: required plugin argument %<fd%> is missing",
|
|||
|
plugin_info->base_name);
|
|||
|
|
|||
|
current_context = new plugin_context (fd);
|
|||
|
|
|||
|
// Handshake.
|
|||
|
cc1_plugin::protocol_int h_version;
|
|||
|
if (!current_context->require ('H')
|
|||
|
|| ! ::cc1_plugin::unmarshall (current_context, &h_version))
|
|||
|
fatal_error (input_location,
|
|||
|
"%s: handshake failed", plugin_info->base_name);
|
|||
|
if (h_version != version)
|
|||
|
fatal_error (input_location,
|
|||
|
"%s: unknown version in handshake", plugin_info->base_name);
|
|||
|
|
|||
|
register_callback (plugin_info->base_name, PLUGIN_GGC_MARKING,
|
|||
|
gc_mark, NULL);
|
|||
|
|
|||
|
lang_hooks.print_error_function = plugin_print_error_function;
|
|||
|
}
|