public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/5] export finish_bitfield_layout from stor-layout
  2014-05-16 15:26 [PATCH 0/5] let gdb reuse gcc'c C compiler Tom Tromey
@ 2014-05-16 15:26 ` Tom Tromey
  2014-05-16 18:27   ` Jeff Law
  2014-05-16 15:27 ` [PATCH 2/5] c_diagnostic_ignored_function hack Tom Tromey
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 101+ messages in thread
From: Tom Tromey @ 2014-05-16 15:26 UTC (permalink / raw)
  To: gcc-patches; +Cc: Tom Tromey

The gdb plugin handles some aspects of type layout on its own.  It
does this because it knows the layout of types, but not the path by
which the layout was determined -- so normal gcc things like
TYPE_PACKED cannot be used.

This patch exposes one bit of stor-layout so it can be used by the
plugin.

2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* stor-layout.c (finish_bitfield_layout): Now public.  Change
	argument type to 'tree'.
	(finish_record_layout): Update.
	* stor-layout.h (finish_bitfield_layout): Declare.
---
 gcc/ChangeLog     |  8 ++++++++
 gcc/stor-layout.c | 12 ++++++------
 gcc/stor-layout.h |  1 +
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 8fa4dc8..ad057d9 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -1931,10 +1931,10 @@ finish_bitfield_representative (tree repr, tree field)
 }
 
 /* Compute and set FIELD_DECLs for the underlying objects we should
-   use for bitfield access for the structure laid out with RLI.  */
+   use for bitfield access for the structure T.  */
 
-static void
-finish_bitfield_layout (record_layout_info rli)
+void
+finish_bitfield_layout (tree t)
 {
   tree field, prev;
   tree repr = NULL_TREE;
@@ -1943,10 +1943,10 @@ finish_bitfield_layout (record_layout_info rli)
      we could use the underlying type as hint for the representative
      if the bitfield would fit and the representative would not exceed
      the union in size.  */
-  if (TREE_CODE (rli->t) != RECORD_TYPE)
+  if (TREE_CODE (t) != RECORD_TYPE)
     return;
 
-  for (prev = NULL_TREE, field = TYPE_FIELDS (rli->t);
+  for (prev = NULL_TREE, field = TYPE_FIELDS (t);
        field; field = DECL_CHAIN (field))
     {
       if (TREE_CODE (field) != FIELD_DECL)
@@ -2033,7 +2033,7 @@ finish_record_layout (record_layout_info rli, int free_p)
   finalize_type_size (rli->t);
 
   /* Compute bitfield representatives.  */
-  finish_bitfield_layout (rli);
+  finish_bitfield_layout (rli->t);
 
   /* Propagate TYPE_PACKED to variants.  With C++ templates,
      handle_packed_attribute is too early to do this.  */
diff --git a/gcc/stor-layout.h b/gcc/stor-layout.h
index 0ff98f8..cd58672 100644
--- a/gcc/stor-layout.h
+++ b/gcc/stor-layout.h
@@ -35,6 +35,7 @@ extern tree rli_size_so_far (record_layout_info);
 extern void normalize_rli (record_layout_info);
 extern void place_field (record_layout_info, tree);
 extern void compute_record_mode (tree);
+extern void finish_bitfield_layout (tree);
 extern void finish_record_layout (record_layout_info, int);
 extern unsigned int element_precision (const_tree);
 extern void finalize_size_functions (void);
-- 
1.9.0

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [PATCH 0/5] let gdb reuse gcc'c C compiler
@ 2014-05-16 15:26 Tom Tromey
  2014-05-16 15:26 ` [PATCH 1/5] export finish_bitfield_layout from stor-layout Tom Tromey
                   ` (6 more replies)
  0 siblings, 7 replies; 101+ messages in thread
From: Tom Tromey @ 2014-05-16 15:26 UTC (permalink / raw)
  To: gcc-patches

Hi!

This patch series is half of a project to let gdb reuse gcc (which
half depends on which list you are seeing this on), so that users can
compile small snippets of code and evaluate them in the current
context of the inferior.

This first series implements this idea for C.  A user can compile a
code snippet and it will be inserted into the inferior and evaluated.
Declarations needed by the snippet are supplied by gdb, and there is a
bit of magic so that the snippets can refer to local variables in the
current frame.

The new command allows for arbitrary code to be inserted -- not just
expressions.  For example:

    (gdb) compile code int i; for (i = 0; i < 3; ++i) printf ("#%d\n", i)
    #0
    #1
    #2

This series supplies a gcc plugin to do most of the work, so that any
gcc crashes -- seen during development due to translation bugs -- do
not also crash gdb.

The interface between gdb and gcc is defined by a few files added to
include/.

There is a new shared library which gdb loads in order to communicate
with the gcc plugin.  This library communicates with the gcc plugin
using a simple, ad-hoc RPC mechanism.

This shared library exports a single public function which is used to
instantiate any needed objects.  This makes it simple to version the
API and avoid undue synchronization between gcc and gdb.

We think the plugin is best suited to be put into the gcc repository
because it is coupled more tightly to gcc than to gdb.

To try it out, just build gcc and gdb with the patches applied.  Then
set your PATH and LD_LIBRARY_PATH to point to the right subdirectories
of the new gcc install directory.

In later series we plan to extend this functionality; either on the
gcc side, say by writing a similar plugin for C++; or on the gdb side,
say by making it possible to compile breakpoint conditions.  However,
we haven't yet decided exactly which future projects we will tackle or
in what order.


^ permalink raw reply	[flat|nested] 101+ messages in thread

* [PATCH 2/5] c_diagnostic_ignored_function hack
  2014-05-16 15:26 [PATCH 0/5] let gdb reuse gcc'c C compiler Tom Tromey
  2014-05-16 15:26 ` [PATCH 1/5] export finish_bitfield_layout from stor-layout Tom Tromey
@ 2014-05-16 15:27 ` Tom Tromey
  2014-05-16 16:05   ` Joseph S. Myers
  2014-05-16 18:33   ` Jeff Law
  2014-05-16 15:27 ` [PATCH 3/5] introduce the binding oracle Tom Tromey
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 101+ messages in thread
From: Tom Tromey @ 2014-05-16 15:27 UTC (permalink / raw)
  To: gcc-patches; +Cc: Tom Tromey

In the typical case, when compiling a snippet of user code, gdb wraps
the user's text in a dummy function.

It's somewhat odd for users if an error in their code is mentioned as
coming from this dummy function.

This patch makes it possible to suppress the function-name display in
a straightforward way: it adds a new global which the plugin can set
to declare the name of the dummy function.

This patch seems like a bit of a hack, but there didn't seem to be a
notably cleaner approach.

2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* c-lang.c (c_diagnostic_ignored_function): New global.
	(c_print_error_function): New function.
	(LANG_HOOKS_PRINT_ERROR_FUNCTION): Define.
	* c-lang.h (c_diagnostic_ignored_function): Declare.
---
 gcc/c/ChangeLog |  8 ++++++++
 gcc/c/c-lang.c  | 22 ++++++++++++++++++++++
 gcc/c/c-lang.h  |  4 ++++
 3 files changed, 34 insertions(+)

diff --git a/gcc/c/c-lang.c b/gcc/c/c-lang.c
index 97c0443..e563813 100644
--- a/gcc/c/c-lang.c
+++ b/gcc/c/c-lang.c
@@ -35,6 +35,26 @@ along with GCC; see the file COPYING3.  If not see
 
 enum c_language_kind c_language = clk_c;
 
+// If non-zero, this names a function which should not be reported in
+// a diagnostic.  This is used by the gdb plugin to avoid showing the
+// generated function name to the user.
+const char *c_diagnostic_ignored_function;
+
+// An implementation of the print_error_function langhook that
+// respects C_DIAGNOSTIC_IGNORED_FUNCTION.
+static void
+c_print_error_function (diagnostic_context *context, const char *file,
+			diagnostic_info *diagnostic)
+{
+  if (c_diagnostic_ignored_function != NULL
+      && current_function_decl != NULL_TREE
+      && DECL_NAME (current_function_decl) != NULL_TREE
+      && strcmp (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
+		 c_diagnostic_ignored_function) == 0)
+    return;
+  lhd_print_error_function (context, file, diagnostic);
+}
+
 /* Lang hooks common to C and ObjC are declared in c-objc-common.h;
    consequently, there should be very few hooks below.  */
 
@@ -44,6 +64,8 @@ enum c_language_kind c_language = clk_c;
 #define LANG_HOOKS_INIT c_objc_common_init
 #undef LANG_HOOKS_INIT_TS
 #define LANG_HOOKS_INIT_TS c_common_init_ts
+#undef LANG_HOOKS_PRINT_ERROR_FUNCTION
+#define LANG_HOOKS_PRINT_ERROR_FUNCTION c_print_error_function
 
 /* Each front end provides its own lang hook initializer.  */
 struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
index 7fcf333..022206f 100644
--- a/gcc/c/c-lang.h
+++ b/gcc/c/c-lang.h
@@ -59,4 +59,8 @@ struct GTY(()) language_function {
    attribute lists.  */
 extern GTY(()) int current_omp_declare_target_attribute;
 
+/* If non-zero, the name of a function whose name should not be
+   reported in a diagnostic.  */
+extern const char *c_diagnostic_ignored_function;
+
 #endif /* ! GCC_C_LANG_H */
-- 
1.9.0

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [PATCH 4/5] add gcc/gdb interface files
  2014-05-16 15:26 [PATCH 0/5] let gdb reuse gcc'c C compiler Tom Tromey
                   ` (2 preceding siblings ...)
  2014-05-16 15:27 ` [PATCH 3/5] introduce the binding oracle Tom Tromey
@ 2014-05-16 15:27 ` Tom Tromey
  2014-05-22 12:52   ` Jeff Law
  2014-05-16 16:29 ` [PATCH 0/5] let gdb reuse gcc'c C compiler Mike Stump
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 101+ messages in thread
From: Tom Tromey @ 2014-05-16 15:27 UTC (permalink / raw)
  To: gcc-patches; +Cc: Tom Tromey

The gcc plugin is split into two parts.  One part is an ordinary gcc
plugin.  The other part is a shared library that is loaded by gdb.

This patch adds some files that define the interface exported by this
shared library to gdb.  These files also define the internal API by
which the gdb- and gcc-sides communicate.

These files will be kept in sync between gcc and gdb like much of
include/.

The exported API has been intentionally kept very simple.  In
particular only a single function is exported from the gdb-side
library; symbol visibility is used to hide everything else.  This
exported symbol is a function which is called to return a structure
holding function pointers that gdb then uses.  This structure is
versioned so that changes can be made without necessarily requiring a
simultaneous gdb upgrade.

Note that the C compiler API is broken out separately.  This lets us
extend it to other GCC front ends as desired.  We plan to investigate
C++ in the future.

2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
	    Jan Kratochvil  <jan.kratochvil@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* gcc-c-fe.def: New file.
	* gcc-c-interface.h: New file.
	* gcc-interface.h: New file.
---
 include/ChangeLog         |   8 ++
 include/gcc-c-fe.def      | 195 ++++++++++++++++++++++++++++++++++++++++
 include/gcc-c-interface.h | 220 ++++++++++++++++++++++++++++++++++++++++++++++
 include/gcc-interface.h   | 120 +++++++++++++++++++++++++
 4 files changed, 543 insertions(+)
 create mode 100644 include/gcc-c-fe.def
 create mode 100644 include/gcc-c-interface.h
 create mode 100644 include/gcc-interface.h

diff --git a/include/gcc-c-fe.def b/include/gcc-c-fe.def
new file mode 100644
index 0000000..dc5a41a
--- /dev/null
+++ b/include/gcc-c-fe.def
@@ -0,0 +1,195 @@
+/* Interface between GCC C FE and GDB  -*- c -*-
+
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program 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 of the License, or
+   (at your option) any later version.
+
+   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+
+/* Create a new "decl" in GCC.  A decl is a declaration, basically a
+   kind of symbol.
+
+   NAME is the name of the new symbol.  SYM_KIND is the kind of
+   symbol being requested.  SYM_TYPE is the new symbol's C type;
+   except for labels, where this is not meaningful and should be
+   zero.  If SUBSTITUTION_NAME is not NULL, then a reference to this
+   decl in the source will later be substituted with a dereference
+   of a variable of the given name.  Otherwise, for symbols having
+   an address (e.g., functions), ADDRESS is the address.  FILENAME
+   and LINE_NUMBER refer to the symbol's source location.  If this
+   is not known, FILENAME can be NULL and LINE_NUMBER can be 0.
+   This function returns the new decl.  */
+
+GCC_METHOD7 (gcc_decl, build_decl,
+	     const char */* name */,
+	     enum gcc_c_symbol_kind /* sym_kind */,
+	     gcc_type /* sym_type */,
+	     const char */* substitution_name */,
+	     gcc_address /* address */,
+	     const char */* filename */,
+	     unsigned int /* line_number */)
+
+/* Insert a GCC decl into the symbol table.  DECL is the decl to
+   insert.  IS_GLOBAL is true if this is an outermost binding, and
+   false if it is a possibly-shadowing binding.  */
+
+GCC_METHOD2 (int /* bool */, bind, gcc_decl /* decl */,
+	     int /* bool */ /* is_global */)
+
+/* Insert a tagged type into the symbol table.  NAME is the tag name
+   of the type and TAGGED_TYPE is the type itself.  TAGGED_TYPE must
+   be either a struct, union, or enum type, as these are the only
+   types that have tags.  FILENAME and LINE_NUMBER refer to the type's
+   source location.  If this is not known, FILENAME can be NULL and
+   LINE_NUMBER can be 0.  */
+
+GCC_METHOD4 (int /* bool */, tagbind,
+	     const char */* name */,
+	     gcc_type /* tagged_type */,
+	     const char * /* filename */,
+	     unsigned int /* line_number */)
+
+/* Return the type of a pointer to a given base type.  */
+
+GCC_METHOD1 (gcc_type, build_pointer_type,
+	     gcc_type /* base_type */)
+
+/* Create a new 'struct' type.  Initially it has no fields.  */
+
+GCC_METHOD0 (gcc_type, build_record_type)
+
+/* Create a new 'union' type.  Initially it has no fields.  */
+
+GCC_METHOD0 (gcc_type, build_union_type)
+
+/* Add a field to a struct or union type.  FIELD_NAME is the field's
+   name.  FIELD_TYPE is the type of the field.  BITSIZE and BITPOS
+   indicate where in the struct the field occurs.  */
+
+GCC_METHOD5 (int /* bool */, build_add_field,
+	     gcc_type /* record_or_union_type */,
+	     const char */* field_name */,
+	     gcc_type /* field_type */,
+	     unsigned long /* bitsize */,
+	     unsigned long /* bitpos */)
+
+/* After all the fields have been added to a struct or union, the
+   struct or union type must be "finished".  This does some final
+   cleanups in GCC.  */
+
+GCC_METHOD2 (int /* bool */, finish_record_or_union,
+	     gcc_type /* record_or_union_type */,
+	     unsigned long /* size_in_bytes */)
+
+/* Create a new 'enum' type.  The new type initially has no
+   associated constants.  */
+
+GCC_METHOD1 (gcc_type, build_enum_type,
+	     gcc_type /* underlying_int_type */)
+
+/* Add a new constant to an enum type.  NAME is the constant's
+   name and VALUE is its value.  */
+
+GCC_METHOD3 (int /* bool */, build_add_enum_constant,
+	     gcc_type /* enum_type */,
+	     const char */* name */,
+	     unsigned long /* value */)
+
+/* After all the constants have been added to an enum, the type must
+   be "finished".  This does some final cleanups in GCC.  */
+
+GCC_METHOD1 (int /* bool */, finish_enum_type, gcc_type /* enum_type */)
+
+/* Create a new function type.  RETURN_TYPE is the type returned by
+   the function, and ARGUMENT_TYPES is a vector, of length NARGS, of
+   the argument types.  IS_VARARGS is true if the function is
+   varargs.  */
+
+GCC_METHOD3 (gcc_type, build_function_type,
+	     gcc_type /* return_type */,
+	     const struct gcc_type_array * /* argument_types */,
+	     int /* bool */ /* is_varargs */)
+
+/* Return an integer type with the given properties.  */
+
+GCC_METHOD2 (gcc_type, int_type,
+	     int /* bool */ /* is_unsigned */,
+	     unsigned long /* size_in_bytes */)
+
+/* Return a floating point type with the given properties.  */
+
+GCC_METHOD1 (gcc_type, float_type,
+	     unsigned long /* size_in_bytes */)
+
+/* Return the 'void' type.  */
+
+GCC_METHOD0 (gcc_type, void_type)
+
+/* Return the 'bool' type.  */
+
+GCC_METHOD0 (gcc_type, bool_type)
+
+/* Create a new array type.  If NUM_ELEMENTS is -1, then the array
+   is assumed to have an unknown length.  */
+
+GCC_METHOD2 (gcc_type, build_array_type,
+	     gcc_type /* element_type */,
+	     int /* num_elements */)
+
+/* Create a new variably-sized array type.  UPPER_BOUND_NAME is the
+   name of a local variable that holds the upper bound of the array;
+   it is one less than the array size.  */
+
+GCC_METHOD2 (gcc_type, build_vla_array_type,
+	     gcc_type /* element_type */,
+	     const char * /* upper_bound_name */)
+
+/* Return a qualified variant of a given base type.  QUALIFIERS says
+   which qualifiers to use; it is composed of or'd together
+   constants from 'enum gcc_qualifiers'.  */
+
+GCC_METHOD2 (gcc_type, build_qualified_type,
+	     gcc_type /* unqualified_type */,
+	     enum gcc_qualifiers /* qualifiers */)
+
+/* Build a complex type given its element type.  */
+
+GCC_METHOD1 (gcc_type, build_complex_type,
+	     gcc_type /* element_type */)
+
+/* Build a vector type given its element type and number of
+   elements.  */
+
+GCC_METHOD2 (gcc_type, build_vector_type,
+	     gcc_type /* element_type */,
+	     int /* num_elements */)
+
+/* Build a constant.  NAME is the constant's name and VALUE is its
+   value.  FILENAME and LINE_NUMBER refer to the type's source
+   location.  If this is not known, FILENAME can be NULL and
+   LINE_NUMBER can be 0.  */
+
+GCC_METHOD5 (int /* bool */, build_constant,
+	     gcc_type /* type */,
+	     const char */* name */,
+	     unsigned long /* value */,
+	     const char * /* filename */,
+	     unsigned int /* line_number */)
+
+/* Emit an error and return an error type object.  */
+
+GCC_METHOD1 (gcc_type, error,
+	     const char */* message */)
diff --git a/include/gcc-c-interface.h b/include/gcc-c-interface.h
new file mode 100644
index 0000000..6cf81d2
--- /dev/null
+++ b/include/gcc-c-interface.h
@@ -0,0 +1,220 @@
+/* Interface between GCC C FE and GDB
+
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program 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 of the License, or
+   (at your option) any later version.
+
+   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_C_INTERFACE_H
+#define GCC_C_INTERFACE_H
+
+#include "gcc-interface.h"
+
+/* This header defines the interface to the GCC API.  It must be both
+   valid C and valid C++, because it is included by both programs.  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declaration.  */
+
+struct gcc_c_context;
+
+/*
+ * Definitions and declarations for the C front end.
+ */
+
+/* Defined versions of the C front-end API.  */
+
+enum gcc_c_api_version
+{
+  GCC_C_FE_VERSION_0 = 0
+};
+
+/* Qualifiers.  */
+
+enum gcc_qualifiers
+{
+  GCC_QUALIFIER_CONST = 1,
+  GCC_QUALIFIER_VOLATILE = 2,
+  GCC_QUALIFIER_RESTRICT = 4
+};
+
+/* This enumerates the kinds of decls that GDB can create.  */
+
+enum gcc_c_symbol_kind
+{
+  /* A function.  */
+
+  GCC_C_SYMBOL_FUNCTION,
+
+  /* A variable.  */
+
+  GCC_C_SYMBOL_VARIABLE,
+
+  /* A typedef.  */
+
+  GCC_C_SYMBOL_TYPEDEF,
+
+  /* A label.  */
+
+  GCC_C_SYMBOL_LABEL
+};
+
+/* This enumerates the types of symbols that GCC might request from
+   GDB.  */
+
+enum gcc_c_oracle_request
+{
+  /* An ordinary symbol -- a variable, function, typedef, or enum
+     constant.  */
+
+  GCC_C_ORACLE_SYMBOL,
+
+  /* A struct, union, or enum tag.  */
+
+  GCC_C_ORACLE_TAG,
+
+  /* A label.  */
+
+  GCC_C_ORACLE_LABEL
+};
+
+/* The type of the function called by GCC to ask GDB for a symbol's
+   definition.  DATUM is an arbitrary value supplied when the oracle
+   function is registered.  CONTEXT is the GCC context in which the
+   request is being made.  REQUEST specifies what sort of symbol is
+   being requested, and IDENTIFIER is the name of the symbol.  */
+
+typedef void gcc_c_oracle_function (void *datum,
+				    struct gcc_c_context *context,
+				    enum gcc_c_oracle_request request,
+				    const char *identifier);
+
+/* The type of the function called by GCC to ask GDB for a symbol's
+   address.  This should return 0 if the address is not known.  */
+
+typedef gcc_address gcc_c_symbol_address_function (void *datum,
+						   struct gcc_c_context *ctxt,
+						   const char *identifier);
+
+/* An array of types used for creating a function type.  */
+
+struct gcc_type_array
+{
+  /* Number of elements.  */
+
+  int n_elements;
+
+  /* The elements.  */
+
+  gcc_type *elements;
+};
+
+/* The vtable used by the C front end.  */
+
+struct gcc_c_fe_vtable
+{
+  /* The version of the C interface.  The value is one of the
+     gcc_c_api_version constants.  */
+
+  unsigned int c_version;
+
+  /* Set the callbacks for this context.
+
+     The binding oracle is called whenever the C parser needs to look
+     up a symbol.  This gives the caller a chance to lazily
+     instantiate symbols using other parts of the gcc_c_fe_interface
+     API.
+
+     The address oracle is called whenever the C parser needs to look
+     up a symbol.  This is only called for symbols not provided by the
+     symbol oracle -- that is, just built-in functions where GCC
+     provides the declaration.
+
+     DATUM is an arbitrary piece of data that is passed back verbatim
+     to the callbakcs in requests.  */
+
+  void (*set_callbacks) (struct gcc_c_context *self,
+			 gcc_c_oracle_function *binding_oracle,
+			 gcc_c_symbol_address_function *address_oracle,
+			 void *datum);
+
+#define GCC_METHOD0(R, N) \
+  R (*N) (struct gcc_c_context *);
+#define GCC_METHOD1(R, N, A) \
+  R (*N) (struct gcc_c_context *, A);
+#define GCC_METHOD2(R, N, A, B) \
+  R (*N) (struct gcc_c_context *, A, B);
+#define GCC_METHOD3(R, N, A, B, C) \
+  R (*N) (struct gcc_c_context *, A, B, C);
+#define GCC_METHOD4(R, N, A, B, C, D) \
+  R (*N) (struct gcc_c_context *, A, B, C, D);
+#define GCC_METHOD5(R, N, A, B, C, D, E) \
+  R (*N) (struct gcc_c_context *, A, B, C, D, E);
+#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
+  R (*N) (struct gcc_c_context *, A, B, C, D, E, F, G);
+
+#include "gcc-c-fe.def"
+
+#undef GCC_METHOD0
+#undef GCC_METHOD1
+#undef GCC_METHOD2
+#undef GCC_METHOD3
+#undef GCC_METHOD4
+#undef GCC_METHOD5
+#undef GCC_METHOD7
+
+};
+
+/* The C front end object.  */
+
+struct gcc_c_context
+{
+  /* Base class.  */
+
+  struct gcc_base_context base;
+
+  /* Our vtable.  This is a separate field because this is simpler
+     than implementing a vtable inheritance scheme in C.  */
+
+  const struct gcc_c_fe_vtable *c_ops;
+};
+
+/* The name of the .so that the compiler builds.  We dlopen this
+   later.  */
+
+#define GCC_C_FE_LIBCC libcc1.so
+
+/* The compiler exports a single initialization function.  This macro
+   holds its name as a symbol.  */
+
+#define GCC_C_FE_CONTEXT gcc_c_fe_context
+
+/* The type of the initialization function.  The caller passes in the
+   desired base version and desired C-specific version.  If the
+   request can be satisfied, a compatible gcc_context object will be
+   returned.  Otherwise, the function returns NULL.  */
+
+typedef struct gcc_c_context *gcc_c_fe_context_function
+    (enum gcc_base_api_version,
+     enum gcc_c_api_version);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GCC_C_INTERFACE_H */
diff --git a/include/gcc-interface.h b/include/gcc-interface.h
new file mode 100644
index 0000000..7131727
--- /dev/null
+++ b/include/gcc-interface.h
@@ -0,0 +1,120 @@
+/* Generic interface between GCC and GDB
+
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program 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 of the License, or
+   (at your option) any later version.
+
+   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_INTERFACE_H
+#define GCC_INTERFACE_H
+
+/* This header defines the interface to the GCC API.  It must be both
+   valid C and valid C++, because it is included by both programs.  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Opaque typedefs for objects passed through the interface.  */
+
+typedef unsigned long long gcc_type;
+typedef unsigned long long gcc_decl;
+
+/* An address in the inferior.  */
+
+typedef unsigned long long gcc_address;
+
+/* Forward declaration.  */
+
+struct gcc_base_context;
+
+/* Defined versions of the generic API.  */
+
+enum gcc_base_api_version
+{
+  GCC_FE_VERSION_0 = 0
+};
+
+/* The operations defined by the GCC base API.  This is the vtable for
+   the real context structure which is passed around.
+
+   The "base" API is concerned with basics shared by all compiler
+   front ends: setting command-line arguments, the file names, etc.
+
+   Front-end-specific interfaces inherit from this one.  */
+
+struct gcc_base_vtable
+{
+  /* The actual version implemented in this interface.  This field can
+     be relied on not to move, so users can always check it if they
+     desire.  The value is one of the gcc_base_api_version constants.
+  */
+
+  unsigned int version;
+
+  /* Set the compiler's command-line options for the next compilation.
+     The arguments are copied by GCC.  ARGV need not be
+     NULL-terminated.  The arguments must be set separately for each
+     compilation; that is, after a compile is requested, the
+     previously-set arguments cannot be reused.  */
+
+  void (*set_arguments) (struct gcc_base_context *self, int argc, char **argv);
+
+  /* Set the file name of the program to compile.  The string is
+     copied by the method implementation, but the caller must
+     guarantee that the file exists through the compilation.  */
+
+  void (*set_source_file) (struct gcc_base_context *self, const char *file);
+
+  /* Set a callback to use for printing error messages.  DATUM is
+     passed through to the callback unchanged.  */
+
+  void (*set_print_callback) (struct gcc_base_context *self,
+			      void (*print_function) (void *datum,
+						      const char *message),
+			      void *datum);
+
+  /* Perform the compilation.  FILENAME is the name of the resulting
+     object file.  VERBOSE can be set to cause GCC to print some
+     information as it works.  Returns true on success, false on
+     error.  */
+
+  int /* bool */ (*compile) (struct gcc_base_context *self,
+			     const char *filename,
+			     int /* bool */ verbose);
+
+  /* Destroy this object.  */
+
+  void (*destroy) (struct gcc_base_context *self);
+};
+
+/* The GCC object.  */
+
+struct gcc_base_context
+{
+  /* The virtual table.  */
+
+  const struct gcc_base_vtable *ops;
+};
+
+/* The name of the dummy wrapper function generated by gdb.  */
+
+#define GCC_FE_WRAPPER_FUNCTION "_gdb_expr"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GCC_INTERFACE_H */
-- 
1.9.0

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [PATCH 3/5] introduce the binding oracle
  2014-05-16 15:26 [PATCH 0/5] let gdb reuse gcc'c C compiler Tom Tromey
  2014-05-16 15:26 ` [PATCH 1/5] export finish_bitfield_layout from stor-layout Tom Tromey
  2014-05-16 15:27 ` [PATCH 2/5] c_diagnostic_ignored_function hack Tom Tromey
@ 2014-05-16 15:27 ` Tom Tromey
  2014-05-16 19:12   ` Jeff Law
  2014-05-16 15:27 ` [PATCH 4/5] add gcc/gdb interface files Tom Tromey
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 101+ messages in thread
From: Tom Tromey @ 2014-05-16 15:27 UTC (permalink / raw)
  To: gcc-patches; +Cc: Tom Tromey

gdb wants to supply any declarations that may be referred to by the
user's code.  Hooking into symbol lookup was an efficient way to
accomplish this.

This patch introducing a "binding oracle" that is consulted whenever a
symbol binding is looked up for the first time.  The oracle is just a
global function pointer.  If it is NULL, no special work is done.  It
is called with the identifier to supply and with an enum argument
indicating the kind of binding being requested.  The oracle can then
call back into the C front end (via the new functions c_pushtag and
c_bind) to supply a binding; or it can silently do nothing if the
request could not be fulfilled.

The code caches Whether the oracle has been called to avoid repeated
useless queries.

There is a little hack in c_print_identifier to avoid calling the
binding oracle here.  This makes debugging gcc in the presence of the
plugin remain relatively sane -- without this, calling debug_tree or
the like can confusingly call into the plugin.

2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* c-tree.h (enum c_oracle_request): New.
	(c_binding_oracle_function): New typedef.
	(c_binding_oracle, c_pushtag, c_bind): Declare.
	* c-decl.c (c_binding_oracle): New global.
	(I_SYMBOL_CHECKED): New macro.
	(i_symbol_binding): New function.
	(I_SYMBOL_BINDING, I_SYMBOL_DECL): Redefine.
	(I_TAG_CHECKED): New macro.
	(i_tag_binding): New function.
	(I_TAG_BINDING, I_TAG_DECL): Redefine.
	(I_LABEL_CHECKED): New macro.
	(i_label_binding): New function.
	(I_LABEL_BINDING, I_LABEL_DECL): Redefine.
	(c_print_identifier): Save and restore c_binding_oracle.
	(c_pushtag, c_bind): New functions.
---
 gcc/c/ChangeLog |  19 +++++++
 gcc/c/c-decl.c  | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 gcc/c/c-tree.h  |  24 +++++++++
 3 files changed, 189 insertions(+), 15 deletions(-)

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index d52dcc9..b391add 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -215,21 +215,6 @@ struct GTY((chain_next ("%h.prev"))) c_binding {
 #define B_IN_FILE_SCOPE(b) ((b)->depth == 1 /*file_scope->depth*/)
 #define B_IN_EXTERNAL_SCOPE(b) ((b)->depth == 0 /*external_scope->depth*/)
 
-#define I_SYMBOL_BINDING(node) \
-  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->symbol_binding)
-#define I_SYMBOL_DECL(node) \
- (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
-
-#define I_TAG_BINDING(node) \
-  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->tag_binding)
-#define I_TAG_DECL(node) \
- (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
-
-#define I_LABEL_BINDING(node) \
-  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->label_binding)
-#define I_LABEL_DECL(node) \
- (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
-
 /* Each C symbol points to three linked lists of c_binding structures.
    These describe the values of the identifier in the three different
    namespaces defined by the language.  */
@@ -245,6 +230,96 @@ struct GTY(()) lang_identifier {
 extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
 [(sizeof(struct lang_identifier) == C_SIZEOF_STRUCT_LANG_IDENTIFIER) ? 1 : -1];
 
+/* The binding oracle; see c-tree.h.  */
+void (*c_binding_oracle) (enum c_oracle_request, tree identifier);
+
+/* This flag is set on an identifier if we have previously asked the
+   binding oracle for this identifier's symbol binding.  */
+#define I_SYMBOL_CHECKED(node) \
+  (TREE_LANG_FLAG_4 (IDENTIFIER_NODE_CHECK (node)))
+
+static inline struct c_binding* *
+i_symbol_binding (tree node)
+{
+  struct lang_identifier *lid
+    = (struct lang_identifier *) IDENTIFIER_NODE_CHECK (node);
+
+  if (lid->symbol_binding == NULL
+      && c_binding_oracle != NULL
+      && !I_SYMBOL_CHECKED (node))
+    {
+      /* Set the "checked" flag first, to avoid infinite recursion
+	 when the binding oracle calls back into gcc.  */
+      I_SYMBOL_CHECKED (node) = 1;
+      c_binding_oracle (C_ORACLE_SYMBOL, node);
+    }
+
+  return &lid->symbol_binding;
+}
+
+#define I_SYMBOL_BINDING(node) (*i_symbol_binding (node))
+
+#define I_SYMBOL_DECL(node) \
+ (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
+
+/* This flag is set on an identifier if we have previously asked the
+   binding oracle for this identifier's tag binding.  */
+#define I_TAG_CHECKED(node) \
+  (TREE_LANG_FLAG_5 (IDENTIFIER_NODE_CHECK (node)))
+
+static inline struct c_binding **
+i_tag_binding (tree node)
+{
+  struct lang_identifier *lid
+    = (struct lang_identifier *) IDENTIFIER_NODE_CHECK (node);
+
+  if (lid->tag_binding == NULL
+      && c_binding_oracle != NULL
+      && !I_TAG_CHECKED (node))
+    {
+      /* Set the "checked" flag first, to avoid infinite recursion
+	 when the binding oracle calls back into gcc.  */
+      I_TAG_CHECKED (node) = 1;
+      c_binding_oracle (C_ORACLE_TAG, node);
+    }
+
+  return &lid->tag_binding;
+}
+
+#define I_TAG_BINDING(node) (*i_tag_binding (node))
+
+#define I_TAG_DECL(node) \
+ (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
+
+/* This flag is set on an identifier if we have previously asked the
+   binding oracle for this identifier's label binding.  */
+#define I_LABEL_CHECKED(node) \
+  (TREE_LANG_FLAG_6 (IDENTIFIER_NODE_CHECK (node)))
+
+static inline struct c_binding **
+i_label_binding (tree node)
+{
+  struct lang_identifier *lid
+    = (struct lang_identifier *) IDENTIFIER_NODE_CHECK (node);
+
+  if (lid->label_binding == NULL
+      && c_binding_oracle != NULL
+      && !I_LABEL_CHECKED (node))
+    {
+      /* Set the "checked" flag first, to avoid infinite recursion
+	 when the binding oracle calls back into gcc.  */
+      I_LABEL_CHECKED (node) = 1;
+      c_binding_oracle (C_ORACLE_LABEL, node);
+    }
+
+  return &lid->label_binding;
+}
+
+#define I_LABEL_BINDING(node) (*i_label_binding (node))
+
+#define I_LABEL_DECL(node) \
+ (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
+
 /* The resulting tree type.  */
 
 union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
@@ -611,6 +686,12 @@ decl_jump_unsafe (tree decl)
 void
 c_print_identifier (FILE *file, tree node, int indent)
 {
+  void (*save) (enum c_oracle_request, tree identifier);
+
+  // This makes debugging much more sane.
+  save = c_binding_oracle;
+  c_binding_oracle = NULL;
+
   print_node (file, "symbol", I_SYMBOL_DECL (node), indent + 4);
   print_node (file, "tag", I_TAG_DECL (node), indent + 4);
   print_node (file, "label", I_LABEL_DECL (node), indent + 4);
@@ -621,6 +702,8 @@ c_print_identifier (FILE *file, tree node, int indent)
       fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"",
 	       (void *) rid, IDENTIFIER_POINTER (rid));
     }
+
+  c_binding_oracle = save;
 }
 
 /* Establish a binding between NAME, an IDENTIFIER_NODE, and DECL,
@@ -1485,6 +1568,54 @@ pushtag (location_t loc, tree name, tree type)
 	}
     }
 }
+
+/* An exported interface to pushtag.  This is used by the gdb plugin's
+   binding oracle to introduce a new tag binding.  */
+
+void
+c_pushtag (location_t loc, tree name, tree type)
+{
+  pushtag (loc, name, type);
+}
+
+/* An exported interface to bind a declaration.  LOC is the location
+   to use.  DECL is the declaration to bind.  The decl's name is used
+   to determine how it is bound.  If DECL is a VAR_DECL, then
+   IS_GLOBAL determines whether the decl is put into the global (file
+   and external) scope or the current function's scope; if DECL is not
+   a VAR_DECL then it is always put into the file scope.  */
+
+void
+c_bind (location_t loc, tree decl, bool is_global)
+{
+  struct c_scope *scope;
+  bool nested = false;
+
+  if (TREE_CODE (decl) != VAR_DECL || current_function_scope == NULL)
+    {
+      /* Types and functions are always considered to be global.  */
+      scope = file_scope;
+      DECL_EXTERNAL (decl) = 1;
+      TREE_PUBLIC (decl) = 1;
+    }
+  else if (is_global)
+    {
+      /* Also bind it into the external scope.  */
+      bind (DECL_NAME (decl), decl, external_scope, true, false, loc);
+      nested = true;
+      scope = file_scope;
+      DECL_EXTERNAL (decl) = 1;
+      TREE_PUBLIC (decl) = 1;
+    }
+  else
+    {
+      DECL_CONTEXT (decl) = current_function_decl;
+      TREE_PUBLIC (decl) = 0;
+      scope = current_function_scope;
+    }
+
+  bind (DECL_NAME (decl), decl, scope, false, nested, loc);
+}
 \f
 /* Subroutine of compare_decls.  Allow harmless mismatches in return
    and argument types provided that the type modes match.  This function
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index e7dcb35..9370fa6 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -665,12 +665,36 @@ extern int current_function_returns_abnormally;
 extern enum machine_mode c_default_pointer_mode;
 
 /* In c-decl.c */
+
+/* Tell the binding oracle what kind of binding we are looking for.  */
+
+enum c_oracle_request
+{
+  C_ORACLE_SYMBOL,
+  C_ORACLE_TAG,
+  C_ORACLE_LABEL
+};
+
+/* If this is non-NULL, then it is a "binding oracle" which can lazily
+   create bindings when needed by the C compiler.  The oracle is told
+   the name and type of the binding to create.  It can call pushdecl
+   or the like to ensure the binding is visible; or do nothing,
+   leaving the binding untouched.  c-decl.c takes note of when the
+   oracle has been called and will not call it again if it fails to
+   create a given binding.  */
+
+typedef void c_binding_oracle_function (enum c_oracle_request, tree identifier);
+
+extern c_binding_oracle_function *c_binding_oracle;
+
 extern void c_finish_incomplete_decl (tree);
 extern void c_write_global_declarations (void);
 extern tree c_omp_reduction_id (enum tree_code, tree);
 extern tree c_omp_reduction_decl (tree);
 extern tree c_omp_reduction_lookup (tree, tree);
 extern tree c_check_omp_declare_reduction_r (tree *, int *, void *);
+extern void c_pushtag (location_t, tree, tree);
+extern void c_bind (location_t, tree, bool);
 
 /* In c-errors.c */
 extern void pedwarn_c90 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
-- 
1.9.0

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 2/5] c_diagnostic_ignored_function hack
  2014-05-16 15:27 ` [PATCH 2/5] c_diagnostic_ignored_function hack Tom Tromey
@ 2014-05-16 16:05   ` Joseph S. Myers
  2014-06-19 20:46     ` Tom Tromey
  2014-05-16 18:33   ` Jeff Law
  1 sibling, 1 reply; 101+ messages in thread
From: Joseph S. Myers @ 2014-05-16 16:05 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gcc-patches

On Fri, 16 May 2014, Tom Tromey wrote:

> In the typical case, when compiling a snippet of user code, gdb wraps
> the user's text in a dummy function.
> 
> It's somewhat odd for users if an error in their code is mentioned as
> coming from this dummy function.
> 
> This patch makes it possible to suppress the function-name display in
> a straightforward way: it adds a new global which the plugin can set
> to declare the name of the dummy function.
> 
> This patch seems like a bit of a hack, but there didn't seem to be a
> notably cleaner approach.

I'd say this global actually belongs somewhere in the diagnostic_context 
(i.e., instead of the diagnostic_context_auxiliary_data (DC) actually 
being a tree as it is at present, it should point to a structure with 
whatever extra information clients wish to use to control aspects of 
diagnostic reporting).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 0/5] let gdb reuse gcc'c C compiler
  2014-05-16 15:26 [PATCH 0/5] let gdb reuse gcc'c C compiler Tom Tromey
                   ` (3 preceding siblings ...)
  2014-05-16 15:27 ` [PATCH 4/5] add gcc/gdb interface files Tom Tromey
@ 2014-05-16 16:29 ` Mike Stump
  2014-05-16 18:48 ` [PATCH 5/5] add libcc1 Tom Tromey
  2014-06-19 20:42 ` [PATCH 0/5] let gdb reuse gcc'c C compiler Tom Tromey
  6 siblings, 0 replies; 101+ messages in thread
From: Mike Stump @ 2014-05-16 16:29 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gcc-patches

On May 16, 2014, at 8:26 AM, Tom Tromey <tromey@redhat.com> wrote:
> This patch series is half of a project to let gdb reuse gcc (which
> half depends on which list you are seeing this on), so that users can
> compile small snippets of code and evaluate them in the current
> context of the inferior.

Nice…  I looked though it, nice and lightweight and seems like the api can hold up through time.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 1/5] export finish_bitfield_layout from stor-layout
  2014-05-16 15:26 ` [PATCH 1/5] export finish_bitfield_layout from stor-layout Tom Tromey
@ 2014-05-16 18:27   ` Jeff Law
  0 siblings, 0 replies; 101+ messages in thread
From: Jeff Law @ 2014-05-16 18:27 UTC (permalink / raw)
  To: Tom Tromey, gcc-patches

On 05/16/14 09:26, Tom Tromey wrote:
> The gdb plugin handles some aspects of type layout on its own.  It
> does this because it knows the layout of types, but not the path by
> which the layout was determined -- so normal gcc things like
> TYPE_PACKED cannot be used.
>
> This patch exposes one bit of stor-layout so it can be used by the
> plugin.
>
> 2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
> 	    Tom Tromey  <tromey@redhat.com>
>
> 	* stor-layout.c (finish_bitfield_layout): Now public.  Change
> 	argument type to 'tree'.
> 	(finish_record_layout): Update.
> 	* stor-layout.h (finish_bitfield_layout): Declare.
OK.  However, please hold off installing until the entire set is approved.



Jeff

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 2/5] c_diagnostic_ignored_function hack
  2014-05-16 15:27 ` [PATCH 2/5] c_diagnostic_ignored_function hack Tom Tromey
  2014-05-16 16:05   ` Joseph S. Myers
@ 2014-05-16 18:33   ` Jeff Law
  2014-05-16 18:42     ` Tom Tromey
  1 sibling, 1 reply; 101+ messages in thread
From: Jeff Law @ 2014-05-16 18:33 UTC (permalink / raw)
  To: Tom Tromey, gcc-patches

On 05/16/14 09:26, Tom Tromey wrote:
> In the typical case, when compiling a snippet of user code, gdb wraps
> the user's text in a dummy function.
>
> It's somewhat odd for users if an error in their code is mentioned as
> coming from this dummy function.
>
> This patch makes it possible to suppress the function-name display in
> a straightforward way: it adds a new global which the plugin can set
> to declare the name of the dummy function.
>
> This patch seems like a bit of a hack, but there didn't seem to be a
> notably cleaner approach.
>
> 2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
> 	    Tom Tromey  <tromey@redhat.com>
>
> 	* c-lang.c (c_diagnostic_ignored_function): New global.
> 	(c_print_error_function): New function.
> 	(LANG_HOOKS_PRINT_ERROR_FUNCTION): Define.
> 	* c-lang.h (c_diagnostic_ignored_function): Declare.
Just a few nites.

In c-lang.c, please use the old C-style comments.  If for no other 
reason than it's consistent with all the other nearby code.   Consider 
using non-NULL when referring to pointers rather than non-zero.  */

Otherwise OK.  Please wait to install until the entire kit is approved.

BTW, didn't see patch #5 of the series.

jeff

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 2/5] c_diagnostic_ignored_function hack
  2014-05-16 18:33   ` Jeff Law
@ 2014-05-16 18:42     ` Tom Tromey
  0 siblings, 0 replies; 101+ messages in thread
From: Tom Tromey @ 2014-05-16 18:42 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches

Jeff> BTW, didn't see patch #5 of the series.

Maybe it was too big.
I will try to resend it compressed.

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [PATCH 5/5] add libcc1
  2014-05-16 15:26 [PATCH 0/5] let gdb reuse gcc'c C compiler Tom Tromey
                   ` (4 preceding siblings ...)
  2014-05-16 16:29 ` [PATCH 0/5] let gdb reuse gcc'c C compiler Mike Stump
@ 2014-05-16 18:48 ` Tom Tromey
  2014-05-16 20:29   ` Joseph S. Myers
                     ` (3 more replies)
  2014-06-19 20:42 ` [PATCH 0/5] let gdb reuse gcc'c C compiler Tom Tromey
  6 siblings, 4 replies; 101+ messages in thread
From: Tom Tromey @ 2014-05-16 18:48 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 4263 bytes --]

>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:

Tom> This patch series is half of a project to let gdb reuse gcc (which
Tom> half depends on which list you are seeing this on), so that users can
Tom> compile small snippets of code and evaluate them in the current
Tom> context of the inferior.

Jeff noted that patch #5 didn't make it through.

I've edited this one down by removing the auto-generated stuff , and
then compressed it.

If anybody wants to apply this to try it out, it's all on github.

    https://github.com/tromey/gcc
    https://github.com/tromey/gdb

In each repository the branch named "submit/compile" holds the rebased
series that were submitted.

The development branches are both named "gdbjit".  These are much
messier but not ever rebased, so perhaps safer to track.

Tom

This patch adds the plugin to the gcc tree and updates the top-level
configury.

It seems better to have this code in the gcc tree than in the gdb
tree, because it is bound more tightly to gcc.  The gcc plugin makes
direct calls into various parts of gcc to do its work; whereas on the
gdb side everything is done via a relatively simple API, without any
direct connection to gdb internals.  This breakdown made the most
sense because most calls are from gdb to gcc rather than vice versa.

The plugin itself consists of two parts.  These parts communicate via
a simple ad hoc RPC system implemented in the plugin code.

2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* Makefile.def: Add libcc1 to host_modules.
	* configure.ac (host_tools): Add libcc1.
	* Makefile.in, configure: Rebuild.

2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
	    Jan Kratochvil  <jan.kratochvil@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* aclocal.m4: New file.
	* callbacks.cc: New file.
	* callbacks.hh: New file.
	* cc1plugin-config.h.in: New file.
	* configure: New file.
	* configure.ac: New file.
	* connection.cc: New file.
	* connection.hh: New file.
	* libcc1.cc: New file.
	* libcc1plugin.sym: New file.
	* libcc1.sym: New file.
	* Makefile.am: New file.
	* Makefile.in: New file.
	* marshall.cc: New file.
	* marshall.hh: New file.
	* names.cc: New file.
	* names.hh: New file.
	* plugin.cc: New file.
	* rpc.hh: New file.
	* status.hh: New file.
---
 ChangeLog                    |     7 +
 Makefile.def                 |     5 +
 Makefile.in                  |   995 ++-
 configure                    |     2 +-
 configure.ac                 |     4 +-
 libcc1/ChangeLog             |    24 +
 libcc1/Makefile.am           |    42 +
 libcc1/Makefile.in           |   614 ++
 libcc1/aclocal.m4            |   980 +++
 libcc1/callbacks.cc          |    90 +
 libcc1/callbacks.hh          |    64 +
 libcc1/cc1plugin-config.h.in |    92 +
 libcc1/configure             | 16956 +++++++++++++++++++++++++++++++++++++++++
 libcc1/configure.ac          |    65 +
 libcc1/connection.cc         |   153 +
 libcc1/connection.hh         |   114 +
 libcc1/libcc1.cc             |   454 ++
 libcc1/libcc1.sym            |     1 +
 libcc1/libcc1plugin.sym      |     2 +
 libcc1/marshall.cc           |   166 +
 libcc1/marshall.hh           |    93 +
 libcc1/names.cc              |    46 +
 libcc1/names.hh              |    55 +
 libcc1/plugin.cc             |   895 +++
 libcc1/rpc.hh                |   486 ++
 libcc1/status.hh             |    33 +
 26 files changed, 22430 insertions(+), 8 deletions(-)
 create mode 100644 libcc1/ChangeLog
 create mode 100644 libcc1/Makefile.am
 create mode 100644 libcc1/Makefile.in
 create mode 100644 libcc1/aclocal.m4
 create mode 100644 libcc1/callbacks.cc
 create mode 100644 libcc1/callbacks.hh
 create mode 100644 libcc1/cc1plugin-config.h.in
 create mode 100755 libcc1/configure
 create mode 100644 libcc1/configure.ac
 create mode 100644 libcc1/connection.cc
 create mode 100644 libcc1/connection.hh
 create mode 100644 libcc1/libcc1.cc
 create mode 100644 libcc1/libcc1.sym
 create mode 100644 libcc1/libcc1plugin.sym
 create mode 100644 libcc1/marshall.cc
 create mode 100644 libcc1/marshall.hh
 create mode 100644 libcc1/names.cc
 create mode 100644 libcc1/names.hh
 create mode 100644 libcc1/plugin.cc
 create mode 100644 libcc1/rpc.hh
 create mode 100644 libcc1/status.hh


[-- Attachment #2: the patch --]
[-- Type: application/gzip, Size: 15988 bytes --]

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 3/5] introduce the binding oracle
  2014-05-16 15:27 ` [PATCH 3/5] introduce the binding oracle Tom Tromey
@ 2014-05-16 19:12   ` Jeff Law
  2014-06-05 15:31     ` Tom Tromey
  2014-06-19 20:43     ` Tom Tromey
  0 siblings, 2 replies; 101+ messages in thread
From: Jeff Law @ 2014-05-16 19:12 UTC (permalink / raw)
  To: Tom Tromey, gcc-patches

On 05/16/14 09:26, Tom Tromey wrote:
> gdb wants to supply any declarations that may be referred to by the
> user's code.  Hooking into symbol lookup was an efficient way to
> accomplish this.
>
> This patch introducing a "binding oracle" that is consulted whenever a
> symbol binding is looked up for the first time.  The oracle is just a
> global function pointer.  If it is NULL, no special work is done.  It
> is called with the identifier to supply and with an enum argument
> indicating the kind of binding being requested.  The oracle can then
> call back into the C front end (via the new functions c_pushtag and
> c_bind) to supply a binding; or it can silently do nothing if the
> request could not be fulfilled.
>
> The code caches Whether the oracle has been called to avoid repeated
> useless queries.
>
> There is a little hack in c_print_identifier to avoid calling the
> binding oracle here.  This makes debugging gcc in the presence of the
> plugin remain relatively sane -- without this, calling debug_tree or
> the like can confusingly call into the plugin.
>
> 2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
> 	    Tom Tromey  <tromey@redhat.com>
>
> 	* c-tree.h (enum c_oracle_request): New.
> 	(c_binding_oracle_function): New typedef.
> 	(c_binding_oracle, c_pushtag, c_bind): Declare.
> 	* c-decl.c (c_binding_oracle): New global.
> 	(I_SYMBOL_CHECKED): New macro.
> 	(i_symbol_binding): New function.
> 	(I_SYMBOL_BINDING, I_SYMBOL_DECL): Redefine.
> 	(I_TAG_CHECKED): New macro.
> 	(i_tag_binding): New function.
> 	(I_TAG_BINDING, I_TAG_DECL): Redefine.
> 	(I_LABEL_CHECKED): New macro.
> 	(i_label_binding): New function.
> 	(I_LABEL_BINDING, I_LABEL_DECL): Redefine.
> 	(c_print_identifier): Save and restore c_binding_oracle.
> 	(c_pushtag, c_bind): New functions.
> ---
>   void
>   c_print_identifier (FILE *file, tree node, int indent)
>   {
> +  void (*save) (enum c_oracle_request, tree identifier);
> +
> +  // This makes debugging much more sane.
> +  save = c_binding_oracle;
> +  c_binding_oracle = NULL;
> +
Just a nit.  C-style comment would be appreciated.  It might also help 
to clarify what "much more sane" really means here.

Otherwise, it looks OK to me.

jeff

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-05-16 18:48 ` [PATCH 5/5] add libcc1 Tom Tromey
@ 2014-05-16 20:29   ` Joseph S. Myers
  2014-05-16 21:03     ` Tom Tromey
                       ` (2 more replies)
  2014-05-16 21:36   ` Mike Stump
                     ` (2 subsequent siblings)
  3 siblings, 3 replies; 101+ messages in thread
From: Joseph S. Myers @ 2014-05-16 20:29 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gcc-patches

On Fri, 16 May 2014, Tom Tromey wrote:

> This patch adds the plugin to the gcc tree and updates the top-level
> configury.

I don't see anything obvious that would disable the plugin if plugins are 
unsupported (e.g. on Windows host) or disabled (--disable-plugin).  
Probably the relevant support from gcc/configure.ac needs to go somewhere 
it can be used at toplevel.

> +  self->args.push_back ("gcc");

seems wrong - at least you should use the appropriate compiler name after 
transformation for cross compilers / --program-transform-name.  Though 
really the *versioned* driver $(target_noncanonical)-gcc-$(version) is the 
right one to use, in that the plugin should presumably be closely 
associated with a particular compiler installation when e.g. a 
distribution has multiple GCC versions packaged that can be installed 
simultaneously.  Having multiple copies of the plugin installed in the 
same prefix for different targets should be supported.  I'm not clear on 
which library does what - does libcc1 depend in any way on the target or 
GCC version?

How are the compiler multilib options (e.g. -m32 / -m64) specified?  Is 
that something GDB passes through, based on examining properties of the 
binary being debugged?  (Unfortunately there may not be a good way in 
general for GDB to tell what the required options for a particular binary 
are.  It can at least reasonably default to using a copy of the plugin for 
the same target triplet as GDB was configured for.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-05-16 20:29   ` Joseph S. Myers
@ 2014-05-16 21:03     ` Tom Tromey
  2014-06-18 21:07     ` Tom Tromey
  2014-06-19 20:47     ` Tom Tromey
  2 siblings, 0 replies; 101+ messages in thread
From: Tom Tromey @ 2014-05-16 21:03 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches

>>>>> "Joseph" == Joseph S Myers <joseph@codesourcery.com> writes:

>> +  self->args.push_back ("gcc");

Joseph> seems wrong - at least you should use the appropriate compiler
Joseph> name after transformation for cross compilers /
Joseph> --program-transform-name.

Ok, we'll look into it.

Joseph> I'm not clear on which library does what - does libcc1 depend in
Joseph> any way on the target or GCC version?

It doesn't depend on the target at all.  It does rely on the GCC plugin
using the same .def file -- in fact we should probably add a handshake
at the start so that we don't wind up with a version mismatch there.
The plugin is of course exposed to GCC internals changes as all plugins
are; but this is why we think it should be part of GCC.

Joseph> How are the compiler multilib options (e.g. -m32 / -m64)
Joseph> specified?  Is that something GDB passes through, based on
Joseph> examining properties of the binary being debugged?
Joseph> (Unfortunately there may not be a good way in general for GDB to
Joseph> tell what the required options for a particular binary are.  It
Joseph> can at least reasonably default to using a copy of the plugin
Joseph> for the same target triplet as GDB was configured for.)

gdb extracts some information from the debuginfo.
Some information is provided by a new gdbarch method; for example this
is where -m32 / -m64 / -m31 (hi S390) come from.

I am not sure if we can get the proper $(target_noncanonical) for a
given gdbarch.  We'll look into it.

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-05-16 18:48 ` [PATCH 5/5] add libcc1 Tom Tromey
  2014-05-16 20:29   ` Joseph S. Myers
@ 2014-05-16 21:36   ` Mike Stump
  2014-05-16 22:17   ` Mike Stump
  2014-06-19 20:52   ` Tom Tromey
  3 siblings, 0 replies; 101+ messages in thread
From: Mike Stump @ 2014-05-16 21:36 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gcc-patches

On May 16, 2014, at 11:48 AM, Tom Tromey <tromey@redhat.com> wrote:
> I've edited this one down by removing the auto-generated stuff , and
> then compressed it.

+  // remove the "const" and handle deallcation from pointer types.

sp: deallocation

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-05-16 18:48 ` [PATCH 5/5] add libcc1 Tom Tromey
  2014-05-16 20:29   ` Joseph S. Myers
  2014-05-16 21:36   ` Mike Stump
@ 2014-05-16 22:17   ` Mike Stump
  2014-06-05 19:34     ` Tom Tromey
  2014-06-19 20:52   ` Tom Tromey
  3 siblings, 1 reply; 101+ messages in thread
From: Mike Stump @ 2014-05-16 22:17 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gcc-patches

On May 16, 2014, at 11:48 AM, Tom Tromey <tromey@redhat.com> wrote:
> This patch adds the plugin to the gcc tree

So, this code isn’t as portable as gcc (I can run a native gcc bootstrap on my binutils sim simulator for my target, and I’m a newlib target), so it needs autoconf to explain if enough features are present; sockets I think would be one of the many things that would kill my build for example.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 4/5] add gcc/gdb interface files
  2014-05-16 15:27 ` [PATCH 4/5] add gcc/gdb interface files Tom Tromey
@ 2014-05-22 12:52   ` Jeff Law
  2014-05-22 13:16     ` Jakub Jelinek
  0 siblings, 1 reply; 101+ messages in thread
From: Jeff Law @ 2014-05-22 12:52 UTC (permalink / raw)
  To: Tom Tromey, gcc-patches

On 05/16/14 09:26, Tom Tromey wrote:
>
> 2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> 	    Tom Tromey  <tromey@redhat.com>
>
> 	* gcc-c-fe.def: New file.
> 	* gcc-c-interface.h: New file.
> 	* gcc-interface.h: New file.
> ---

+GCC_METHOD7 (gcc_decl, build_decl,
+	     const char */* name */,
+	     enum gcc_c_symbol_kind /* sym_kind */,
+	     gcc_type /* sym_type */,
+	     const char */* substitution_name */,
+	     gcc_address /* address */,
+	     const char */* filename */,
+	     unsigned int /* line_number */)

I must say that I hate the embedded comments in the signatures. 
Especially when you end up with something like:

const char */* name */,

My brain just doesn't parse it.

const char * /* name */

is marginally better, but I still don't like it.

const char *, /* name */

Parses better as long as every argument is on a separate line.  But I 
still don't like it...

I'm curious how others feel about this.

All these files say they're part of GDB, not sure if that was 
intentional.  Obviously a nit.

Otherwise it's pretty reasonable.  If we could come up with a better way 
to handle the signatures, then I think this part is good to go.

jeff

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 4/5] add gcc/gdb interface files
  2014-05-22 12:52   ` Jeff Law
@ 2014-05-22 13:16     ` Jakub Jelinek
  2014-05-22 15:13       ` Jeff Law
  2014-06-04 20:39       ` Tom Tromey
  0 siblings, 2 replies; 101+ messages in thread
From: Jakub Jelinek @ 2014-05-22 13:16 UTC (permalink / raw)
  To: Jeff Law; +Cc: Tom Tromey, gcc-patches

On Thu, May 22, 2014 at 06:52:05AM -0600, Jeff Law wrote:
> On 05/16/14 09:26, Tom Tromey wrote:
> >
> >2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
> >	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> >	    Tom Tromey  <tromey@redhat.com>
> >
> >	* gcc-c-fe.def: New file.
> >	* gcc-c-interface.h: New file.
> >	* gcc-interface.h: New file.
> >---
> 
> +GCC_METHOD7 (gcc_decl, build_decl,
> +	     const char */* name */,
> +	     enum gcc_c_symbol_kind /* sym_kind */,
> +	     gcc_type /* sym_type */,
> +	     const char */* substitution_name */,
> +	     gcc_address /* address */,
> +	     const char */* filename */,
> +	     unsigned int /* line_number */)
> 
> I must say that I hate the embedded comments in the signatures.
> Especially when you end up with something like:

Why it can't be:
GCC_METHOD7 (gcc_decl, build_decl,
	     const char *name,
	     enum gfc_c_symbol_kind sym_kind,
...
i.e. provide comments in the form of argument names
(sure, you can't use bool for the name of the parameter then...).

	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 4/5] add gcc/gdb interface files
  2014-05-22 13:16     ` Jakub Jelinek
@ 2014-05-22 15:13       ` Jeff Law
  2014-06-04 20:39       ` Tom Tromey
  1 sibling, 0 replies; 101+ messages in thread
From: Jeff Law @ 2014-05-22 15:13 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Tom Tromey, gcc-patches

On 05/22/14 07:16, Jakub Jelinek wrote:
> On Thu, May 22, 2014 at 06:52:05AM -0600, Jeff Law wrote:
>> On 05/16/14 09:26, Tom Tromey wrote:
>>>
>>> 2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
>>> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
>>> 	    Tom Tromey  <tromey@redhat.com>
>>>
>>> 	* gcc-c-fe.def: New file.
>>> 	* gcc-c-interface.h: New file.
>>> 	* gcc-interface.h: New file.
>>> ---
>>
>> +GCC_METHOD7 (gcc_decl, build_decl,
>> +	     const char */* name */,
>> +	     enum gcc_c_symbol_kind /* sym_kind */,
>> +	     gcc_type /* sym_type */,
>> +	     const char */* substitution_name */,
>> +	     gcc_address /* address */,
>> +	     const char */* filename */,
>> +	     unsigned int /* line_number */)
>>
>> I must say that I hate the embedded comments in the signatures.
>> Especially when you end up with something like:
>
> Why it can't be:
> GCC_METHOD7 (gcc_decl, build_decl,
> 	     const char *name,
> 	     enum gfc_c_symbol_kind sym_kind,
> ...
> i.e. provide comments in the form of argument names
> (sure, you can't use bool for the name of the parameter then...).
No idea.  I'd assumed they had it in a comment rather than in the 
signature for a reason.

jeff

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 4/5] add gcc/gdb interface files
  2014-05-22 13:16     ` Jakub Jelinek
  2014-05-22 15:13       ` Jeff Law
@ 2014-06-04 20:39       ` Tom Tromey
  2014-06-05 19:23         ` Jeff Law
  1 sibling, 1 reply; 101+ messages in thread
From: Tom Tromey @ 2014-06-04 20:39 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Jeff Law, gcc-patches

>>>>> "Jakub" == Jakub Jelinek <jakub@redhat.com> writes:

>> +GCC_METHOD7 (gcc_decl, build_decl,
>> +	     const char */* name */,
>> +	     enum gcc_c_symbol_kind /* sym_kind */,
>> +	     gcc_type /* sym_type */,
>> +	     const char */* substitution_name */,
>> +	     gcc_address /* address */,
>> +	     const char */* filename */,
>> +	     unsigned int /* line_number */)
>> 
>> I must say that I hate the embedded comments in the signatures.
>> Especially when you end up with something like:

It's not so bad with colorizing but not everybody likes fruit salad.  I
can see how it would be pretty painful without.

Jakub> Why it can't be:
Jakub> GCC_METHOD7 (gcc_decl, build_decl,
Jakub> 	     const char *name,
Jakub> 	     enum gfc_c_symbol_kind sym_kind,
Jakub> ...
Jakub> i.e. provide comments in the form of argument names
Jakub> (sure, you can't use bool for the name of the parameter then...).

It's important that just the types are there.
For example the .def file is used to instantiate C++ templates:

#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
  rpc<R, cc1_plugin::N, A, B, C, D, E, F, G>,

Here we can't have a parameter name.


I chose this commenting approach since it named the parameters, albeit
in comments.

The "/* bool */" comments are there because gdb doesn't have a bool
type, but it still seemed worthwhile to document the intent.


I could drop the names and extend the various introductory comments to
explain argument ordering.  What do you think of that?

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 3/5] introduce the binding oracle
  2014-05-16 19:12   ` Jeff Law
@ 2014-06-05 15:31     ` Tom Tromey
  2014-06-19 20:43     ` Tom Tromey
  1 sibling, 0 replies; 101+ messages in thread
From: Tom Tromey @ 2014-06-05 15:31 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches

>>>>> "Jeff" == Jeff Law <law@redhat.com> writes:

Jeff> Just a nit.  C-style comment would be appreciated.  It might also help
Jeff> to clarify what "much more sane" really means here.

I made this change locally.
The new comment reads:

  /* Temporarily hide any binding oracle.  Without this, calls to
     debug_tree from the debugger will end up calling into the oracle,
     making for a confusing debug session.  As the oracle isn't needed
     here for normal operation, it's simplest to suppress it.  */

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 4/5] add gcc/gdb interface files
  2014-06-04 20:39       ` Tom Tromey
@ 2014-06-05 19:23         ` Jeff Law
  2014-06-05 19:30           ` Jakub Jelinek
  0 siblings, 1 reply; 101+ messages in thread
From: Jeff Law @ 2014-06-05 19:23 UTC (permalink / raw)
  To: Tom Tromey, Jakub Jelinek; +Cc: gcc-patches

On 06/04/14 14:39, Tom Tromey wrote:
>>>>>> "Jakub" == Jakub Jelinek <jakub@redhat.com> writes:
>
>>> +GCC_METHOD7 (gcc_decl, build_decl,
>>> +	     const char */* name */,
>>> +	     enum gcc_c_symbol_kind /* sym_kind */,
>>> +	     gcc_type /* sym_type */,
>>> +	     const char */* substitution_name */,
>>> +	     gcc_address /* address */,
>>> +	     const char */* filename */,
>>> +	     unsigned int /* line_number */)
>>>
>>> I must say that I hate the embedded comments in the signatures.
>>> Especially when you end up with something like:
>
> It's not so bad with colorizing but not everybody likes fruit salad.  I
> can see how it would be pretty painful without.
Yea, maybe I need different colors, but anytime something colorizes my 
first reaction is to get annoyed because I can't find what I'm looking 
for.  Probably a consequence of my white-on-black terminals not playing 
well with the default colors.

[ OK, not entirely true, when looking at diffs a trailing whitespace 
gets colorized, so I tend not to have those leak through in my own 
patches anymore. ]


>
> Jakub> Why it can't be:
> Jakub> GCC_METHOD7 (gcc_decl, build_decl,
> Jakub> 	     const char *name,
> Jakub> 	     enum gfc_c_symbol_kind sym_kind,
> Jakub> ...
> Jakub> i.e. provide comments in the form of argument names
> Jakub> (sure, you can't use bool for the name of the parameter then...).
>
> It's important that just the types are there.
> For example the .def file is used to instantiate C++ templates:
>
> #define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
>    rpc<R, cc1_plugin::N, A, B, C, D, E, F, G>,
>
> Here we can't have a parameter name.
>
>
> I chose this commenting approach since it named the parameters, albeit
> in comments.
>
> The "/* bool */" comments are there because gdb doesn't have a bool
> type, but it still seemed worthwhile to document the intent.
>
>
> I could drop the names and extend the various introductory comments to
> explain argument ordering.  What do you think of that?
Seems reasonable to me.

jeff

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 4/5] add gcc/gdb interface files
  2014-06-05 19:23         ` Jeff Law
@ 2014-06-05 19:30           ` Jakub Jelinek
  2014-06-06  1:54             ` Tom Tromey
  0 siblings, 1 reply; 101+ messages in thread
From: Jakub Jelinek @ 2014-06-05 19:30 UTC (permalink / raw)
  To: Jeff Law; +Cc: Tom Tromey, gcc-patches

On Thu, Jun 05, 2014 at 01:23:37PM -0600, Jeff Law wrote:
> >>>+GCC_METHOD7 (gcc_decl, build_decl,
> >>>+	     const char */* name */,
> >>>+	     enum gcc_c_symbol_kind /* sym_kind */,
> >>>+	     gcc_type /* sym_type */,
> >>>+	     const char */* substitution_name */,
> >>>+	     gcc_address /* address */,
> >>>+	     const char */* filename */,
> >>>+	     unsigned int /* line_number */)
> 
> [ OK, not entirely true, when looking at diffs a trailing whitespace
> gets colorized, so I tend not to have those leak through in my own
> patches anymore. ]

Another possibility would be to give the macros twice as many arguments
as there are parameters and just through the odd arguments away when
expanding to the template parameters.  That would mean you write
GCC_METHOD7 (gcc_decl, build_decl,
	     const char *, name,
	     enum gcc_c_symbol_kind, sym_kind,
	     const char *, substitution_name,
	     gcc_address, address,
	     const char *, filename,
	     unsigned int, line_number);
though it isn't very nice either, guess I'm bikeshedding... ;)

	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-05-16 22:17   ` Mike Stump
@ 2014-06-05 19:34     ` Tom Tromey
  2014-06-05 21:35       ` Mike Stump
  0 siblings, 1 reply; 101+ messages in thread
From: Tom Tromey @ 2014-06-05 19:34 UTC (permalink / raw)
  To: Mike Stump; +Cc: gcc-patches

>>>>> "Mike" == Mike Stump <mikestump@comcast.net> writes:

Mike> On May 16, 2014, at 11:48 AM, Tom Tromey <tromey@redhat.com> wrote:
>> This patch adds the plugin to the gcc tree

Mike> So, this code isn’t as portable as gcc (I can run a native gcc
Mike> bootstrap on my binutils sim simulator for my target, and I’m a newlib
Mike> target), so it needs autoconf to explain if enough features are
Mike> present; sockets I think would be one of the many things that would
Mike> kill my build for example.

If you could enumerate the things you think are necessary to check, I
can arrange for the plugin to not be built if those are not available.

I added a check like this for socketpair to my tree.  I also plan to
deal with the lack of plugin functionality as Joseph pointed out.

I suppose I will add a check for fork.  How about pipe?  select?

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-06-05 19:34     ` Tom Tromey
@ 2014-06-05 21:35       ` Mike Stump
  0 siblings, 0 replies; 101+ messages in thread
From: Mike Stump @ 2014-06-05 21:35 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gcc-patches

On Jun 5, 2014, at 12:34 PM, Tom Tromey <tromey@redhat.com> wrote:
> If you could enumerate the things you think are necessary to check, I
> can arrange for the plugin to not be built if those are not available.

So, I think it a single check on socketpair is likely good enough.  If it is present, likely all the rest are, and if it isn’t turning it off likely is reasonable until someone wants to port more.  It isn’t your job to do that port…  the person who wants it will do it.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 4/5] add gcc/gdb interface files
  2014-06-05 19:30           ` Jakub Jelinek
@ 2014-06-06  1:54             ` Tom Tromey
  2014-06-06  5:35               ` Jakub Jelinek
  2014-06-09 17:09               ` Jeff Law
  0 siblings, 2 replies; 101+ messages in thread
From: Tom Tromey @ 2014-06-06  1:54 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Jeff Law, gcc-patches

>>>>> "Jakub" == Jakub Jelinek <jakub@redhat.com> writes:

Jakub> Another possibility would be to give the macros twice as many arguments
Jakub> as there are parameters and just through the odd arguments away when
Jakub> expanding to the template parameters.  That would mean you write
Jakub> GCC_METHOD7 (gcc_decl, build_decl,
Jakub> 	     const char *, name,
Jakub> 	     enum gcc_c_symbol_kind, sym_kind,
Jakub> 	     const char *, substitution_name,
Jakub> 	     gcc_address, address,
Jakub> 	     const char *, filename,
Jakub> 	     unsigned int, line_number);
Jakub> though it isn't very nice either, guess I'm bikeshedding... ;)

Bikeshed away, I don't mind ... in this case :)

I'm not super fond of this idea, though, I think because the names are
all "useless" -- they don't have any meaning to any of the actual uses,
they are just there for documentation purposes.

One other random idea was something like:

GCC_METHOD7 (gcc_decl, build_decl,
             const char *,             /* Argument NAME.  */
             enum gcc_c_symbol_kind,   /* Argument SYM_KIND.  */
...

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 4/5] add gcc/gdb interface files
  2014-06-06  1:54             ` Tom Tromey
@ 2014-06-06  5:35               ` Jakub Jelinek
  2014-06-09 17:09               ` Jeff Law
  1 sibling, 0 replies; 101+ messages in thread
From: Jakub Jelinek @ 2014-06-06  5:35 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Jeff Law, gcc-patches

On Thu, Jun 05, 2014 at 07:54:30PM -0600, Tom Tromey wrote:
> >>>>> "Jakub" == Jakub Jelinek <jakub@redhat.com> writes:
> 
> Jakub> Another possibility would be to give the macros twice as many arguments
> Jakub> as there are parameters and just through the odd arguments away when
> Jakub> expanding to the template parameters.  That would mean you write
> Jakub> GCC_METHOD7 (gcc_decl, build_decl,
> Jakub> 	     const char *, name,
> Jakub> 	     enum gcc_c_symbol_kind, sym_kind,
> Jakub> 	     const char *, substitution_name,
> Jakub> 	     gcc_address, address,
> Jakub> 	     const char *, filename,
> Jakub> 	     unsigned int, line_number);
> Jakub> though it isn't very nice either, guess I'm bikeshedding... ;)
> 
> Bikeshed away, I don't mind ... in this case :)
> 
> I'm not super fond of this idea, though, I think because the names are
> all "useless" -- they don't have any meaning to any of the actual uses,
> they are just there for documentation purposes.
> 
> One other random idea was something like:
> 
> GCC_METHOD7 (gcc_decl, build_decl,
>              const char *,             /* Argument NAME.  */
>              enum gcc_c_symbol_kind,   /* Argument SYM_KIND.  */

LGTM.

	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 4/5] add gcc/gdb interface files
  2014-06-06  1:54             ` Tom Tromey
  2014-06-06  5:35               ` Jakub Jelinek
@ 2014-06-09 17:09               ` Jeff Law
  2014-06-19 20:45                 ` Tom Tromey
  1 sibling, 1 reply; 101+ messages in thread
From: Jeff Law @ 2014-06-09 17:09 UTC (permalink / raw)
  To: Tom Tromey, Jakub Jelinek; +Cc: gcc-patches

On 06/05/14 19:54, Tom Tromey wrote:
>>>>>> "Jakub" == Jakub Jelinek <jakub@redhat.com> writes:
>
> Jakub> Another possibility would be to give the macros twice as many arguments
> Jakub> as there are parameters and just through the odd arguments away when
> Jakub> expanding to the template parameters.  That would mean you write
> Jakub> GCC_METHOD7 (gcc_decl, build_decl,
> Jakub> 	     const char *, name,
> Jakub> 	     enum gcc_c_symbol_kind, sym_kind,
> Jakub> 	     const char *, substitution_name,
> Jakub> 	     gcc_address, address,
> Jakub> 	     const char *, filename,
> Jakub> 	     unsigned int, line_number);
> Jakub> though it isn't very nice either, guess I'm bikeshedding... ;)
>
> Bikeshed away, I don't mind ... in this case :)
>
> I'm not super fond of this idea, though, I think because the names are
> all "useless" -- they don't have any meaning to any of the actual uses,
> they are just there for documentation purposes.
>
> One other random idea was something like:
>
> GCC_METHOD7 (gcc_decl, build_decl,
>               const char *,             /* Argument NAME.  */
>               enum gcc_c_symbol_kind,   /* Argument SYM_KIND.  */
Works for me.
jeff

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-05-16 20:29   ` Joseph S. Myers
  2014-05-16 21:03     ` Tom Tromey
@ 2014-06-18 21:07     ` Tom Tromey
  2014-06-19 20:47     ` Tom Tromey
  2 siblings, 0 replies; 101+ messages in thread
From: Tom Tromey @ 2014-06-18 21:07 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches

>>>>> "Joseph" == Joseph S Myers <joseph@codesourcery.com> writes:

Tom> This patch adds the plugin to the gcc tree and updates the
Tom> top-level configury.

Following up on your review.

Joseph> I don't see anything obvious that would disable the plugin if
Joseph> plugins are unsupported (e.g. on Windows host) or disabled
Joseph> (--disable-plugin).  Probably the relevant support from
Joseph> gcc/configure.ac needs to go somewhere it can be used at
Joseph> toplevel.

I've moved some relevant code to a new .m4 file in config and used it
from the plugin itself.  This seemed simpler than dealing with it at the
top level.  The plugin also self-disables if its configury needs are not
met.

Tom> +  self->args.push_back ("gcc");

Joseph> seems wrong - at least you should use the appropriate compiler
Joseph> name after transformation for cross compilers /
Joseph> --program-transform-name.  Though really the *versioned* driver
Joseph> $(target_noncanonical)-gcc-$(version) is the right one to use,

This turned out to be a pain :-) There are two basic problems.

First, gdb gets the names of its architectures from BFD, which doesn't
always use the same naming scheme as the GNU configury triplets.  It
does generally use the same names, but for x86 targets it differs quite
a bit.

Second, the configury triplets can vary in annoying ways that don't
really affect correct operation.  For example, "i586-" versus "i686-"
(there is a difference, but I think ignorable given the compiler flags
in the debuginfo, and anyway I suspect not discoverable by gdb); or
"-unknown-" versus "-pc-" (completely irrelevant AFAIK); or even
"x86_64-redhat-linux" versus "x86_64-unknown-linux-gnu" (seemingly
gratuitous).

In the end I added some code to gdb and to libcc1.so to construct a
regexp matching plausible results and then search $PATH for matches.
Which seems rather gross, but workable in reasonable scenarios.

I didn't try to apply the program transform name.  I suppose I could
apply it to the final "gcc" component of the name, though, without much
trouble.  I'll fix this up tomorrow.

Let me know if you have any issue with the above.  Barring that, I will
be resubmitting the series soon, most likely this week.

thanks,
Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 0/5] let gdb reuse gcc'c C compiler
  2014-05-16 15:26 [PATCH 0/5] let gdb reuse gcc'c C compiler Tom Tromey
                   ` (5 preceding siblings ...)
  2014-05-16 18:48 ` [PATCH 5/5] add libcc1 Tom Tromey
@ 2014-06-19 20:42 ` Tom Tromey
  2014-07-30 16:28   ` Tom Tromey
  6 siblings, 1 reply; 101+ messages in thread
From: Tom Tromey @ 2014-06-19 20:42 UTC (permalink / raw)
  To: gcc-patches

>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:

Tom> This patch series is half of a project to let gdb reuse gcc (which
Tom> half depends on which list you are seeing this on), so that users can
Tom> compile small snippets of code and evaluate them in the current
Tom> context of the inferior.

We've updated the patches according to the reviews.

Since I'm not sure if GCC prefers new patch series submissions or
follow-ups; and not all the patches changed; and patch #5 didn't make it
through the email filter unmangled the first time -- I'm just sending
the new patches as individual follow-ups.  I'm happy to "git send-email"
again though if you'd prefer.

I believe we've addressed all the review comments.

On the gdb side a new series will be ready very soon.  We're just
finishing fixing up the documentation according to the review.

thanks,
Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 3/5] introduce the binding oracle
  2014-05-16 19:12   ` Jeff Law
  2014-06-05 15:31     ` Tom Tromey
@ 2014-06-19 20:43     ` Tom Tromey
  1 sibling, 0 replies; 101+ messages in thread
From: Tom Tromey @ 2014-06-19 20:43 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches

Jeff> Just a nit.  C-style comment would be appreciated.  It might also help
Jeff> to clarify what "much more sane" really means here.

Jeff> Otherwise, it looks OK to me.

Here's the updated patch.

Tom

2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* c-tree.h (enum c_oracle_request): New.
	(c_binding_oracle_function): New typedef.
	(c_binding_oracle, c_pushtag, c_bind): Declare.
	* c-decl.c (c_binding_oracle): New global.
	(I_SYMBOL_CHECKED): New macro.
	(i_symbol_binding): New function.
	(I_SYMBOL_BINDING, I_SYMBOL_DECL): Redefine.
	(I_TAG_CHECKED): New macro.
	(i_tag_binding): New function.
	(I_TAG_BINDING, I_TAG_DECL): Redefine.
	(I_LABEL_CHECKED): New macro.
	(i_label_binding): New function.
	(I_LABEL_BINDING, I_LABEL_DECL): Redefine.
	(c_print_identifier): Save and restore c_binding_oracle.
	(c_pushtag, c_bind): New functions.

---
 gcc/c/ChangeLog |  19 +++++++
 gcc/c/c-decl.c  | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 gcc/c/c-tree.h  |  24 +++++++++
 3 files changed, 192 insertions(+), 15 deletions(-)

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 3456030..b0f47af 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -216,21 +216,6 @@ struct GTY((chain_next ("%h.prev"))) c_binding {
 #define B_IN_FILE_SCOPE(b) ((b)->depth == 1 /*file_scope->depth*/)
 #define B_IN_EXTERNAL_SCOPE(b) ((b)->depth == 0 /*external_scope->depth*/)
 
-#define I_SYMBOL_BINDING(node) \
-  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->symbol_binding)
-#define I_SYMBOL_DECL(node) \
- (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
-
-#define I_TAG_BINDING(node) \
-  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->tag_binding)
-#define I_TAG_DECL(node) \
- (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
-
-#define I_LABEL_BINDING(node) \
-  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->label_binding)
-#define I_LABEL_DECL(node) \
- (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
-
 /* Each C symbol points to three linked lists of c_binding structures.
    These describe the values of the identifier in the three different
    namespaces defined by the language.  */
@@ -246,6 +231,96 @@ struct GTY(()) lang_identifier {
 extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
 [(sizeof(struct lang_identifier) == C_SIZEOF_STRUCT_LANG_IDENTIFIER) ? 1 : -1];
 
+/* The binding oracle; see c-tree.h.  */
+void (*c_binding_oracle) (enum c_oracle_request, tree identifier);
+
+/* This flag is set on an identifier if we have previously asked the
+   binding oracle for this identifier's symbol binding.  */
+#define I_SYMBOL_CHECKED(node) \
+  (TREE_LANG_FLAG_4 (IDENTIFIER_NODE_CHECK (node)))
+
+static inline struct c_binding* *
+i_symbol_binding (tree node)
+{
+  struct lang_identifier *lid
+    = (struct lang_identifier *) IDENTIFIER_NODE_CHECK (node);
+
+  if (lid->symbol_binding == NULL
+      && c_binding_oracle != NULL
+      && !I_SYMBOL_CHECKED (node))
+    {
+      /* Set the "checked" flag first, to avoid infinite recursion
+	 when the binding oracle calls back into gcc.  */
+      I_SYMBOL_CHECKED (node) = 1;
+      c_binding_oracle (C_ORACLE_SYMBOL, node);
+    }
+
+  return &lid->symbol_binding;
+}
+
+#define I_SYMBOL_BINDING(node) (*i_symbol_binding (node))
+
+#define I_SYMBOL_DECL(node) \
+ (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
+
+/* This flag is set on an identifier if we have previously asked the
+   binding oracle for this identifier's tag binding.  */
+#define I_TAG_CHECKED(node) \
+  (TREE_LANG_FLAG_5 (IDENTIFIER_NODE_CHECK (node)))
+
+static inline struct c_binding **
+i_tag_binding (tree node)
+{
+  struct lang_identifier *lid
+    = (struct lang_identifier *) IDENTIFIER_NODE_CHECK (node);
+
+  if (lid->tag_binding == NULL
+      && c_binding_oracle != NULL
+      && !I_TAG_CHECKED (node))
+    {
+      /* Set the "checked" flag first, to avoid infinite recursion
+	 when the binding oracle calls back into gcc.  */
+      I_TAG_CHECKED (node) = 1;
+      c_binding_oracle (C_ORACLE_TAG, node);
+    }
+
+  return &lid->tag_binding;
+}
+
+#define I_TAG_BINDING(node) (*i_tag_binding (node))
+
+#define I_TAG_DECL(node) \
+ (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
+
+/* This flag is set on an identifier if we have previously asked the
+   binding oracle for this identifier's label binding.  */
+#define I_LABEL_CHECKED(node) \
+  (TREE_LANG_FLAG_6 (IDENTIFIER_NODE_CHECK (node)))
+
+static inline struct c_binding **
+i_label_binding (tree node)
+{
+  struct lang_identifier *lid
+    = (struct lang_identifier *) IDENTIFIER_NODE_CHECK (node);
+
+  if (lid->label_binding == NULL
+      && c_binding_oracle != NULL
+      && !I_LABEL_CHECKED (node))
+    {
+      /* Set the "checked" flag first, to avoid infinite recursion
+	 when the binding oracle calls back into gcc.  */
+      I_LABEL_CHECKED (node) = 1;
+      c_binding_oracle (C_ORACLE_LABEL, node);
+    }
+
+  return &lid->label_binding;
+}
+
+#define I_LABEL_BINDING(node) (*i_label_binding (node))
+
+#define I_LABEL_DECL(node) \
+ (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
+
 /* The resulting tree type.  */
 
 union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
@@ -612,6 +687,15 @@ decl_jump_unsafe (tree decl)
 void
 c_print_identifier (FILE *file, tree node, int indent)
 {
+  void (*save) (enum c_oracle_request, tree identifier);
+
+  /* Temporarily hide any binding oracle.  Without this, calls to
+     debug_tree from the debugger will end up calling into the oracle,
+     making for a confusing debug session.  As the oracle isn't needed
+     here for normal operation, it's simplest to suppress it.  */
+  save = c_binding_oracle;
+  c_binding_oracle = NULL;
+
   print_node (file, "symbol", I_SYMBOL_DECL (node), indent + 4);
   print_node (file, "tag", I_TAG_DECL (node), indent + 4);
   print_node (file, "label", I_LABEL_DECL (node), indent + 4);
@@ -622,6 +706,8 @@ c_print_identifier (FILE *file, tree node, int indent)
       fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"",
 	       (void *) rid, IDENTIFIER_POINTER (rid));
     }
+
+  c_binding_oracle = save;
 }
 
 /* Establish a binding between NAME, an IDENTIFIER_NODE, and DECL,
@@ -1486,6 +1572,54 @@ pushtag (location_t loc, tree name, tree type)
 	}
     }
 }
+
+/* An exported interface to pushtag.  This is used by the gdb plugin's
+   binding oracle to introduce a new tag binding.  */
+
+void
+c_pushtag (location_t loc, tree name, tree type)
+{
+  pushtag (loc, name, type);
+}
+
+/* An exported interface to bind a declaration.  LOC is the location
+   to use.  DECL is the declaration to bind.  The decl's name is used
+   to determine how it is bound.  If DECL is a VAR_DECL, then
+   IS_GLOBAL determines whether the decl is put into the global (file
+   and external) scope or the current function's scope; if DECL is not
+   a VAR_DECL then it is always put into the file scope.  */
+
+void
+c_bind (location_t loc, tree decl, bool is_global)
+{
+  struct c_scope *scope;
+  bool nested = false;
+
+  if (TREE_CODE (decl) != VAR_DECL || current_function_scope == NULL)
+    {
+      /* Types and functions are always considered to be global.  */
+      scope = file_scope;
+      DECL_EXTERNAL (decl) = 1;
+      TREE_PUBLIC (decl) = 1;
+    }
+  else if (is_global)
+    {
+      /* Also bind it into the external scope.  */
+      bind (DECL_NAME (decl), decl, external_scope, true, false, loc);
+      nested = true;
+      scope = file_scope;
+      DECL_EXTERNAL (decl) = 1;
+      TREE_PUBLIC (decl) = 1;
+    }
+  else
+    {
+      DECL_CONTEXT (decl) = current_function_decl;
+      TREE_PUBLIC (decl) = 0;
+      scope = current_function_scope;
+    }
+
+  bind (DECL_NAME (decl), decl, scope, false, nested, loc);
+}
 \f
 /* Subroutine of compare_decls.  Allow harmless mismatches in return
    and argument types provided that the type modes match.  This function
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 133930f..a6c3527 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -665,12 +665,36 @@ extern int current_function_returns_abnormally;
 extern enum machine_mode c_default_pointer_mode;
 
 /* In c-decl.c */
+
+/* Tell the binding oracle what kind of binding we are looking for.  */
+
+enum c_oracle_request
+{
+  C_ORACLE_SYMBOL,
+  C_ORACLE_TAG,
+  C_ORACLE_LABEL
+};
+
+/* If this is non-NULL, then it is a "binding oracle" which can lazily
+   create bindings when needed by the C compiler.  The oracle is told
+   the name and type of the binding to create.  It can call pushdecl
+   or the like to ensure the binding is visible; or do nothing,
+   leaving the binding untouched.  c-decl.c takes note of when the
+   oracle has been called and will not call it again if it fails to
+   create a given binding.  */
+
+typedef void c_binding_oracle_function (enum c_oracle_request, tree identifier);
+
+extern c_binding_oracle_function *c_binding_oracle;
+
 extern void c_finish_incomplete_decl (tree);
 extern void c_write_global_declarations (void);
 extern tree c_omp_reduction_id (enum tree_code, tree);
 extern tree c_omp_reduction_decl (tree);
 extern tree c_omp_reduction_lookup (tree, tree);
 extern tree c_check_omp_declare_reduction_r (tree *, int *, void *);
+extern void c_pushtag (location_t, tree, tree);
+extern void c_bind (location_t, tree, bool);
 
 /* In c-errors.c */
 extern void pedwarn_c90 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
-- 
1.9.3

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 4/5] add gcc/gdb interface files
  2014-06-09 17:09               ` Jeff Law
@ 2014-06-19 20:45                 ` Tom Tromey
  0 siblings, 0 replies; 101+ messages in thread
From: Tom Tromey @ 2014-06-19 20:45 UTC (permalink / raw)
  To: Jeff Law; +Cc: Jakub Jelinek, gcc-patches

>>>>> "Jeff" == Jeff Law <law@redhat.com> writes:

>> One other random idea was something like:

>> GCC_METHOD7 (gcc_decl, build_decl,
>> const char *,             /* Argument NAME.  */
>> enum gcc_c_symbol_kind,   /* Argument SYM_KIND.  */

Jeff> Works for me.

I took this approach.  Other changes in this version are - a minor
change to one of the generic gcc methods to make it possible to choose
the correct compiler, and changing "GDB" in the "part of" comments to
"GCC".

Tom

2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
	    Jan Kratochvil  <jan.kratochvil@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* gcc-c-fe.def: New file.
	* gcc-c-interface.h: New file.
	* gcc-interface.h: New file.

---
 include/ChangeLog         |   8 ++
 include/gcc-c-fe.def      | 197 +++++++++++++++++++++++++++++++++++++++++
 include/gcc-c-interface.h | 220 ++++++++++++++++++++++++++++++++++++++++++++++
 include/gcc-interface.h   | 127 ++++++++++++++++++++++++++
 4 files changed, 552 insertions(+)
 create mode 100644 include/gcc-c-fe.def
 create mode 100644 include/gcc-c-interface.h
 create mode 100644 include/gcc-interface.h

diff --git a/include/gcc-c-fe.def b/include/gcc-c-fe.def
new file mode 100644
index 0000000..19cb867
--- /dev/null
+++ b/include/gcc-c-fe.def
@@ -0,0 +1,197 @@
+/* Interface between GCC C FE and GDB  -*- c -*-
+
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   This program 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 of the License, or
+   (at your option) any later version.
+
+   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+
+/* Create a new "decl" in GCC.  A decl is a declaration, basically a
+   kind of symbol.
+
+   NAME is the name of the new symbol.  SYM_KIND is the kind of
+   symbol being requested.  SYM_TYPE is the new symbol's C type;
+   except for labels, where this is not meaningful and should be
+   zero.  If SUBSTITUTION_NAME is not NULL, then a reference to this
+   decl in the source will later be substituted with a dereference
+   of a variable of the given name.  Otherwise, for symbols having
+   an address (e.g., functions), ADDRESS is the address.  FILENAME
+   and LINE_NUMBER refer to the symbol's source location.  If this
+   is not known, FILENAME can be NULL and LINE_NUMBER can be 0.
+   This function returns the new decl.  */
+
+GCC_METHOD7 (gcc_decl, build_decl,
+	     const char *,	      /* Argument NAME.  */
+	     enum gcc_c_symbol_kind,  /* Argument SYM_KIND.  */
+	     gcc_type,		      /* Argument SYM_TYPE.  */
+	     const char *,	      /* Argument SUBSTITUTION_NAME.  */
+	     gcc_address,	      /* Argument ADDRESS.  */
+	     const char *,	      /* Argument FILENAME.  */
+	     unsigned int)	      /* Argument LINE_NUMBER.  */
+
+/* Insert a GCC decl into the symbol table.  DECL is the decl to
+   insert.  IS_GLOBAL is true if this is an outermost binding, and
+   false if it is a possibly-shadowing binding.  */
+
+GCC_METHOD2 (int /* bool */, bind,
+	     gcc_decl,		   /* Argument DECL.  */
+	     int /* bool */)       /* Argument IS_GLOBAL.  */
+
+/* Insert a tagged type into the symbol table.  NAME is the tag name
+   of the type and TAGGED_TYPE is the type itself.  TAGGED_TYPE must
+   be either a struct, union, or enum type, as these are the only
+   types that have tags.  FILENAME and LINE_NUMBER refer to the type's
+   source location.  If this is not known, FILENAME can be NULL and
+   LINE_NUMBER can be 0.  */
+
+GCC_METHOD4 (int /* bool */, tagbind,
+	     const char *,	      /* Argument NAME.  */
+	     gcc_type,		      /* Argument TAGGED_TYPE.  */
+	     const char *,	      /* Argument FILENAME.  */
+	     unsigned int)	      /* Argument LINE_NUMBER.  */
+
+/* Return the type of a pointer to a given base type.  */
+
+GCC_METHOD1 (gcc_type, build_pointer_type,
+	     gcc_type)			/* Argument BASE_TYPE.  */
+
+/* Create a new 'struct' type.  Initially it has no fields.  */
+
+GCC_METHOD0 (gcc_type, build_record_type)
+
+/* Create a new 'union' type.  Initially it has no fields.  */
+
+GCC_METHOD0 (gcc_type, build_union_type)
+
+/* Add a field to a struct or union type.  FIELD_NAME is the field's
+   name.  FIELD_TYPE is the type of the field.  BITSIZE and BITPOS
+   indicate where in the struct the field occurs.  */
+
+GCC_METHOD5 (int /* bool */, build_add_field,
+	     gcc_type,			   /* Argument RECORD_OR_UNION_TYPE. */
+	     const char *,		   /* Argument FIELD_NAME.  */
+	     gcc_type,			   /* Argument FIELD_TYPE.  */
+	     unsigned long,		   /* Argument BITSIZE.  */
+	     unsigned long)		   /* Argument BITPOS.  */
+
+/* After all the fields have been added to a struct or union, the
+   struct or union type must be "finished".  This does some final
+   cleanups in GCC.  */
+
+GCC_METHOD2 (int /* bool */, finish_record_or_union,
+	     gcc_type,			   /* Argument RECORD_OR_UNION_TYPE. */
+	     unsigned long)		   /* Argument SIZE_IN_BYTES.  */
+
+/* Create a new 'enum' type.  The new type initially has no
+   associated constants.  */
+
+GCC_METHOD1 (gcc_type, build_enum_type,
+	     gcc_type)			    /* Argument UNDERLYING_INT_TYPE. */
+
+/* Add a new constant to an enum type.  NAME is the constant's
+   name and VALUE is its value.  */
+
+GCC_METHOD3 (int /* bool */, build_add_enum_constant,
+	     gcc_type,		       /* Argument ENUM_TYPE.  */
+	     const char *,	       /* Argument NAME.  */
+	     unsigned long)	       /* Argument VALUE.  */
+
+/* After all the constants have been added to an enum, the type must
+   be "finished".  This does some final cleanups in GCC.  */
+
+GCC_METHOD1 (int /* bool */, finish_enum_type,
+	     gcc_type)		       /* Argument ENUM_TYPE.  */
+
+/* Create a new function type.  RETURN_TYPE is the type returned by
+   the function, and ARGUMENT_TYPES is a vector, of length NARGS, of
+   the argument types.  IS_VARARGS is true if the function is
+   varargs.  */
+
+GCC_METHOD3 (gcc_type, build_function_type,
+	     gcc_type,			   /* Argument RETURN_TYPE.  */
+	     const struct gcc_type_array *, /* Argument ARGUMENT_TYPES.  */
+	     int /* bool */)               /* Argument IS_VARARGS.  */
+
+/* Return an integer type with the given properties.  */
+
+GCC_METHOD2 (gcc_type, int_type,
+	     int /* bool */,               /* Argument IS_UNSIGNED.  */
+	     unsigned long)                /* Argument SIZE_IN_BYTES.  */
+
+/* Return a floating point type with the given properties.  */
+
+GCC_METHOD1 (gcc_type, float_type,
+	     unsigned long)			/* Argument SIZE_IN_BYTES.  */
+
+/* Return the 'void' type.  */
+
+GCC_METHOD0 (gcc_type, void_type)
+
+/* Return the 'bool' type.  */
+
+GCC_METHOD0 (gcc_type, bool_type)
+
+/* Create a new array type.  If NUM_ELEMENTS is -1, then the array
+   is assumed to have an unknown length.  */
+
+GCC_METHOD2 (gcc_type, build_array_type,
+	     gcc_type,			  /* Argument ELEMENT_TYPE.  */
+	     int)			  /* Argument NUM_ELEMENTS.  */
+
+/* Create a new variably-sized array type.  UPPER_BOUND_NAME is the
+   name of a local variable that holds the upper bound of the array;
+   it is one less than the array size.  */
+
+GCC_METHOD2 (gcc_type, build_vla_array_type,
+	     gcc_type,			  /* Argument ELEMENT_TYPE.  */
+	     const char *)		  /* Argument UPPER_BOUND_NAME.  */
+
+/* Return a qualified variant of a given base type.  QUALIFIERS says
+   which qualifiers to use; it is composed of or'd together
+   constants from 'enum gcc_qualifiers'.  */
+
+GCC_METHOD2 (gcc_type, build_qualified_type,
+	     gcc_type,			      /* Argument UNQUALIFIED_TYPE.  */
+	     enum gcc_qualifiers)	      /* Argument QUALIFIERS.  */
+
+/* Build a complex type given its element type.  */
+
+GCC_METHOD1 (gcc_type, build_complex_type,
+	     gcc_type)			  /* Argument ELEMENT_TYPE.  */
+
+/* Build a vector type given its element type and number of
+   elements.  */
+
+GCC_METHOD2 (gcc_type, build_vector_type,
+	     gcc_type,			  /* Argument ELEMENT_TYPE.  */
+	     int)			  /* Argument NUM_ELEMENTS.  */
+
+/* Build a constant.  NAME is the constant's name and VALUE is its
+   value.  FILENAME and LINE_NUMBER refer to the type's source
+   location.  If this is not known, FILENAME can be NULL and
+   LINE_NUMBER can be 0.  */
+
+GCC_METHOD5 (int /* bool */, build_constant,
+	     gcc_type,		  /* Argument TYPE.  */
+	     const char *,	  /* Argument NAME.  */
+	     unsigned long,	  /* Argument VALUE.  */
+	     const char *,	  /* Argument FILENAME.  */
+	     unsigned int)	  /* Argument LINE_NUMBER.  */
+
+/* Emit an error and return an error type object.  */
+
+GCC_METHOD1 (gcc_type, error,
+	     const char *)		 /* Argument MESSAGE.  */
diff --git a/include/gcc-c-interface.h b/include/gcc-c-interface.h
new file mode 100644
index 0000000..25ef62f
--- /dev/null
+++ b/include/gcc-c-interface.h
@@ -0,0 +1,220 @@
+/* Interface between GCC C FE and GDB
+
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   This program 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 of the License, or
+   (at your option) any later version.
+
+   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_C_INTERFACE_H
+#define GCC_C_INTERFACE_H
+
+#include "gcc-interface.h"
+
+/* This header defines the interface to the GCC API.  It must be both
+   valid C and valid C++, because it is included by both programs.  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declaration.  */
+
+struct gcc_c_context;
+
+/*
+ * Definitions and declarations for the C front end.
+ */
+
+/* Defined versions of the C front-end API.  */
+
+enum gcc_c_api_version
+{
+  GCC_C_FE_VERSION_0 = 0
+};
+
+/* Qualifiers.  */
+
+enum gcc_qualifiers
+{
+  GCC_QUALIFIER_CONST = 1,
+  GCC_QUALIFIER_VOLATILE = 2,
+  GCC_QUALIFIER_RESTRICT = 4
+};
+
+/* This enumerates the kinds of decls that GDB can create.  */
+
+enum gcc_c_symbol_kind
+{
+  /* A function.  */
+
+  GCC_C_SYMBOL_FUNCTION,
+
+  /* A variable.  */
+
+  GCC_C_SYMBOL_VARIABLE,
+
+  /* A typedef.  */
+
+  GCC_C_SYMBOL_TYPEDEF,
+
+  /* A label.  */
+
+  GCC_C_SYMBOL_LABEL
+};
+
+/* This enumerates the types of symbols that GCC might request from
+   GDB.  */
+
+enum gcc_c_oracle_request
+{
+  /* An ordinary symbol -- a variable, function, typedef, or enum
+     constant.  */
+
+  GCC_C_ORACLE_SYMBOL,
+
+  /* A struct, union, or enum tag.  */
+
+  GCC_C_ORACLE_TAG,
+
+  /* A label.  */
+
+  GCC_C_ORACLE_LABEL
+};
+
+/* The type of the function called by GCC to ask GDB for a symbol's
+   definition.  DATUM is an arbitrary value supplied when the oracle
+   function is registered.  CONTEXT is the GCC context in which the
+   request is being made.  REQUEST specifies what sort of symbol is
+   being requested, and IDENTIFIER is the name of the symbol.  */
+
+typedef void gcc_c_oracle_function (void *datum,
+				    struct gcc_c_context *context,
+				    enum gcc_c_oracle_request request,
+				    const char *identifier);
+
+/* The type of the function called by GCC to ask GDB for a symbol's
+   address.  This should return 0 if the address is not known.  */
+
+typedef gcc_address gcc_c_symbol_address_function (void *datum,
+						   struct gcc_c_context *ctxt,
+						   const char *identifier);
+
+/* An array of types used for creating a function type.  */
+
+struct gcc_type_array
+{
+  /* Number of elements.  */
+
+  int n_elements;
+
+  /* The elements.  */
+
+  gcc_type *elements;
+};
+
+/* The vtable used by the C front end.  */
+
+struct gcc_c_fe_vtable
+{
+  /* The version of the C interface.  The value is one of the
+     gcc_c_api_version constants.  */
+
+  unsigned int c_version;
+
+  /* Set the callbacks for this context.
+
+     The binding oracle is called whenever the C parser needs to look
+     up a symbol.  This gives the caller a chance to lazily
+     instantiate symbols using other parts of the gcc_c_fe_interface
+     API.
+
+     The address oracle is called whenever the C parser needs to look
+     up a symbol.  This is only called for symbols not provided by the
+     symbol oracle -- that is, just built-in functions where GCC
+     provides the declaration.
+
+     DATUM is an arbitrary piece of data that is passed back verbatim
+     to the callbakcs in requests.  */
+
+  void (*set_callbacks) (struct gcc_c_context *self,
+			 gcc_c_oracle_function *binding_oracle,
+			 gcc_c_symbol_address_function *address_oracle,
+			 void *datum);
+
+#define GCC_METHOD0(R, N) \
+  R (*N) (struct gcc_c_context *);
+#define GCC_METHOD1(R, N, A) \
+  R (*N) (struct gcc_c_context *, A);
+#define GCC_METHOD2(R, N, A, B) \
+  R (*N) (struct gcc_c_context *, A, B);
+#define GCC_METHOD3(R, N, A, B, C) \
+  R (*N) (struct gcc_c_context *, A, B, C);
+#define GCC_METHOD4(R, N, A, B, C, D) \
+  R (*N) (struct gcc_c_context *, A, B, C, D);
+#define GCC_METHOD5(R, N, A, B, C, D, E) \
+  R (*N) (struct gcc_c_context *, A, B, C, D, E);
+#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
+  R (*N) (struct gcc_c_context *, A, B, C, D, E, F, G);
+
+#include "gcc-c-fe.def"
+
+#undef GCC_METHOD0
+#undef GCC_METHOD1
+#undef GCC_METHOD2
+#undef GCC_METHOD3
+#undef GCC_METHOD4
+#undef GCC_METHOD5
+#undef GCC_METHOD7
+
+};
+
+/* The C front end object.  */
+
+struct gcc_c_context
+{
+  /* Base class.  */
+
+  struct gcc_base_context base;
+
+  /* Our vtable.  This is a separate field because this is simpler
+     than implementing a vtable inheritance scheme in C.  */
+
+  const struct gcc_c_fe_vtable *c_ops;
+};
+
+/* The name of the .so that the compiler builds.  We dlopen this
+   later.  */
+
+#define GCC_C_FE_LIBCC libcc1.so
+
+/* The compiler exports a single initialization function.  This macro
+   holds its name as a symbol.  */
+
+#define GCC_C_FE_CONTEXT gcc_c_fe_context
+
+/* The type of the initialization function.  The caller passes in the
+   desired base version and desired C-specific version.  If the
+   request can be satisfied, a compatible gcc_context object will be
+   returned.  Otherwise, the function returns NULL.  */
+
+typedef struct gcc_c_context *gcc_c_fe_context_function
+    (enum gcc_base_api_version,
+     enum gcc_c_api_version);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GCC_C_INTERFACE_H */
diff --git a/include/gcc-interface.h b/include/gcc-interface.h
new file mode 100644
index 0000000..34010f2
--- /dev/null
+++ b/include/gcc-interface.h
@@ -0,0 +1,127 @@
+/* Generic interface between GCC and GDB
+
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   This program 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 of the License, or
+   (at your option) any later version.
+
+   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_INTERFACE_H
+#define GCC_INTERFACE_H
+
+/* This header defines the interface to the GCC API.  It must be both
+   valid C and valid C++, because it is included by both programs.  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Opaque typedefs for objects passed through the interface.  */
+
+typedef unsigned long long gcc_type;
+typedef unsigned long long gcc_decl;
+
+/* An address in the inferior.  */
+
+typedef unsigned long long gcc_address;
+
+/* Forward declaration.  */
+
+struct gcc_base_context;
+
+/* Defined versions of the generic API.  */
+
+enum gcc_base_api_version
+{
+  GCC_FE_VERSION_0 = 0
+};
+
+/* The operations defined by the GCC base API.  This is the vtable for
+   the real context structure which is passed around.
+
+   The "base" API is concerned with basics shared by all compiler
+   front ends: setting command-line arguments, the file names, etc.
+
+   Front-end-specific interfaces inherit from this one.  */
+
+struct gcc_base_vtable
+{
+  /* The actual version implemented in this interface.  This field can
+     be relied on not to move, so users can always check it if they
+     desire.  The value is one of the gcc_base_api_version constants.
+  */
+
+  unsigned int version;
+
+  /* Set the compiler's command-line options for the next compilation.
+     TRIPLET_REGEXP is a regular expression that is used to match the
+     configury triplet prefix to the compiler.
+     The arguments are copied by GCC.  ARGV need not be
+     NULL-terminated.  The arguments must be set separately for each
+     compilation; that is, after a compile is requested, the
+     previously-set arguments cannot be reused.
+
+     This returns NULL on success.  On failure, returns a malloc()d
+     error message.  The caller is responsible for freeing it.  */
+
+  char *(*set_arguments) (struct gcc_base_context *self,
+			  const char *triplet_regexp,
+			  int argc, char **argv);
+
+  /* Set the file name of the program to compile.  The string is
+     copied by the method implementation, but the caller must
+     guarantee that the file exists through the compilation.  */
+
+  void (*set_source_file) (struct gcc_base_context *self, const char *file);
+
+  /* Set a callback to use for printing error messages.  DATUM is
+     passed through to the callback unchanged.  */
+
+  void (*set_print_callback) (struct gcc_base_context *self,
+			      void (*print_function) (void *datum,
+						      const char *message),
+			      void *datum);
+
+  /* Perform the compilation.  FILENAME is the name of the resulting
+     object file.  VERBOSE can be set to cause GCC to print some
+     information as it works.  Returns true on success, false on
+     error.  */
+
+  int /* bool */ (*compile) (struct gcc_base_context *self,
+			     const char *filename,
+			     int /* bool */ verbose);
+
+  /* Destroy this object.  */
+
+  void (*destroy) (struct gcc_base_context *self);
+};
+
+/* The GCC object.  */
+
+struct gcc_base_context
+{
+  /* The virtual table.  */
+
+  const struct gcc_base_vtable *ops;
+};
+
+/* The name of the dummy wrapper function generated by gdb.  */
+
+#define GCC_FE_WRAPPER_FUNCTION "_gdb_expr"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GCC_INTERFACE_H */
-- 
1.9.3

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 2/5] c_diagnostic_ignored_function hack
  2014-05-16 16:05   ` Joseph S. Myers
@ 2014-06-19 20:46     ` Tom Tromey
  0 siblings, 0 replies; 101+ messages in thread
From: Tom Tromey @ 2014-06-19 20:46 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches

Joseph> I'd say this global actually belongs somewhere in the
Joseph> diagnostic_context (i.e., instead of the
Joseph> diagnostic_context_auxiliary_data (DC) actually being a tree as
Joseph> it is at present, it should point to a structure with whatever
Joseph> extra information clients wish to use to control aspects of
Joseph> diagnostic reporting).

We dropped this patch from the series and instead the diagnostic stuff
is all handled in the plugin itself.  You can see it in the new patch #5.

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-05-16 20:29   ` Joseph S. Myers
  2014-05-16 21:03     ` Tom Tromey
  2014-06-18 21:07     ` Tom Tromey
@ 2014-06-19 20:47     ` Tom Tromey
  2 siblings, 0 replies; 101+ messages in thread
From: Tom Tromey @ 2014-06-19 20:47 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches

Joseph> I don't see anything obvious that would disable the plugin if
Joseph> plugins are unsupported (e.g. on Windows host) or disabled
Joseph> (--disable-plugin).  Probably the relevant support from
Joseph> gcc/configure.ac needs to go somewhere it can be used at
Joseph> toplevel.

Here's the patch to pull this out to a separate file.
I've omitted generated code from this mail.

Tom

b/config/ChangeLog:
2014-06-19  Tom Tromey  <tromey@redhat.com>

	* gcc-plugin.m4: New file.

b/gcc/ChangeLog:
2014-06-19  Tom Tromey  <tromey@redhat.com>

	* aclocal.m4, configure: Rebuild.
	* Makefile.in (aclocal_deps): Add gcc-plugin.m4.
	* configure.ac: Use GCC_ENABLE_PLUGINS.

---
 config/ChangeLog     |   4 ++
 config/gcc-plugin.m4 | 113 +++++++++++++++++++++++++++++++++
 gcc/ChangeLog        |   6 ++
 gcc/Makefile.in      |   1 +
 gcc/aclocal.m4       |  89 +-------------------------
 gcc/configure        | 172 +++++++++++++++++++++++++--------------------------
 gcc/configure.ac     | 100 +-----------------------------
 7 files changed, 212 insertions(+), 273 deletions(-)
 create mode 100644 config/gcc-plugin.m4

diff --git a/config/gcc-plugin.m4 b/config/gcc-plugin.m4
new file mode 100644
index 0000000..dd06a58
--- /dev/null
+++ b/config/gcc-plugin.m4
@@ -0,0 +1,113 @@
+# gcc-plugin.m4 -*- Autoconf -*-
+# Check whether GCC is able to be built with plugin support.
+
+dnl Copyright (C) 2014 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+# Check for plugin support.
+# Respects --enable-plugin.
+# Sets the shell variables enable_plugin and pluginlibs.
+AC_DEFUN([GCC_ENABLE_PLUGINS],
+  [# Check for plugin support
+   AC_ARG_ENABLE(plugin,
+   [AS_HELP_STRING([--enable-plugin], [enable plugin support])],
+   enable_plugin=$enableval,
+   enable_plugin=yes; default_plugin=yes)
+
+   pluginlibs=
+
+   case "${host}" in
+     *-*-darwin*)
+       if test x$build = x$host; then
+	 export_sym_check="nm${exeext} -g"
+       elif test x$host = x$target; then
+	 export_sym_check="$gcc_cv_nm -g"
+       else
+	 export_sym_check=
+       fi
+     ;;
+     *)
+       if test x$build = x$host; then
+	 export_sym_check="objdump${exeext} -T"
+       elif test x$host = x$target; then
+	 export_sym_check="$gcc_cv_objdump -T"
+       else
+	 export_sym_check=
+       fi
+     ;;
+   esac
+
+   if test x"$enable_plugin" = x"yes"; then
+
+     AC_MSG_CHECKING([for exported symbols])
+     if test "x$export_sym_check" != x; then
+       echo "int main() {return 0;} int foobar() {return 0;}" > conftest.c
+       ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest$ac_exeext > /dev/null 2>&1
+       if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then
+	 : # No need to use a flag
+	 AC_MSG_RESULT([yes])
+       else
+	 AC_MSG_RESULT([yes])
+	 AC_MSG_CHECKING([for -rdynamic])
+	 ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest$ac_exeext > /dev/null 2>&1
+	 if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then
+	   plugin_rdynamic=yes
+	   pluginlibs="-rdynamic"
+	 else
+	   plugin_rdynamic=no
+	   enable_plugin=no
+	 fi
+	 AC_MSG_RESULT([$plugin_rdynamic])
+       fi
+     else
+       AC_MSG_RESULT([unable to check])
+     fi
+
+     # Check -ldl
+     saved_LIBS="$LIBS"
+     AC_SEARCH_LIBS([dlopen], [dl])
+     if test x"$ac_cv_search_dlopen" = x"-ldl"; then
+       pluginlibs="$pluginlibs -ldl"
+     fi
+     LIBS="$saved_LIBS"
+
+     # Check that we can build shared objects with -fPIC -shared
+     saved_LDFLAGS="$LDFLAGS"
+     saved_CFLAGS="$CFLAGS"
+     case "${host}" in
+       *-*-darwin*)
+	 CFLAGS=`echo $CFLAGS | sed s/-mdynamic-no-pic//g`
+	 CFLAGS="$CFLAGS -fPIC"
+	 LDFLAGS="$LDFLAGS -shared -undefined dynamic_lookup"
+       ;;
+       *)
+	 CFLAGS="$CFLAGS -fPIC"
+	 LDFLAGS="$LDFLAGS -fPIC -shared"
+       ;;
+     esac
+     AC_MSG_CHECKING([for -fPIC -shared])
+     AC_TRY_LINK(
+       [extern int X;],[return X == 0;],
+       [AC_MSG_RESULT([yes]); have_pic_shared=yes],
+       [AC_MSG_RESULT([no]); have_pic_shared=no])
+     if test x"$have_pic_shared" != x"yes" -o x"$ac_cv_search_dlopen" = x"no"; then
+       pluginlibs=
+       enable_plugin=no
+     fi
+     LDFLAGS="$saved_LDFLAGS"
+     CFLAGS="$saved_CFLAGS"
+
+     # If plugin support had been requested but not available, fail.
+     if test x"$enable_plugin" = x"no" ; then
+       if test x"$default_plugin" != x"yes"; then
+	 AC_MSG_ERROR([
+   Building GCC with plugin support requires a host that supports
+   -fPIC, -shared, -ldl and -rdynamic.])
+       fi
+     fi
+   fi
+])
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 5587b75..b17530a 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1672,6 +1672,7 @@ aclocal_deps = \
 	$(srcdir)/../config/codeset.m4 \
 	$(srcdir)/../config/extensions.m4 \
 	$(srcdir)/../config/gettext-sister.m4 \
+	$(srcdir)/../config/gcc-plugin.m4 \
 	$(srcdir)/../config/iconv.m4 \
 	$(srcdir)/../config/lcmessage.m4 \
 	$(srcdir)/../config/lib-ld.m4 \
diff --git a/gcc/configure.ac b/gcc/configure.ac
index a1cf901..b9eedc5 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -5443,105 +5443,7 @@ if test "x${CLOOGLIBS}" != "x" ; then
    AC_DEFINE(HAVE_cloog, 1, [Define if cloog is in use.])
 fi
 
-# Check for plugin support
-AC_ARG_ENABLE(plugin,
-[AS_HELP_STRING([--enable-plugin], [enable plugin support])],
-enable_plugin=$enableval,
-enable_plugin=yes; default_plugin=yes)
-
-pluginlibs=
-
-case "${host}" in
-  *-*-darwin*)
-    if test x$build = x$host; then
-      export_sym_check="nm${exeext} -g"
-    elif test x$host = x$target; then
-      export_sym_check="$gcc_cv_nm -g"
-    else
-      export_sym_check=
-    fi
-  ;;
-  *)
-    if test x$build = x$host; then
-      export_sym_check="objdump${exeext} -T"
-    elif test x$host = x$target; then
-      export_sym_check="$gcc_cv_objdump -T"
-    else
-      export_sym_check=
-    fi
-  ;;
-esac
-
-if test x"$enable_plugin" = x"yes"; then
-
-  AC_MSG_CHECKING([for exported symbols])
-  if test "x$export_sym_check" != x; then
-    echo "int main() {return 0;} int foobar() {return 0;}" > conftest.c
-    ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest$ac_exeext > /dev/null 2>&1
-    if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then
-      : # No need to use a flag
-      AC_MSG_RESULT([yes])
-    else
-      AC_MSG_RESULT([yes])
-      AC_MSG_CHECKING([for -rdynamic])
-      ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest$ac_exeext > /dev/null 2>&1
-      if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then
-        plugin_rdynamic=yes
-        pluginlibs="-rdynamic"
-      else
-        plugin_rdynamic=no
-        enable_plugin=no
-      fi
-      AC_MSG_RESULT([$plugin_rdynamic])
-    fi
-  else
-    AC_MSG_RESULT([unable to check])
-  fi
-
-  # Check -ldl
-  saved_LIBS="$LIBS"
-  AC_SEARCH_LIBS([dlopen], [dl])
-  if test x"$ac_cv_search_dlopen" = x"-ldl"; then
-    pluginlibs="$pluginlibs -ldl"
-  fi
-  LIBS="$saved_LIBS"
-
-  # Check that we can build shared objects with -fPIC -shared
-  saved_LDFLAGS="$LDFLAGS"
-  saved_CFLAGS="$CFLAGS"
-  case "${host}" in
-    *-*-darwin*)
-      CFLAGS=`echo $CFLAGS | sed s/-mdynamic-no-pic//g`
-      CFLAGS="$CFLAGS -fPIC"
-      LDFLAGS="$LDFLAGS -shared -undefined dynamic_lookup"
-    ;;
-    *)
-      CFLAGS="$CFLAGS -fPIC"
-      LDFLAGS="$LDFLAGS -fPIC -shared"
-    ;;
-  esac
-  AC_MSG_CHECKING([for -fPIC -shared])
-  AC_TRY_LINK(
-    [extern int X;],[return X == 0;],
-    [AC_MSG_RESULT([yes]); have_pic_shared=yes],
-    [AC_MSG_RESULT([no]); have_pic_shared=no])
-  if test x"$have_pic_shared" != x"yes" -o x"$ac_cv_search_dlopen" = x"no"; then
-    pluginlibs=
-    enable_plugin=no
-  fi
-  LDFLAGS="$saved_LDFLAGS"
-  CFLAGS="$saved_CFLAGS"
-
-  # If plugin support had been requested but not available, fail.
-  if test x"$enable_plugin" = x"no" ; then
-    if test x"$default_plugin" != x"yes"; then
-      AC_MSG_ERROR([
-Building GCC with plugin support requires a host that supports
--fPIC, -shared, -ldl and -rdynamic.])
-    fi
-  fi
-fi
-
+GCC_ENABLE_PLUGINS
 AC_SUBST(pluginlibs)
 AC_SUBST(enable_plugin)
 if test x"$enable_plugin" = x"yes"; then
-- 
1.9.3

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-05-16 18:48 ` [PATCH 5/5] add libcc1 Tom Tromey
                     ` (2 preceding siblings ...)
  2014-05-16 22:17   ` Mike Stump
@ 2014-06-19 20:52   ` Tom Tromey
  2014-06-19 21:45     ` Jakub Jelinek
                       ` (3 more replies)
  3 siblings, 4 replies; 101+ messages in thread
From: Tom Tromey @ 2014-06-19 20:52 UTC (permalink / raw)
  To: gcc-patches

Tom> I've edited this one down by removing the auto-generated stuff , and
Tom> then compressed it.

Here's a new version of patch #5.
I've removed the generated code; let's see if it gets through without
compression.

I think this addresses all the reviews:

* It uses gcc-plugin.m4 to disable the plugin
* It does some configure checks for needed functionality, and disables
  the plugin if they are not found
* libcc1 and the plugin now do a protocol version handshake at
  startup
* The diagnostic overriding code is now in the plugin, not in gcc proper
* gdb now tells libcc1 about the target triplet, and libcc1 uses
  this to invoke the proper GCC.  This is done by (ewww) searching $PATH.

Tom

2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* Makefile.def: Add libcc1 to host_modules.
	* configure.ac (host_tools): Add libcc1.
	* Makefile.in, configure: Rebuild.

2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
	    Jan Kratochvil  <jan.kratochvil@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* aclocal.m4: New file.
	* callbacks.cc: New file.
	* callbacks.hh: New file.
	* cc1plugin-config.h.in: New file.
	* configure: New file.
	* configure.ac: New file.
	* connection.cc: New file.
	* connection.hh: New file.
	* findcomp.cc: New file.
	* findcomp.hh: New file.
	* libcc1.cc: New file.
	* libcc1plugin.sym: New file.
	* libcc1.sym: New file.
	* Makefile.am: New file.
	* Makefile.in: New file.
	* marshall.cc: New file.
	* marshall.hh: New file.
	* names.cc: New file.
	* names.hh: New file.
	* plugin.cc: New file.
	* rpc.hh: New file.
	* status.hh: New file.

---
 ChangeLog                    |     7 +
 Makefile.def                 |     5 +
 Makefile.in                  |   997 ++-
 configure                    |     2 +-
 configure.ac                 |     4 +-
 libcc1/ChangeLog             |    26 +
 libcc1/Makefile.am           |    52 +
 libcc1/Makefile.in           |   627 ++
 libcc1/aclocal.m4            |   981 +++
 libcc1/callbacks.cc          |    90 +
 libcc1/callbacks.hh          |    64 +
 libcc1/cc1plugin-config.h.in |    92 +
 libcc1/configure             | 17176 +++++++++++++++++++++++++++++++++++++++++
 libcc1/configure.ac          |    73 +
 libcc1/connection.cc         |   153 +
 libcc1/connection.hh         |   114 +
 libcc1/findcomp.cc           |   139 +
 libcc1/findcomp.hh           |    25 +
 libcc1/libcc1.cc             |   529 ++
 libcc1/libcc1.sym            |     1 +
 libcc1/libcc1plugin.sym      |     2 +
 libcc1/marshall.cc           |   166 +
 libcc1/marshall.hh           |    93 +
 libcc1/names.cc              |    46 +
 libcc1/names.hh              |    55 +
 libcc1/plugin.cc             |   922 +++
 libcc1/rpc.hh                |   486 ++
 libcc1/status.hh             |    33 +
 28 files changed, 22952 insertions(+), 8 deletions(-)
 create mode 100644 libcc1/ChangeLog
 create mode 100644 libcc1/Makefile.am
 create mode 100644 libcc1/Makefile.in
 create mode 100644 libcc1/aclocal.m4
 create mode 100644 libcc1/callbacks.cc
 create mode 100644 libcc1/callbacks.hh
 create mode 100644 libcc1/cc1plugin-config.h.in
 create mode 100755 libcc1/configure
 create mode 100644 libcc1/configure.ac
 create mode 100644 libcc1/connection.cc
 create mode 100644 libcc1/connection.hh
 create mode 100644 libcc1/findcomp.cc
 create mode 100644 libcc1/findcomp.hh
 create mode 100644 libcc1/libcc1.cc
 create mode 100644 libcc1/libcc1.sym
 create mode 100644 libcc1/libcc1plugin.sym
 create mode 100644 libcc1/marshall.cc
 create mode 100644 libcc1/marshall.hh
 create mode 100644 libcc1/names.cc
 create mode 100644 libcc1/names.hh
 create mode 100644 libcc1/plugin.cc
 create mode 100644 libcc1/rpc.hh
 create mode 100644 libcc1/status.hh

diff --git a/Makefile.def b/Makefile.def
index 239ad36..ed9bac6 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -121,6 +121,8 @@ host_modules= { module= gnattools; };
 host_modules= { module= lto-plugin; bootstrap=true;
 		extra_configure_flags='--enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@';
 		extra_make_flags='@extra_linker_plugin_flags@'; };
+host_modules= { module= libcc1; bootstrap=true;
+		extra_configure_flags=--enable-shared; };
 
 target_modules = { module= libstdc++-v3;
 		   bootstrap=true;
@@ -352,6 +354,9 @@ dependencies = { module=all-gnattools; on=all-target-libstdc++-v3; };
 dependencies = { module=all-lto-plugin; on=all-libiberty; };
 dependencies = { module=all-lto-plugin; on=all-libiberty-linker-plugin; };
 
+dependencies = { module=configure-libcc1; on=configure-gcc; };
+dependencies = { module=all-libcc1; on=all-gcc; };
+
 dependencies = { module=all-utils; on=all-libiberty; };
 
 dependencies = { module=configure-mpfr; on=all-gmp; };
diff --git a/configure.ac b/configure.ac
index 9048cd1..0388dc2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-#   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+#   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2014
 #   Free Software Foundation, Inc.
 #
 # This file is free software; you can redistribute it and/or modify it
@@ -141,7 +141,7 @@ host_libs="intl libiberty opcodes bfd readline tcl tk itcl libgui zlib libbacktr
 # binutils, gas and ld appear in that order because it makes sense to run
 # "make check" in that particular order.
 # If --enable-gold is used, "gold" may replace "ld".
-host_tools="texinfo flex bison binutils gas ld fixincludes gcc cgen sid sim gdb gprof etc expect dejagnu m4 utils guile fastjar gnattools"
+host_tools="texinfo flex bison binutils gas ld fixincludes gcc cgen sid sim gdb gprof etc expect dejagnu m4 utils guile fastjar gnattools libcc1"
 
 # libgcj represents the runtime libraries only used by gcj.
 libgcj="target-libffi \
diff --git a/libcc1/Makefile.am b/libcc1/Makefile.am
new file mode 100644
index 0000000..574557a
--- /dev/null
+++ b/libcc1/Makefile.am
@@ -0,0 +1,52 @@
+## Copyright (C) 2014 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/>.
+
+ACLOCAL_AMFLAGS = -I .. -I ../config
+gcc_build_dir = ../$(host_subdir)/gcc
+AM_CPPFLAGS = -I $(srcdir)/../include -I $(srcdir)/../libgcc \
+	-I $(gcc_build_dir) -I$(srcdir)/../gcc \
+	-I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
+	-I $(srcdir)/../libcpp/include
+WERROR_FLAG = -Werror
+AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
+
+
+plugindir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/plugin
+cc1libdir = $(libdir)/$(libsuffix)
+
+if ENABLE_PLUGIN
+plugin_LTLIBRARIES = libcc1plugin.la
+cc1lib_LTLIBRARIES = libcc1.la
+endif
+
+BUILT_SOURCES = compiler-name.h
+
+# Put this in a header so we don't run sed for each compilation.  This
+# is also simpler to debug as one can easily see the constant.
+compiler-name.h: Makefile
+	echo "#define COMPILER_NAME \"`echo gcc | sed '$(transform)'`\"" > compiler-name.h
+
+
+shared_source = callbacks.cc callbacks.hh connection.cc connection.hh \
+    marshall.cc marshall.hh rpc.hh status.hh
+
+libcc1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1plugin.sym
+libcc1plugin_la_SOURCES = plugin.cc $(shared_source)
+
+libcc1_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1.sym
+libcc1_la_SOURCES = findcomp.cc libcc1.cc names.cc names.hh $(shared_source)
diff --git a/libcc1/callbacks.cc b/libcc1/callbacks.cc
new file mode 100644
index 0000000..3c4eda6
--- /dev/null
+++ b/libcc1/callbacks.cc
@@ -0,0 +1,90 @@
+/* Callback management.
+   Copyright (C) 2014 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>
+#include <string.h>
+#include <stdlib.h>
+#include "callbacks.hh"
+#include "libiberty.h"
+
+// An entry in the hash table.
+struct method
+{
+  const char *name;
+  cc1_plugin::callback_ftype *func;
+};
+
+// Hash function for struct method.
+static hashval_t
+hash_method (const void *a)
+{
+  const struct method *m = (const struct method *) a;
+
+  return htab_hash_string (m->name);
+}
+
+// Equality function for struct method.
+static int
+eq_method (const void *a, const void *b)
+{
+  const struct method *ma = (const struct method *) a;
+  const struct method *mb = (const struct method *) b;
+
+  return strcmp (ma->name, mb->name) == 0;
+}
+
+cc1_plugin::callbacks::callbacks ()
+  : m_registry (htab_create_alloc (10, hash_method, eq_method,
+				   free, xcalloc, free))
+{
+}
+
+cc1_plugin::callbacks::~callbacks ()
+{
+  htab_delete (m_registry);
+}
+
+void
+cc1_plugin::callbacks::add_callback (const char *name,
+				     cc1_plugin::callback_ftype *func)
+{
+  method m;
+  method **slot;
+
+  m.name = name;
+  m.func = func;
+
+  slot = (method **) htab_find_slot (m_registry, &m, INSERT);
+  *slot = XNEW (method);
+  **slot = m;
+}
+
+cc1_plugin::callback_ftype *
+cc1_plugin::callbacks::find_callback (const char *name)
+{
+  method m, *found;
+
+  m.name = name;
+
+  found = (method *) htab_find (m_registry, &m);
+  if (found == NULL)
+    return NULL;
+
+  return found->func;
+}
diff --git a/libcc1/callbacks.hh b/libcc1/callbacks.hh
new file mode 100644
index 0000000..bde1100
--- /dev/null
+++ b/libcc1/callbacks.hh
@@ -0,0 +1,64 @@
+/* Callback management
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_CALLBACKS_HH
+#define CC1_PLUGIN_CALLBACKS_HH
+
+#include "status.hh"
+#include "hashtab.h"
+
+namespace cc1_plugin
+{
+  class connection;
+
+  // The type of a callback method.
+  typedef status callback_ftype (connection *);
+
+  // This class manages callback functions.  A callback has a name and
+  // an underlying function.  When a query packet arrives, the name is
+  // inspected and the corresponding function is called.  A callback
+  // function has to know how to decode its own arguments, but
+  // wrappers are provided elsewhere to automate this.
+  class callbacks
+  {
+  public:
+
+    callbacks ();
+    ~callbacks ();
+
+    // Add a callback named NAME.  FUNC is the function to call when
+    // this method is invoked.
+    void add_callback (const char *name, callback_ftype *func);
+
+    // Look up a callback by name.  Returns NULL if the method is not
+    // found.
+    callback_ftype *find_callback (const char *name);
+
+  private:
+
+    // Declared but not defined to avoid use.
+    callbacks (const callbacks &);
+    callbacks &operator= (const callbacks &);
+
+    // The mapping.
+    htab_t m_registry;
+  };
+};
+
+#endif // CC1_PLUGIN_CALLBACKS_HH
diff --git a/libcc1/configure.ac b/libcc1/configure.ac
new file mode 100644
index 0000000..7328977
--- /dev/null
+++ b/libcc1/configure.ac
@@ -0,0 +1,73 @@
+dnl   Copyright (C) 2014 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GCC.
+dnl
+dnl GCC is free software; you can redistribute it and/or modify it under
+dnl the terms of the GNU General Public License as published by the Free
+dnl Software Foundation; either version 3, or (at your option) any later
+dnl version.
+dnl
+dnl GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+dnl WARRANTY; without even the implied warranty of MERCHANTABILITY or
+dnl FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+dnl for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GCC; see the file COPYING3.  If not see
+dnl <http://www.gnu.org/licenses/>.
+
+AC_PREREQ(2.64)
+AC_INIT([libcc1], [version-unused])
+AC_CONFIG_SRCDIR([libcc1.cc])
+AC_CONFIG_HEADER(cc1plugin-config.h)
+
+AC_CANONICAL_SYSTEM
+AC_USE_SYSTEM_EXTENSIONS
+# Determine the noncanonical target name, for directory use.
+ACX_NONCANONICAL_TARGET
+GCC_TOPLEV_SUBDIRS
+
+# 1.11.1: Require that version of automake.
+# foreign: Don't require README, INSTALL, NEWS, etc.
+# no-define: Don't define PACKAGE and VERSION.
+# -Wall: Issue all automake warnings.
+# -Wno-portability: Don't warn about constructs supported by GNU make.
+#    (because GCC requires GNU make anyhow).
+AM_INIT_AUTOMAKE([1.11.1 foreign no-dist no-define -Wall -Wno-portability])
+AM_MAINTAINER_MODE
+
+LT_INIT([disable-static])
+AM_PROG_LIBTOOL
+AC_PROG_CXX
+
+visibility=
+if test "$GXX" = yes; then
+  visibility=-fvisibility=hidden
+fi
+AC_SUBST(visibility)
+
+AC_CHECK_DECLS([basename])
+
+gcc_version=`cat $srcdir/../gcc/BASE-VER`
+AC_SUBST(gcc_version)
+
+ACX_PROG_CC_WARNING_OPTS([-W -Wall], [WARN_FLAGS])
+WARN_FLAGS="$WARN_FLAGS -Werror"
+AC_SUBST(WARN_FLAGS)
+
+libsuffix=
+if test "$GXX" = yes; then
+  libsuffix=`$CXX -print-multi-os-directory`
+fi
+AC_SUBST(libsuffix)
+
+# If any of these functions are missing, simply don't bother building
+# this plugin.
+GCC_ENABLE_PLUGINS
+AC_CHECK_FUNC(socketpair, , enable_plugin=no)
+AC_CHECK_FUNC(select, , enable_plugin=no)
+AC_CHECK_FUNC(fork, , enable_plugin=no)
+AM_CONDITIONAL(ENABLE_PLUGIN, test $enable_plugin = yes)
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/libcc1/connection.cc b/libcc1/connection.cc
new file mode 100644
index 0000000..3e57bbc
--- /dev/null
+++ b/libcc1/connection.cc
@@ -0,0 +1,153 @@
+/* Connect implementation
+   Copyright (C) 2014 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>
+#include <string>
+#include <unistd.h>
+#include <sys/types.h>
+#include <errno.h>
+#include "marshall.hh"
+#include "connection.hh"
+#include "rpc.hh"
+
+cc1_plugin::connection::~connection ()
+{
+}
+
+void
+cc1_plugin::connection::print (const char *)
+{
+}
+
+cc1_plugin::status
+cc1_plugin::connection::send (char c)
+{
+  if (write (m_fd, &c, 1) != 1)
+    return FAIL;
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::connection::send (const void *buf, int len)
+{
+  if (write (m_fd, buf, len) != len)
+    return FAIL;
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::connection::require (char c)
+{
+  char result;
+
+  if (read (m_fd, &result, 1) != 1
+      || result != c)
+    return FAIL;
+
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::connection::get (void *buf, int len)
+{
+  if (read (m_fd, buf, len) != len)
+    return FAIL;
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::connection::do_wait (bool want_result)
+{
+  while (true)
+    {
+      char result;
+      fd_set read_set;
+
+      FD_ZERO (&read_set);
+      FD_SET (m_fd, &read_set);
+      if (m_aux_fd != -1)
+	FD_SET (m_aux_fd, &read_set);
+
+      int nfds = select (FD_SETSIZE, &read_set, NULL, NULL, NULL);
+      if (nfds == -1)
+	{
+	  if (errno == EINTR)
+	    continue;
+	  return FAIL;
+	}
+
+      // We have to check the stderr fd first, to avoid a possible
+      // blocking scenario when do_wait is called reentrantly.  In
+      // such a call, if we handle the primary fd first, then we may
+      // re-enter this function, read from gcc's stderr, causing the
+      // outer invocation of this function to block when trying to
+      // read.
+      if (m_aux_fd != -1 && FD_ISSET (m_aux_fd, &read_set))
+	{
+	  char buf[1024];
+	  int n = read (m_aux_fd, buf, sizeof (buf) - 1);
+	  if (n < 0)
+	    return FAIL;
+	  if (n > 0)
+	    {
+	      buf[n] = '\0';
+	      print (buf);
+	    }
+	}
+
+      if (FD_ISSET (m_fd, &read_set))
+	{
+	  int n = read (m_fd, &result, 1);
+	  if (n == 0)
+	    return want_result ? FAIL : OK;
+	  if (n != 1)
+	    return FAIL;
+
+	  switch (result)
+	    {
+	    case 'R':
+	      // The reply is ready; the caller will unmarshall it.
+	      return want_result ? OK : FAIL;
+
+	    case 'Q':
+	      // While waiting for a reply, the other side made a method
+	      // call.
+	      {
+		// Use an argument_wrapper here to simplify management
+		// of the string's lifetime.
+		argument_wrapper<char *> method_name;
+
+		if (!method_name.unmarshall (this))
+		  return FAIL;
+
+		callback_ftype *callback
+		  = m_callbacks.find_callback (method_name);
+		// The call to CALLBACK is where we may end up in a
+		// reentrant call.
+		if (callback == NULL || !callback (this))
+		  return FAIL;
+	      }
+	      break;
+
+	    default:
+	      return FAIL;
+	    }
+	}
+    }
+}
diff --git a/libcc1/connection.hh b/libcc1/connection.hh
new file mode 100644
index 0000000..242deec
--- /dev/null
+++ b/libcc1/connection.hh
@@ -0,0 +1,114 @@
+/* Plugin connection declarations
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_CONNECTION_HH
+#define CC1_PLUGIN_CONNECTION_HH
+
+#include "status.hh"
+#include "callbacks.hh"
+
+namespace cc1_plugin
+{
+  // The connection class represents one side of the connection
+  // between the gdb-side library and the gcc plugin.  It handles the
+  // low-level details of reading and writing data.
+  class connection
+  {
+  public:
+
+    connection (int fd)
+      : m_fd (fd),
+	m_aux_fd (-1),
+	m_callbacks ()
+    {
+    }
+
+    connection (int fd, int aux_fd)
+      : m_fd (fd),
+	m_aux_fd (aux_fd),
+	m_callbacks ()
+    {
+    }
+
+    virtual ~connection ();
+
+    // Send a single character.  This is used to introduce various
+    // higher-level protocol elements.
+    status send (char c);
+
+    // Send data in bulk.
+    status send (const void *buf, int len);
+
+    // Read a single byte from the connection and verify that it
+    // matches the argument C.
+    status require (char c);
+
+    // Read data in bulk.
+    status get (void *buf, int len);
+
+    // This is called after a query (remote function call) has been
+    // sent to the remote.  It waits for a response packet.  The
+    // response character is read before returning.  Any query packets
+    // sent from the remote while waiting for a response are handled
+    // by this function.
+    status wait_for_result ()
+    {
+      return do_wait (true);
+    }
+
+    // Read and respond to query packets sent by the remote.  This
+    // function returns when the connection is closed.
+    status wait_for_query ()
+    {
+      return do_wait (false);
+    }
+
+    // Register a callback with this connection.  NAME is the name of
+    // the method being registered.  FUNC is the function.  It must
+    // know how to decode its own arguments.  When a query packet is
+    // received by one of the wait_* methods, the corresponding
+    // callback is invoked.
+    void add_callback (const char *name, callback_ftype *func)
+    {
+      m_callbacks.add_callback (name, func);
+    }
+
+    virtual void print (const char *);
+
+  private:
+
+    // Declared but not defined, to prevent use.
+    connection (const connection &);
+    connection &operator= (const connection &);
+
+    // Helper function for the wait_* methods.
+    status do_wait (bool);
+
+    // The file descriptor.
+    int m_fd;
+
+    // An auxiliary file descriptor, or -1 if none.
+    int m_aux_fd;
+
+    // Callbacks associated with this connection.
+    callbacks m_callbacks;
+  };
+}
+
+#endif // CC1_PLUGIN_CONNECTION_HH
diff --git a/libcc1/findcomp.cc b/libcc1/findcomp.cc
new file mode 100644
index 0000000..f02b1df
--- /dev/null
+++ b/libcc1/findcomp.cc
@@ -0,0 +1,139 @@
+/* Find the correct compiler.
+   Copyright (C) 2014 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 <config.h>
+#include <string>
+#include <dirent.h>
+#include <stdlib.h>
+
+#include "libiberty.h"
+#include "xregex.h"
+#include "findcomp.hh"
+
+class scanner
+{
+public:
+
+  scanner (const std::string &dir)
+  {
+    m_dir = opendir (dir.c_str ());
+  }
+
+  ~scanner ()
+  {
+    if (m_dir != NULL)
+      closedir (m_dir);
+  }
+
+  const char *next ()
+  {
+    if (m_dir == NULL)
+      return NULL;
+
+    struct dirent *entry = readdir (m_dir);
+    if (entry == NULL)
+      return NULL;
+
+    return entry->d_name;
+  }
+
+private:
+
+  DIR *m_dir;
+};
+
+static bool
+search_dir (const regex_t &regexp, const std::string &dir, std::string *result)
+{
+  scanner scan (dir);
+  const char *filename;
+
+  while ((filename = scan.next ()) != NULL)
+    {
+      if (regexec (&regexp, filename, 0, NULL, 0) == 0)
+	{
+	  *result = filename;
+	  return true;
+	}
+    }
+
+  return false;
+}
+
+class tokenizer
+{
+public:
+
+  tokenizer (const char *str)
+    : m_str (str),
+      m_pos (0)
+  {
+  }
+
+  bool done () const
+  {
+    return m_pos == std::string::npos;
+  }
+
+  std::string next ()
+  {
+    std::string::size_type last_pos = m_pos;
+    std::string::size_type colon = m_str.find(':', last_pos);
+
+    std::string result;
+    if (colon == std::string::npos)
+      {
+	m_pos = colon;
+	result = m_str.substr(last_pos, colon);
+      }
+    else
+      {
+	m_pos = colon + 1;
+	result = m_str.substr(last_pos, colon - last_pos);
+      }
+    if (result == "")
+      result = ".";
+
+    return result;
+  }
+
+private:
+
+  std::string m_str;
+  std::string::size_type m_pos;
+};
+
+bool
+find_compiler (const regex_t &regexp, std::string *result)
+{
+  const char *cpath = getenv ("PATH");
+
+  if (cpath == NULL)
+    return false;
+
+  tokenizer dirs (cpath);
+  while (!dirs.done ())
+    {
+      std::string dir = dirs.next ();
+      if (search_dir (regexp, dir, result))
+	return true;
+    }
+
+  return false;
+}
diff --git a/libcc1/findcomp.hh b/libcc1/findcomp.hh
new file mode 100644
index 0000000..a55a283
--- /dev/null
+++ b/libcc1/findcomp.hh
@@ -0,0 +1,25 @@
+/* Find the correct compiler.
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_FINDCOMP_HH
+#define CC1_PLUGIN_FINDCOMP_HH
+
+extern bool find_compiler (const regex_t &regexp, std::string *result);
+
+#endif // CC1_PLUGIN_FINDCOMP_HH
diff --git a/libcc1/libcc1.cc b/libcc1/libcc1.cc
new file mode 100644
index 0000000..7d3b9fe
--- /dev/null
+++ b/libcc1/libcc1.cc
@@ -0,0 +1,529 @@
+/* The library used by gdb.
+   Copyright (C) 2014 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>
+#include <vector>
+#include <string>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <sstream>
+#include "rpc.hh"
+#include "connection.hh"
+#include "names.hh"
+#include "callbacks.hh"
+#include "gcc-interface.h"
+#include "libiberty.h"
+#include "xregex.h"
+#include "findcomp.hh"
+#include "compiler-name.h"
+
+struct libcc1;
+
+class libcc1_connection;
+
+// The C compiler context that we hand back to our caller.
+struct libcc1 : public gcc_c_context
+{
+  libcc1 (const gcc_base_vtable *, const gcc_c_fe_vtable *);
+  ~libcc1 ();
+
+  // A convenience function to print something.
+  void print (const char *str)
+  {
+    this->print_function (this->print_datum, str);
+  }
+
+  libcc1_connection *connection;
+
+  gcc_c_oracle_function *binding_oracle;
+  gcc_c_symbol_address_function *address_oracle;
+  void *oracle_datum;
+
+  void (*print_function) (void *datum, const char *message);
+  void *print_datum;
+
+  std::vector<std::string> args;
+  std::string source_file;
+};
+
+// A local subclass of connection that holds a back-pointer to the
+// gcc_c_context object that we provide to our caller.
+class libcc1_connection : public cc1_plugin::connection
+{
+public:
+
+  libcc1_connection (int fd, int aux_fd, libcc1 *b)
+    : connection (fd, aux_fd),
+      back_ptr (b)
+  {
+  }
+
+  void print (const char *buf)
+  {
+    back_ptr->print (buf);
+  }
+
+  libcc1 *back_ptr;
+};
+
+libcc1::libcc1 (const gcc_base_vtable *v,
+		const gcc_c_fe_vtable *cv)
+  : connection (NULL),
+    binding_oracle (NULL),
+    address_oracle (NULL),
+    oracle_datum (NULL),
+    print_function (NULL),
+    print_datum (NULL),
+    args (),
+    source_file ()
+{
+  base.ops = v;
+  c_ops = cv;
+}
+
+libcc1::~libcc1 ()
+{
+  delete connection;
+}
+
+\f
+
+// This is a wrapper function that is called by the RPC system and
+// that then forwards the call to the library user.  Note that the
+// return value is not used; the type cannot be 'void' due to
+// limitations in our simple RPC.
+int
+call_binding_oracle (cc1_plugin::connection *conn,
+		     enum gcc_c_oracle_request request,
+		     const char *identifier)
+{
+  libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
+
+  self->binding_oracle (self->oracle_datum, self, request, identifier);
+  return 1;
+}
+
+// This is a wrapper function that is called by the RPC system and
+// that then forwards the call to the library user.  Note that the
+// return value is not used; the type cannot be 'void' due to
+// limitations in our simple RPC.
+gcc_address
+call_symbol_address (cc1_plugin::connection *conn, const char *identifier)
+{
+  libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
+
+  return self->address_oracle (self->oracle_datum, self, identifier);
+}
+
+\f
+
+static void
+set_callbacks (struct gcc_c_context *s,
+	       gcc_c_oracle_function *binding_oracle,
+	       gcc_c_symbol_address_function *address_oracle,
+	       void *datum)
+{
+  libcc1 *self = (libcc1 *) s;
+
+  self->binding_oracle = binding_oracle;
+  self->address_oracle = address_oracle;
+  self->oracle_datum = datum;
+}
+
+// Instances of these rpc<> template functions are installed into the
+// "c_vtable".  These functions are parameterized by type and method
+// name and forward the call via the connection.
+
+template<typename R, const char *&NAME>
+R rpc (struct gcc_c_context *s)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result))
+    return 0;
+  return result;
+}
+
+template<typename R, const char *&NAME, typename A>
+R rpc (struct gcc_c_context *s, A arg)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result, arg))
+    return 0;
+  return result;
+}
+
+template<typename R, const char *&NAME, typename A1, typename A2>
+R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2))
+    return 0;
+  return result;
+}
+
+template<typename R, const char *&NAME, typename A1, typename A2, typename A3>
+R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3))
+    return 0;
+  return result;
+}
+
+template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
+	 typename A4>
+R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
+			 arg4))
+    return 0;
+  return result;
+}
+
+template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
+	 typename A4, typename A5>
+R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
+			 arg4, arg5))
+    return 0;
+  return result;
+}
+
+template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
+	 typename A4, typename A5, typename A6, typename A7>
+R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5,
+       A6 arg6, A7 arg7)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
+			 arg4, arg5, arg6, arg7))
+    return 0;
+  return result;
+}
+
+static const struct gcc_c_fe_vtable c_vtable =
+{
+  GCC_C_FE_VERSION_0,
+  set_callbacks,
+
+#define GCC_METHOD0(R, N) \
+  rpc<R, cc1_plugin::N>,
+#define GCC_METHOD1(R, N, A) \
+  rpc<R, cc1_plugin::N, A>,
+#define GCC_METHOD2(R, N, A, B) \
+  rpc<R, cc1_plugin::N, A, B>,
+#define GCC_METHOD3(R, N, A, B, C) \
+  rpc<R, cc1_plugin::N, A, B, C>,
+#define GCC_METHOD4(R, N, A, B, C, D) \
+  rpc<R, cc1_plugin::N, A, B, C, D>,
+#define GCC_METHOD5(R, N, A, B, C, D, E) \
+  rpc<R, cc1_plugin::N, A, B, C, D, E>,
+#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
+  rpc<R, cc1_plugin::N, A, B, C, D, E, F, G>,
+
+#include "gcc-c-fe.def"
+
+#undef GCC_METHOD0
+#undef GCC_METHOD1
+#undef GCC_METHOD2
+#undef GCC_METHOD3
+#undef GCC_METHOD4
+#undef GCC_METHOD5
+#undef GCC_METHOD7
+};
+
+\f
+
+// Construct an appropriate regexp to match the compiler name.
+static std::string
+make_regexp (const char *triplet_regexp, const char *compiler)
+{
+  std::stringstream buf;
+
+  buf << "^" << triplet_regexp << "-";
+
+  // Quote the compiler name in case it has something funny in it.
+  for (const char *p = compiler; *p; ++p)
+    {
+      switch (*p)
+	{
+	case '.':
+	case '^':
+	case '$':
+	case '*':
+	case '+':
+	case '?':
+	case '(':
+	case ')':
+	case '[':
+	case '{':
+	case '\\':
+	case '|':
+	  buf << '\\';
+	  break;
+	}
+      buf << *p;
+    }
+  buf << "$";
+
+  return buf.str ();
+}
+
+static char *
+libcc1_set_arguments (struct gcc_base_context *s,
+		      const char *triplet_regexp,
+		      int argc, char **argv)
+{
+  libcc1 *self = (libcc1 *) s;
+  regex_t triplet;
+  int code;
+
+  std::string rx = make_regexp (triplet_regexp, COMPILER_NAME);
+  code = regcomp (&triplet, rx.c_str (), REG_EXTENDED | REG_NOSUB);
+  if (code != 0)
+    {
+      size_t len = regerror (code, &triplet, NULL, 0);
+      char err[len];
+
+      regerror (code, &triplet, err, len);
+
+      return concat ("Could not compile regexp \"",
+		     rx.c_str (),
+		     "\": ",
+		     err,
+		     (char *) NULL);
+    }
+
+  std::string compiler;
+  if (!find_compiler (triplet, &compiler))
+    {
+      regfree (&triplet);
+      return concat ("Could not find a compiler matching \"",
+		     rx.c_str (),
+		     "\"",
+		     (char *) NULL);
+    }
+  regfree (&triplet);
+
+  self->args.push_back (compiler);
+
+  for (int i = 0; i < argc; ++i)
+    self->args.push_back (argv[i]);
+
+  return NULL;
+}
+
+static void
+libcc1_set_source_file (struct gcc_base_context *s,
+			const char *file)
+{
+  libcc1 *self = (libcc1 *) s;
+
+  self->source_file = file;
+}
+
+static void
+libcc1_set_print_callback (struct gcc_base_context *s,
+			   void (*print_function) (void *datum,
+						   const char *message),
+			   void *datum)
+{
+  libcc1 *self = (libcc1 *) s;
+
+  self->print_function = print_function;
+  self->print_datum = datum;
+}
+
+static int
+fork_exec (libcc1 *self, char **argv, int spair_fds[2], int stderr_fds[2])
+{
+  pid_t child_pid = fork ();
+
+  if (child_pid == -1)
+    {
+      close (spair_fds[0]);
+      close (spair_fds[1]);
+      close (stderr_fds[0]);
+      close (stderr_fds[1]);
+      return 0;
+    }
+
+  if (child_pid == 0)
+    {
+      // Child.
+      dup2 (stderr_fds[1], 1);
+      dup2 (stderr_fds[1], 2);
+      close (stderr_fds[0]);
+      close (stderr_fds[1]);
+      close (spair_fds[0]);
+
+      execvp (argv[0], argv);
+      _exit (127);
+    }
+  else
+    {
+      // Parent.
+      close (spair_fds[1]);
+      close (stderr_fds[1]);
+
+      cc1_plugin::status result = cc1_plugin::FAIL;
+      if (self->connection->send ('H')
+	  && ::cc1_plugin::marshall (self->connection, GCC_C_FE_VERSION_0))
+	result = self->connection->wait_for_query ();
+
+      close (spair_fds[0]);
+      close (stderr_fds[0]);
+
+      while (true)
+	{
+	  int status;
+
+	  if (waitpid (child_pid, &status, 0) == -1)
+	    {
+	      if (errno != EINTR)
+		return 0;
+	    }
+
+	  if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
+	    return 0;
+	  break;
+	}
+
+      if (!result)
+	return 0;
+      return 1;
+    }
+}
+
+static int
+libcc1_compile (struct gcc_base_context *s,
+		const char *filename,
+		int verbose)
+{
+  libcc1 *self = (libcc1 *) s;
+
+  int fds[2];
+  if (socketpair (AF_LOCAL, SOCK_STREAM, 0, fds) != 0)
+    {
+      self->print ("could not create socketpair\n");
+      return 0;
+    }
+
+  int stderr_fds[2];
+  if (pipe (stderr_fds) != 0)
+    {
+      self->print ("could not create pipe\n");
+      close (fds[0]);
+      close (fds[1]);
+      return 0;
+    }
+
+  self->args.push_back ("-fplugin=libcc1plugin");
+  char buf[100];
+  if (snprintf (buf, sizeof (buf), "-fplugin-arg-libcc1plugin-fd=%d", fds[1])
+      >= (long) sizeof (buf))
+    abort ();
+  self->args.push_back (buf);
+
+  self->args.push_back (self->source_file);
+  self->args.push_back ("-c");
+  self->args.push_back ("-o");
+  self->args.push_back (filename);
+  if (verbose)
+    self->args.push_back ("-v");
+
+  self->connection = new libcc1_connection (fds[0], stderr_fds[0], self);
+
+  cc1_plugin::callback_ftype *fun
+    = cc1_plugin::callback<int,
+			   enum gcc_c_oracle_request,
+			   const char *,
+			   call_binding_oracle>;
+  self->connection->add_callback ("binding_oracle", fun);
+
+  fun = cc1_plugin::callback<gcc_address,
+			     const char *,
+			     call_symbol_address>;
+  self->connection->add_callback ("address_oracle", fun);
+
+  char **argv = new (std::nothrow) char *[self->args.size () + 1];
+  for (unsigned int i = 0; i < self->args.size (); ++i)
+    argv[i] = const_cast<char *> (self->args[i].c_str ());
+  argv[self->args.size ()] = NULL;
+
+  return fork_exec (self, argv, fds, stderr_fds);
+}
+
+static void
+libcc1_destroy (struct gcc_base_context *s)
+{
+  libcc1 *self = (libcc1 *) s;
+
+  delete self;
+}
+
+static const struct gcc_base_vtable vtable =
+{
+  GCC_FE_VERSION_0,
+  libcc1_set_arguments,
+  libcc1_set_source_file,
+  libcc1_set_print_callback,
+  libcc1_compile,
+  libcc1_destroy
+};
+
+extern "C" gcc_c_fe_context_function gcc_c_fe_context;
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+
+extern "C"
+struct gcc_c_context *
+gcc_c_fe_context (enum gcc_base_api_version base_version,
+		  enum gcc_c_api_version c_version)
+{
+  if (base_version != GCC_FE_VERSION_0 || c_version != GCC_C_FE_VERSION_0)
+    return NULL;
+
+  return new libcc1 (&vtable, &c_vtable);
+}
diff --git a/libcc1/libcc1.sym b/libcc1/libcc1.sym
new file mode 100644
index 0000000..86b1e3e
--- /dev/null
+++ b/libcc1/libcc1.sym
@@ -0,0 +1 @@
+gcc_c_fe_context
diff --git a/libcc1/libcc1plugin.sym b/libcc1/libcc1plugin.sym
new file mode 100644
index 0000000..05d0f7b
--- /dev/null
+++ b/libcc1/libcc1plugin.sym
@@ -0,0 +1,2 @@
+plugin_init
+plugin_is_GPL_compatible
diff --git a/libcc1/marshall.cc b/libcc1/marshall.cc
new file mode 100644
index 0000000..9119de6
--- /dev/null
+++ b/libcc1/marshall.cc
@@ -0,0 +1,166 @@
+/* Marshalling and unmarshalling.
+   Copyright (C) 2014 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>
+#include <new>
+#include <string.h>
+#include "marshall.hh"
+#include "connection.hh"
+
+cc1_plugin::status
+cc1_plugin::unmarshall_check (connection *conn, unsigned long long check)
+{
+  unsigned long long r;
+
+  if (!unmarshall (conn, &r))
+    return FAIL;
+  return check == r ? OK : FAIL;
+}
+
+cc1_plugin::status
+cc1_plugin::marshall_intlike (connection *conn, unsigned long long val)
+{
+  if (!conn->send ('i'))
+    return FAIL;
+  return conn->send (&val, sizeof (val));
+}
+
+cc1_plugin::status
+cc1_plugin::unmarshall_intlike (connection *conn, unsigned long long *result)
+{
+  if (!conn->require ('i'))
+    return FAIL;
+  return conn->get (result, sizeof (*result));
+}
+
+cc1_plugin::status
+cc1_plugin::unmarshall (connection *conn, enum gcc_c_symbol_kind *result)
+{
+  protocol_int p;
+  if (!unmarshall_intlike (conn, &p))
+    return FAIL;
+  *result = (enum gcc_c_symbol_kind) p;
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::unmarshall (connection *conn, enum gcc_c_oracle_request *result)
+{
+  protocol_int p;
+  if (!unmarshall_intlike (conn, &p))
+    return FAIL;
+  *result = (enum gcc_c_oracle_request) p;
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::unmarshall (connection *conn, enum gcc_qualifiers *result)
+{
+  protocol_int p;
+  if (!unmarshall_intlike (conn, &p))
+    return FAIL;
+  *result = (enum gcc_qualifiers) p;
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::marshall (connection *conn, const char *str)
+{
+  if (!conn->send ('s'))
+    return FAIL;
+
+  unsigned long long len = str == NULL ? -1ULL : strlen (str);
+  if (!conn->send (&len, sizeof (len)))
+    return FAIL;
+
+  if (str == NULL)
+    return OK;
+
+  return conn->send (str, len);
+}
+
+cc1_plugin::status
+cc1_plugin::unmarshall (connection *conn, char **result)
+{
+  unsigned long long len;
+
+  if (!conn->require ('s'))
+    return FAIL;
+  if (!conn->get (&len, sizeof (len)))
+    return FAIL;
+
+  if (len == -1ULL)
+    {
+      *result = NULL;
+      return OK;
+    }
+
+  char *str = new (std::nothrow) char[len + 1];
+  if (str == NULL)
+    return FAIL;
+
+  if (!conn->get (str, len))
+    {
+      delete[] str;
+      return FAIL;
+    }
+
+  str[len] = '\0';
+  *result = str;
+
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::marshall (connection *conn, const gcc_type_array *a)
+{
+  if (!conn->send ('a'))
+    return FAIL;
+
+  unsigned long long r = a->n_elements;
+  if (!conn->send (&r, sizeof (r)))
+    return FAIL;
+
+  return conn->send (a->elements, r * sizeof (a->elements[0]));
+}
+
+cc1_plugin::status
+cc1_plugin::unmarshall (connection *conn, gcc_type_array **result)
+{
+  unsigned long long len;
+
+  if (!conn->require ('a'))
+    return FAIL;
+  if (!conn->get (&len, sizeof (len)))
+    return FAIL;
+
+  *result = new gcc_type_array;
+
+  (*result)->n_elements = len;
+  (*result)->elements = new gcc_type[len];
+
+  if (!conn->get ((*result)->elements, len * sizeof ((*result)->elements[0])))
+    {
+      delete[] (*result)->elements;
+      delete *result;
+      return FAIL;
+    }
+
+  return OK;
+}
diff --git a/libcc1/marshall.hh b/libcc1/marshall.hh
new file mode 100644
index 0000000..3f936e7
--- /dev/null
+++ b/libcc1/marshall.hh
@@ -0,0 +1,93 @@
+/* Marshalling and unmarshalling.
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_MARSHALL_HH
+#define CC1_PLUGIN_MARSHALL_HH
+
+#include "status.hh"
+#include "gcc-c-interface.h"
+
+namespace cc1_plugin
+{
+  class connection;
+
+  // Only a single kind of integer is ever sent over the wire, and
+  // this is it.
+  typedef unsigned long long protocol_int;
+
+  // Read an integer from the connection and verify that it has the
+  // value V.
+  status unmarshall_check (connection *, protocol_int v);
+
+  // Write an integer, prefixed with the integer type marker, to the
+  // connection.
+  status marshall_intlike (connection *, protocol_int);
+
+  // Read a type marker from the connection and verify that it is an
+  // integer type marker.  If not, return FAIL.  If so, read an
+  // integer store it in the out argument.
+  status unmarshall_intlike (connection *, protocol_int *);
+
+  // A template function that can handle marshalling various integer
+  // objects to the connection.
+  template<typename T>
+  status marshall (connection *conn, T scalar)
+  {
+    return marshall_intlike (conn, scalar);
+  }
+
+  // A template function that can handle unmarshalling various integer
+  // objects from the connection.  Note that this can't be
+  // instantiated for enum types.  Note also that there's no way at
+  // the protocol level to distinguish different int types.
+  template<typename T>
+  status unmarshall (connection *conn, T *scalar)
+  {
+    protocol_int result;
+
+    if (!unmarshall_intlike (conn, &result))
+      return FAIL;
+    *scalar = result;
+    return OK;
+  }
+
+  // Unmarshallers for some specific enum types.  With C++11 we
+  // wouldn't need these, as we could add type traits to the scalar
+  // unmarshaller.
+  status unmarshall (connection *, enum gcc_c_symbol_kind *);
+  status unmarshall (connection *, enum gcc_qualifiers *);
+  status unmarshall (connection *, enum gcc_c_oracle_request *);
+
+  // Send a string type marker followed by a string.
+  status marshall (connection *, const char *);
+
+  // Read a string type marker followed by a string.  The caller is
+  // responsible for freeing the resulting string using 'delete[]'.
+  status unmarshall (connection *, char **);
+
+  // Send a gcc_type_array marker followed by the array.
+  status marshall (connection *, const gcc_type_array *);
+
+  // Read a gcc_type_array marker, followed by a gcc_type_array.  The
+  // resulting array must be freed by the caller, using 'delete[]' on
+  // the elements, and 'delete' on the array object itself.
+  status unmarshall (connection *, struct gcc_type_array **);
+};
+
+#endif // CC1_PLUGIN_MARSHALL_HH
diff --git a/libcc1/names.cc b/libcc1/names.cc
new file mode 100644
index 0000000..5ddfa7b
--- /dev/null
+++ b/libcc1/names.cc
@@ -0,0 +1,46 @@
+/* String definitions.
+   Copyright (C) 2014 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>
+#include "names.hh"
+
+#define GCC_METHOD0(R, N) \
+  const char *cc1_plugin::N = # N;
+#define GCC_METHOD1(R, N, A) \
+  const char *cc1_plugin::N = # N;
+#define GCC_METHOD2(R, N, A, B) \
+  const char *cc1_plugin::N = # N;
+#define GCC_METHOD3(R, N, A, B, C) \
+  const char *cc1_plugin::N = # N;
+#define GCC_METHOD4(R, N, A, B, C, D) \
+  const char *cc1_plugin::N = # N;
+#define GCC_METHOD5(R, N, A, B, C, D, E) \
+  const char *cc1_plugin::N = # N;
+#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
+  const char *cc1_plugin::N = # N;
+
+#include "gcc-c-fe.def"
+
+#undef GCC_METHOD0
+#undef GCC_METHOD1
+#undef GCC_METHOD2
+#undef GCC_METHOD3
+#undef GCC_METHOD4
+#undef GCC_METHOD5
+#undef GCC_METHOD7
diff --git a/libcc1/names.hh b/libcc1/names.hh
new file mode 100644
index 0000000..9bda8d5
--- /dev/null
+++ b/libcc1/names.hh
@@ -0,0 +1,55 @@
+/* String declarations.
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_NAMES_HH
+#define CC1_PLUGIN_NAMES_HH
+
+namespace cc1_plugin
+{
+  // This code defines global string constants, one for each method in
+  // gcc-c-fe.def.  This is needed so that they can be used as
+  // template arguments elsewhere.
+
+#define GCC_METHOD0(R, N) \
+  extern const char *N;
+#define GCC_METHOD1(R, N, A) \
+  extern const char *N;
+#define GCC_METHOD2(R, N, A, B) \
+  extern const char *N;
+#define GCC_METHOD3(R, N, A, B, C) \
+  extern const char *N;
+#define GCC_METHOD4(R, N, A, B, C, D) \
+  extern const char *N;
+#define GCC_METHOD5(R, N, A, B, C, D, E) \
+  extern const char *N;
+#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
+  extern const char *N;
+
+#include "gcc-c-fe.def"
+
+#undef GCC_METHOD0
+#undef GCC_METHOD1
+#undef GCC_METHOD2
+#undef GCC_METHOD3
+#undef GCC_METHOD4
+#undef GCC_METHOD5
+#undef GCC_METHOD7
+};
+
+#endif // CC1_PLUGIN_NAMES_HH
diff --git a/libcc1/plugin.cc b/libcc1/plugin.cc
new file mode 100644
index 0000000..965e803
--- /dev/null
+++ b/libcc1/plugin.cc
@@ -0,0 +1,922 @@
+/* Library interface to C front end
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+   Parser actions based on the old Bison parser; structure somewhat
+   influenced by and fragments based on the C++ parser.
+
+   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 "gcc-interface.h"
+#include "tree-core.h"
+#include "wide-int.h"
+#include "stor-layout.h"
+#include "c-tree.h"
+#include "toplev.h"
+#include "timevar.h"
+#include "hash-table.h"
+#include "tm.h"
+#include "c-family/c-pragma.h"
+#include "c-lang.h"
+#include "diagnostic.h"
+#include "langhooks.h"
+#include "langhooks-def.h"
+
+#include "callbacks.hh"
+#include "connection.hh"
+#include "rpc.hh"
+
+#include <string>
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+int plugin_is_GPL_compatible;
+#ifdef __GNUC__
+#pragma GCC visibility pop
+#endif
+
+\f
+
+// 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);
+}
+
+\f
+
+static unsigned long long
+convert_out (tree t)
+{
+  return (unsigned long long) (uintptr_t) t;
+}
+
+static tree
+convert_in (unsigned long long v)
+{
+  return (tree) (uintptr_t) v;
+}
+
+\f
+
+struct decl_addr_value
+{
+  tree decl;
+  tree address;
+};
+
+struct decl_addr_hasher : typed_free_remove<decl_addr_value>
+{
+  typedef decl_addr_value value_type;
+  typedef decl_addr_value compare_type;
+
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+decl_addr_hasher::hash (const value_type *e)
+{
+  return IDENTIFIER_HASH_VALUE (DECL_NAME (e->decl));
+}
+
+inline bool
+decl_addr_hasher::equal (const value_type *p1, const compare_type *p2)
+{
+  return p1->decl == p2->decl;
+}
+
+\f
+
+struct string_hasher : typed_noop_remove<char>
+{
+  typedef char value_type;
+  typedef char compare_type;
+
+  static inline hashval_t hash (const value_type *s)
+  {
+    return htab_hash_string (s);
+  }
+
+  static inline bool equal (const value_type *p1, const value_type *p2)
+  {
+    return strcmp (p1, p2) == 0;
+  }
+};
+
+\f
+
+// A wrapper for pushdecl that doesn't let gdb have a chance to
+// instantiate a symbol.
+
+static void
+pushdecl_safe (tree decl)
+{
+  void (*save) (enum c_oracle_request, tree identifier);
+
+  save = c_binding_oracle;
+  c_binding_oracle = NULL;
+  pushdecl (decl);
+  c_binding_oracle = save;
+}
+
+\f
+
+struct plugin_context : public cc1_plugin::connection
+{
+  plugin_context (int fd);
+
+  // Map decls to addresses.
+  hash_table<decl_addr_hasher> address_map;
+
+  // A collection of trees that are preserved for the GC.
+  hash_table< pointer_hash<tree_node> > preserved;
+
+  // File name cache.
+  hash_table<string_hasher> file_names;
+
+  // Perform GC marking.
+  void mark ();
+
+  // Preserve a tree during the plugin's operation.
+  tree preserve (tree t)
+  {
+    tree_node **slot = preserved.find_slot (t, INSERT);
+    *slot = t;
+    return t;
+  }
+
+  source_location get_source_location (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);
+    source_location loc = linemap_line_start (line_table, line_number, 0);
+    linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+    return loc;
+  }
+
+private:
+
+  // Add a file name to FILE_NAMES and return the canonical copy.
+  const char *intern_filename (const char *filename)
+  {
+    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;
+  }
+};
+
+static plugin_context *current_context;
+
+\f
+
+plugin_context::plugin_context (int fd)
+  : cc1_plugin::connection (fd),
+    address_map (),
+    preserved (),
+    file_names ()
+{
+  address_map.create (20);
+  preserved.create (20);
+  file_names.create (20);
+}
+
+void
+plugin_context::mark ()
+{
+  for (hash_table<decl_addr_hasher>::iterator it = address_map.begin ();
+       it != address_map.end ();
+       ++it)
+    {
+      ggc_mark ((*it).decl);
+      ggc_mark ((*it).address);
+    }
+
+  for (hash_table< pointer_hash<tree_node> >::iterator it = preserved.begin ();
+       it != preserved.end ();
+       ++it)
+    ggc_mark (&*it);
+}
+
+static void
+plugin_binding_oracle (enum c_oracle_request kind, tree identifier)
+{
+  enum gcc_c_oracle_request request;
+
+  gcc_assert (current_context != NULL);
+
+  switch (kind)
+    {
+    case C_ORACLE_SYMBOL:
+      request = GCC_C_ORACLE_SYMBOL;
+      break;
+    case C_ORACLE_TAG:
+      request = GCC_C_ORACLE_TAG;
+      break;
+    case C_ORACLE_LABEL:
+      request = GCC_C_ORACLE_LABEL;
+      break;
+    default:
+      abort ();
+    }
+
+  int ignore;
+  cc1_plugin::call (current_context, "binding_oracle", &ignore,
+		    request, IDENTIFIER_POINTER (identifier));
+}
+
+static void
+plugin_pragma_user_expression (cpp_reader *)
+{
+  c_binding_oracle = plugin_binding_oracle;
+}
+
+static void
+plugin_init_extra_pragmas (void *, void *)
+{
+  c_register_pragma ("GCC", "user_expression", plugin_pragma_user_expression);
+}
+
+\f
+
+// Maybe rewrite a decl to its address.
+static tree
+address_rewriter (tree *in, int *walk_subtrees, void *arg)
+{
+  plugin_context *ctx = (plugin_context *) arg;
+
+  if (!DECL_P (*in) || DECL_NAME (*in) == NULL_TREE)
+    return NULL_TREE;
+
+  decl_addr_value value;
+  value.decl = *in;
+  decl_addr_value *found_value = ctx->address_map.find (&value);
+  if (found_value != NULL)
+    {
+      // At this point we don't need VLA sizes for gdb-supplied
+      // variables, and having them here confuses later passes, so we
+      // drop them.
+      if (C_TYPE_VARIABLE_SIZE (TREE_TYPE (*in)))
+	{
+	  TREE_TYPE (*in)
+	    = build_array_type_nelts (TREE_TYPE (TREE_TYPE (*in)), 1);
+	  DECL_SIZE (*in) = TYPE_SIZE (TREE_TYPE (*in));
+	  DECL_SIZE_UNIT (*in) = TYPE_SIZE_UNIT (TREE_TYPE (*in));
+	}
+    }
+  else if (DECL_IS_BUILTIN (*in))
+    {
+      gcc_address address;
+
+      if (!cc1_plugin::call (ctx, "address_oracle", &address,
+			     IDENTIFIER_POINTER (DECL_NAME (*in))))
+	return NULL_TREE;
+      if (address == 0)
+	return NULL_TREE;
+
+      // Insert the decl into the address map in case it is referenced
+      // again.
+      value.address = build_int_cst_type (ptr_type_node, address);
+      decl_addr_value **slot = ctx->address_map.find_slot (&value, INSERT);
+      gcc_assert (*slot == NULL);
+      *slot
+	= static_cast<decl_addr_value *> (xmalloc (sizeof (decl_addr_value)));
+      **slot = value;
+      found_value = *slot;
+    }
+  else
+    return NULL_TREE;
+
+  if (found_value->address != error_mark_node)
+    {
+      // We have an address for the decl, so rewrite the tree.
+      tree ptr_type = build_pointer_type (TREE_TYPE (*in));
+      *in = fold_build1 (INDIRECT_REF, TREE_TYPE (*in),
+			 fold_build1 (CONVERT_EXPR, ptr_type,
+				      found_value->address));
+    }
+
+  *walk_subtrees = 0;
+
+  return NULL_TREE;
+}
+
+// When generating code for gdb, we want to be able to use absolute
+// addresses to refer to otherwise external objects that gdb knows
+// about.  gdb passes in these addresses when building decls, and then
+// before gimplification we go through the trees, rewriting uses to
+// the equivalent of "*(TYPE *) ADDR".
+static void
+rewrite_decls_to_addresses (void *function_in, void *)
+{
+  tree function = (tree) function_in;
+
+  // Do nothing if we're not in gdb.
+  if (current_context == NULL)
+    return;
+
+  walk_tree (&DECL_SAVED_TREE (function), address_rewriter, current_context,
+	     NULL);
+}
+
+\f
+
+gcc_decl
+plugin_build_decl (cc1_plugin::connection *self,
+		   const char *name,
+		   enum gcc_c_symbol_kind sym_kind,
+		   gcc_type sym_type_in,
+		   const char *substitution_name,
+		   gcc_address address,
+		   const char *filename,
+		   unsigned int line_number)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  tree identifier = get_identifier (name);
+  enum tree_code code;
+  tree decl;
+  tree sym_type = convert_in (sym_type_in);
+
+  switch (sym_kind)
+    {
+    case GCC_C_SYMBOL_FUNCTION:
+      code = FUNCTION_DECL;
+      break;
+
+    case GCC_C_SYMBOL_VARIABLE:
+      code = VAR_DECL;
+      break;
+
+    case GCC_C_SYMBOL_TYPEDEF:
+      code = TYPE_DECL;
+      break;
+
+    case GCC_C_SYMBOL_LABEL:
+      // FIXME: we aren't ready to handle labels yet.
+      // It isn't clear how to translate them properly
+      // and in any case a "goto" isn't likely to work.
+      return convert_out (error_mark_node);
+
+    default:
+      abort ();
+    }
+
+  source_location loc = ctx->get_source_location (filename, line_number);
+
+  decl = build_decl (loc, code, identifier, sym_type);
+  TREE_USED (decl) = 1;
+  TREE_ADDRESSABLE (decl) = 1;
+
+  if (sym_kind != GCC_C_SYMBOL_TYPEDEF)
+    {
+      decl_addr_value value;
+
+      value.decl = decl;
+      if (substitution_name != NULL)
+	{
+	  // If the translator gave us a name without a binding,
+	  // we can just substitute error_mark_node, since we know the
+	  // translator will be reporting an error anyhow.
+	  value.address
+	    = lookup_name (get_identifier (substitution_name));
+	  if (value.address == NULL_TREE)
+	    value.address = error_mark_node;
+	}
+      else
+	value.address = build_int_cst_type (ptr_type_node, address);
+      decl_addr_value **slot = ctx->address_map.find_slot (&value, INSERT);
+      gcc_assert (*slot == NULL);
+      *slot
+	= static_cast<decl_addr_value *> (xmalloc (sizeof (decl_addr_value)));
+      **slot = value;
+    }
+
+  return convert_out (ctx->preserve (decl));
+}
+
+int
+plugin_bind (cc1_plugin::connection *,
+	     gcc_decl decl_in, int is_global)
+{
+  tree decl = convert_in (decl_in);
+  c_bind (DECL_SOURCE_LOCATION (decl), decl, is_global);
+  rest_of_decl_compilation (decl, is_global, 0);
+  return 1;
+}
+
+int
+plugin_tagbind (cc1_plugin::connection *self,
+		const char *name, gcc_type tagged_type,
+		const char *filename, unsigned int line_number)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  c_pushtag (ctx->get_source_location (filename, line_number),
+	     get_identifier (name), convert_in (tagged_type));
+  return 1;
+}
+
+gcc_type
+plugin_build_pointer_type (cc1_plugin::connection *,
+			   gcc_type base_type)
+{
+  // No need to preserve a pointer type as the base type is preserved.
+  return convert_out (build_pointer_type (convert_in (base_type)));
+}
+
+gcc_type
+plugin_build_record_type (cc1_plugin::connection *self)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (make_node (RECORD_TYPE)));
+}
+
+gcc_type
+plugin_build_union_type (cc1_plugin::connection *self)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (make_node (UNION_TYPE)));
+}
+
+int
+plugin_build_add_field (cc1_plugin::connection *,
+			gcc_type record_or_union_type_in,
+			const char *field_name,
+			gcc_type field_type_in,
+			unsigned long bitsize,
+			unsigned long bitpos)
+{
+  tree record_or_union_type = convert_in (record_or_union_type_in);
+  tree field_type = convert_in (field_type_in);
+
+  gcc_assert (TREE_CODE (record_or_union_type) == RECORD_TYPE
+	      || TREE_CODE (record_or_union_type) == UNION_TYPE);
+
+  /* Note that gdb does not preserve the location of field decls, so
+     we can't provide a decent location here.  */
+  tree decl = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+			  get_identifier (field_name), field_type);
+  DECL_FIELD_CONTEXT (decl) = record_or_union_type;
+
+  if (TREE_CODE (field_type) == INTEGER_TYPE
+      && TYPE_PRECISION (field_type) != bitsize)
+    {
+      DECL_BIT_FIELD_TYPE (decl) = field_type;
+      TREE_TYPE (decl)
+	= c_build_bitfield_integer_type (bitsize, TYPE_UNSIGNED (field_type));
+    }
+
+  DECL_MODE (decl) = TYPE_MODE (TREE_TYPE (decl));
+
+  // There's no way to recover this from DWARF.
+  SET_DECL_OFFSET_ALIGN (decl, TYPE_PRECISION (pointer_sized_int_node));
+
+  tree pos = bitsize_int (bitpos);
+  pos_from_bit (&DECL_FIELD_OFFSET (decl), &DECL_FIELD_BIT_OFFSET (decl),
+		DECL_OFFSET_ALIGN (decl), pos);
+
+  DECL_SIZE (decl) = bitsize_int (bitsize);
+  DECL_SIZE_UNIT (decl) = size_int ((bitsize + BITS_PER_UNIT - 1)
+				    / BITS_PER_UNIT);
+
+  DECL_CHAIN (decl) = TYPE_FIELDS (record_or_union_type);
+  TYPE_FIELDS (record_or_union_type) = decl;
+
+  return 1;
+}
+
+int
+plugin_finish_record_or_union (cc1_plugin::connection *,
+			       gcc_type record_or_union_type_in,
+			       unsigned long size_in_bytes)
+{
+  tree record_or_union_type = convert_in (record_or_union_type_in);
+
+  gcc_assert (TREE_CODE (record_or_union_type) == RECORD_TYPE
+	      || TREE_CODE (record_or_union_type) == UNION_TYPE);
+
+  /* We built the field list in reverse order, so fix it now.  */
+  TYPE_FIELDS (record_or_union_type)
+    = nreverse (TYPE_FIELDS (record_or_union_type));
+
+  if (TREE_CODE (record_or_union_type) == UNION_TYPE)
+    {
+      /* Unions can just be handled by the generic code.  */
+      layout_type (record_or_union_type);
+    }
+  else
+    {
+      // FIXME there's no way to get this from DWARF,
+      // or even, it seems, a particularly good way to deduce it.
+      TYPE_ALIGN (record_or_union_type)
+	= TYPE_PRECISION (pointer_sized_int_node);
+
+      TYPE_SIZE (record_or_union_type) = bitsize_int (size_in_bytes
+						      * BITS_PER_UNIT);
+      TYPE_SIZE_UNIT (record_or_union_type) = size_int (size_in_bytes);
+
+      compute_record_mode (record_or_union_type);
+      finish_bitfield_layout (record_or_union_type);
+      // FIXME we have no idea about TYPE_PACKED
+    }
+
+  return 1;
+}
+
+gcc_type
+plugin_build_enum_type (cc1_plugin::connection *self,
+			gcc_type underlying_int_type_in)
+{
+  tree underlying_int_type = convert_in (underlying_int_type_in);
+
+  if (underlying_int_type == error_mark_node)
+    return convert_out (error_mark_node);
+
+  tree result = make_node (ENUMERAL_TYPE);
+
+  TYPE_PRECISION (result) = TYPE_PRECISION (underlying_int_type);
+  TYPE_UNSIGNED (result) = TYPE_UNSIGNED (underlying_int_type);
+
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (result));
+}
+
+int
+plugin_build_add_enum_constant (cc1_plugin::connection *,
+				gcc_type enum_type_in,
+				const char *name,
+				unsigned long value)
+{
+  tree cst, decl, cons;
+  tree enum_type = convert_in (enum_type_in);
+
+  gcc_assert (TREE_CODE (enum_type) == ENUMERAL_TYPE);
+
+  cst = build_int_cst (enum_type, value);
+  /* Note that gdb does not preserve the location of enum constants,
+     so we can't provide a decent location here.  */
+  decl = build_decl (BUILTINS_LOCATION, CONST_DECL,
+		     get_identifier (name), enum_type);
+  DECL_INITIAL (decl) = cst;
+  pushdecl_safe (decl);
+
+  cons = tree_cons (DECL_NAME (decl), cst, TYPE_VALUES (enum_type));
+  TYPE_VALUES (enum_type) = cons;
+
+  return 1;
+}
+
+int
+plugin_finish_enum_type (cc1_plugin::connection *,
+			 gcc_type enum_type_in)
+{
+  tree enum_type = convert_in (enum_type_in);
+  tree minnode, maxnode, iter;
+
+  iter = TYPE_VALUES (enum_type);
+  minnode = maxnode = TREE_VALUE (iter);
+  for (iter = TREE_CHAIN (iter);
+       iter != NULL_TREE;
+       iter = TREE_CHAIN (iter))
+    {
+      tree value = TREE_VALUE (iter);
+      if (tree_int_cst_lt (maxnode, value))
+	maxnode = value;
+      if (tree_int_cst_lt (value, minnode))
+	minnode = value;
+    }
+  TYPE_MIN_VALUE (enum_type) = minnode;
+  TYPE_MAX_VALUE (enum_type) = maxnode;
+
+  layout_type (enum_type);
+
+  return 1;
+}
+
+gcc_type
+plugin_build_function_type (cc1_plugin::connection *self,
+			    gcc_type return_type_in,
+			    const struct gcc_type_array *argument_types_in,
+			    int is_varargs)
+{
+  tree *argument_types;
+  tree return_type = convert_in (return_type_in);
+  tree result;
+
+  argument_types = new tree[argument_types_in->n_elements];
+  for (int i = 0; i < argument_types_in->n_elements; ++i)
+    argument_types[i] = convert_in (argument_types_in->elements[i]);
+
+  if (is_varargs)
+    result = build_varargs_function_type_array (return_type,
+						argument_types_in->n_elements,
+						argument_types);
+  else
+    result = build_function_type_array (return_type,
+					argument_types_in->n_elements,
+					argument_types);
+
+  delete[] argument_types;
+
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (result));
+}
+
+gcc_type
+plugin_int_type (cc1_plugin::connection *self,
+		 int is_unsigned, unsigned long size_in_bytes)
+{
+  tree result = c_common_type_for_size (BITS_PER_UNIT * size_in_bytes,
+					is_unsigned);
+  if (result == NULL_TREE)
+    result = error_mark_node;
+  else
+    {
+      plugin_context *ctx = static_cast<plugin_context *> (self);
+      ctx->preserve (result);
+    }
+  return convert_out (result);
+}
+
+gcc_type
+plugin_float_type (cc1_plugin::connection *,
+		   unsigned long size_in_bytes)
+{
+  if (BITS_PER_UNIT * size_in_bytes == TYPE_PRECISION (float_type_node))
+    return convert_out (float_type_node);
+  if (BITS_PER_UNIT * size_in_bytes == TYPE_PRECISION (double_type_node))
+    return convert_out (double_type_node);
+  if (BITS_PER_UNIT * size_in_bytes == TYPE_PRECISION (long_double_type_node))
+    return convert_out (long_double_type_node);
+  return convert_out (error_mark_node);
+}
+
+gcc_type
+plugin_void_type (cc1_plugin::connection *)
+{
+  return convert_out (void_type_node);
+}
+
+gcc_type
+plugin_bool_type (cc1_plugin::connection *)
+{
+  return convert_out (boolean_type_node);
+}
+
+gcc_type
+plugin_build_array_type (cc1_plugin::connection *self,
+			 gcc_type element_type_in, int num_elements)
+{
+  tree element_type = convert_in (element_type_in);
+  tree result;
+
+  if (num_elements == -1)
+    result = build_array_type (element_type, NULL_TREE);
+  else
+    result = build_array_type_nelts (element_type, num_elements);
+
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (result));
+}
+
+gcc_type
+plugin_build_vla_array_type (cc1_plugin::connection *self,
+			     gcc_type element_type_in,
+			     const char *upper_bound_name)
+{
+  tree element_type = convert_in (element_type_in);
+  tree upper_bound = lookup_name (get_identifier (upper_bound_name));
+  tree range = build_index_type (upper_bound);
+
+  tree result = build_array_type (element_type, range);
+  C_TYPE_VARIABLE_SIZE (result) = 1;
+
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (result));
+}
+
+gcc_type
+plugin_build_qualified_type (cc1_plugin::connection *,
+			     gcc_type unqualified_type_in,
+			     enum gcc_qualifiers qualifiers)
+{
+  tree unqualified_type = convert_in (unqualified_type_in);
+  int quals = 0;
+
+  if ((qualifiers & GCC_QUALIFIER_CONST) != 0)
+    quals |= TYPE_QUAL_CONST;
+  if ((qualifiers & GCC_QUALIFIER_VOLATILE) != 0)
+    quals |= TYPE_QUAL_VOLATILE;
+  if ((qualifiers & GCC_QUALIFIER_RESTRICT) != 0)
+    quals |= TYPE_QUAL_RESTRICT;
+
+  return convert_out (build_qualified_type (unqualified_type, quals));
+}
+
+gcc_type
+plugin_build_complex_type (cc1_plugin::connection *self,
+			   gcc_type base_type)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (build_complex_type (convert_in (base_type))));
+}
+
+gcc_type
+plugin_build_vector_type (cc1_plugin::connection *self,
+			  gcc_type base_type, int nunits)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (build_vector_type (convert_in (base_type),
+							nunits)));
+}
+
+int
+plugin_build_constant (cc1_plugin::connection *self, gcc_type type_in,
+		       const char *name, unsigned long value,
+		       const char *filename, unsigned int line_number)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  tree cst, decl;
+  tree type = convert_in (type_in);
+
+  cst = build_int_cst (type, value);
+  decl = build_decl (ctx->get_source_location (filename, line_number),
+		     CONST_DECL, get_identifier (name), type);
+  DECL_INITIAL (decl) = cst;
+  pushdecl_safe (decl);
+
+  return 1;
+}
+
+gcc_type
+plugin_error (cc1_plugin::connection *,
+	      const char *message)
+{
+  error ("%s", message);
+  return convert_out (error_mark_node);
+}
+
+\f
+
+// Perform GC marking.
+
+static void
+gc_mark (void *, void *)
+{
+  if (current_context != NULL)
+    current_context->mark ();
+}
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+	     struct plugin_gcc_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 ("%s: invalid file descriptor argument to plugin",
+			 plugin_info->base_name);
+	  break;
+	}
+    }
+  if (fd == -1)
+    fatal_error ("%s: required plugin argument %<fd%> is missing",
+		 plugin_info->base_name);
+
+  current_context = new plugin_context (fd);
+
+  // Handshake.
+  cc1_plugin::protocol_int version;
+  if (!current_context->require ('H')
+      || ! ::cc1_plugin::unmarshall (current_context, &version))
+    fatal_error ("%s: handshake failed", plugin_info->base_name);
+  if (version != GCC_C_FE_VERSION_0)
+    fatal_error ("%s: unknown version in handshake", plugin_info->base_name);
+
+  register_callback (plugin_info->base_name, PLUGIN_PRAGMAS,
+		     plugin_init_extra_pragmas, NULL);
+  register_callback (plugin_info->base_name, PLUGIN_PRE_GENERICIZE,
+		     rewrite_decls_to_addresses, NULL);
+  register_callback (plugin_info->base_name, PLUGIN_GGC_MARKING,
+		     gc_mark, NULL);
+
+  lang_hooks.print_error_function = plugin_print_error_function;
+
+#define GCC_METHOD0(R, N)			\
+  {						\
+    cc1_plugin::callback_ftype *fun		\
+      = cc1_plugin::callback<R, plugin_ ## N>;	\
+    current_context->add_callback (# N, fun);	\
+  }
+#define GCC_METHOD1(R, N, A)				\
+  {							\
+    cc1_plugin::callback_ftype *fun			\
+      = cc1_plugin::callback<R, A, plugin_ ## N>;	\
+    current_context->add_callback (# N, fun);		\
+  }
+#define GCC_METHOD2(R, N, A, B)				\
+  {							\
+    cc1_plugin::callback_ftype *fun			\
+      = cc1_plugin::callback<R, A, B, plugin_ ## N>;	\
+    current_context->add_callback (# N, fun);		\
+  }
+#define GCC_METHOD3(R, N, A, B, C)			\
+  {							\
+    cc1_plugin::callback_ftype *fun			\
+      = cc1_plugin::callback<R, A, B, C, plugin_ ## N>;	\
+    current_context->add_callback (# N, fun);		\
+  }
+#define GCC_METHOD4(R, N, A, B, C, D)		\
+  {						\
+    cc1_plugin::callback_ftype *fun		\
+      = cc1_plugin::callback<R, A, B, C, D,	\
+			     plugin_ ## N>;	\
+    current_context->add_callback (# N, fun);	\
+  }
+#define GCC_METHOD5(R, N, A, B, C, D, E)	\
+  {						\
+    cc1_plugin::callback_ftype *fun		\
+      = cc1_plugin::callback<R, A, B, C, D, E,	\
+			     plugin_ ## N>;	\
+    current_context->add_callback (# N, fun);	\
+  }
+#define GCC_METHOD7(R, N, A, B, C, D, E, F, G)		\
+  {							\
+    cc1_plugin::callback_ftype *fun			\
+      = cc1_plugin::callback<R, A, B, C, D, E, F, G,	\
+			     plugin_ ## N>;		\
+    current_context->add_callback (# N, fun);		\
+  }
+
+#include "gcc-c-fe.def"
+
+#undef GCC_METHOD0
+#undef GCC_METHOD1
+#undef GCC_METHOD2
+#undef GCC_METHOD3
+#undef GCC_METHOD4
+#undef GCC_METHOD5
+#undef GCC_METHOD7
+
+  return 0;
+}
diff --git a/libcc1/rpc.hh b/libcc1/rpc.hh
new file mode 100644
index 0000000..58758d3
--- /dev/null
+++ b/libcc1/rpc.hh
@@ -0,0 +1,486 @@
+/* RPC call and callback templates
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_RPC_HH
+#define CC1_PLUGIN_RPC_HH
+
+#include "status.hh"
+#include "marshall.hh"
+#include "connection.hh"
+
+namespace cc1_plugin
+{
+  // The plugin API may contain some "const" method parameters.
+  // However, when unmarshalling we cannot unmarshall into a const
+  // object; and furthermore we want to be able to deallocate pointers
+  // when finished with them.  This wrapper class lets us properly
+  // remove the "const" and handle deallocation from pointer types.
+
+  template<typename T>
+  class argument_wrapper
+  {
+  public:
+
+    argument_wrapper () { }
+    ~argument_wrapper () { }
+
+    operator T () const { return m_object; }
+
+    status unmarshall (connection *conn)
+    {
+      return ::cc1_plugin::unmarshall (conn, &m_object);
+    }
+
+  private:
+
+    T m_object;
+
+    // No copying or assignment allowed.
+    argument_wrapper (const argument_wrapper &);
+    argument_wrapper &operator= (const argument_wrapper &);
+  };
+
+  // Specialization for any kind of pointer.  This is declared but not
+  // defined to avoid bugs if a new pointer type is introduced into
+  // the API.  Instead you will just get a compilation error.
+  template<typename T>
+  class argument_wrapper<const T *>;
+
+  // Specialization for string types.
+  template<>
+  class argument_wrapper<const char *>
+  {
+  public:
+    argument_wrapper () : m_object (NULL) { }
+    ~argument_wrapper ()
+    {
+      delete[] m_object;
+    }
+
+    operator const char * () const
+    {
+      return m_object;
+    }
+
+    status unmarshall (connection *conn)
+    {
+      return ::cc1_plugin::unmarshall (conn, &m_object);
+    }
+
+  private:
+
+    char *m_object;
+
+    // No copying or assignment allowed.
+    argument_wrapper (const argument_wrapper &);
+    argument_wrapper &operator= (const argument_wrapper &);
+  };
+
+  // Specialization for gcc_type_array.
+  template<>
+  class argument_wrapper<const gcc_type_array *>
+  {
+  public:
+    argument_wrapper () : m_object (NULL) { }
+    ~argument_wrapper ()
+    {
+      // It would be nicer if gcc_type_array could have a destructor.
+      // But, it is in code shared with gdb and cannot.
+      if (m_object != NULL)
+	delete[] m_object->elements;
+      delete m_object;
+    }
+
+    operator const gcc_type_array * () const
+    {
+      return m_object;
+    }
+
+    status unmarshall (connection *conn)
+    {
+      return ::cc1_plugin::unmarshall (conn, &m_object);
+    }
+
+  private:
+
+    gcc_type_array *m_object;
+
+    // No copying or assignment allowed.
+    argument_wrapper (const argument_wrapper &);
+    argument_wrapper &operator= (const argument_wrapper &);
+  };
+
+  // There are two kinds of template functions here: "call" and
+  // "callback".  They are each repeated multiple times to handle
+  // different numbers of arguments.  (This would be improved with
+  // C++11, though applying a call is still tricky until C++14 can be
+  // used.)
+
+  // The "call" template is used for making a remote procedure call.
+  // It starts a query ('Q') packet, marshalls its arguments, waits
+  // for a result, and finally reads and returns the result via an
+  // "out" parameter.
+
+  // The "callback" template is used when receiving a remote procedure
+  // call.  This template function is suitable for use with the
+  // "callbacks" and "connection" classes.  It decodes incoming
+  // arguments, passes them to the wrapped function, and finally
+  // marshalls a reply packet.
+
+  template<typename R>
+  status
+  call (connection *conn, const char *method, R *result)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 0))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, R (*func) (connection *)>
+  status
+  callback (connection *conn)
+  {
+    R result;
+
+    if (!unmarshall_check (conn, 0))
+      return FAIL;
+    result = func (conn);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+
+  template<typename R, typename A>
+  status
+  call (connection *conn, const char *method, R *result, A arg)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 1))
+      return FAIL;
+    if (!marshall (conn, arg))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, typename A, R (*func) (connection *, A)>
+  status
+  callback (connection *conn)
+  {
+    argument_wrapper<A> arg;
+    R result;
+
+    if (!unmarshall_check (conn, 1))
+      return FAIL;
+    if (!arg.unmarshall (conn))
+      return FAIL;
+    result = func (conn, arg);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+
+  template<typename R, typename A1, typename A2>
+  status
+  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 2))
+      return FAIL;
+    if (!marshall (conn, arg1))
+      return FAIL;
+    if (!marshall (conn, arg2))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, typename A1, typename A2, R (*func) (connection *,
+							    A1, A2)>
+  status
+  callback (connection *conn)
+  {
+    argument_wrapper<A1> arg1;
+    argument_wrapper<A2> arg2;
+    R result;
+
+    if (!unmarshall_check (conn, 2))
+      return FAIL;
+    if (!arg1.unmarshall (conn))
+      return FAIL;
+    if (!arg2.unmarshall (conn))
+      return FAIL;
+    result = func (conn, arg1, arg2);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+
+  template<typename R, typename A1, typename A2, typename A3>
+  status
+  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
+	A3 arg3)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 3))
+      return FAIL;
+    if (!marshall (conn, arg1))
+      return FAIL;
+    if (!marshall (conn, arg2))
+      return FAIL;
+    if (!marshall (conn, arg3))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, typename A1, typename A2, typename A3,
+	   R (*func) (connection *, A1, A2, A3)>
+  status
+  callback (connection *conn)
+  {
+    argument_wrapper<A1> arg1;
+    argument_wrapper<A2> arg2;
+    argument_wrapper<A3> arg3;
+    R result;
+
+    if (!unmarshall_check (conn, 3))
+      return FAIL;
+    if (!arg1.unmarshall (conn))
+      return FAIL;
+    if (!arg2.unmarshall (conn))
+      return FAIL;
+    if (!arg3.unmarshall (conn))
+      return FAIL;
+    result = func (conn, arg1, arg2, arg3);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+
+  template<typename R, typename A1, typename A2, typename A3, typename A4>
+  status
+  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
+	A3 arg3, A4 arg4)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 4))
+      return FAIL;
+    if (!marshall (conn, arg1))
+      return FAIL;
+    if (!marshall (conn, arg2))
+      return FAIL;
+    if (!marshall (conn, arg3))
+      return FAIL;
+    if (!marshall (conn, arg4))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, typename A1, typename A2, typename A3, typename A4,
+	   R (*func) (connection *, A1, A2, A3, A4)>
+  status
+  callback (connection *conn)
+  {
+    argument_wrapper<A1> arg1;
+    argument_wrapper<A2> arg2;
+    argument_wrapper<A3> arg3;
+    argument_wrapper<A4> arg4;
+    R result;
+
+    if (!unmarshall_check (conn, 4))
+      return FAIL;
+    if (!arg1.unmarshall (conn))
+      return FAIL;
+    if (!arg2.unmarshall (conn))
+      return FAIL;
+    if (!arg3.unmarshall (conn))
+      return FAIL;
+    if (!arg4.unmarshall (conn))
+      return FAIL;
+    result = func (conn, arg1, arg2, arg3, arg4);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+
+  template<typename R, typename A1, typename A2, typename A3, typename A4,
+	   typename A5>
+  status
+  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
+	A3 arg3, A4 arg4, A5 arg5)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 5))
+      return FAIL;
+    if (!marshall (conn, arg1))
+      return FAIL;
+    if (!marshall (conn, arg2))
+      return FAIL;
+    if (!marshall (conn, arg3))
+      return FAIL;
+    if (!marshall (conn, arg4))
+      return FAIL;
+    if (!marshall (conn, arg5))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, typename A1, typename A2, typename A3, typename A4,
+	   typename A5, R (*func) (connection *, A1, A2, A3, A4, A5)>
+  status
+  callback (connection *conn)
+  {
+    argument_wrapper<A1> arg1;
+    argument_wrapper<A2> arg2;
+    argument_wrapper<A3> arg3;
+    argument_wrapper<A4> arg4;
+    argument_wrapper<A5> arg5;
+    R result;
+
+    if (!unmarshall_check (conn, 5))
+      return FAIL;
+    if (!arg1.unmarshall (conn))
+      return FAIL;
+    if (!arg2.unmarshall (conn))
+      return FAIL;
+    if (!arg3.unmarshall (conn))
+      return FAIL;
+    if (!arg4.unmarshall (conn))
+      return FAIL;
+    if (!arg5.unmarshall (conn))
+      return FAIL;
+    result = func (conn, arg1, arg2, arg3, arg4, arg5);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+
+  template<typename R, typename A1, typename A2, typename A3, typename A4,
+	   typename A5, typename A6, typename A7>
+  status
+  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
+	A3 arg3, A4 arg4, A5 arg5, A6 arg6, A7 arg7)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 7))
+      return FAIL;
+    if (!marshall (conn, arg1))
+      return FAIL;
+    if (!marshall (conn, arg2))
+      return FAIL;
+    if (!marshall (conn, arg3))
+      return FAIL;
+    if (!marshall (conn, arg4))
+      return FAIL;
+    if (!marshall (conn, arg5))
+      return FAIL;
+    if (!marshall (conn, arg6))
+      return FAIL;
+    if (!marshall (conn, arg7))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, typename A1, typename A2, typename A3, typename A4,
+	   typename A5, typename A6, typename A7,
+	   R (*func) (connection *, A1, A2, A3, A4, A5, A6, A7)>
+  status
+  callback (connection *conn)
+  {
+    argument_wrapper<A1> arg1;
+    argument_wrapper<A2> arg2;
+    argument_wrapper<A3> arg3;
+    argument_wrapper<A4> arg4;
+    argument_wrapper<A5> arg5;
+    argument_wrapper<A6> arg6;
+    argument_wrapper<A7> arg7;
+    R result;
+
+    if (!unmarshall_check (conn, 7))
+      return FAIL;
+    if (!arg1.unmarshall (conn))
+      return FAIL;
+    if (!arg2.unmarshall (conn))
+      return FAIL;
+    if (!arg3.unmarshall (conn))
+      return FAIL;
+    if (!arg4.unmarshall (conn))
+      return FAIL;
+    if (!arg5.unmarshall (conn))
+      return FAIL;
+    if (!arg6.unmarshall (conn))
+      return FAIL;
+    if (!arg7.unmarshall (conn))
+      return FAIL;
+    result = func (conn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+};
+
+#endif // CC1_PLUGIN_RPC_HH
diff --git a/libcc1/status.hh b/libcc1/status.hh
new file mode 100644
index 0000000..764c7ff
--- /dev/null
+++ b/libcc1/status.hh
@@ -0,0 +1,33 @@
+/* status type definition
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_STATUS_HH
+#define CC1_PLUGIN_STATUS_HH
+
+namespace cc1_plugin
+{
+  // The status returned by various connection functions.
+  enum status
+  {
+    FAIL = 0,
+    OK = 1
+  };
+}
+
+#endif // CC1_PLUGIN_STATUS_HH
-- 
1.9.3

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-06-19 20:52   ` Tom Tromey
@ 2014-06-19 21:45     ` Jakub Jelinek
  2014-06-19 22:22       ` Tom Tromey
  2014-06-20  3:11     ` Trevor Saunders
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 101+ messages in thread
From: Jakub Jelinek @ 2014-06-19 21:45 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gcc-patches

On Thu, Jun 19, 2014 at 02:52:12PM -0600, Tom Tromey wrote:
> Tom> I've edited this one down by removing the auto-generated stuff , and
> Tom> then compressed it.
> 
> Here's a new version of patch #5.
> I've removed the generated code; let's see if it gets through without
> compression.
> 
> I think this addresses all the reviews:
> 
> * It uses gcc-plugin.m4 to disable the plugin
> * It does some configure checks for needed functionality, and disables
>   the plugin if they are not found
> * libcc1 and the plugin now do a protocol version handshake at
>   startup
> * The diagnostic overriding code is now in the plugin, not in gcc proper
> * gdb now tells libcc1 about the target triplet, and libcc1 uses
>   this to invoke the proper GCC.  This is done by (ewww) searching $PATH.

If you plan to implement this for other frontends (cc1plus, f951?) in the
future, would that be still libcc1 and perhaps new plugins in there, or are
we going to have new toplevel directories for each such a plugin?

	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-06-19 21:45     ` Jakub Jelinek
@ 2014-06-19 22:22       ` Tom Tromey
  0 siblings, 0 replies; 101+ messages in thread
From: Tom Tromey @ 2014-06-19 22:22 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

>>>>> "Jakub" == Jakub Jelinek <jakub@redhat.com> writes:

Jakub> If you plan to implement this for other frontends (cc1plus,
Jakub> f951?) in the future, would that be still libcc1 and perhaps new
Jakub> plugins in there, or are we going to have new toplevel
Jakub> directories for each such a plugin?

We're planning to do this for g++ but, as far as I know, not anything
else.  I was planning to put the C++ plugin into this same directory, as
I expect it to share a reasonable amount of code with the C plugin -- at
least all the RPC stuff.

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-06-19 20:52   ` Tom Tromey
  2014-06-19 21:45     ` Jakub Jelinek
@ 2014-06-20  3:11     ` Trevor Saunders
  2014-06-20 15:34       ` Tom Tromey
  2014-07-18 19:00     ` Tom Tromey
  2014-07-31  4:49     ` Jeff Law
  3 siblings, 1 reply; 101+ messages in thread
From: Trevor Saunders @ 2014-06-20  3:11 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 101759 bytes --]

Hi,

I'm curious, what is the reason you choose not to write this in C++11 or
later?  Its distributed with gcc, so the only case where you aren't
building with the in tree compiler and libraries is when your cross
compiling gcc, and it doesn't seem particularly important to support
building the plugin or library in that configuration.  So istm you could
go all the way and assume you are being built with trunk gcc and
libraries.

Some more comments inline.

On Thu, Jun 19, 2014 at 02:52:12PM -0600, Tom Tromey wrote:
> Tom> I've edited this one down by removing the auto-generated stuff , and
> Tom> then compressed it.
> 
> Here's a new version of patch #5.
> I've removed the generated code; let's see if it gets through without
> compression.
> 
> I think this addresses all the reviews:
> 
> * It uses gcc-plugin.m4 to disable the plugin
> * It does some configure checks for needed functionality, and disables
>   the plugin if they are not found
> * libcc1 and the plugin now do a protocol version handshake at
>   startup
> * The diagnostic overriding code is now in the plugin, not in gcc proper
> * gdb now tells libcc1 about the target triplet, and libcc1 uses
>   this to invoke the proper GCC.  This is done by (ewww) searching $PATH.
> 
> Tom
> 
> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
> 	    Tom Tromey  <tromey@redhat.com>
> 
> 	* Makefile.def: Add libcc1 to host_modules.
> 	* configure.ac (host_tools): Add libcc1.
> 	* Makefile.in, configure: Rebuild.
> 
> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> 	    Tom Tromey  <tromey@redhat.com>
> 
> 	* aclocal.m4: New file.
> 	* callbacks.cc: New file.
> 	* callbacks.hh: New file.
> 	* cc1plugin-config.h.in: New file.
> 	* configure: New file.
> 	* configure.ac: New file.
> 	* connection.cc: New file.
> 	* connection.hh: New file.
> 	* findcomp.cc: New file.
> 	* findcomp.hh: New file.
> 	* libcc1.cc: New file.
> 	* libcc1plugin.sym: New file.
> 	* libcc1.sym: New file.
> 	* Makefile.am: New file.
> 	* Makefile.in: New file.
> 	* marshall.cc: New file.
> 	* marshall.hh: New file.
> 	* names.cc: New file.
> 	* names.hh: New file.
> 	* plugin.cc: New file.
> 	* rpc.hh: New file.
> 	* status.hh: New file.
> 
> ---
>  ChangeLog                    |     7 +
>  Makefile.def                 |     5 +
>  Makefile.in                  |   997 ++-
>  configure                    |     2 +-
>  configure.ac                 |     4 +-
>  libcc1/ChangeLog             |    26 +
>  libcc1/Makefile.am           |    52 +
>  libcc1/Makefile.in           |   627 ++
>  libcc1/aclocal.m4            |   981 +++
>  libcc1/callbacks.cc          |    90 +
>  libcc1/callbacks.hh          |    64 +
>  libcc1/cc1plugin-config.h.in |    92 +
>  libcc1/configure             | 17176 +++++++++++++++++++++++++++++++++++++++++
>  libcc1/configure.ac          |    73 +
>  libcc1/connection.cc         |   153 +
>  libcc1/connection.hh         |   114 +
>  libcc1/findcomp.cc           |   139 +
>  libcc1/findcomp.hh           |    25 +
>  libcc1/libcc1.cc             |   529 ++
>  libcc1/libcc1.sym            |     1 +
>  libcc1/libcc1plugin.sym      |     2 +
>  libcc1/marshall.cc           |   166 +
>  libcc1/marshall.hh           |    93 +
>  libcc1/names.cc              |    46 +
>  libcc1/names.hh              |    55 +
>  libcc1/plugin.cc             |   922 +++
>  libcc1/rpc.hh                |   486 ++
>  libcc1/status.hh             |    33 +
>  28 files changed, 22952 insertions(+), 8 deletions(-)
>  create mode 100644 libcc1/ChangeLog
>  create mode 100644 libcc1/Makefile.am
>  create mode 100644 libcc1/Makefile.in
>  create mode 100644 libcc1/aclocal.m4
>  create mode 100644 libcc1/callbacks.cc
>  create mode 100644 libcc1/callbacks.hh
>  create mode 100644 libcc1/cc1plugin-config.h.in
>  create mode 100755 libcc1/configure
>  create mode 100644 libcc1/configure.ac
>  create mode 100644 libcc1/connection.cc
>  create mode 100644 libcc1/connection.hh
>  create mode 100644 libcc1/findcomp.cc
>  create mode 100644 libcc1/findcomp.hh
>  create mode 100644 libcc1/libcc1.cc
>  create mode 100644 libcc1/libcc1.sym
>  create mode 100644 libcc1/libcc1plugin.sym
>  create mode 100644 libcc1/marshall.cc
>  create mode 100644 libcc1/marshall.hh
>  create mode 100644 libcc1/names.cc
>  create mode 100644 libcc1/names.hh
>  create mode 100644 libcc1/plugin.cc
>  create mode 100644 libcc1/rpc.hh
>  create mode 100644 libcc1/status.hh
> 
> diff --git a/Makefile.def b/Makefile.def
> index 239ad36..ed9bac6 100644
> --- a/Makefile.def
> +++ b/Makefile.def
> @@ -121,6 +121,8 @@ host_modules= { module= gnattools; };
>  host_modules= { module= lto-plugin; bootstrap=true;
>  		extra_configure_flags='--enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@';
>  		extra_make_flags='@extra_linker_plugin_flags@'; };
> +host_modules= { module= libcc1; bootstrap=true;
> +		extra_configure_flags=--enable-shared; };
>  
>  target_modules = { module= libstdc++-v3;
>  		   bootstrap=true;
> @@ -352,6 +354,9 @@ dependencies = { module=all-gnattools; on=all-target-libstdc++-v3; };
>  dependencies = { module=all-lto-plugin; on=all-libiberty; };
>  dependencies = { module=all-lto-plugin; on=all-libiberty-linker-plugin; };
>  
> +dependencies = { module=configure-libcc1; on=configure-gcc; };
> +dependencies = { module=all-libcc1; on=all-gcc; };
> +
>  dependencies = { module=all-utils; on=all-libiberty; };
>  
>  dependencies = { module=configure-mpfr; on=all-gmp; };
> diff --git a/configure.ac b/configure.ac
> index 9048cd1..0388dc2 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1,5 +1,5 @@
>  #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
> -#   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
> +#   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2014
>  #   Free Software Foundation, Inc.
>  #
>  # This file is free software; you can redistribute it and/or modify it
> @@ -141,7 +141,7 @@ host_libs="intl libiberty opcodes bfd readline tcl tk itcl libgui zlib libbacktr
>  # binutils, gas and ld appear in that order because it makes sense to run
>  # "make check" in that particular order.
>  # If --enable-gold is used, "gold" may replace "ld".
> -host_tools="texinfo flex bison binutils gas ld fixincludes gcc cgen sid sim gdb gprof etc expect dejagnu m4 utils guile fastjar gnattools"
> +host_tools="texinfo flex bison binutils gas ld fixincludes gcc cgen sid sim gdb gprof etc expect dejagnu m4 utils guile fastjar gnattools libcc1"
>  
>  # libgcj represents the runtime libraries only used by gcj.
>  libgcj="target-libffi \
> diff --git a/libcc1/Makefile.am b/libcc1/Makefile.am
> new file mode 100644
> index 0000000..574557a
> --- /dev/null
> +++ b/libcc1/Makefile.am
> @@ -0,0 +1,52 @@
> +## Copyright (C) 2014 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/>.
> +
> +ACLOCAL_AMFLAGS = -I .. -I ../config
> +gcc_build_dir = ../$(host_subdir)/gcc
> +AM_CPPFLAGS = -I $(srcdir)/../include -I $(srcdir)/../libgcc \
> +	-I $(gcc_build_dir) -I$(srcdir)/../gcc \
> +	-I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
> +	-I $(srcdir)/../libcpp/include
> +WERROR_FLAG = -Werror
> +AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
> +
> +
> +plugindir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/plugin
> +cc1libdir = $(libdir)/$(libsuffix)
> +
> +if ENABLE_PLUGIN
> +plugin_LTLIBRARIES = libcc1plugin.la
> +cc1lib_LTLIBRARIES = libcc1.la
> +endif
> +
> +BUILT_SOURCES = compiler-name.h
> +
> +# Put this in a header so we don't run sed for each compilation.  This
> +# is also simpler to debug as one can easily see the constant.
> +compiler-name.h: Makefile
> +	echo "#define COMPILER_NAME \"`echo gcc | sed '$(transform)'`\"" > compiler-name.h
> +
> +
> +shared_source = callbacks.cc callbacks.hh connection.cc connection.hh \
> +    marshall.cc marshall.hh rpc.hh status.hh
> +
> +libcc1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1plugin.sym
> +libcc1plugin_la_SOURCES = plugin.cc $(shared_source)
> +
> +libcc1_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1.sym
> +libcc1_la_SOURCES = findcomp.cc libcc1.cc names.cc names.hh $(shared_source)
> diff --git a/libcc1/callbacks.cc b/libcc1/callbacks.cc
> new file mode 100644
> index 0000000..3c4eda6
> --- /dev/null
> +++ b/libcc1/callbacks.cc
> @@ -0,0 +1,90 @@
> +/* Callback management.
> +   Copyright (C) 2014 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>
> +#include <string.h>
> +#include <stdlib.h>
> +#include "callbacks.hh"
> +#include "libiberty.h"
> +
> +// An entry in the hash table.
> +struct method
> +{
> +  const char *name;
> +  cc1_plugin::callback_ftype *func;
> +};
> +
> +// Hash function for struct method.
> +static hashval_t
> +hash_method (const void *a)
> +{
> +  const struct method *m = (const struct method *) a;
> +
> +  return htab_hash_string (m->name);
> +}
> +
> +// Equality function for struct method.
> +static int
> +eq_method (const void *a, const void *b)
> +{
> +  const struct method *ma = (const struct method *) a;
> +  const struct method *mb = (const struct method *) b;
> +
> +  return strcmp (ma->name, mb->name) == 0;
> +}
> +
> +cc1_plugin::callbacks::callbacks ()
> +  : m_registry (htab_create_alloc (10, hash_method, eq_method,
> +				   free, xcalloc, free))
> +{
> +}
> +
> +cc1_plugin::callbacks::~callbacks ()
> +{
> +  htab_delete (m_registry);
> +}
> +
> +void
> +cc1_plugin::callbacks::add_callback (const char *name,
> +				     cc1_plugin::callback_ftype *func)
> +{
> +  method m;
> +  method **slot;
> +
> +  m.name = name;
> +  m.func = func;
> +
> +  slot = (method **) htab_find_slot (m_registry, &m, INSERT);
> +  *slot = XNEW (method);
> +  **slot = m;
> +}
> +
> +cc1_plugin::callback_ftype *
> +cc1_plugin::callbacks::find_callback (const char *name)
> +{
> +  method m, *found;
> +
> +  m.name = name;
> +
> +  found = (method *) htab_find (m_registry, &m);
> +  if (found == NULL)
> +    return NULL;
> +
> +  return found->func;
> +}
> diff --git a/libcc1/callbacks.hh b/libcc1/callbacks.hh
> new file mode 100644
> index 0000000..bde1100
> --- /dev/null
> +++ b/libcc1/callbacks.hh
> @@ -0,0 +1,64 @@
> +/* Callback management
> +   Copyright (C) 2014 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/>.  */
> +
> +#ifndef CC1_PLUGIN_CALLBACKS_HH
> +#define CC1_PLUGIN_CALLBACKS_HH
> +
> +#include "status.hh"
> +#include "hashtab.h"
> +
> +namespace cc1_plugin
> +{
> +  class connection;
> +
> +  // The type of a callback method.
> +  typedef status callback_ftype (connection *);
> +
> +  // This class manages callback functions.  A callback has a name and
> +  // an underlying function.  When a query packet arrives, the name is
> +  // inspected and the corresponding function is called.  A callback
> +  // function has to know how to decode its own arguments, but
> +  // wrappers are provided elsewhere to automate this.
> +  class callbacks

I'm going to use this as an excuse to bring up something I've wanted to
discuss for a while.  This class is yet another wrapper around htab.  It
sort of makes sense to do this because hash_table and pointer_map both
rely on code only in gcc.  istm the basic problem here is that gcc/ now
has C++ified data structures that are better than those in libiberty,
but it would be useful to be able to use them outside of gcc/ here, and
in libcpp at least.  So can we add C++ stuff to libiberty and allow
building libiberty without it for binutils / gdb, or can we do something
else to avoid this kind of stuff?

This question also arises in the case of templating splay_tree, and I
imagine if gdb switches to C++ some day they'll want to reuse vec.h.

> +  {
> +  public:
> +
> +    callbacks ();
> +    ~callbacks ();
> +
> +    // Add a callback named NAME.  FUNC is the function to call when
> +    // this method is invoked.
> +    void add_callback (const char *name, callback_ftype *func);
> +
> +    // Look up a callback by name.  Returns NULL if the method is not
> +    // found.
> +    callback_ftype *find_callback (const char *name);
> +
> +  private:
> +
> +    // Declared but not defined to avoid use.
> +    callbacks (const callbacks &);
> +    callbacks &operator= (const callbacks &);
> +
> +    // The mapping.
> +    htab_t m_registry;
> +  };
> +};
> +
> +#endif // CC1_PLUGIN_CALLBACKS_HH
> diff --git a/libcc1/configure.ac b/libcc1/configure.ac
> new file mode 100644
> index 0000000..7328977
> --- /dev/null
> +++ b/libcc1/configure.ac
> @@ -0,0 +1,73 @@
> +dnl   Copyright (C) 2014 Free Software Foundation, Inc.
> +dnl
> +dnl This file is part of GCC.
> +dnl
> +dnl GCC is free software; you can redistribute it and/or modify it under
> +dnl the terms of the GNU General Public License as published by the Free
> +dnl Software Foundation; either version 3, or (at your option) any later
> +dnl version.
> +dnl
> +dnl GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +dnl WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +dnl FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +dnl for more details.
> +dnl
> +dnl You should have received a copy of the GNU General Public License
> +dnl along with GCC; see the file COPYING3.  If not see
> +dnl <http://www.gnu.org/licenses/>.
> +
> +AC_PREREQ(2.64)
> +AC_INIT([libcc1], [version-unused])
> +AC_CONFIG_SRCDIR([libcc1.cc])
> +AC_CONFIG_HEADER(cc1plugin-config.h)
> +
> +AC_CANONICAL_SYSTEM
> +AC_USE_SYSTEM_EXTENSIONS
> +# Determine the noncanonical target name, for directory use.
> +ACX_NONCANONICAL_TARGET
> +GCC_TOPLEV_SUBDIRS
> +
> +# 1.11.1: Require that version of automake.
> +# foreign: Don't require README, INSTALL, NEWS, etc.
> +# no-define: Don't define PACKAGE and VERSION.
> +# -Wall: Issue all automake warnings.
> +# -Wno-portability: Don't warn about constructs supported by GNU make.
> +#    (because GCC requires GNU make anyhow).
> +AM_INIT_AUTOMAKE([1.11.1 foreign no-dist no-define -Wall -Wno-portability])
> +AM_MAINTAINER_MODE
> +
> +LT_INIT([disable-static])
> +AM_PROG_LIBTOOL
> +AC_PROG_CXX
> +
> +visibility=
> +if test "$GXX" = yes; then
> +  visibility=-fvisibility=hidden
> +fi
> +AC_SUBST(visibility)
> +
> +AC_CHECK_DECLS([basename])
> +
> +gcc_version=`cat $srcdir/../gcc/BASE-VER`
> +AC_SUBST(gcc_version)
> +
> +ACX_PROG_CC_WARNING_OPTS([-W -Wall], [WARN_FLAGS])
> +WARN_FLAGS="$WARN_FLAGS -Werror"
> +AC_SUBST(WARN_FLAGS)
> +
> +libsuffix=
> +if test "$GXX" = yes; then
> +  libsuffix=`$CXX -print-multi-os-directory`
> +fi
> +AC_SUBST(libsuffix)
> +
> +# If any of these functions are missing, simply don't bother building
> +# this plugin.
> +GCC_ENABLE_PLUGINS
> +AC_CHECK_FUNC(socketpair, , enable_plugin=no)
> +AC_CHECK_FUNC(select, , enable_plugin=no)
> +AC_CHECK_FUNC(fork, , enable_plugin=no)
> +AM_CONDITIONAL(ENABLE_PLUGIN, test $enable_plugin = yes)
> +
> +AC_CONFIG_FILES([Makefile])
> +AC_OUTPUT
> diff --git a/libcc1/connection.cc b/libcc1/connection.cc
> new file mode 100644
> index 0000000..3e57bbc
> --- /dev/null
> +++ b/libcc1/connection.cc
> @@ -0,0 +1,153 @@
> +/* Connect implementation
> +   Copyright (C) 2014 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>
> +#include <string>
> +#include <unistd.h>
> +#include <sys/types.h>
> +#include <errno.h>
> +#include "marshall.hh"
> +#include "connection.hh"
> +#include "rpc.hh"
> +
> +cc1_plugin::connection::~connection ()
> +{
> +}
> +
> +void
> +cc1_plugin::connection::print (const char *)
> +{
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::connection::send (char c)
> +{
> +  if (write (m_fd, &c, 1) != 1)
> +    return FAIL;
> +  return OK;
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::connection::send (const void *buf, int len)
> +{
> +  if (write (m_fd, buf, len) != len)
> +    return FAIL;
> +  return OK;
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::connection::require (char c)
> +{
> +  char result;
> +
> +  if (read (m_fd, &result, 1) != 1
> +      || result != c)
> +    return FAIL;
> +
> +  return OK;
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::connection::get (void *buf, int len)
> +{
> +  if (read (m_fd, buf, len) != len)
> +    return FAIL;
> +  return OK;
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::connection::do_wait (bool want_result)
> +{
> +  while (true)
> +    {
> +      char result;
> +      fd_set read_set;
> +
> +      FD_ZERO (&read_set);
> +      FD_SET (m_fd, &read_set);
> +      if (m_aux_fd != -1)
> +	FD_SET (m_aux_fd, &read_set);
> +
> +      int nfds = select (FD_SETSIZE, &read_set, NULL, NULL, NULL);
> +      if (nfds == -1)
> +	{
> +	  if (errno == EINTR)
> +	    continue;
> +	  return FAIL;
> +	}
> +
> +      // We have to check the stderr fd first, to avoid a possible
> +      // blocking scenario when do_wait is called reentrantly.  In
> +      // such a call, if we handle the primary fd first, then we may
> +      // re-enter this function, read from gcc's stderr, causing the
> +      // outer invocation of this function to block when trying to
> +      // read.
> +      if (m_aux_fd != -1 && FD_ISSET (m_aux_fd, &read_set))
> +	{
> +	  char buf[1024];
> +	  int n = read (m_aux_fd, buf, sizeof (buf) - 1);
> +	  if (n < 0)
> +	    return FAIL;
> +	  if (n > 0)
> +	    {
> +	      buf[n] = '\0';
> +	      print (buf);
> +	    }
> +	}
> +
> +      if (FD_ISSET (m_fd, &read_set))
> +	{
> +	  int n = read (m_fd, &result, 1);
> +	  if (n == 0)
> +	    return want_result ? FAIL : OK;
> +	  if (n != 1)
> +	    return FAIL;
> +
> +	  switch (result)
> +	    {
> +	    case 'R':
> +	      // The reply is ready; the caller will unmarshall it.
> +	      return want_result ? OK : FAIL;
> +
> +	    case 'Q':
> +	      // While waiting for a reply, the other side made a method
> +	      // call.
> +	      {
> +		// Use an argument_wrapper here to simplify management
> +		// of the string's lifetime.
> +		argument_wrapper<char *> method_name;
> +
> +		if (!method_name.unmarshall (this))
> +		  return FAIL;
> +
> +		callback_ftype *callback
> +		  = m_callbacks.find_callback (method_name);
> +		// The call to CALLBACK is where we may end up in a
> +		// reentrant call.
> +		if (callback == NULL || !callback (this))
> +		  return FAIL;
> +	      }
> +	      break;
> +
> +	    default:
> +	      return FAIL;
> +	    }
> +	}
> +    }
> +}
> diff --git a/libcc1/connection.hh b/libcc1/connection.hh
> new file mode 100644
> index 0000000..242deec
> --- /dev/null
> +++ b/libcc1/connection.hh
> @@ -0,0 +1,114 @@
> +/* Plugin connection declarations
> +   Copyright (C) 2014 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/>.  */
> +
> +#ifndef CC1_PLUGIN_CONNECTION_HH
> +#define CC1_PLUGIN_CONNECTION_HH
> +
> +#include "status.hh"
> +#include "callbacks.hh"
> +
> +namespace cc1_plugin
> +{
> +  // The connection class represents one side of the connection
> +  // between the gdb-side library and the gcc plugin.  It handles the
> +  // low-level details of reading and writing data.
> +  class connection
> +  {
> +  public:
> +
> +    connection (int fd)
> +      : m_fd (fd),
> +	m_aux_fd (-1),
> +	m_callbacks ()

 Personally I'd leave that to the compiler to write, but I guess there's
 something to be said for being explicit.

> +    {
> +    }
> +
> +    connection (int fd, int aux_fd)
> +      : m_fd (fd),
> +	m_aux_fd (aux_fd),
> +	m_callbacks ()
> +    {
> +    }
> +
> +    virtual ~connection ();
> +
> +    // Send a single character.  This is used to introduce various
> +    // higher-level protocol elements.
> +    status send (char c);
> +
> +    // Send data in bulk.
> +    status send (const void *buf, int len);
> +
> +    // Read a single byte from the connection and verify that it
> +    // matches the argument C.
> +    status require (char c);
> +
> +    // Read data in bulk.
> +    status get (void *buf, int len);
> +
> +    // This is called after a query (remote function call) has been
> +    // sent to the remote.  It waits for a response packet.  The
> +    // response character is read before returning.  Any query packets
> +    // sent from the remote while waiting for a response are handled
> +    // by this function.
> +    status wait_for_result ()
> +    {
> +      return do_wait (true);
> +    }
> +
> +    // Read and respond to query packets sent by the remote.  This
> +    // function returns when the connection is closed.
> +    status wait_for_query ()
> +    {
> +      return do_wait (false);
> +    }
> +
> +    // Register a callback with this connection.  NAME is the name of
> +    // the method being registered.  FUNC is the function.  It must
> +    // know how to decode its own arguments.  When a query packet is
> +    // received by one of the wait_* methods, the corresponding
> +    // callback is invoked.
> +    void add_callback (const char *name, callback_ftype *func)
> +    {
> +      m_callbacks.add_callback (name, func);
> +    }
> +
> +    virtual void print (const char *);
> +
> +  private:
> +
> +    // Declared but not defined, to prevent use.
> +    connection (const connection &);
> +    connection &operator= (const connection &);
> +
> +    // Helper function for the wait_* methods.
> +    status do_wait (bool);
> +
> +    // The file descriptor.
> +    int m_fd;
> +
> +    // An auxiliary file descriptor, or -1 if none.
> +    int m_aux_fd;
> +
> +    // Callbacks associated with this connection.
> +    callbacks m_callbacks;
> +  };
> +}
> +
> +#endif // CC1_PLUGIN_CONNECTION_HH
> diff --git a/libcc1/findcomp.cc b/libcc1/findcomp.cc
> new file mode 100644
> index 0000000..f02b1df
> --- /dev/null
> +++ b/libcc1/findcomp.cc
> @@ -0,0 +1,139 @@
> +/* Find the correct compiler.
> +   Copyright (C) 2014 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 <config.h>
> +#include <string>
> +#include <dirent.h>
> +#include <stdlib.h>
> +
> +#include "libiberty.h"
> +#include "xregex.h"
> +#include "findcomp.hh"
> +
> +class scanner
> +{
> +public:
> +
> +  scanner (const std::string &dir)
> +  {
> +    m_dir = opendir (dir.c_str ());
> +  }
> +
> +  ~scanner ()
> +  {
> +    if (m_dir != NULL)
> +      closedir (m_dir);
> +  }
> +
> +  const char *next ()
> +  {
> +    if (m_dir == NULL)
> +      return NULL;
> +
> +    struct dirent *entry = readdir (m_dir);
> +    if (entry == NULL)
> +      return NULL;
> +
> +    return entry->d_name;
> +  }
> +
> +private:
> +
> +  DIR *m_dir;
> +};
> +
> +static bool
> +search_dir (const regex_t &regexp, const std::string &dir, std::string *result)
> +{
> +  scanner scan (dir);
> +  const char *filename;
> +
> +  while ((filename = scan.next ()) != NULL)
> +    {
> +      if (regexec (&regexp, filename, 0, NULL, 0) == 0)
> +	{
> +	  *result = filename;
> +	  return true;
> +	}
> +    }
> +
> +  return false;
> +}
> +
> +class tokenizer
> +{
> +public:
> +
> +  tokenizer (const char *str)
> +    : m_str (str),
> +      m_pos (0)
> +  {
> +  }
> +
> +  bool done () const
> +  {
> +    return m_pos == std::string::npos;
> +  }
> +
> +  std::string next ()
> +  {
> +    std::string::size_type last_pos = m_pos;
> +    std::string::size_type colon = m_str.find(':', last_pos);
> +
> +    std::string result;
> +    if (colon == std::string::npos)
> +      {
> +	m_pos = colon;
> +	result = m_str.substr(last_pos, colon);
> +      }
> +    else
> +      {
> +	m_pos = colon + 1;
> +	result = m_str.substr(last_pos, colon - last_pos);
> +      }
> +    if (result == "")
> +      result = ".";
> +
> +    return result;
> +  }
> +
> +private:
> +
> +  std::string m_str;
> +  std::string::size_type m_pos;
> +};
> +
> +bool
> +find_compiler (const regex_t &regexp, std::string *result)
> +{
> +  const char *cpath = getenv ("PATH");
> +
> +  if (cpath == NULL)
> +    return false;
> +
> +  tokenizer dirs (cpath);
> +  while (!dirs.done ())
> +    {
> +      std::string dir = dirs.next ();
> +      if (search_dir (regexp, dir, result))
> +	return true;
> +    }
> +
> +  return false;
> +}
> diff --git a/libcc1/findcomp.hh b/libcc1/findcomp.hh
> new file mode 100644
> index 0000000..a55a283
> --- /dev/null
> +++ b/libcc1/findcomp.hh
> @@ -0,0 +1,25 @@
> +/* Find the correct compiler.
> +   Copyright (C) 2014 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/>.  */
> +
> +#ifndef CC1_PLUGIN_FINDCOMP_HH
> +#define CC1_PLUGIN_FINDCOMP_HH
> +
> +extern bool find_compiler (const regex_t &regexp, std::string *result);
> +
> +#endif // CC1_PLUGIN_FINDCOMP_HH
> diff --git a/libcc1/libcc1.cc b/libcc1/libcc1.cc
> new file mode 100644
> index 0000000..7d3b9fe
> --- /dev/null
> +++ b/libcc1/libcc1.cc
> @@ -0,0 +1,529 @@
> +/* The library used by gdb.
> +   Copyright (C) 2014 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>
> +#include <vector>
> +#include <string>
> +#include <sys/socket.h>
> +#include <sys/types.h>
> +#include <unistd.h>
> +#include <sys/wait.h>
> +#include <stdio.h>
> +#include <errno.h>
> +#include <sys/stat.h>
> +#include <stdlib.h>
> +#include <sstream>
> +#include "rpc.hh"
> +#include "connection.hh"
> +#include "names.hh"
> +#include "callbacks.hh"
> +#include "gcc-interface.h"
> +#include "libiberty.h"
> +#include "xregex.h"
> +#include "findcomp.hh"
> +#include "compiler-name.h"
> +
> +struct libcc1;
> +
> +class libcc1_connection;
> +
> +// The C compiler context that we hand back to our caller.
> +struct libcc1 : public gcc_c_context
> +{
> +  libcc1 (const gcc_base_vtable *, const gcc_c_fe_vtable *);
> +  ~libcc1 ();
> +
> +  // A convenience function to print something.
> +  void print (const char *str)
> +  {
> +    this->print_function (this->print_datum, str);
> +  }
> +
> +  libcc1_connection *connection;
> +
> +  gcc_c_oracle_function *binding_oracle;
> +  gcc_c_symbol_address_function *address_oracle;
> +  void *oracle_datum;
> +
> +  void (*print_function) (void *datum, const char *message);
> +  void *print_datum;
> +
> +  std::vector<std::string> args;
> +  std::string source_file;
> +};
> +
> +// A local subclass of connection that holds a back-pointer to the
> +// gcc_c_context object that we provide to our caller.
> +class libcc1_connection : public cc1_plugin::connection
> +{
> +public:
> +
> +  libcc1_connection (int fd, int aux_fd, libcc1 *b)
> +    : connection (fd, aux_fd),
> +      back_ptr (b)
> +  {
> +  }
> +
> +  void print (const char *buf)

explicitly mark it as virtual?

> +  {
> +    back_ptr->print (buf);
> +  }
> +
> +  libcc1 *back_ptr;
> +};
> +
> +libcc1::libcc1 (const gcc_base_vtable *v,
> +		const gcc_c_fe_vtable *cv)
> +  : connection (NULL),
> +    binding_oracle (NULL),
> +    address_oracle (NULL),
> +    oracle_datum (NULL),
> +    print_function (NULL),
> +    print_datum (NULL),
> +    args (),
> +    source_file ()
> +{
> +  base.ops = v;
> +  c_ops = cv;
> +}
> +
> +libcc1::~libcc1 ()
> +{
> +  delete connection;
> +}
> +
> +\f
> +
> +// This is a wrapper function that is called by the RPC system and
> +// that then forwards the call to the library user.  Note that the
> +// return value is not used; the type cannot be 'void' due to
> +// limitations in our simple RPC.
> +int
> +call_binding_oracle (cc1_plugin::connection *conn,
> +		     enum gcc_c_oracle_request request,
> +		     const char *identifier)
> +{
> +  libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
> +
> +  self->binding_oracle (self->oracle_datum, self, request, identifier);
> +  return 1;
> +}
> +
> +// This is a wrapper function that is called by the RPC system and
> +// that then forwards the call to the library user.  Note that the
> +// return value is not used; the type cannot be 'void' due to
> +// limitations in our simple RPC.
> +gcc_address

looks like this one probably is used?

> +call_symbol_address (cc1_plugin::connection *conn, const char *identifier)
> +{
> +  libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
> +
> +  return self->address_oracle (self->oracle_datum, self, identifier);
> +}
> +
> +\f
> +
> +static void
> +set_callbacks (struct gcc_c_context *s,
> +	       gcc_c_oracle_function *binding_oracle,
> +	       gcc_c_symbol_address_function *address_oracle,
> +	       void *datum)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +
> +  self->binding_oracle = binding_oracle;
> +  self->address_oracle = address_oracle;
> +  self->oracle_datum = datum;
> +}
> +
> +// Instances of these rpc<> template functions are installed into the
> +// "c_vtable".  These functions are parameterized by type and method
> +// name and forward the call via the connection.
> +
> +template<typename R, const char *&NAME>
> +R rpc (struct gcc_c_context *s)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +  R result;
> +
> +  if (!cc1_plugin::call (self->connection, NAME, &result))
> +    return 0;
> +  return result;
> +}
> +
> +template<typename R, const char *&NAME, typename A>
> +R rpc (struct gcc_c_context *s, A arg)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +  R result;
> +
> +  if (!cc1_plugin::call (self->connection, NAME, &result, arg))
> +    return 0;
> +  return result;
> +}
> +
> +template<typename R, const char *&NAME, typename A1, typename A2>
> +R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +  R result;
> +
> +  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2))
> +    return 0;
> +  return result;
> +}
> +
> +template<typename R, const char *&NAME, typename A1, typename A2, typename A3>
> +R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +  R result;
> +
> +  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3))
> +    return 0;
> +  return result;
> +}
> +
> +template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
> +	 typename A4>
> +R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +  R result;
> +
> +  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
> +			 arg4))
> +    return 0;
> +  return result;
> +}
> +
> +template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
> +	 typename A4, typename A5>
> +R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +  R result;
> +
> +  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
> +			 arg4, arg5))
> +    return 0;
> +  return result;
> +}
> +
> +template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
> +	 typename A4, typename A5, typename A6, typename A7>
> +R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5,
> +       A6 arg6, A7 arg7)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +  R result;
> +
> +  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
> +			 arg4, arg5, arg6, arg7))
> +    return 0;
> +  return result;
> +}
> +
> +static const struct gcc_c_fe_vtable c_vtable =
> +{
> +  GCC_C_FE_VERSION_0,
> +  set_callbacks,
> +
> +#define GCC_METHOD0(R, N) \
> +  rpc<R, cc1_plugin::N>,
> +#define GCC_METHOD1(R, N, A) \
> +  rpc<R, cc1_plugin::N, A>,
> +#define GCC_METHOD2(R, N, A, B) \
> +  rpc<R, cc1_plugin::N, A, B>,
> +#define GCC_METHOD3(R, N, A, B, C) \
> +  rpc<R, cc1_plugin::N, A, B, C>,
> +#define GCC_METHOD4(R, N, A, B, C, D) \
> +  rpc<R, cc1_plugin::N, A, B, C, D>,
> +#define GCC_METHOD5(R, N, A, B, C, D, E) \
> +  rpc<R, cc1_plugin::N, A, B, C, D, E>,
> +#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
> +  rpc<R, cc1_plugin::N, A, B, C, D, E, F, G>,
> +
> +#include "gcc-c-fe.def"
> +
> +#undef GCC_METHOD0
> +#undef GCC_METHOD1
> +#undef GCC_METHOD2
> +#undef GCC_METHOD3
> +#undef GCC_METHOD4
> +#undef GCC_METHOD5
> +#undef GCC_METHOD7
> +};
> +
> +\f
> +
> +// Construct an appropriate regexp to match the compiler name.
> +static std::string
> +make_regexp (const char *triplet_regexp, const char *compiler)
> +{
> +  std::stringstream buf;
> +
> +  buf << "^" << triplet_regexp << "-";
> +
> +  // Quote the compiler name in case it has something funny in it.
> +  for (const char *p = compiler; *p; ++p)
> +    {
> +      switch (*p)
> +	{
> +	case '.':
> +	case '^':
> +	case '$':
> +	case '*':
> +	case '+':
> +	case '?':
> +	case '(':
> +	case ')':
> +	case '[':
> +	case '{':
> +	case '\\':
> +	case '|':
> +	  buf << '\\';
> +	  break;
> +	}
> +      buf << *p;
> +    }
> +  buf << "$";
> +
> +  return buf.str ();
> +}
> +
> +static char *
> +libcc1_set_arguments (struct gcc_base_context *s,
> +		      const char *triplet_regexp,
> +		      int argc, char **argv)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +  regex_t triplet;
> +  int code;
> +
> +  std::string rx = make_regexp (triplet_regexp, COMPILER_NAME);
> +  code = regcomp (&triplet, rx.c_str (), REG_EXTENDED | REG_NOSUB);
> +  if (code != 0)
> +    {
> +      size_t len = regerror (code, &triplet, NULL, 0);
> +      char err[len];
> +
> +      regerror (code, &triplet, err, len);
> +
> +      return concat ("Could not compile regexp \"",
> +		     rx.c_str (),
> +		     "\": ",
> +		     err,
> +		     (char *) NULL);
> +    }
> +
> +  std::string compiler;
> +  if (!find_compiler (triplet, &compiler))
> +    {
> +      regfree (&triplet);
> +      return concat ("Could not find a compiler matching \"",
> +		     rx.c_str (),
> +		     "\"",
> +		     (char *) NULL);
> +    }
> +  regfree (&triplet);
> +
> +  self->args.push_back (compiler);
> +
> +  for (int i = 0; i < argc; ++i)
> +    self->args.push_back (argv[i]);
> +
> +  return NULL;
> +}
> +
> +static void
> +libcc1_set_source_file (struct gcc_base_context *s,
> +			const char *file)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +
> +  self->source_file = file;
> +}
> +
> +static void
> +libcc1_set_print_callback (struct gcc_base_context *s,
> +			   void (*print_function) (void *datum,
> +						   const char *message),
> +			   void *datum)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +
> +  self->print_function = print_function;
> +  self->print_datum = datum;
> +}
> +
> +static int
> +fork_exec (libcc1 *self, char **argv, int spair_fds[2], int stderr_fds[2])
> +{
> +  pid_t child_pid = fork ();
> +
> +  if (child_pid == -1)
> +    {
> +      close (spair_fds[0]);
> +      close (spair_fds[1]);
> +      close (stderr_fds[0]);
> +      close (stderr_fds[1]);
> +      return 0;
> +    }
> +
> +  if (child_pid == 0)
> +    {
> +      // Child.
> +      dup2 (stderr_fds[1], 1);
> +      dup2 (stderr_fds[1], 2);
> +      close (stderr_fds[0]);
> +      close (stderr_fds[1]);
> +      close (spair_fds[0]);
> +
> +      execvp (argv[0], argv);
> +      _exit (127);
> +    }
> +  else
> +    {
> +      // Parent.
> +      close (spair_fds[1]);
> +      close (stderr_fds[1]);
> +
> +      cc1_plugin::status result = cc1_plugin::FAIL;
> +      if (self->connection->send ('H')
> +	  && ::cc1_plugin::marshall (self->connection, GCC_C_FE_VERSION_0))
> +	result = self->connection->wait_for_query ();
> +
> +      close (spair_fds[0]);
> +      close (stderr_fds[0]);
> +
> +      while (true)
> +	{
> +	  int status;
> +
> +	  if (waitpid (child_pid, &status, 0) == -1)
> +	    {
> +	      if (errno != EINTR)
> +		return 0;
> +	    }
> +
> +	  if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
> +	    return 0;
> +	  break;
> +	}
> +
> +      if (!result)
> +	return 0;
> +      return 1;
> +    }
> +}
> +
> +static int
> +libcc1_compile (struct gcc_base_context *s,
> +		const char *filename,
> +		int verbose)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +
> +  int fds[2];
> +  if (socketpair (AF_LOCAL, SOCK_STREAM, 0, fds) != 0)
> +    {
> +      self->print ("could not create socketpair\n");
> +      return 0;
> +    }
> +
> +  int stderr_fds[2];
> +  if (pipe (stderr_fds) != 0)
> +    {
> +      self->print ("could not create pipe\n");
> +      close (fds[0]);
> +      close (fds[1]);
> +      return 0;
> +    }
> +
> +  self->args.push_back ("-fplugin=libcc1plugin");
> +  char buf[100];
> +  if (snprintf (buf, sizeof (buf), "-fplugin-arg-libcc1plugin-fd=%d", fds[1])
> +      >= (long) sizeof (buf))
> +    abort ();
> +  self->args.push_back (buf);
> +
> +  self->args.push_back (self->source_file);
> +  self->args.push_back ("-c");
> +  self->args.push_back ("-o");
> +  self->args.push_back (filename);
> +  if (verbose)
> +    self->args.push_back ("-v");
> +
> +  self->connection = new libcc1_connection (fds[0], stderr_fds[0], self);
> +
> +  cc1_plugin::callback_ftype *fun
> +    = cc1_plugin::callback<int,
> +			   enum gcc_c_oracle_request,
> +			   const char *,
> +			   call_binding_oracle>;
> +  self->connection->add_callback ("binding_oracle", fun);
> +
> +  fun = cc1_plugin::callback<gcc_address,
> +			     const char *,
> +			     call_symbol_address>;
> +  self->connection->add_callback ("address_oracle", fun);
> +
> +  char **argv = new (std::nothrow) char *[self->args.size () + 1];

What's the point of making this no throw? you don't null check it so
you'll crash anyway afaict.

> +  for (unsigned int i = 0; i < self->args.size (); ++i)
> +    argv[i] = const_cast<char *> (self->args[i].c_str ());
> +  argv[self->args.size ()] = NULL;
> +
> +  return fork_exec (self, argv, fds, stderr_fds);
> +}
> +
> +static void
> +libcc1_destroy (struct gcc_base_context *s)
> +{
> +  libcc1 *self = (libcc1 *) s;
> +
> +  delete self;
> +}
> +
> +static const struct gcc_base_vtable vtable =
> +{
> +  GCC_FE_VERSION_0,
> +  libcc1_set_arguments,
> +  libcc1_set_source_file,
> +  libcc1_set_print_callback,
> +  libcc1_compile,
> +  libcc1_destroy
> +};
> +
> +extern "C" gcc_c_fe_context_function gcc_c_fe_context;
> +
> +#ifdef __GNUC__
> +#pragma GCC visibility push(default)
> +#endif
> +
> +extern "C"
> +struct gcc_c_context *
> +gcc_c_fe_context (enum gcc_base_api_version base_version,
> +		  enum gcc_c_api_version c_version)
> +{
> +  if (base_version != GCC_FE_VERSION_0 || c_version != GCC_C_FE_VERSION_0)
> +    return NULL;
> +
> +  return new libcc1 (&vtable, &c_vtable);
> +}
> diff --git a/libcc1/libcc1.sym b/libcc1/libcc1.sym
> new file mode 100644
> index 0000000..86b1e3e
> --- /dev/null
> +++ b/libcc1/libcc1.sym
> @@ -0,0 +1 @@
> +gcc_c_fe_context
> diff --git a/libcc1/libcc1plugin.sym b/libcc1/libcc1plugin.sym
> new file mode 100644
> index 0000000..05d0f7b
> --- /dev/null
> +++ b/libcc1/libcc1plugin.sym
> @@ -0,0 +1,2 @@
> +plugin_init
> +plugin_is_GPL_compatible
> diff --git a/libcc1/marshall.cc b/libcc1/marshall.cc
> new file mode 100644
> index 0000000..9119de6
> --- /dev/null
> +++ b/libcc1/marshall.cc
> @@ -0,0 +1,166 @@
> +/* Marshalling and unmarshalling.
> +   Copyright (C) 2014 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>
> +#include <new>
> +#include <string.h>
> +#include "marshall.hh"
> +#include "connection.hh"
> +
> +cc1_plugin::status
> +cc1_plugin::unmarshall_check (connection *conn, unsigned long long check)
> +{
> +  unsigned long long r;
> +
> +  if (!unmarshall (conn, &r))
> +    return FAIL;
> +  return check == r ? OK : FAIL;
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::marshall_intlike (connection *conn, unsigned long long val)
> +{
> +  if (!conn->send ('i'))
> +    return FAIL;
> +  return conn->send (&val, sizeof (val));
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::unmarshall_intlike (connection *conn, unsigned long long *result)
> +{
> +  if (!conn->require ('i'))
> +    return FAIL;
> +  return conn->get (result, sizeof (*result));
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::unmarshall (connection *conn, enum gcc_c_symbol_kind *result)
> +{
> +  protocol_int p;
> +  if (!unmarshall_intlike (conn, &p))
> +    return FAIL;
> +  *result = (enum gcc_c_symbol_kind) p;
> +  return OK;
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::unmarshall (connection *conn, enum gcc_c_oracle_request *result)
> +{
> +  protocol_int p;
> +  if (!unmarshall_intlike (conn, &p))
> +    return FAIL;
> +  *result = (enum gcc_c_oracle_request) p;
> +  return OK;
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::unmarshall (connection *conn, enum gcc_qualifiers *result)
> +{
> +  protocol_int p;
> +  if (!unmarshall_intlike (conn, &p))
> +    return FAIL;
> +  *result = (enum gcc_qualifiers) p;
> +  return OK;
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::marshall (connection *conn, const char *str)
> +{
> +  if (!conn->send ('s'))
> +    return FAIL;
> +
> +  unsigned long long len = str == NULL ? -1ULL : strlen (str);
> +  if (!conn->send (&len, sizeof (len)))
> +    return FAIL;
> +
> +  if (str == NULL)
> +    return OK;
> +
> +  return conn->send (str, len);
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::unmarshall (connection *conn, char **result)
> +{
> +  unsigned long long len;
> +
> +  if (!conn->require ('s'))
> +    return FAIL;
> +  if (!conn->get (&len, sizeof (len)))
> +    return FAIL;
> +
> +  if (len == -1ULL)
> +    {
> +      *result = NULL;
> +      return OK;
> +    }
> +
> +  char *str = new (std::nothrow) char[len + 1];
It'd be really nice if the type of the out arg forced the caller to deal
with deleting the string like unique_ptr<char>, it would be even nicer
if you could stick a random buffer in a std::string, but I guess you
can't :(

Also where does this array get deleted?

> +  if (str == NULL)
> +    return FAIL;
> +
> +  if (!conn->get (str, len))
> +    {
> +      delete[] str;
> +      return FAIL;
> +    }
> +
> +  str[len] = '\0';
> +  *result = str;
> +
> +  return OK;
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::marshall (connection *conn, const gcc_type_array *a)
> +{
> +  if (!conn->send ('a'))
> +    return FAIL;
> +
> +  unsigned long long r = a->n_elements;
> +  if (!conn->send (&r, sizeof (r)))
> +    return FAIL;
> +
> +  return conn->send (a->elements, r * sizeof (a->elements[0]));
> +}
> +
> +cc1_plugin::status
> +cc1_plugin::unmarshall (connection *conn, gcc_type_array **result)
> +{
> +  unsigned long long len;
> +
> +  if (!conn->require ('a'))
> +    return FAIL;
> +  if (!conn->get (&len, sizeof (len)))
> +    return FAIL;
> +
> +  *result = new gcc_type_array;
> +
> +  (*result)->n_elements = len;
> +  (*result)->elements = new gcc_type[len];
> +
> +  if (!conn->get ((*result)->elements, len * sizeof ((*result)->elements[0])))
> +    {
> +      delete[] (*result)->elements;
> +      delete *result;
> +      return FAIL;
> +    }
> +
> +  return OK;
> +}
> diff --git a/libcc1/marshall.hh b/libcc1/marshall.hh
> new file mode 100644
> index 0000000..3f936e7
> --- /dev/null
> +++ b/libcc1/marshall.hh
> @@ -0,0 +1,93 @@
> +/* Marshalling and unmarshalling.
> +   Copyright (C) 2014 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/>.  */
> +
> +#ifndef CC1_PLUGIN_MARSHALL_HH
> +#define CC1_PLUGIN_MARSHALL_HH
> +
> +#include "status.hh"
> +#include "gcc-c-interface.h"
> +
> +namespace cc1_plugin
> +{
> +  class connection;
> +
> +  // Only a single kind of integer is ever sent over the wire, and
> +  // this is it.
> +  typedef unsigned long long protocol_int;
> +
> +  // Read an integer from the connection and verify that it has the
> +  // value V.
> +  status unmarshall_check (connection *, protocol_int v);
> +
> +  // Write an integer, prefixed with the integer type marker, to the
> +  // connection.
> +  status marshall_intlike (connection *, protocol_int);
> +
> +  // Read a type marker from the connection and verify that it is an
> +  // integer type marker.  If not, return FAIL.  If so, read an
> +  // integer store it in the out argument.
> +  status unmarshall_intlike (connection *, protocol_int *);
> +
> +  // A template function that can handle marshalling various integer
> +  // objects to the connection.
> +  template<typename T>
> +  status marshall (connection *conn, T scalar)
> +  {
> +    return marshall_intlike (conn, scalar);
> +  }
> +
> +  // A template function that can handle unmarshalling various integer
> +  // objects from the connection.  Note that this can't be
> +  // instantiated for enum types.  Note also that there's no way at
> +  // the protocol level to distinguish different int types.
> +  template<typename T>
> +  status unmarshall (connection *conn, T *scalar)
> +  {
> +    protocol_int result;
> +
> +    if (!unmarshall_intlike (conn, &result))
> +      return FAIL;
> +    *scalar = result;
> +    return OK;
> +  }
> +
> +  // Unmarshallers for some specific enum types.  With C++11 we
> +  // wouldn't need these, as we could add type traits to the scalar
> +  // unmarshaller.
> +  status unmarshall (connection *, enum gcc_c_symbol_kind *);
> +  status unmarshall (connection *, enum gcc_qualifiers *);
> +  status unmarshall (connection *, enum gcc_c_oracle_request *);
> +
> +  // Send a string type marker followed by a string.
> +  status marshall (connection *, const char *);
> +
> +  // Read a string type marker followed by a string.  The caller is
> +  // responsible for freeing the resulting string using 'delete[]'.
> +  status unmarshall (connection *, char **);
> +
> +  // Send a gcc_type_array marker followed by the array.
> +  status marshall (connection *, const gcc_type_array *);
> +
> +  // Read a gcc_type_array marker, followed by a gcc_type_array.  The
> +  // resulting array must be freed by the caller, using 'delete[]' on
> +  // the elements, and 'delete' on the array object itself.
> +  status unmarshall (connection *, struct gcc_type_array **);
> +};
> +
> +#endif // CC1_PLUGIN_MARSHALL_HH
> diff --git a/libcc1/names.cc b/libcc1/names.cc
> new file mode 100644
> index 0000000..5ddfa7b
> --- /dev/null
> +++ b/libcc1/names.cc
> @@ -0,0 +1,46 @@
> +/* String definitions.
> +   Copyright (C) 2014 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>
> +#include "names.hh"
> +
> +#define GCC_METHOD0(R, N) \
> +  const char *cc1_plugin::N = # N;
> +#define GCC_METHOD1(R, N, A) \
> +  const char *cc1_plugin::N = # N;
> +#define GCC_METHOD2(R, N, A, B) \
> +  const char *cc1_plugin::N = # N;
> +#define GCC_METHOD3(R, N, A, B, C) \
> +  const char *cc1_plugin::N = # N;
> +#define GCC_METHOD4(R, N, A, B, C, D) \
> +  const char *cc1_plugin::N = # N;
> +#define GCC_METHOD5(R, N, A, B, C, D, E) \
> +  const char *cc1_plugin::N = # N;
> +#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
> +  const char *cc1_plugin::N = # N;
> +
> +#include "gcc-c-fe.def"
> +
> +#undef GCC_METHOD0
> +#undef GCC_METHOD1
> +#undef GCC_METHOD2
> +#undef GCC_METHOD3
> +#undef GCC_METHOD4
> +#undef GCC_METHOD5
> +#undef GCC_METHOD7
> diff --git a/libcc1/names.hh b/libcc1/names.hh
> new file mode 100644
> index 0000000..9bda8d5
> --- /dev/null
> +++ b/libcc1/names.hh
> @@ -0,0 +1,55 @@
> +/* String declarations.
> +   Copyright (C) 2014 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/>.  */
> +
> +#ifndef CC1_PLUGIN_NAMES_HH
> +#define CC1_PLUGIN_NAMES_HH
> +
> +namespace cc1_plugin
> +{
> +  // This code defines global string constants, one for each method in
> +  // gcc-c-fe.def.  This is needed so that they can be used as
> +  // template arguments elsewhere.
> +
> +#define GCC_METHOD0(R, N) \
> +  extern const char *N;
> +#define GCC_METHOD1(R, N, A) \
> +  extern const char *N;
> +#define GCC_METHOD2(R, N, A, B) \
> +  extern const char *N;
> +#define GCC_METHOD3(R, N, A, B, C) \
> +  extern const char *N;
> +#define GCC_METHOD4(R, N, A, B, C, D) \
> +  extern const char *N;
> +#define GCC_METHOD5(R, N, A, B, C, D, E) \
> +  extern const char *N;
> +#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
> +  extern const char *N;
> +
> +#include "gcc-c-fe.def"
> +
> +#undef GCC_METHOD0
> +#undef GCC_METHOD1
> +#undef GCC_METHOD2
> +#undef GCC_METHOD3
> +#undef GCC_METHOD4
> +#undef GCC_METHOD5
> +#undef GCC_METHOD7
> +};
> +
> +#endif // CC1_PLUGIN_NAMES_HH
> diff --git a/libcc1/plugin.cc b/libcc1/plugin.cc
> new file mode 100644
> index 0000000..965e803
> --- /dev/null
> +++ b/libcc1/plugin.cc
> @@ -0,0 +1,922 @@
> +/* Library interface to C front end
> +   Copyright (C) 2014 Free Software Foundation, Inc.
> +
> +   Parser actions based on the old Bison parser; structure somewhat
> +   influenced by and fragments based on the C++ parser.
> +
> +   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 "gcc-interface.h"
> +#include "tree-core.h"
> +#include "wide-int.h"
> +#include "stor-layout.h"
> +#include "c-tree.h"
> +#include "toplev.h"
> +#include "timevar.h"
> +#include "hash-table.h"
> +#include "tm.h"
> +#include "c-family/c-pragma.h"
> +#include "c-lang.h"
> +#include "diagnostic.h"
> +#include "langhooks.h"
> +#include "langhooks-def.h"
> +
> +#include "callbacks.hh"
> +#include "connection.hh"
> +#include "rpc.hh"
> +
> +#include <string>
> +
> +#ifdef __GNUC__
> +#pragma GCC visibility push(default)
> +#endif
> +int plugin_is_GPL_compatible;
> +#ifdef __GNUC__
> +#pragma GCC visibility pop
> +#endif
> +
> +\f
> +
> +// 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);
> +}
> +
> +\f
> +
> +static unsigned long long
> +convert_out (tree t)
> +{
> +  return (unsigned long long) (uintptr_t) t;
> +}
> +
> +static tree
> +convert_in (unsigned long long v)
> +{
> +  return (tree) (uintptr_t) v;
> +}
> +
> +\f
> +
> +struct decl_addr_value
> +{
> +  tree decl;
> +  tree address;
> +};
> +
> +struct decl_addr_hasher : typed_free_remove<decl_addr_value>
> +{
> +  typedef decl_addr_value value_type;
> +  typedef decl_addr_value compare_type;
> +
> +  static inline hashval_t hash (const value_type *);
> +  static inline bool equal (const value_type *, const compare_type *);
> +};
> +
> +inline hashval_t
> +decl_addr_hasher::hash (const value_type *e)
> +{
> +  return IDENTIFIER_HASH_VALUE (DECL_NAME (e->decl));
> +}
> +
> +inline bool
> +decl_addr_hasher::equal (const value_type *p1, const compare_type *p2)
> +{
> +  return p1->decl == p2->decl;
> +}
> +
> +\f
> +
> +struct string_hasher : typed_noop_remove<char>
> +{
> +  typedef char value_type;
> +  typedef char compare_type;
> +
> +  static inline hashval_t hash (const value_type *s)
> +  {
> +    return htab_hash_string (s);
> +  }
> +
> +  static inline bool equal (const value_type *p1, const value_type *p2)
> +  {
> +    return strcmp (p1, p2) == 0;
> +  }
> +};
> +
> +\f
> +
> +// A wrapper for pushdecl that doesn't let gdb have a chance to
> +// instantiate a symbol.
> +
> +static void
> +pushdecl_safe (tree decl)
> +{
> +  void (*save) (enum c_oracle_request, tree identifier);
> +
> +  save = c_binding_oracle;
> +  c_binding_oracle = NULL;
> +  pushdecl (decl);
> +  c_binding_oracle = save;
> +}
> +
> +\f
> +
> +struct plugin_context : public cc1_plugin::connection
> +{
> +  plugin_context (int fd);
> +
> +  // Map decls to addresses.
> +  hash_table<decl_addr_hasher> address_map;
> +
> +  // A collection of trees that are preserved for the GC.
> +  hash_table< pointer_hash<tree_node> > preserved;
> +
> +  // File name cache.
> +  hash_table<string_hasher> file_names;
> +
> +  // Perform GC marking.
> +  void mark ();
> +
> +  // Preserve a tree during the plugin's operation.
> +  tree preserve (tree t)
> +  {
> +    tree_node **slot = preserved.find_slot (t, INSERT);
> +    *slot = t;
> +    return t;
> +  }
> +
> +  source_location get_source_location (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);
> +    source_location loc = linemap_line_start (line_table, line_number, 0);
> +    linemap_add (line_table, LC_LEAVE, false, NULL, 0);
> +    return loc;
> +  }
> +
> +private:
> +
> +  // Add a file name to FILE_NAMES and return the canonical copy.
> +  const char *intern_filename (const char *filename)
> +  {
> +    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;
> +  }
> +};
> +
> +static plugin_context *current_context;
> +
> +\f
> +
> +plugin_context::plugin_context (int fd)
> +  : cc1_plugin::connection (fd),
> +    address_map (),
> +    preserved (),
> +    file_names ()
> +{
> +  address_map.create (20);
> +  preserved.create (20);
> +  file_names.create (20);
> +}
> +
> +void
> +plugin_context::mark ()
> +{
> +  for (hash_table<decl_addr_hasher>::iterator it = address_map.begin ();
> +       it != address_map.end ();
> +       ++it)
> +    {
> +      ggc_mark ((*it).decl);
> +      ggc_mark ((*it).address);
> +    }
> +
> +  for (hash_table< pointer_hash<tree_node> >::iterator it = preserved.begin ();
> +       it != preserved.end ();
> +       ++it)
> +    ggc_mark (&*it);
> +}
> +
> +static void
> +plugin_binding_oracle (enum c_oracle_request kind, tree identifier)
> +{
> +  enum gcc_c_oracle_request request;
> +
> +  gcc_assert (current_context != NULL);
> +
> +  switch (kind)
> +    {
> +    case C_ORACLE_SYMBOL:
> +      request = GCC_C_ORACLE_SYMBOL;
> +      break;
> +    case C_ORACLE_TAG:
> +      request = GCC_C_ORACLE_TAG;
> +      break;
> +    case C_ORACLE_LABEL:
> +      request = GCC_C_ORACLE_LABEL;
> +      break;
> +    default:
> +      abort ();
> +    }
> +
> +  int ignore;
> +  cc1_plugin::call (current_context, "binding_oracle", &ignore,
> +		    request, IDENTIFIER_POINTER (identifier));
> +}
> +
> +static void
> +plugin_pragma_user_expression (cpp_reader *)
> +{
> +  c_binding_oracle = plugin_binding_oracle;
> +}
> +
> +static void
> +plugin_init_extra_pragmas (void *, void *)
> +{
> +  c_register_pragma ("GCC", "user_expression", plugin_pragma_user_expression);
> +}
> +
> +\f
> +
> +// Maybe rewrite a decl to its address.
> +static tree
> +address_rewriter (tree *in, int *walk_subtrees, void *arg)
> +{
> +  plugin_context *ctx = (plugin_context *) arg;
> +
> +  if (!DECL_P (*in) || DECL_NAME (*in) == NULL_TREE)
> +    return NULL_TREE;
> +
> +  decl_addr_value value;
> +  value.decl = *in;
> +  decl_addr_value *found_value = ctx->address_map.find (&value);
> +  if (found_value != NULL)
> +    {
> +      // At this point we don't need VLA sizes for gdb-supplied
> +      // variables, and having them here confuses later passes, so we
> +      // drop them.
> +      if (C_TYPE_VARIABLE_SIZE (TREE_TYPE (*in)))
> +	{
> +	  TREE_TYPE (*in)
> +	    = build_array_type_nelts (TREE_TYPE (TREE_TYPE (*in)), 1);
> +	  DECL_SIZE (*in) = TYPE_SIZE (TREE_TYPE (*in));
> +	  DECL_SIZE_UNIT (*in) = TYPE_SIZE_UNIT (TREE_TYPE (*in));
> +	}
> +    }
> +  else if (DECL_IS_BUILTIN (*in))
> +    {
> +      gcc_address address;
> +
> +      if (!cc1_plugin::call (ctx, "address_oracle", &address,
> +			     IDENTIFIER_POINTER (DECL_NAME (*in))))
> +	return NULL_TREE;
> +      if (address == 0)
> +	return NULL_TREE;
> +
> +      // Insert the decl into the address map in case it is referenced
> +      // again.
> +      value.address = build_int_cst_type (ptr_type_node, address);
> +      decl_addr_value **slot = ctx->address_map.find_slot (&value, INSERT);
> +      gcc_assert (*slot == NULL);
> +      *slot
> +	= static_cast<decl_addr_value *> (xmalloc (sizeof (decl_addr_value)));
> +      **slot = value;
> +      found_value = *slot;
> +    }
> +  else
> +    return NULL_TREE;
> +
> +  if (found_value->address != error_mark_node)
> +    {
> +      // We have an address for the decl, so rewrite the tree.
> +      tree ptr_type = build_pointer_type (TREE_TYPE (*in));
> +      *in = fold_build1 (INDIRECT_REF, TREE_TYPE (*in),
> +			 fold_build1 (CONVERT_EXPR, ptr_type,
> +				      found_value->address));
> +    }
> +
> +  *walk_subtrees = 0;
> +
> +  return NULL_TREE;
> +}
> +
> +// When generating code for gdb, we want to be able to use absolute
> +// addresses to refer to otherwise external objects that gdb knows
> +// about.  gdb passes in these addresses when building decls, and then
> +// before gimplification we go through the trees, rewriting uses to
> +// the equivalent of "*(TYPE *) ADDR".
> +static void
> +rewrite_decls_to_addresses (void *function_in, void *)
> +{
> +  tree function = (tree) function_in;
> +
> +  // Do nothing if we're not in gdb.
> +  if (current_context == NULL)
> +    return;
> +
> +  walk_tree (&DECL_SAVED_TREE (function), address_rewriter, current_context,
> +	     NULL);
> +}
> +
> +\f
> +
> +gcc_decl
> +plugin_build_decl (cc1_plugin::connection *self,
> +		   const char *name,
> +		   enum gcc_c_symbol_kind sym_kind,
> +		   gcc_type sym_type_in,
> +		   const char *substitution_name,
> +		   gcc_address address,
> +		   const char *filename,
> +		   unsigned int line_number)
> +{
> +  plugin_context *ctx = static_cast<plugin_context *> (self);
> +  tree identifier = get_identifier (name);
> +  enum tree_code code;
> +  tree decl;
> +  tree sym_type = convert_in (sym_type_in);
> +
> +  switch (sym_kind)
> +    {
> +    case GCC_C_SYMBOL_FUNCTION:
> +      code = FUNCTION_DECL;
> +      break;
> +
> +    case GCC_C_SYMBOL_VARIABLE:
> +      code = VAR_DECL;
> +      break;
> +
> +    case GCC_C_SYMBOL_TYPEDEF:
> +      code = TYPE_DECL;
> +      break;
> +
> +    case GCC_C_SYMBOL_LABEL:
> +      // FIXME: we aren't ready to handle labels yet.
> +      // It isn't clear how to translate them properly
> +      // and in any case a "goto" isn't likely to work.
> +      return convert_out (error_mark_node);
> +
> +    default:
> +      abort ();
> +    }
> +
> +  source_location loc = ctx->get_source_location (filename, line_number);
> +
> +  decl = build_decl (loc, code, identifier, sym_type);
> +  TREE_USED (decl) = 1;
> +  TREE_ADDRESSABLE (decl) = 1;
> +
> +  if (sym_kind != GCC_C_SYMBOL_TYPEDEF)
> +    {
> +      decl_addr_value value;
> +
> +      value.decl = decl;
> +      if (substitution_name != NULL)
> +	{
> +	  // If the translator gave us a name without a binding,
> +	  // we can just substitute error_mark_node, since we know the
> +	  // translator will be reporting an error anyhow.
> +	  value.address
> +	    = lookup_name (get_identifier (substitution_name));
> +	  if (value.address == NULL_TREE)
> +	    value.address = error_mark_node;
> +	}
> +      else
> +	value.address = build_int_cst_type (ptr_type_node, address);
> +      decl_addr_value **slot = ctx->address_map.find_slot (&value, INSERT);
> +      gcc_assert (*slot == NULL);
> +      *slot
> +	= static_cast<decl_addr_value *> (xmalloc (sizeof (decl_addr_value)));
> +      **slot = value;
> +    }
> +
> +  return convert_out (ctx->preserve (decl));
> +}
> +
> +int
> +plugin_bind (cc1_plugin::connection *,
> +	     gcc_decl decl_in, int is_global)
> +{
> +  tree decl = convert_in (decl_in);
> +  c_bind (DECL_SOURCE_LOCATION (decl), decl, is_global);
> +  rest_of_decl_compilation (decl, is_global, 0);
> +  return 1;
> +}
> +
> +int
> +plugin_tagbind (cc1_plugin::connection *self,
> +		const char *name, gcc_type tagged_type,
> +		const char *filename, unsigned int line_number)
> +{
> +  plugin_context *ctx = static_cast<plugin_context *> (self);
> +  c_pushtag (ctx->get_source_location (filename, line_number),
> +	     get_identifier (name), convert_in (tagged_type));
> +  return 1;
> +}
> +
> +gcc_type
> +plugin_build_pointer_type (cc1_plugin::connection *,
> +			   gcc_type base_type)
> +{
> +  // No need to preserve a pointer type as the base type is preserved.
> +  return convert_out (build_pointer_type (convert_in (base_type)));
> +}
> +
> +gcc_type
> +plugin_build_record_type (cc1_plugin::connection *self)
> +{
> +  plugin_context *ctx = static_cast<plugin_context *> (self);
> +  return convert_out (ctx->preserve (make_node (RECORD_TYPE)));
> +}
> +
> +gcc_type
> +plugin_build_union_type (cc1_plugin::connection *self)
> +{
> +  plugin_context *ctx = static_cast<plugin_context *> (self);
> +  return convert_out (ctx->preserve (make_node (UNION_TYPE)));
> +}
> +
> +int
> +plugin_build_add_field (cc1_plugin::connection *,
> +			gcc_type record_or_union_type_in,
> +			const char *field_name,
> +			gcc_type field_type_in,
> +			unsigned long bitsize,
> +			unsigned long bitpos)
> +{
> +  tree record_or_union_type = convert_in (record_or_union_type_in);
> +  tree field_type = convert_in (field_type_in);
> +
> +  gcc_assert (TREE_CODE (record_or_union_type) == RECORD_TYPE
> +	      || TREE_CODE (record_or_union_type) == UNION_TYPE);
> +
> +  /* Note that gdb does not preserve the location of field decls, so
> +     we can't provide a decent location here.  */
> +  tree decl = build_decl (BUILTINS_LOCATION, FIELD_DECL,
> +			  get_identifier (field_name), field_type);
> +  DECL_FIELD_CONTEXT (decl) = record_or_union_type;
> +
> +  if (TREE_CODE (field_type) == INTEGER_TYPE
> +      && TYPE_PRECISION (field_type) != bitsize)
> +    {
> +      DECL_BIT_FIELD_TYPE (decl) = field_type;
> +      TREE_TYPE (decl)
> +	= c_build_bitfield_integer_type (bitsize, TYPE_UNSIGNED (field_type));
> +    }
> +
> +  DECL_MODE (decl) = TYPE_MODE (TREE_TYPE (decl));
> +
> +  // There's no way to recover this from DWARF.
> +  SET_DECL_OFFSET_ALIGN (decl, TYPE_PRECISION (pointer_sized_int_node));
> +
> +  tree pos = bitsize_int (bitpos);
> +  pos_from_bit (&DECL_FIELD_OFFSET (decl), &DECL_FIELD_BIT_OFFSET (decl),
> +		DECL_OFFSET_ALIGN (decl), pos);
> +
> +  DECL_SIZE (decl) = bitsize_int (bitsize);
> +  DECL_SIZE_UNIT (decl) = size_int ((bitsize + BITS_PER_UNIT - 1)
> +				    / BITS_PER_UNIT);
> +
> +  DECL_CHAIN (decl) = TYPE_FIELDS (record_or_union_type);
> +  TYPE_FIELDS (record_or_union_type) = decl;
> +
> +  return 1;
> +}
> +
> +int
> +plugin_finish_record_or_union (cc1_plugin::connection *,
> +			       gcc_type record_or_union_type_in,
> +			       unsigned long size_in_bytes)
> +{
> +  tree record_or_union_type = convert_in (record_or_union_type_in);
> +
> +  gcc_assert (TREE_CODE (record_or_union_type) == RECORD_TYPE
> +	      || TREE_CODE (record_or_union_type) == UNION_TYPE);
> +
> +  /* We built the field list in reverse order, so fix it now.  */
> +  TYPE_FIELDS (record_or_union_type)
> +    = nreverse (TYPE_FIELDS (record_or_union_type));
> +
> +  if (TREE_CODE (record_or_union_type) == UNION_TYPE)
> +    {
> +      /* Unions can just be handled by the generic code.  */
> +      layout_type (record_or_union_type);
> +    }
> +  else
> +    {
> +      // FIXME there's no way to get this from DWARF,
> +      // or even, it seems, a particularly good way to deduce it.
> +      TYPE_ALIGN (record_or_union_type)
> +	= TYPE_PRECISION (pointer_sized_int_node);
> +
> +      TYPE_SIZE (record_or_union_type) = bitsize_int (size_in_bytes
> +						      * BITS_PER_UNIT);
> +      TYPE_SIZE_UNIT (record_or_union_type) = size_int (size_in_bytes);
> +
> +      compute_record_mode (record_or_union_type);
> +      finish_bitfield_layout (record_or_union_type);
> +      // FIXME we have no idea about TYPE_PACKED
> +    }
> +
> +  return 1;
> +}
> +
> +gcc_type
> +plugin_build_enum_type (cc1_plugin::connection *self,
> +			gcc_type underlying_int_type_in)
> +{
> +  tree underlying_int_type = convert_in (underlying_int_type_in);
> +
> +  if (underlying_int_type == error_mark_node)
> +    return convert_out (error_mark_node);
> +
> +  tree result = make_node (ENUMERAL_TYPE);
> +
> +  TYPE_PRECISION (result) = TYPE_PRECISION (underlying_int_type);
> +  TYPE_UNSIGNED (result) = TYPE_UNSIGNED (underlying_int_type);
> +
> +  plugin_context *ctx = static_cast<plugin_context *> (self);
> +  return convert_out (ctx->preserve (result));
> +}
> +
> +int
> +plugin_build_add_enum_constant (cc1_plugin::connection *,
> +				gcc_type enum_type_in,
> +				const char *name,
> +				unsigned long value)
> +{
> +  tree cst, decl, cons;
> +  tree enum_type = convert_in (enum_type_in);
> +
> +  gcc_assert (TREE_CODE (enum_type) == ENUMERAL_TYPE);
> +
> +  cst = build_int_cst (enum_type, value);
> +  /* Note that gdb does not preserve the location of enum constants,
> +     so we can't provide a decent location here.  */
> +  decl = build_decl (BUILTINS_LOCATION, CONST_DECL,
> +		     get_identifier (name), enum_type);
> +  DECL_INITIAL (decl) = cst;
> +  pushdecl_safe (decl);
> +
> +  cons = tree_cons (DECL_NAME (decl), cst, TYPE_VALUES (enum_type));
> +  TYPE_VALUES (enum_type) = cons;
> +
> +  return 1;
> +}
> +
> +int
> +plugin_finish_enum_type (cc1_plugin::connection *,
> +			 gcc_type enum_type_in)
> +{
> +  tree enum_type = convert_in (enum_type_in);
> +  tree minnode, maxnode, iter;
> +
> +  iter = TYPE_VALUES (enum_type);
> +  minnode = maxnode = TREE_VALUE (iter);
> +  for (iter = TREE_CHAIN (iter);
> +       iter != NULL_TREE;
> +       iter = TREE_CHAIN (iter))
> +    {
> +      tree value = TREE_VALUE (iter);
> +      if (tree_int_cst_lt (maxnode, value))
> +	maxnode = value;
> +      if (tree_int_cst_lt (value, minnode))
> +	minnode = value;
> +    }
> +  TYPE_MIN_VALUE (enum_type) = minnode;
> +  TYPE_MAX_VALUE (enum_type) = maxnode;
> +
> +  layout_type (enum_type);
> +
> +  return 1;
> +}
> +
> +gcc_type
> +plugin_build_function_type (cc1_plugin::connection *self,
> +			    gcc_type return_type_in,
> +			    const struct gcc_type_array *argument_types_in,
> +			    int is_varargs)
> +{
> +  tree *argument_types;
> +  tree return_type = convert_in (return_type_in);
> +  tree result;
> +
> +  argument_types = new tree[argument_types_in->n_elements];
> +  for (int i = 0; i < argument_types_in->n_elements; ++i)
> +    argument_types[i] = convert_in (argument_types_in->elements[i]);
> +
> +  if (is_varargs)
> +    result = build_varargs_function_type_array (return_type,
> +						argument_types_in->n_elements,
> +						argument_types);
> +  else
> +    result = build_function_type_array (return_type,
> +					argument_types_in->n_elements,
> +					argument_types);
> +
> +  delete[] argument_types;
> +
> +  plugin_context *ctx = static_cast<plugin_context *> (self);
> +  return convert_out (ctx->preserve (result));
> +}
> +
> +gcc_type
> +plugin_int_type (cc1_plugin::connection *self,
> +		 int is_unsigned, unsigned long size_in_bytes)
> +{
> +  tree result = c_common_type_for_size (BITS_PER_UNIT * size_in_bytes,
> +					is_unsigned);
> +  if (result == NULL_TREE)
> +    result = error_mark_node;
> +  else
> +    {
> +      plugin_context *ctx = static_cast<plugin_context *> (self);
> +      ctx->preserve (result);
> +    }
> +  return convert_out (result);
> +}
> +
> +gcc_type
> +plugin_float_type (cc1_plugin::connection *,
> +		   unsigned long size_in_bytes)
> +{
> +  if (BITS_PER_UNIT * size_in_bytes == TYPE_PRECISION (float_type_node))
> +    return convert_out (float_type_node);
> +  if (BITS_PER_UNIT * size_in_bytes == TYPE_PRECISION (double_type_node))
> +    return convert_out (double_type_node);
> +  if (BITS_PER_UNIT * size_in_bytes == TYPE_PRECISION (long_double_type_node))
> +    return convert_out (long_double_type_node);
> +  return convert_out (error_mark_node);
> +}
> +
> +gcc_type
> +plugin_void_type (cc1_plugin::connection *)
> +{
> +  return convert_out (void_type_node);
> +}
> +
> +gcc_type
> +plugin_bool_type (cc1_plugin::connection *)
> +{
> +  return convert_out (boolean_type_node);
> +}
> +
> +gcc_type
> +plugin_build_array_type (cc1_plugin::connection *self,
> +			 gcc_type element_type_in, int num_elements)
> +{
> +  tree element_type = convert_in (element_type_in);
> +  tree result;
> +
> +  if (num_elements == -1)
> +    result = build_array_type (element_type, NULL_TREE);
> +  else
> +    result = build_array_type_nelts (element_type, num_elements);
> +
> +  plugin_context *ctx = static_cast<plugin_context *> (self);
> +  return convert_out (ctx->preserve (result));
> +}
> +
> +gcc_type
> +plugin_build_vla_array_type (cc1_plugin::connection *self,
> +			     gcc_type element_type_in,
> +			     const char *upper_bound_name)
> +{
> +  tree element_type = convert_in (element_type_in);
> +  tree upper_bound = lookup_name (get_identifier (upper_bound_name));
> +  tree range = build_index_type (upper_bound);
> +
> +  tree result = build_array_type (element_type, range);
> +  C_TYPE_VARIABLE_SIZE (result) = 1;
> +
> +  plugin_context *ctx = static_cast<plugin_context *> (self);
> +  return convert_out (ctx->preserve (result));
> +}
> +
> +gcc_type
> +plugin_build_qualified_type (cc1_plugin::connection *,
> +			     gcc_type unqualified_type_in,
> +			     enum gcc_qualifiers qualifiers)
> +{
> +  tree unqualified_type = convert_in (unqualified_type_in);
> +  int quals = 0;
> +
> +  if ((qualifiers & GCC_QUALIFIER_CONST) != 0)
> +    quals |= TYPE_QUAL_CONST;
> +  if ((qualifiers & GCC_QUALIFIER_VOLATILE) != 0)
> +    quals |= TYPE_QUAL_VOLATILE;
> +  if ((qualifiers & GCC_QUALIFIER_RESTRICT) != 0)
> +    quals |= TYPE_QUAL_RESTRICT;
> +
> +  return convert_out (build_qualified_type (unqualified_type, quals));
> +}
> +
> +gcc_type
> +plugin_build_complex_type (cc1_plugin::connection *self,
> +			   gcc_type base_type)
> +{
> +  plugin_context *ctx = static_cast<plugin_context *> (self);
> +  return convert_out (ctx->preserve (build_complex_type (convert_in (base_type))));
> +}
> +
> +gcc_type
> +plugin_build_vector_type (cc1_plugin::connection *self,
> +			  gcc_type base_type, int nunits)
> +{
> +  plugin_context *ctx = static_cast<plugin_context *> (self);
> +  return convert_out (ctx->preserve (build_vector_type (convert_in (base_type),
> +							nunits)));
> +}
> +
> +int
> +plugin_build_constant (cc1_plugin::connection *self, gcc_type type_in,
> +		       const char *name, unsigned long value,
> +		       const char *filename, unsigned int line_number)
> +{
> +  plugin_context *ctx = static_cast<plugin_context *> (self);
> +  tree cst, decl;
> +  tree type = convert_in (type_in);
> +
> +  cst = build_int_cst (type, value);
> +  decl = build_decl (ctx->get_source_location (filename, line_number),
> +		     CONST_DECL, get_identifier (name), type);
> +  DECL_INITIAL (decl) = cst;
> +  pushdecl_safe (decl);
> +
> +  return 1;
> +}
> +
> +gcc_type
> +plugin_error (cc1_plugin::connection *,
> +	      const char *message)
> +{
> +  error ("%s", message);
> +  return convert_out (error_mark_node);
> +}
> +
> +\f
> +
> +// Perform GC marking.
> +
> +static void
> +gc_mark (void *, void *)
> +{
> +  if (current_context != NULL)
> +    current_context->mark ();
> +}
> +
> +#ifdef __GNUC__
> +#pragma GCC visibility push(default)
> +#endif
> +
> +int
> +plugin_init (struct plugin_name_args *plugin_info,
> +	     struct plugin_gcc_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 ("%s: invalid file descriptor argument to plugin",
> +			 plugin_info->base_name);
> +	  break;
> +	}
> +    }
> +  if (fd == -1)
> +    fatal_error ("%s: required plugin argument %<fd%> is missing",
> +		 plugin_info->base_name);
> +
> +  current_context = new plugin_context (fd);
> +
> +  // Handshake.
> +  cc1_plugin::protocol_int version;
> +  if (!current_context->require ('H')
> +      || ! ::cc1_plugin::unmarshall (current_context, &version))
> +    fatal_error ("%s: handshake failed", plugin_info->base_name);
> +  if (version != GCC_C_FE_VERSION_0)
> +    fatal_error ("%s: unknown version in handshake", plugin_info->base_name);
> +
> +  register_callback (plugin_info->base_name, PLUGIN_PRAGMAS,
> +		     plugin_init_extra_pragmas, NULL);
> +  register_callback (plugin_info->base_name, PLUGIN_PRE_GENERICIZE,
> +		     rewrite_decls_to_addresses, NULL);
> +  register_callback (plugin_info->base_name, PLUGIN_GGC_MARKING,
> +		     gc_mark, NULL);
> +
> +  lang_hooks.print_error_function = plugin_print_error_function;
> +
> +#define GCC_METHOD0(R, N)			\
> +  {						\
> +    cc1_plugin::callback_ftype *fun		\
> +      = cc1_plugin::callback<R, plugin_ ## N>;	\
> +    current_context->add_callback (# N, fun);	\
> +  }
> +#define GCC_METHOD1(R, N, A)				\
> +  {							\
> +    cc1_plugin::callback_ftype *fun			\
> +      = cc1_plugin::callback<R, A, plugin_ ## N>;	\
> +    current_context->add_callback (# N, fun);		\
> +  }
> +#define GCC_METHOD2(R, N, A, B)				\
> +  {							\
> +    cc1_plugin::callback_ftype *fun			\
> +      = cc1_plugin::callback<R, A, B, plugin_ ## N>;	\
> +    current_context->add_callback (# N, fun);		\
> +  }
> +#define GCC_METHOD3(R, N, A, B, C)			\
> +  {							\
> +    cc1_plugin::callback_ftype *fun			\
> +      = cc1_plugin::callback<R, A, B, C, plugin_ ## N>;	\
> +    current_context->add_callback (# N, fun);		\
> +  }
> +#define GCC_METHOD4(R, N, A, B, C, D)		\
> +  {						\
> +    cc1_plugin::callback_ftype *fun		\
> +      = cc1_plugin::callback<R, A, B, C, D,	\
> +			     plugin_ ## N>;	\
> +    current_context->add_callback (# N, fun);	\
> +  }
> +#define GCC_METHOD5(R, N, A, B, C, D, E)	\
> +  {						\
> +    cc1_plugin::callback_ftype *fun		\
> +      = cc1_plugin::callback<R, A, B, C, D, E,	\
> +			     plugin_ ## N>;	\
> +    current_context->add_callback (# N, fun);	\
> +  }
> +#define GCC_METHOD7(R, N, A, B, C, D, E, F, G)		\
> +  {							\
> +    cc1_plugin::callback_ftype *fun			\
> +      = cc1_plugin::callback<R, A, B, C, D, E, F, G,	\
> +			     plugin_ ## N>;		\
> +    current_context->add_callback (# N, fun);		\
> +  }
> +
> +#include "gcc-c-fe.def"
> +
> +#undef GCC_METHOD0
> +#undef GCC_METHOD1
> +#undef GCC_METHOD2
> +#undef GCC_METHOD3
> +#undef GCC_METHOD4
> +#undef GCC_METHOD5
> +#undef GCC_METHOD7
> +
> +  return 0;
> +}
> diff --git a/libcc1/rpc.hh b/libcc1/rpc.hh
> new file mode 100644
> index 0000000..58758d3
> --- /dev/null
> +++ b/libcc1/rpc.hh
> @@ -0,0 +1,486 @@
> +/* RPC call and callback templates
> +   Copyright (C) 2014 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/>.  */
> +
> +#ifndef CC1_PLUGIN_RPC_HH
> +#define CC1_PLUGIN_RPC_HH
> +
> +#include "status.hh"
> +#include "marshall.hh"
> +#include "connection.hh"
> +
> +namespace cc1_plugin
> +{
> +  // The plugin API may contain some "const" method parameters.
> +  // However, when unmarshalling we cannot unmarshall into a const
> +  // object; and furthermore we want to be able to deallocate pointers
> +  // when finished with them.  This wrapper class lets us properly
> +  // remove the "const" and handle deallocation from pointer types.
> +
> +  template<typename T>
> +  class argument_wrapper
> +  {
> +  public:
> +
> +    argument_wrapper () { }
> +    ~argument_wrapper () { }
> +
> +    operator T () const { return m_object; }
> +
> +    status unmarshall (connection *conn)
> +    {
> +      return ::cc1_plugin::unmarshall (conn, &m_object);
> +    }
> +
> +  private:
> +
> +    T m_object;
> +
> +    // No copying or assignment allowed.
> +    argument_wrapper (const argument_wrapper &);
> +    argument_wrapper &operator= (const argument_wrapper &);
> +  };
> +
> +  // Specialization for any kind of pointer.  This is declared but not
> +  // defined to avoid bugs if a new pointer type is introduced into
> +  // the API.  Instead you will just get a compilation error.
> +  template<typename T>
> +  class argument_wrapper<const T *>;
> +
> +  // Specialization for string types.
> +  template<>
> +  class argument_wrapper<const char *>
> +  {
> +  public:
> +    argument_wrapper () : m_object (NULL) { }
> +    ~argument_wrapper ()
> +    {
> +      delete[] m_object;
> +    }
> +
> +    operator const char * () const
> +    {
> +      return m_object;
> +    }
> +
> +    status unmarshall (connection *conn)
> +    {
> +      return ::cc1_plugin::unmarshall (conn, &m_object);
> +    }
> +
> +  private:
> +
> +    char *m_object;
> +
> +    // No copying or assignment allowed.
> +    argument_wrapper (const argument_wrapper &);
> +    argument_wrapper &operator= (const argument_wrapper &);
> +  };
> +
> +  // Specialization for gcc_type_array.
> +  template<>
> +  class argument_wrapper<const gcc_type_array *>
> +  {
> +  public:
> +    argument_wrapper () : m_object (NULL) { }
> +    ~argument_wrapper ()
> +    {
> +      // It would be nicer if gcc_type_array could have a destructor.
> +      // But, it is in code shared with gdb and cannot.
> +      if (m_object != NULL)
> +	delete[] m_object->elements;
> +      delete m_object;
> +    }
> +
> +    operator const gcc_type_array * () const
> +    {
> +      return m_object;
> +    }
> +
> +    status unmarshall (connection *conn)
> +    {
> +      return ::cc1_plugin::unmarshall (conn, &m_object);
> +    }
> +
> +  private:
> +
> +    gcc_type_array *m_object;
> +
> +    // No copying or assignment allowed.
> +    argument_wrapper (const argument_wrapper &);
> +    argument_wrapper &operator= (const argument_wrapper &);
> +  };
> +
> +  // There are two kinds of template functions here: "call" and
> +  // "callback".  They are each repeated multiple times to handle
> +  // different numbers of arguments.  (This would be improved with
> +  // C++11, though applying a call is still tricky until C++14 can be
> +  // used.)
> +
> +  // The "call" template is used for making a remote procedure call.
> +  // It starts a query ('Q') packet, marshalls its arguments, waits
> +  // for a result, and finally reads and returns the result via an
> +  // "out" parameter.
> +
> +  // The "callback" template is used when receiving a remote procedure
> +  // call.  This template function is suitable for use with the
> +  // "callbacks" and "connection" classes.  It decodes incoming
> +  // arguments, passes them to the wrapped function, and finally
> +  // marshalls a reply packet.
> +
> +  template<typename R>
> +  status
> +  call (connection *conn, const char *method, R *result)
> +  {
> +    if (!conn->send ('Q'))
> +      return FAIL;
> +    if (!marshall (conn, method))
> +      return FAIL;
> +    if (!marshall (conn, 0))
> +      return FAIL;
> +    if (!conn->wait_for_result ())
> +      return FAIL;
> +    if (!unmarshall (conn, result))
> +      return FAIL;
> +    return OK;
> +  }
> +
> +  template<typename R, R (*func) (connection *)>
> +  status
> +  callback (connection *conn)
> +  {
> +    R result;
> +
> +    if (!unmarshall_check (conn, 0))
> +      return FAIL;
> +    result = func (conn);
> +    if (!conn->send ('R'))
> +      return FAIL;
> +    return marshall (conn, result);
> +  }
> +
> +  template<typename R, typename A>
> +  status
> +  call (connection *conn, const char *method, R *result, A arg)
> +  {
> +    if (!conn->send ('Q'))
> +      return FAIL;
> +    if (!marshall (conn, method))
> +      return FAIL;
> +    if (!marshall (conn, 1))
> +      return FAIL;
> +    if (!marshall (conn, arg))
> +      return FAIL;
> +    if (!conn->wait_for_result ())
> +      return FAIL;
> +    if (!unmarshall (conn, result))
> +      return FAIL;
> +    return OK;
> +  }
> +
> +  template<typename R, typename A, R (*func) (connection *, A)>
> +  status
> +  callback (connection *conn)
> +  {
> +    argument_wrapper<A> arg;
> +    R result;
> +
> +    if (!unmarshall_check (conn, 1))
> +      return FAIL;
> +    if (!arg.unmarshall (conn))
> +      return FAIL;
> +    result = func (conn, arg);
> +    if (!conn->send ('R'))
> +      return FAIL;
> +    return marshall (conn, result);
> +  }
> +
> +  template<typename R, typename A1, typename A2>
> +  status
> +  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2)
> +  {
> +    if (!conn->send ('Q'))
> +      return FAIL;
> +    if (!marshall (conn, method))
> +      return FAIL;
> +    if (!marshall (conn, 2))
> +      return FAIL;
> +    if (!marshall (conn, arg1))
> +      return FAIL;
> +    if (!marshall (conn, arg2))
> +      return FAIL;
> +    if (!conn->wait_for_result ())
> +      return FAIL;
> +    if (!unmarshall (conn, result))
> +      return FAIL;
> +    return OK;
> +  }
> +
> +  template<typename R, typename A1, typename A2, R (*func) (connection *,
> +							    A1, A2)>
> +  status
> +  callback (connection *conn)
> +  {
> +    argument_wrapper<A1> arg1;
> +    argument_wrapper<A2> arg2;
> +    R result;
> +
> +    if (!unmarshall_check (conn, 2))
> +      return FAIL;
> +    if (!arg1.unmarshall (conn))
> +      return FAIL;
> +    if (!arg2.unmarshall (conn))
> +      return FAIL;
> +    result = func (conn, arg1, arg2);
> +    if (!conn->send ('R'))
> +      return FAIL;
> +    return marshall (conn, result);
> +  }
> +
> +  template<typename R, typename A1, typename A2, typename A3>
> +  status
> +  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
> +	A3 arg3)
> +  {
> +    if (!conn->send ('Q'))
> +      return FAIL;
> +    if (!marshall (conn, method))
> +      return FAIL;
> +    if (!marshall (conn, 3))
> +      return FAIL;
> +    if (!marshall (conn, arg1))
> +      return FAIL;
> +    if (!marshall (conn, arg2))
> +      return FAIL;
> +    if (!marshall (conn, arg3))
> +      return FAIL;
> +    if (!conn->wait_for_result ())
> +      return FAIL;
> +    if (!unmarshall (conn, result))
> +      return FAIL;
> +    return OK;
> +  }
> +
> +  template<typename R, typename A1, typename A2, typename A3,
> +	   R (*func) (connection *, A1, A2, A3)>
> +  status
> +  callback (connection *conn)
> +  {
> +    argument_wrapper<A1> arg1;
> +    argument_wrapper<A2> arg2;
> +    argument_wrapper<A3> arg3;
> +    R result;
> +
> +    if (!unmarshall_check (conn, 3))
> +      return FAIL;
> +    if (!arg1.unmarshall (conn))
> +      return FAIL;
> +    if (!arg2.unmarshall (conn))
> +      return FAIL;
> +    if (!arg3.unmarshall (conn))
> +      return FAIL;
> +    result = func (conn, arg1, arg2, arg3);
> +    if (!conn->send ('R'))
> +      return FAIL;
> +    return marshall (conn, result);
> +  }
> +
> +  template<typename R, typename A1, typename A2, typename A3, typename A4>
> +  status
> +  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
> +	A3 arg3, A4 arg4)
> +  {
> +    if (!conn->send ('Q'))
> +      return FAIL;
> +    if (!marshall (conn, method))
> +      return FAIL;
> +    if (!marshall (conn, 4))
> +      return FAIL;
> +    if (!marshall (conn, arg1))
> +      return FAIL;
> +    if (!marshall (conn, arg2))
> +      return FAIL;
> +    if (!marshall (conn, arg3))
> +      return FAIL;
> +    if (!marshall (conn, arg4))
> +      return FAIL;
> +    if (!conn->wait_for_result ())
> +      return FAIL;
> +    if (!unmarshall (conn, result))
> +      return FAIL;
> +    return OK;
> +  }
> +
> +  template<typename R, typename A1, typename A2, typename A3, typename A4,
> +	   R (*func) (connection *, A1, A2, A3, A4)>
> +  status
> +  callback (connection *conn)
> +  {
> +    argument_wrapper<A1> arg1;
> +    argument_wrapper<A2> arg2;
> +    argument_wrapper<A3> arg3;
> +    argument_wrapper<A4> arg4;
> +    R result;
> +
> +    if (!unmarshall_check (conn, 4))
> +      return FAIL;
> +    if (!arg1.unmarshall (conn))
> +      return FAIL;
> +    if (!arg2.unmarshall (conn))
> +      return FAIL;
> +    if (!arg3.unmarshall (conn))
> +      return FAIL;
> +    if (!arg4.unmarshall (conn))
> +      return FAIL;
> +    result = func (conn, arg1, arg2, arg3, arg4);
> +    if (!conn->send ('R'))
> +      return FAIL;
> +    return marshall (conn, result);
> +  }
> +
> +  template<typename R, typename A1, typename A2, typename A3, typename A4,
> +	   typename A5>
> +  status
> +  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
> +	A3 arg3, A4 arg4, A5 arg5)
> +  {
> +    if (!conn->send ('Q'))
> +      return FAIL;
> +    if (!marshall (conn, method))
> +      return FAIL;
> +    if (!marshall (conn, 5))
> +      return FAIL;
> +    if (!marshall (conn, arg1))
> +      return FAIL;
> +    if (!marshall (conn, arg2))
> +      return FAIL;
> +    if (!marshall (conn, arg3))
> +      return FAIL;
> +    if (!marshall (conn, arg4))
> +      return FAIL;
> +    if (!marshall (conn, arg5))
> +      return FAIL;
> +    if (!conn->wait_for_result ())
> +      return FAIL;
> +    if (!unmarshall (conn, result))
> +      return FAIL;
> +    return OK;
> +  }
> +
> +  template<typename R, typename A1, typename A2, typename A3, typename A4,
> +	   typename A5, R (*func) (connection *, A1, A2, A3, A4, A5)>
> +  status
> +  callback (connection *conn)
> +  {
> +    argument_wrapper<A1> arg1;
> +    argument_wrapper<A2> arg2;
> +    argument_wrapper<A3> arg3;
> +    argument_wrapper<A4> arg4;
> +    argument_wrapper<A5> arg5;
> +    R result;
> +
> +    if (!unmarshall_check (conn, 5))
> +      return FAIL;
> +    if (!arg1.unmarshall (conn))
> +      return FAIL;
> +    if (!arg2.unmarshall (conn))
> +      return FAIL;
> +    if (!arg3.unmarshall (conn))
> +      return FAIL;
> +    if (!arg4.unmarshall (conn))
> +      return FAIL;
> +    if (!arg5.unmarshall (conn))
> +      return FAIL;
> +    result = func (conn, arg1, arg2, arg3, arg4, arg5);
> +    if (!conn->send ('R'))
> +      return FAIL;
> +    return marshall (conn, result);
> +  }
> +
> +  template<typename R, typename A1, typename A2, typename A3, typename A4,
> +	   typename A5, typename A6, typename A7>
> +  status
> +  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
> +	A3 arg3, A4 arg4, A5 arg5, A6 arg6, A7 arg7)
> +  {
> +    if (!conn->send ('Q'))
> +      return FAIL;
> +    if (!marshall (conn, method))
> +      return FAIL;
> +    if (!marshall (conn, 7))
> +      return FAIL;
> +    if (!marshall (conn, arg1))
> +      return FAIL;
> +    if (!marshall (conn, arg2))
> +      return FAIL;
> +    if (!marshall (conn, arg3))
> +      return FAIL;
> +    if (!marshall (conn, arg4))
> +      return FAIL;
> +    if (!marshall (conn, arg5))
> +      return FAIL;
> +    if (!marshall (conn, arg6))
> +      return FAIL;
> +    if (!marshall (conn, arg7))
> +      return FAIL;
> +    if (!conn->wait_for_result ())
> +      return FAIL;
> +    if (!unmarshall (conn, result))
> +      return FAIL;
> +    return OK;
> +  }
> +
> +  template<typename R, typename A1, typename A2, typename A3, typename A4,
> +	   typename A5, typename A6, typename A7,
> +	   R (*func) (connection *, A1, A2, A3, A4, A5, A6, A7)>
> +  status
> +  callback (connection *conn)
> +  {
> +    argument_wrapper<A1> arg1;
> +    argument_wrapper<A2> arg2;
> +    argument_wrapper<A3> arg3;
> +    argument_wrapper<A4> arg4;
> +    argument_wrapper<A5> arg5;
> +    argument_wrapper<A6> arg6;
> +    argument_wrapper<A7> arg7;
> +    R result;
> +
> +    if (!unmarshall_check (conn, 7))
> +      return FAIL;
> +    if (!arg1.unmarshall (conn))
> +      return FAIL;
> +    if (!arg2.unmarshall (conn))
> +      return FAIL;
> +    if (!arg3.unmarshall (conn))
> +      return FAIL;
> +    if (!arg4.unmarshall (conn))
> +      return FAIL;
> +    if (!arg5.unmarshall (conn))
> +      return FAIL;
> +    if (!arg6.unmarshall (conn))
> +      return FAIL;
> +    if (!arg7.unmarshall (conn))
> +      return FAIL;
> +    result = func (conn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
> +    if (!conn->send ('R'))
> +      return FAIL;
> +    return marshall (conn, result);
> +  }
> +};
> +
> +#endif // CC1_PLUGIN_RPC_HH
> diff --git a/libcc1/status.hh b/libcc1/status.hh
> new file mode 100644
> index 0000000..764c7ff
> --- /dev/null
> +++ b/libcc1/status.hh
> @@ -0,0 +1,33 @@
> +/* status type definition
> +   Copyright (C) 2014 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/>.  */
> +
> +#ifndef CC1_PLUGIN_STATUS_HH
> +#define CC1_PLUGIN_STATUS_HH
> +
> +namespace cc1_plugin
> +{
> +  // The status returned by various connection functions.
> +  enum status
> +  {
> +    FAIL = 0,
> +    OK = 1
> +  };
> +}
> +
> +#endif // CC1_PLUGIN_STATUS_HH
> -- 
> 1.9.3
> 

Trev


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-06-20  3:11     ` Trevor Saunders
@ 2014-06-20 15:34       ` Tom Tromey
  2014-06-23 19:09         ` Jeff Law
  0 siblings, 1 reply; 101+ messages in thread
From: Tom Tromey @ 2014-06-20 15:34 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: gcc-patches

>>>>> "Trevor" == Trevor Saunders <tsaunders@mozilla.com> writes:

Trevor> I'm curious, what is the reason you choose not to write this in C++11 or
Trevor> later?  Its distributed with gcc, so the only case where you aren't
Trevor> building with the in tree compiler and libraries is when your cross
Trevor> compiling gcc, and it doesn't seem particularly important to support
Trevor> building the plugin or library in that configuration.  So istm you could
Trevor> go all the way and assume you are being built with trunk gcc and
Trevor> libraries.

The plugin has to be ABI compatible with GCC itself, and my
understanding was that C++11 and "however GCC is built" are not
necessarily compatible.

Switching to C++11 would be an improvement -- variadic templates would
simplify the RPC code (with a complicated caveat).  So if it is possible
I am interested.

Trevor> I'm going to use this as an excuse to bring up something I've wanted to
Trevor> discuss for a while.

Trevor> So can we add C++ stuff to libiberty and allow building
Trevor> libiberty without it for binutils / gdb, or can we do something
Trevor> else to avoid this kind of stuff?

One way would be to just make a new top-level directory for a new
library.

Trevor> This question also arises in the case of templating splay_tree, and I
Trevor> imagine if gdb switches to C++ some day they'll want to reuse vec.h.

While I would like that to happen, I think the odds are very long now.

>> +    connection (int fd)
>> +      : m_fd (fd),
>> +	m_aux_fd (-1),
>> +	m_callbacks ()

Trevor>  Personally I'd leave that to the compiler to write, but I guess there's
Trevor>  something to be said for being explicit.

I can't recall if I did this in response to a warning or if it was just
because I wanted to be explicit.

I'm inclined to leave it, but I suppose only out of inertia.

>> +  void print (const char *buf)

Trevor> explicitly mark it as virtual?

Good idea, done.

>> +// This is a wrapper function that is called by the RPC system and
>> +// that then forwards the call to the library user.  Note that the
>> +// return value is not used; the type cannot be 'void' due to
>> +// limitations in our simple RPC.
>> +gcc_address

Trevor> looks like this one probably is used?

Thanks, fixed.

>> +  char **argv = new (std::nothrow) char *[self->args.size () + 1];

Trevor> What's the point of making this no throw? you don't null check it so
Trevor> you'll crash anyway afaict.

Thanks.  I changed it to do a NULL check.  It's nothrow because nothing
in libcc1 or gdb is prepared for a C++ exception.  While I like
exceptions (gdb uses its own longjmp-based exception system
extensively), my understanding is that they aren't currently used in
gcc.

>> +cc1_plugin::status
>> +cc1_plugin::unmarshall (connection *conn, char **result)
>> +{
>> +  unsigned long long len;
>> +
>> +  if (!conn->require ('s'))
>> +    return FAIL;
>> +  if (!conn->get (&len, sizeof (len)))
>> +    return FAIL;
>> +
>> +  if (len == -1ULL)
>> +    {
>> +      *result = NULL;
>> +      return OK;
>> +    }
>> +
>> +  char *str = new (std::nothrow) char[len + 1];

Trevor> It'd be really nice if the type of the out arg forced the caller to deal
Trevor> with deleting the string like unique_ptr<char>, it would be even nicer
Trevor> if you could stick a random buffer in a std::string, but I guess you
Trevor> can't :(

Yeah, it's all quite simplistic.  I suppose it could be upgraded, there
just didn't seem to be a need.

Trevor> Also where does this array get deleted?

The unmarshalling methods are generally called via argument_wrappers.
An example is in connection.cc:

		// Use an argument_wrapper here to simplify management
		// of the string's lifetime.
		argument_wrapper<char *> method_name;

		if (!method_name.unmarshall (this))
		  return FAIL;

Then in rpc.hh:

  // Specialization for string types.
  template<>
  class argument_wrapper<const char *>
  {
  public:
    argument_wrapper () : m_object (NULL) { }
    ~argument_wrapper ()
    {
      delete[] m_object;
    }

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-06-20 15:34       ` Tom Tromey
@ 2014-06-23 19:09         ` Jeff Law
  2014-06-24  3:13           ` Trevor Saunders
  0 siblings, 1 reply; 101+ messages in thread
From: Jeff Law @ 2014-06-23 19:09 UTC (permalink / raw)
  To: Tom Tromey, Trevor Saunders; +Cc: gcc-patches

On 06/20/14 09:33, Tom Tromey wrote:
>>>>>> "Trevor" == Trevor Saunders <tsaunders@mozilla.com> writes:
>
> Trevor> I'm curious, what is the reason you choose not to write this in C++11 or
> Trevor> later?  Its distributed with gcc, so the only case where you aren't
> Trevor> building with the in tree compiler and libraries is when your cross
> Trevor> compiling gcc, and it doesn't seem particularly important to support
> Trevor> building the plugin or library in that configuration.  So istm you could
> Trevor> go all the way and assume you are being built with trunk gcc and
> Trevor> libraries.
>
> The plugin has to be ABI compatible with GCC itself, and my
> understanding was that C++11 and "however GCC is built" are not
> necessarily compatible.
Presumably you're referring to the upcoming abi breakage for C++ pair & 
list.

There's ways around that with the ABI tagging we're using, but at least 
for now, the safe thing to do for something that must be ABI compatibile 
with GCC itself is to stick with C++03 mode.

>
> Switching to C++11 would be an improvement -- variadic templates would
> simplify the RPC code (with a complicated caveat).  So if it is possible
> I am interested.
There'll probably be a day when we can bless C++11 for building GCC 
itself and any associated plugins, but we're not at that point right now.

> Trevor> So can we add C++ stuff to libiberty and allow building
> Trevor> libiberty without it for binutils / gdb, or can we do something
> Trevor> else to avoid this kind of stuff?
>
> One way would be to just make a new top-level directory for a new
> library.
Seems like the easiest solution, at least for now.

>
> Thanks.  I changed it to do a NULL check.  It's nothrow because nothing
> in libcc1 or gdb is prepared for a C++ exception.  While I like
> exceptions (gdb uses its own longjmp-based exception system
> extensively), my understanding is that they aren't currently used in
> gcc.
Right.  Or if we're using them in GCC, any such use is well buried in 
non-critical , not widely known & marginally, if at all, tested code.

Jeff

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-06-23 19:09         ` Jeff Law
@ 2014-06-24  3:13           ` Trevor Saunders
  2014-06-24 17:12             ` Tom Tromey
  0 siblings, 1 reply; 101+ messages in thread
From: Trevor Saunders @ 2014-06-24  3:13 UTC (permalink / raw)
  To: Jeff Law; +Cc: Tom Tromey, gcc-patches

On Mon, Jun 23, 2014 at 01:09:41PM -0600, Jeff Law wrote:
> On 06/20/14 09:33, Tom Tromey wrote:
> >>>>>>"Trevor" == Trevor Saunders <tsaunders@mozilla.com> writes:
> >
> >Trevor> I'm curious, what is the reason you choose not to write this in C++11 or
> >Trevor> later?  Its distributed with gcc, so the only case where you aren't
> >Trevor> building with the in tree compiler and libraries is when your cross
> >Trevor> compiling gcc, and it doesn't seem particularly important to support
> >Trevor> building the plugin or library in that configuration.  So istm you could
> >Trevor> go all the way and assume you are being built with trunk gcc and
> >Trevor> libraries.
> >
> >The plugin has to be ABI compatible with GCC itself, and my
> >understanding was that C++11 and "however GCC is built" are not
> >necessarily compatible.
> Presumably you're referring to the upcoming abi breakage for C++ pair &
> list.
> 
> There's ways around that with the ABI tagging we're using, but at least for
> now, the safe thing to do for something that must be ABI compatibile with
> GCC itself is to stick with C++03 mode.
> 

 hrm, I know basically nothing about the upcoming changes, but I would
 have expected linking c++03 code against c++11 code would be fine
 especially when the interface doesn't involve any stl.

> >Switching to C++11 would be an improvement -- variadic templates would
> >simplify the RPC code (with a complicated caveat).  So if it is possible
> >I am interested.
> There'll probably be a day when we can bless C++11 for building GCC itself
> and any associated plugins, but we're not at that point right now.
> 
> >Trevor> So can we add C++ stuff to libiberty and allow building
> >Trevor> libiberty without it for binutils / gdb, or can we do something
> >Trevor> else to avoid this kind of stuff?
> >
> >One way would be to just make a new top-level directory for a new
> >library.
> Seems like the easiest solution, at least for now.

ugh more autotools, but wfm.

> >Thanks.  I changed it to do a NULL check.  It's nothrow because nothing
> >in libcc1 or gdb is prepared for a C++ exception.  While I like
> >exceptions (gdb uses its own longjmp-based exception system
> >extensively), my understanding is that they aren't currently used in
> >gcc.
> Right.  Or if we're using them in GCC, any such use is well buried in
> non-critical , not widely known & marginally, if at all, tested code.

 Well, we build everything or at least everything I've seen with
 -fno-exceptions, so if something does throw we'll just crash right?
 istm we certainly write code calling the throwing new with that
 expectation.

 Trev

> 
> Jeff
> 

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-06-24  3:13           ` Trevor Saunders
@ 2014-06-24 17:12             ` Tom Tromey
  2014-06-24 18:10               ` Trevor Saunders
  0 siblings, 1 reply; 101+ messages in thread
From: Tom Tromey @ 2014-06-24 17:12 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: Jeff Law, gcc-patches

Trevor>  hrm, I know basically nothing about the upcoming changes, but I would
Trevor>  have expected linking c++03 code against c++11 code would be fine
Trevor>  especially when the interface doesn't involve any stl.

    https://gcc.gnu.org/wiki/Cxx11AbiCompatibility

This warns against mixing with C++98, which seems to be how GCC is
built.

While I agree that in this specific case it is probably safe, since gcc
in general isn't a heavy user of libstdc++, I think it's reasonable to
simply follow gcc.  This is safer in case gcc changes; and the benefit
from C++11 in libcc1 is modest, especially when you consider the extra
template magic we'd need in order to actually use variadic templates for
the RPC stuff.

Trevor>  Well, we build everything or at least everything I've seen with
Trevor>  -fno-exceptions, so if something does throw we'll just crash right?
Trevor>  istm we certainly write code calling the throwing new with that
Trevor>  expectation.

Gcc's coding conventions say that code ought to be exception-safe in
case exceptions are used in the future.  Search for "Exceptions" here:

    https://gcc.gnu.org/wiki/CppConventions

I think retaining the std::nothrow is safer in view of this, and doesn't
cause any problems.

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-06-24 17:12             ` Tom Tromey
@ 2014-06-24 18:10               ` Trevor Saunders
  0 siblings, 0 replies; 101+ messages in thread
From: Trevor Saunders @ 2014-06-24 18:10 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Jeff Law, gcc-patches

On Tue, Jun 24, 2014 at 11:12:38AM -0600, Tom Tromey wrote:
> Trevor>  hrm, I know basically nothing about the upcoming changes, but I would
> Trevor>  have expected linking c++03 code against c++11 code would be fine
> Trevor>  especially when the interface doesn't involve any stl.
> 
>     https://gcc.gnu.org/wiki/Cxx11AbiCompatibility
> 
> This warns against mixing with C++98, which seems to be how GCC is
> built.
> 
> While I agree that in this specific case it is probably safe, since gcc
> in general isn't a heavy user of libstdc++, I think it's reasonable to
> simply follow gcc.  This is safer in case gcc changes; and the benefit

yeah, I'm not disagreeing at this point.

> from C++11 in libcc1 is modest, especially when you consider the extra
> template magic we'd need in order to actually use variadic templates for
> the RPC stuff.

It would get a little more than that, actually deleting the copy ctors
and stuff you don't want people to call is one thing that comes to mind.

> 
> Trevor>  Well, we build everything or at least everything I've seen with
> Trevor>  -fno-exceptions, so if something does throw we'll just crash right?
> Trevor>  istm we certainly write code calling the throwing new with that
> Trevor>  expectation.
> 
> Gcc's coding conventions say that code ought to be exception-safe in
> case exceptions are used in the future.  Search for "Exceptions" here:
> 
>     https://gcc.gnu.org/wiki/CppConventions

I think that's a good idea in general, mostly because it results in
simpler code, I think the idea gcc will be exception safe in a
reasonable amount of time is a bit of a pipe dream.

> 
> I think retaining the std::nothrow is safer in view of this, and doesn't
> cause any problems.

 I think in general trying to handle allocator failure is a waste of
 time, that is all the places we call the throwing new today we'd want
 to keep doing that in a world with exceptions and just let the
 exception kill us.  So assuming you actually want to handle allocator
 failure in this particular case for some reason that seems reasonable.

 Trev

> 
> Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-06-19 20:52   ` Tom Tromey
  2014-06-19 21:45     ` Jakub Jelinek
  2014-06-20  3:11     ` Trevor Saunders
@ 2014-07-18 19:00     ` Tom Tromey
  2014-07-31  4:49     ` Jeff Law
  3 siblings, 0 replies; 101+ messages in thread
From: Tom Tromey @ 2014-07-18 19:00 UTC (permalink / raw)
  To: gcc-patches

>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:

Tom> I've edited this one down by removing the auto-generated stuff , and
Tom> then compressed it.

Tom> Here's a new version of patch #5.
Tom> I've removed the generated code; let's see if it gets through without
Tom> compression.

Here's another new revision.

Phil noticed that libcc1.so relies on some symbols from libiberty, and
these weren't available in some gdb builds.  This version of the patch
changes the build so that libcc1 is linked against the pic libiberty in
the gcc build tree, which should fix the issue.

This version also addresses various comments made by Trevor Saunders,
though it doesn't switch the code to use C++11.  I think it is best here
to follow the rest of gcc.

Tom

2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* Makefile.def: Add libcc1 to host_modules.
	* configure.ac (host_tools): Add libcc1.
	* Makefile.in, configure: Rebuild.

2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
	    Jan Kratochvil  <jan.kratochvil@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* aclocal.m4: New file.
	* callbacks.cc: New file.
	* callbacks.hh: New file.
	* cc1plugin-config.h.in: New file.
	* configure: New file.
	* configure.ac: New file.
	* connection.cc: New file.
	* connection.hh: New file.
	* findcomp.cc: New file.
	* findcomp.hh: New file.
	* libcc1.cc: New file.
	* libcc1plugin.sym: New file.
	* libcc1.sym: New file.
	* Makefile.am: New file.
	* Makefile.in: New file.
	* marshall.cc: New file.
	* marshall.hh: New file.
	* names.cc: New file.
	* names.hh: New file.
	* plugin.cc: New file.
	* rpc.hh: New file.
	* status.hh: New file.

diff --git a/Makefile.def b/Makefile.def
index 239ad36..ed9bac6 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -121,6 +121,8 @@ host_modules= { module= gnattools; };
 host_modules= { module= lto-plugin; bootstrap=true;
 		extra_configure_flags='--enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@';
 		extra_make_flags='@extra_linker_plugin_flags@'; };
+host_modules= { module= libcc1; bootstrap=true;
+		extra_configure_flags=--enable-shared; };
 
 target_modules = { module= libstdc++-v3;
 		   bootstrap=true;
@@ -352,6 +354,9 @@ dependencies = { module=all-gnattools; on=all-target-libstdc++-v3; };
 dependencies = { module=all-lto-plugin; on=all-libiberty; };
 dependencies = { module=all-lto-plugin; on=all-libiberty-linker-plugin; };
 
+dependencies = { module=configure-libcc1; on=configure-gcc; };
+dependencies = { module=all-libcc1; on=all-gcc; };
+
 dependencies = { module=all-utils; on=all-libiberty; };
 
 dependencies = { module=configure-mpfr; on=all-gmp; };
diff --git a/configure.ac b/configure.ac
index 9048cd1..0388dc2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-#   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+#   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2014
 #   Free Software Foundation, Inc.
 #
 # This file is free software; you can redistribute it and/or modify it
@@ -141,7 +141,7 @@ host_libs="intl libiberty opcodes bfd readline tcl tk itcl libgui zlib libbacktr
 # binutils, gas and ld appear in that order because it makes sense to run
 # "make check" in that particular order.
 # If --enable-gold is used, "gold" may replace "ld".
-host_tools="texinfo flex bison binutils gas ld fixincludes gcc cgen sid sim gdb gprof etc expect dejagnu m4 utils guile fastjar gnattools"
+host_tools="texinfo flex bison binutils gas ld fixincludes gcc cgen sid sim gdb gprof etc expect dejagnu m4 utils guile fastjar gnattools libcc1"
 
 # libgcj represents the runtime libraries only used by gcj.
 libgcj="target-libffi \
diff --git a/libcc1/Makefile.am b/libcc1/Makefile.am
new file mode 100644
index 0000000..b3040c5
--- /dev/null
+++ b/libcc1/Makefile.am
@@ -0,0 +1,55 @@
+## Copyright (C) 2014 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/>.
+
+ACLOCAL_AMFLAGS = -I .. -I ../config
+gcc_build_dir = ../$(host_subdir)/gcc
+AM_CPPFLAGS = -I $(srcdir)/../include -I $(srcdir)/../libgcc \
+	-I $(gcc_build_dir) -I$(srcdir)/../gcc \
+	-I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
+	-I $(srcdir)/../libcpp/include
+WERROR_FLAG = -Werror
+AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
+libiberty = ../libiberty/pic/libiberty.a
+
+
+plugindir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/plugin
+cc1libdir = $(libdir)/$(libsuffix)
+
+if ENABLE_PLUGIN
+plugin_LTLIBRARIES = libcc1plugin.la
+cc1lib_LTLIBRARIES = libcc1.la
+endif
+
+BUILT_SOURCES = compiler-name.h
+
+# Put this in a header so we don't run sed for each compilation.  This
+# is also simpler to debug as one can easily see the constant.
+compiler-name.h: Makefile
+	echo "#define COMPILER_NAME \"`echo gcc | sed '$(transform)'`\"" > compiler-name.h
+
+
+shared_source = callbacks.cc callbacks.hh connection.cc connection.hh \
+    marshall.cc marshall.hh rpc.hh status.hh
+
+libcc1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1plugin.sym
+libcc1plugin_la_SOURCES = plugin.cc $(shared_source)
+libcc1plugin_la_LIBADD = $(libiberty)
+
+libcc1_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1.sym
+libcc1_la_SOURCES = findcomp.cc libcc1.cc names.cc names.hh $(shared_source)
+libcc1_la_LIBADD = $(libiberty)
diff --git a/libcc1/callbacks.cc b/libcc1/callbacks.cc
new file mode 100644
index 0000000..3c4eda6
--- /dev/null
+++ b/libcc1/callbacks.cc
@@ -0,0 +1,90 @@
+/* Callback management.
+   Copyright (C) 2014 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>
+#include <string.h>
+#include <stdlib.h>
+#include "callbacks.hh"
+#include "libiberty.h"
+
+// An entry in the hash table.
+struct method
+{
+  const char *name;
+  cc1_plugin::callback_ftype *func;
+};
+
+// Hash function for struct method.
+static hashval_t
+hash_method (const void *a)
+{
+  const struct method *m = (const struct method *) a;
+
+  return htab_hash_string (m->name);
+}
+
+// Equality function for struct method.
+static int
+eq_method (const void *a, const void *b)
+{
+  const struct method *ma = (const struct method *) a;
+  const struct method *mb = (const struct method *) b;
+
+  return strcmp (ma->name, mb->name) == 0;
+}
+
+cc1_plugin::callbacks::callbacks ()
+  : m_registry (htab_create_alloc (10, hash_method, eq_method,
+				   free, xcalloc, free))
+{
+}
+
+cc1_plugin::callbacks::~callbacks ()
+{
+  htab_delete (m_registry);
+}
+
+void
+cc1_plugin::callbacks::add_callback (const char *name,
+				     cc1_plugin::callback_ftype *func)
+{
+  method m;
+  method **slot;
+
+  m.name = name;
+  m.func = func;
+
+  slot = (method **) htab_find_slot (m_registry, &m, INSERT);
+  *slot = XNEW (method);
+  **slot = m;
+}
+
+cc1_plugin::callback_ftype *
+cc1_plugin::callbacks::find_callback (const char *name)
+{
+  method m, *found;
+
+  m.name = name;
+
+  found = (method *) htab_find (m_registry, &m);
+  if (found == NULL)
+    return NULL;
+
+  return found->func;
+}
diff --git a/libcc1/callbacks.hh b/libcc1/callbacks.hh
new file mode 100644
index 0000000..bde1100
--- /dev/null
+++ b/libcc1/callbacks.hh
@@ -0,0 +1,64 @@
+/* Callback management
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_CALLBACKS_HH
+#define CC1_PLUGIN_CALLBACKS_HH
+
+#include "status.hh"
+#include "hashtab.h"
+
+namespace cc1_plugin
+{
+  class connection;
+
+  // The type of a callback method.
+  typedef status callback_ftype (connection *);
+
+  // This class manages callback functions.  A callback has a name and
+  // an underlying function.  When a query packet arrives, the name is
+  // inspected and the corresponding function is called.  A callback
+  // function has to know how to decode its own arguments, but
+  // wrappers are provided elsewhere to automate this.
+  class callbacks
+  {
+  public:
+
+    callbacks ();
+    ~callbacks ();
+
+    // Add a callback named NAME.  FUNC is the function to call when
+    // this method is invoked.
+    void add_callback (const char *name, callback_ftype *func);
+
+    // Look up a callback by name.  Returns NULL if the method is not
+    // found.
+    callback_ftype *find_callback (const char *name);
+
+  private:
+
+    // Declared but not defined to avoid use.
+    callbacks (const callbacks &);
+    callbacks &operator= (const callbacks &);
+
+    // The mapping.
+    htab_t m_registry;
+  };
+};
+
+#endif // CC1_PLUGIN_CALLBACKS_HH
diff --git a/libcc1/configure.ac b/libcc1/configure.ac
new file mode 100644
index 0000000..7328977
--- /dev/null
+++ b/libcc1/configure.ac
@@ -0,0 +1,73 @@
+dnl   Copyright (C) 2014 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GCC.
+dnl
+dnl GCC is free software; you can redistribute it and/or modify it under
+dnl the terms of the GNU General Public License as published by the Free
+dnl Software Foundation; either version 3, or (at your option) any later
+dnl version.
+dnl
+dnl GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+dnl WARRANTY; without even the implied warranty of MERCHANTABILITY or
+dnl FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+dnl for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GCC; see the file COPYING3.  If not see
+dnl <http://www.gnu.org/licenses/>.
+
+AC_PREREQ(2.64)
+AC_INIT([libcc1], [version-unused])
+AC_CONFIG_SRCDIR([libcc1.cc])
+AC_CONFIG_HEADER(cc1plugin-config.h)
+
+AC_CANONICAL_SYSTEM
+AC_USE_SYSTEM_EXTENSIONS
+# Determine the noncanonical target name, for directory use.
+ACX_NONCANONICAL_TARGET
+GCC_TOPLEV_SUBDIRS
+
+# 1.11.1: Require that version of automake.
+# foreign: Don't require README, INSTALL, NEWS, etc.
+# no-define: Don't define PACKAGE and VERSION.
+# -Wall: Issue all automake warnings.
+# -Wno-portability: Don't warn about constructs supported by GNU make.
+#    (because GCC requires GNU make anyhow).
+AM_INIT_AUTOMAKE([1.11.1 foreign no-dist no-define -Wall -Wno-portability])
+AM_MAINTAINER_MODE
+
+LT_INIT([disable-static])
+AM_PROG_LIBTOOL
+AC_PROG_CXX
+
+visibility=
+if test "$GXX" = yes; then
+  visibility=-fvisibility=hidden
+fi
+AC_SUBST(visibility)
+
+AC_CHECK_DECLS([basename])
+
+gcc_version=`cat $srcdir/../gcc/BASE-VER`
+AC_SUBST(gcc_version)
+
+ACX_PROG_CC_WARNING_OPTS([-W -Wall], [WARN_FLAGS])
+WARN_FLAGS="$WARN_FLAGS -Werror"
+AC_SUBST(WARN_FLAGS)
+
+libsuffix=
+if test "$GXX" = yes; then
+  libsuffix=`$CXX -print-multi-os-directory`
+fi
+AC_SUBST(libsuffix)
+
+# If any of these functions are missing, simply don't bother building
+# this plugin.
+GCC_ENABLE_PLUGINS
+AC_CHECK_FUNC(socketpair, , enable_plugin=no)
+AC_CHECK_FUNC(select, , enable_plugin=no)
+AC_CHECK_FUNC(fork, , enable_plugin=no)
+AM_CONDITIONAL(ENABLE_PLUGIN, test $enable_plugin = yes)
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/libcc1/connection.cc b/libcc1/connection.cc
new file mode 100644
index 0000000..3e57bbc
--- /dev/null
+++ b/libcc1/connection.cc
@@ -0,0 +1,153 @@
+/* Connect implementation
+   Copyright (C) 2014 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>
+#include <string>
+#include <unistd.h>
+#include <sys/types.h>
+#include <errno.h>
+#include "marshall.hh"
+#include "connection.hh"
+#include "rpc.hh"
+
+cc1_plugin::connection::~connection ()
+{
+}
+
+void
+cc1_plugin::connection::print (const char *)
+{
+}
+
+cc1_plugin::status
+cc1_plugin::connection::send (char c)
+{
+  if (write (m_fd, &c, 1) != 1)
+    return FAIL;
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::connection::send (const void *buf, int len)
+{
+  if (write (m_fd, buf, len) != len)
+    return FAIL;
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::connection::require (char c)
+{
+  char result;
+
+  if (read (m_fd, &result, 1) != 1
+      || result != c)
+    return FAIL;
+
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::connection::get (void *buf, int len)
+{
+  if (read (m_fd, buf, len) != len)
+    return FAIL;
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::connection::do_wait (bool want_result)
+{
+  while (true)
+    {
+      char result;
+      fd_set read_set;
+
+      FD_ZERO (&read_set);
+      FD_SET (m_fd, &read_set);
+      if (m_aux_fd != -1)
+	FD_SET (m_aux_fd, &read_set);
+
+      int nfds = select (FD_SETSIZE, &read_set, NULL, NULL, NULL);
+      if (nfds == -1)
+	{
+	  if (errno == EINTR)
+	    continue;
+	  return FAIL;
+	}
+
+      // We have to check the stderr fd first, to avoid a possible
+      // blocking scenario when do_wait is called reentrantly.  In
+      // such a call, if we handle the primary fd first, then we may
+      // re-enter this function, read from gcc's stderr, causing the
+      // outer invocation of this function to block when trying to
+      // read.
+      if (m_aux_fd != -1 && FD_ISSET (m_aux_fd, &read_set))
+	{
+	  char buf[1024];
+	  int n = read (m_aux_fd, buf, sizeof (buf) - 1);
+	  if (n < 0)
+	    return FAIL;
+	  if (n > 0)
+	    {
+	      buf[n] = '\0';
+	      print (buf);
+	    }
+	}
+
+      if (FD_ISSET (m_fd, &read_set))
+	{
+	  int n = read (m_fd, &result, 1);
+	  if (n == 0)
+	    return want_result ? FAIL : OK;
+	  if (n != 1)
+	    return FAIL;
+
+	  switch (result)
+	    {
+	    case 'R':
+	      // The reply is ready; the caller will unmarshall it.
+	      return want_result ? OK : FAIL;
+
+	    case 'Q':
+	      // While waiting for a reply, the other side made a method
+	      // call.
+	      {
+		// Use an argument_wrapper here to simplify management
+		// of the string's lifetime.
+		argument_wrapper<char *> method_name;
+
+		if (!method_name.unmarshall (this))
+		  return FAIL;
+
+		callback_ftype *callback
+		  = m_callbacks.find_callback (method_name);
+		// The call to CALLBACK is where we may end up in a
+		// reentrant call.
+		if (callback == NULL || !callback (this))
+		  return FAIL;
+	      }
+	      break;
+
+	    default:
+	      return FAIL;
+	    }
+	}
+    }
+}
diff --git a/libcc1/connection.hh b/libcc1/connection.hh
new file mode 100644
index 0000000..242deec
--- /dev/null
+++ b/libcc1/connection.hh
@@ -0,0 +1,114 @@
+/* Plugin connection declarations
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_CONNECTION_HH
+#define CC1_PLUGIN_CONNECTION_HH
+
+#include "status.hh"
+#include "callbacks.hh"
+
+namespace cc1_plugin
+{
+  // The connection class represents one side of the connection
+  // between the gdb-side library and the gcc plugin.  It handles the
+  // low-level details of reading and writing data.
+  class connection
+  {
+  public:
+
+    connection (int fd)
+      : m_fd (fd),
+	m_aux_fd (-1),
+	m_callbacks ()
+    {
+    }
+
+    connection (int fd, int aux_fd)
+      : m_fd (fd),
+	m_aux_fd (aux_fd),
+	m_callbacks ()
+    {
+    }
+
+    virtual ~connection ();
+
+    // Send a single character.  This is used to introduce various
+    // higher-level protocol elements.
+    status send (char c);
+
+    // Send data in bulk.
+    status send (const void *buf, int len);
+
+    // Read a single byte from the connection and verify that it
+    // matches the argument C.
+    status require (char c);
+
+    // Read data in bulk.
+    status get (void *buf, int len);
+
+    // This is called after a query (remote function call) has been
+    // sent to the remote.  It waits for a response packet.  The
+    // response character is read before returning.  Any query packets
+    // sent from the remote while waiting for a response are handled
+    // by this function.
+    status wait_for_result ()
+    {
+      return do_wait (true);
+    }
+
+    // Read and respond to query packets sent by the remote.  This
+    // function returns when the connection is closed.
+    status wait_for_query ()
+    {
+      return do_wait (false);
+    }
+
+    // Register a callback with this connection.  NAME is the name of
+    // the method being registered.  FUNC is the function.  It must
+    // know how to decode its own arguments.  When a query packet is
+    // received by one of the wait_* methods, the corresponding
+    // callback is invoked.
+    void add_callback (const char *name, callback_ftype *func)
+    {
+      m_callbacks.add_callback (name, func);
+    }
+
+    virtual void print (const char *);
+
+  private:
+
+    // Declared but not defined, to prevent use.
+    connection (const connection &);
+    connection &operator= (const connection &);
+
+    // Helper function for the wait_* methods.
+    status do_wait (bool);
+
+    // The file descriptor.
+    int m_fd;
+
+    // An auxiliary file descriptor, or -1 if none.
+    int m_aux_fd;
+
+    // Callbacks associated with this connection.
+    callbacks m_callbacks;
+  };
+}
+
+#endif // CC1_PLUGIN_CONNECTION_HH
diff --git a/libcc1/findcomp.cc b/libcc1/findcomp.cc
new file mode 100644
index 0000000..f02b1df
--- /dev/null
+++ b/libcc1/findcomp.cc
@@ -0,0 +1,139 @@
+/* Find the correct compiler.
+   Copyright (C) 2014 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 <config.h>
+#include <string>
+#include <dirent.h>
+#include <stdlib.h>
+
+#include "libiberty.h"
+#include "xregex.h"
+#include "findcomp.hh"
+
+class scanner
+{
+public:
+
+  scanner (const std::string &dir)
+  {
+    m_dir = opendir (dir.c_str ());
+  }
+
+  ~scanner ()
+  {
+    if (m_dir != NULL)
+      closedir (m_dir);
+  }
+
+  const char *next ()
+  {
+    if (m_dir == NULL)
+      return NULL;
+
+    struct dirent *entry = readdir (m_dir);
+    if (entry == NULL)
+      return NULL;
+
+    return entry->d_name;
+  }
+
+private:
+
+  DIR *m_dir;
+};
+
+static bool
+search_dir (const regex_t &regexp, const std::string &dir, std::string *result)
+{
+  scanner scan (dir);
+  const char *filename;
+
+  while ((filename = scan.next ()) != NULL)
+    {
+      if (regexec (&regexp, filename, 0, NULL, 0) == 0)
+	{
+	  *result = filename;
+	  return true;
+	}
+    }
+
+  return false;
+}
+
+class tokenizer
+{
+public:
+
+  tokenizer (const char *str)
+    : m_str (str),
+      m_pos (0)
+  {
+  }
+
+  bool done () const
+  {
+    return m_pos == std::string::npos;
+  }
+
+  std::string next ()
+  {
+    std::string::size_type last_pos = m_pos;
+    std::string::size_type colon = m_str.find(':', last_pos);
+
+    std::string result;
+    if (colon == std::string::npos)
+      {
+	m_pos = colon;
+	result = m_str.substr(last_pos, colon);
+      }
+    else
+      {
+	m_pos = colon + 1;
+	result = m_str.substr(last_pos, colon - last_pos);
+      }
+    if (result == "")
+      result = ".";
+
+    return result;
+  }
+
+private:
+
+  std::string m_str;
+  std::string::size_type m_pos;
+};
+
+bool
+find_compiler (const regex_t &regexp, std::string *result)
+{
+  const char *cpath = getenv ("PATH");
+
+  if (cpath == NULL)
+    return false;
+
+  tokenizer dirs (cpath);
+  while (!dirs.done ())
+    {
+      std::string dir = dirs.next ();
+      if (search_dir (regexp, dir, result))
+	return true;
+    }
+
+  return false;
+}
diff --git a/libcc1/findcomp.hh b/libcc1/findcomp.hh
new file mode 100644
index 0000000..a55a283
--- /dev/null
+++ b/libcc1/findcomp.hh
@@ -0,0 +1,25 @@
+/* Find the correct compiler.
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_FINDCOMP_HH
+#define CC1_PLUGIN_FINDCOMP_HH
+
+extern bool find_compiler (const regex_t &regexp, std::string *result);
+
+#endif // CC1_PLUGIN_FINDCOMP_HH
diff --git a/libcc1/libcc1.cc b/libcc1/libcc1.cc
new file mode 100644
index 0000000..15320c2
--- /dev/null
+++ b/libcc1/libcc1.cc
@@ -0,0 +1,530 @@
+/* The library used by gdb.
+   Copyright (C) 2014 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>
+#include <vector>
+#include <string>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <sstream>
+#include "rpc.hh"
+#include "connection.hh"
+#include "names.hh"
+#include "callbacks.hh"
+#include "gcc-interface.h"
+#include "libiberty.h"
+#include "xregex.h"
+#include "findcomp.hh"
+#include "compiler-name.h"
+
+struct libcc1;
+
+class libcc1_connection;
+
+// The C compiler context that we hand back to our caller.
+struct libcc1 : public gcc_c_context
+{
+  libcc1 (const gcc_base_vtable *, const gcc_c_fe_vtable *);
+  ~libcc1 ();
+
+  // A convenience function to print something.
+  void print (const char *str)
+  {
+    this->print_function (this->print_datum, str);
+  }
+
+  libcc1_connection *connection;
+
+  gcc_c_oracle_function *binding_oracle;
+  gcc_c_symbol_address_function *address_oracle;
+  void *oracle_datum;
+
+  void (*print_function) (void *datum, const char *message);
+  void *print_datum;
+
+  std::vector<std::string> args;
+  std::string source_file;
+};
+
+// A local subclass of connection that holds a back-pointer to the
+// gcc_c_context object that we provide to our caller.
+class libcc1_connection : public cc1_plugin::connection
+{
+public:
+
+  libcc1_connection (int fd, int aux_fd, libcc1 *b)
+    : connection (fd, aux_fd),
+      back_ptr (b)
+  {
+  }
+
+  virtual void print (const char *buf)
+  {
+    back_ptr->print (buf);
+  }
+
+  libcc1 *back_ptr;
+};
+
+libcc1::libcc1 (const gcc_base_vtable *v,
+		const gcc_c_fe_vtable *cv)
+  : connection (NULL),
+    binding_oracle (NULL),
+    address_oracle (NULL),
+    oracle_datum (NULL),
+    print_function (NULL),
+    print_datum (NULL),
+    args (),
+    source_file ()
+{
+  base.ops = v;
+  c_ops = cv;
+}
+
+libcc1::~libcc1 ()
+{
+  delete connection;
+}
+
+\f
+
+// This is a wrapper function that is called by the RPC system and
+// that then forwards the call to the library user.  Note that the
+// return value is not used; the type cannot be 'void' due to
+// limitations in our simple RPC.
+int
+call_binding_oracle (cc1_plugin::connection *conn,
+		     enum gcc_c_oracle_request request,
+		     const char *identifier)
+{
+  libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
+
+  self->binding_oracle (self->oracle_datum, self, request, identifier);
+  return 1;
+}
+
+// This is a wrapper function that is called by the RPC system and
+// that then forwards the call to the library user.
+gcc_address
+call_symbol_address (cc1_plugin::connection *conn, const char *identifier)
+{
+  libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
+
+  return self->address_oracle (self->oracle_datum, self, identifier);
+}
+
+\f
+
+static void
+set_callbacks (struct gcc_c_context *s,
+	       gcc_c_oracle_function *binding_oracle,
+	       gcc_c_symbol_address_function *address_oracle,
+	       void *datum)
+{
+  libcc1 *self = (libcc1 *) s;
+
+  self->binding_oracle = binding_oracle;
+  self->address_oracle = address_oracle;
+  self->oracle_datum = datum;
+}
+
+// Instances of these rpc<> template functions are installed into the
+// "c_vtable".  These functions are parameterized by type and method
+// name and forward the call via the connection.
+
+template<typename R, const char *&NAME>
+R rpc (struct gcc_c_context *s)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result))
+    return 0;
+  return result;
+}
+
+template<typename R, const char *&NAME, typename A>
+R rpc (struct gcc_c_context *s, A arg)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result, arg))
+    return 0;
+  return result;
+}
+
+template<typename R, const char *&NAME, typename A1, typename A2>
+R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2))
+    return 0;
+  return result;
+}
+
+template<typename R, const char *&NAME, typename A1, typename A2, typename A3>
+R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3))
+    return 0;
+  return result;
+}
+
+template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
+	 typename A4>
+R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
+			 arg4))
+    return 0;
+  return result;
+}
+
+template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
+	 typename A4, typename A5>
+R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
+			 arg4, arg5))
+    return 0;
+  return result;
+}
+
+template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
+	 typename A4, typename A5, typename A6, typename A7>
+R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5,
+       A6 arg6, A7 arg7)
+{
+  libcc1 *self = (libcc1 *) s;
+  R result;
+
+  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
+			 arg4, arg5, arg6, arg7))
+    return 0;
+  return result;
+}
+
+static const struct gcc_c_fe_vtable c_vtable =
+{
+  GCC_C_FE_VERSION_0,
+  set_callbacks,
+
+#define GCC_METHOD0(R, N) \
+  rpc<R, cc1_plugin::N>,
+#define GCC_METHOD1(R, N, A) \
+  rpc<R, cc1_plugin::N, A>,
+#define GCC_METHOD2(R, N, A, B) \
+  rpc<R, cc1_plugin::N, A, B>,
+#define GCC_METHOD3(R, N, A, B, C) \
+  rpc<R, cc1_plugin::N, A, B, C>,
+#define GCC_METHOD4(R, N, A, B, C, D) \
+  rpc<R, cc1_plugin::N, A, B, C, D>,
+#define GCC_METHOD5(R, N, A, B, C, D, E) \
+  rpc<R, cc1_plugin::N, A, B, C, D, E>,
+#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
+  rpc<R, cc1_plugin::N, A, B, C, D, E, F, G>,
+
+#include "gcc-c-fe.def"
+
+#undef GCC_METHOD0
+#undef GCC_METHOD1
+#undef GCC_METHOD2
+#undef GCC_METHOD3
+#undef GCC_METHOD4
+#undef GCC_METHOD5
+#undef GCC_METHOD7
+};
+
+\f
+
+// Construct an appropriate regexp to match the compiler name.
+static std::string
+make_regexp (const char *triplet_regexp, const char *compiler)
+{
+  std::stringstream buf;
+
+  buf << "^" << triplet_regexp << "-";
+
+  // Quote the compiler name in case it has something funny in it.
+  for (const char *p = compiler; *p; ++p)
+    {
+      switch (*p)
+	{
+	case '.':
+	case '^':
+	case '$':
+	case '*':
+	case '+':
+	case '?':
+	case '(':
+	case ')':
+	case '[':
+	case '{':
+	case '\\':
+	case '|':
+	  buf << '\\';
+	  break;
+	}
+      buf << *p;
+    }
+  buf << "$";
+
+  return buf.str ();
+}
+
+static char *
+libcc1_set_arguments (struct gcc_base_context *s,
+		      const char *triplet_regexp,
+		      int argc, char **argv)
+{
+  libcc1 *self = (libcc1 *) s;
+  regex_t triplet;
+  int code;
+
+  std::string rx = make_regexp (triplet_regexp, COMPILER_NAME);
+  code = regcomp (&triplet, rx.c_str (), REG_EXTENDED | REG_NOSUB);
+  if (code != 0)
+    {
+      size_t len = regerror (code, &triplet, NULL, 0);
+      char err[len];
+
+      regerror (code, &triplet, err, len);
+
+      return concat ("Could not compile regexp \"",
+		     rx.c_str (),
+		     "\": ",
+		     err,
+		     (char *) NULL);
+    }
+
+  std::string compiler;
+  if (!find_compiler (triplet, &compiler))
+    {
+      regfree (&triplet);
+      return concat ("Could not find a compiler matching \"",
+		     rx.c_str (),
+		     "\"",
+		     (char *) NULL);
+    }
+  regfree (&triplet);
+
+  self->args.push_back (compiler);
+
+  for (int i = 0; i < argc; ++i)
+    self->args.push_back (argv[i]);
+
+  return NULL;
+}
+
+static void
+libcc1_set_source_file (struct gcc_base_context *s,
+			const char *file)
+{
+  libcc1 *self = (libcc1 *) s;
+
+  self->source_file = file;
+}
+
+static void
+libcc1_set_print_callback (struct gcc_base_context *s,
+			   void (*print_function) (void *datum,
+						   const char *message),
+			   void *datum)
+{
+  libcc1 *self = (libcc1 *) s;
+
+  self->print_function = print_function;
+  self->print_datum = datum;
+}
+
+static int
+fork_exec (libcc1 *self, char **argv, int spair_fds[2], int stderr_fds[2])
+{
+  pid_t child_pid = fork ();
+
+  if (child_pid == -1)
+    {
+      close (spair_fds[0]);
+      close (spair_fds[1]);
+      close (stderr_fds[0]);
+      close (stderr_fds[1]);
+      return 0;
+    }
+
+  if (child_pid == 0)
+    {
+      // Child.
+      dup2 (stderr_fds[1], 1);
+      dup2 (stderr_fds[1], 2);
+      close (stderr_fds[0]);
+      close (stderr_fds[1]);
+      close (spair_fds[0]);
+
+      execvp (argv[0], argv);
+      _exit (127);
+    }
+  else
+    {
+      // Parent.
+      close (spair_fds[1]);
+      close (stderr_fds[1]);
+
+      cc1_plugin::status result = cc1_plugin::FAIL;
+      if (self->connection->send ('H')
+	  && ::cc1_plugin::marshall (self->connection, GCC_C_FE_VERSION_0))
+	result = self->connection->wait_for_query ();
+
+      close (spair_fds[0]);
+      close (stderr_fds[0]);
+
+      while (true)
+	{
+	  int status;
+
+	  if (waitpid (child_pid, &status, 0) == -1)
+	    {
+	      if (errno != EINTR)
+		return 0;
+	    }
+
+	  if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
+	    return 0;
+	  break;
+	}
+
+      if (!result)
+	return 0;
+      return 1;
+    }
+}
+
+static int
+libcc1_compile (struct gcc_base_context *s,
+		const char *filename,
+		int verbose)
+{
+  libcc1 *self = (libcc1 *) s;
+
+  int fds[2];
+  if (socketpair (AF_LOCAL, SOCK_STREAM, 0, fds) != 0)
+    {
+      self->print ("could not create socketpair\n");
+      return 0;
+    }
+
+  int stderr_fds[2];
+  if (pipe (stderr_fds) != 0)
+    {
+      self->print ("could not create pipe\n");
+      close (fds[0]);
+      close (fds[1]);
+      return 0;
+    }
+
+  self->args.push_back ("-fplugin=libcc1plugin");
+  char buf[100];
+  if (snprintf (buf, sizeof (buf), "-fplugin-arg-libcc1plugin-fd=%d", fds[1])
+      >= (long) sizeof (buf))
+    abort ();
+  self->args.push_back (buf);
+
+  self->args.push_back (self->source_file);
+  self->args.push_back ("-c");
+  self->args.push_back ("-o");
+  self->args.push_back (filename);
+  if (verbose)
+    self->args.push_back ("-v");
+
+  self->connection = new libcc1_connection (fds[0], stderr_fds[0], self);
+
+  cc1_plugin::callback_ftype *fun
+    = cc1_plugin::callback<int,
+			   enum gcc_c_oracle_request,
+			   const char *,
+			   call_binding_oracle>;
+  self->connection->add_callback ("binding_oracle", fun);
+
+  fun = cc1_plugin::callback<gcc_address,
+			     const char *,
+			     call_symbol_address>;
+  self->connection->add_callback ("address_oracle", fun);
+
+  char **argv = new (std::nothrow) char *[self->args.size () + 1];
+  if (argv == NULL)
+    return 0;
+
+  for (unsigned int i = 0; i < self->args.size (); ++i)
+    argv[i] = const_cast<char *> (self->args[i].c_str ());
+  argv[self->args.size ()] = NULL;
+
+  return fork_exec (self, argv, fds, stderr_fds);
+}
+
+static void
+libcc1_destroy (struct gcc_base_context *s)
+{
+  libcc1 *self = (libcc1 *) s;
+
+  delete self;
+}
+
+static const struct gcc_base_vtable vtable =
+{
+  GCC_FE_VERSION_0,
+  libcc1_set_arguments,
+  libcc1_set_source_file,
+  libcc1_set_print_callback,
+  libcc1_compile,
+  libcc1_destroy
+};
+
+extern "C" gcc_c_fe_context_function gcc_c_fe_context;
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+
+extern "C"
+struct gcc_c_context *
+gcc_c_fe_context (enum gcc_base_api_version base_version,
+		  enum gcc_c_api_version c_version)
+{
+  if (base_version != GCC_FE_VERSION_0 || c_version != GCC_C_FE_VERSION_0)
+    return NULL;
+
+  return new libcc1 (&vtable, &c_vtable);
+}
diff --git a/libcc1/libcc1.sym b/libcc1/libcc1.sym
new file mode 100644
index 0000000..86b1e3e
--- /dev/null
+++ b/libcc1/libcc1.sym
@@ -0,0 +1 @@
+gcc_c_fe_context
diff --git a/libcc1/libcc1plugin.sym b/libcc1/libcc1plugin.sym
new file mode 100644
index 0000000..05d0f7b
--- /dev/null
+++ b/libcc1/libcc1plugin.sym
@@ -0,0 +1,2 @@
+plugin_init
+plugin_is_GPL_compatible
diff --git a/libcc1/marshall.cc b/libcc1/marshall.cc
new file mode 100644
index 0000000..9119de6
--- /dev/null
+++ b/libcc1/marshall.cc
@@ -0,0 +1,166 @@
+/* Marshalling and unmarshalling.
+   Copyright (C) 2014 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>
+#include <new>
+#include <string.h>
+#include "marshall.hh"
+#include "connection.hh"
+
+cc1_plugin::status
+cc1_plugin::unmarshall_check (connection *conn, unsigned long long check)
+{
+  unsigned long long r;
+
+  if (!unmarshall (conn, &r))
+    return FAIL;
+  return check == r ? OK : FAIL;
+}
+
+cc1_plugin::status
+cc1_plugin::marshall_intlike (connection *conn, unsigned long long val)
+{
+  if (!conn->send ('i'))
+    return FAIL;
+  return conn->send (&val, sizeof (val));
+}
+
+cc1_plugin::status
+cc1_plugin::unmarshall_intlike (connection *conn, unsigned long long *result)
+{
+  if (!conn->require ('i'))
+    return FAIL;
+  return conn->get (result, sizeof (*result));
+}
+
+cc1_plugin::status
+cc1_plugin::unmarshall (connection *conn, enum gcc_c_symbol_kind *result)
+{
+  protocol_int p;
+  if (!unmarshall_intlike (conn, &p))
+    return FAIL;
+  *result = (enum gcc_c_symbol_kind) p;
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::unmarshall (connection *conn, enum gcc_c_oracle_request *result)
+{
+  protocol_int p;
+  if (!unmarshall_intlike (conn, &p))
+    return FAIL;
+  *result = (enum gcc_c_oracle_request) p;
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::unmarshall (connection *conn, enum gcc_qualifiers *result)
+{
+  protocol_int p;
+  if (!unmarshall_intlike (conn, &p))
+    return FAIL;
+  *result = (enum gcc_qualifiers) p;
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::marshall (connection *conn, const char *str)
+{
+  if (!conn->send ('s'))
+    return FAIL;
+
+  unsigned long long len = str == NULL ? -1ULL : strlen (str);
+  if (!conn->send (&len, sizeof (len)))
+    return FAIL;
+
+  if (str == NULL)
+    return OK;
+
+  return conn->send (str, len);
+}
+
+cc1_plugin::status
+cc1_plugin::unmarshall (connection *conn, char **result)
+{
+  unsigned long long len;
+
+  if (!conn->require ('s'))
+    return FAIL;
+  if (!conn->get (&len, sizeof (len)))
+    return FAIL;
+
+  if (len == -1ULL)
+    {
+      *result = NULL;
+      return OK;
+    }
+
+  char *str = new (std::nothrow) char[len + 1];
+  if (str == NULL)
+    return FAIL;
+
+  if (!conn->get (str, len))
+    {
+      delete[] str;
+      return FAIL;
+    }
+
+  str[len] = '\0';
+  *result = str;
+
+  return OK;
+}
+
+cc1_plugin::status
+cc1_plugin::marshall (connection *conn, const gcc_type_array *a)
+{
+  if (!conn->send ('a'))
+    return FAIL;
+
+  unsigned long long r = a->n_elements;
+  if (!conn->send (&r, sizeof (r)))
+    return FAIL;
+
+  return conn->send (a->elements, r * sizeof (a->elements[0]));
+}
+
+cc1_plugin::status
+cc1_plugin::unmarshall (connection *conn, gcc_type_array **result)
+{
+  unsigned long long len;
+
+  if (!conn->require ('a'))
+    return FAIL;
+  if (!conn->get (&len, sizeof (len)))
+    return FAIL;
+
+  *result = new gcc_type_array;
+
+  (*result)->n_elements = len;
+  (*result)->elements = new gcc_type[len];
+
+  if (!conn->get ((*result)->elements, len * sizeof ((*result)->elements[0])))
+    {
+      delete[] (*result)->elements;
+      delete *result;
+      return FAIL;
+    }
+
+  return OK;
+}
diff --git a/libcc1/marshall.hh b/libcc1/marshall.hh
new file mode 100644
index 0000000..3f936e7
--- /dev/null
+++ b/libcc1/marshall.hh
@@ -0,0 +1,93 @@
+/* Marshalling and unmarshalling.
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_MARSHALL_HH
+#define CC1_PLUGIN_MARSHALL_HH
+
+#include "status.hh"
+#include "gcc-c-interface.h"
+
+namespace cc1_plugin
+{
+  class connection;
+
+  // Only a single kind of integer is ever sent over the wire, and
+  // this is it.
+  typedef unsigned long long protocol_int;
+
+  // Read an integer from the connection and verify that it has the
+  // value V.
+  status unmarshall_check (connection *, protocol_int v);
+
+  // Write an integer, prefixed with the integer type marker, to the
+  // connection.
+  status marshall_intlike (connection *, protocol_int);
+
+  // Read a type marker from the connection and verify that it is an
+  // integer type marker.  If not, return FAIL.  If so, read an
+  // integer store it in the out argument.
+  status unmarshall_intlike (connection *, protocol_int *);
+
+  // A template function that can handle marshalling various integer
+  // objects to the connection.
+  template<typename T>
+  status marshall (connection *conn, T scalar)
+  {
+    return marshall_intlike (conn, scalar);
+  }
+
+  // A template function that can handle unmarshalling various integer
+  // objects from the connection.  Note that this can't be
+  // instantiated for enum types.  Note also that there's no way at
+  // the protocol level to distinguish different int types.
+  template<typename T>
+  status unmarshall (connection *conn, T *scalar)
+  {
+    protocol_int result;
+
+    if (!unmarshall_intlike (conn, &result))
+      return FAIL;
+    *scalar = result;
+    return OK;
+  }
+
+  // Unmarshallers for some specific enum types.  With C++11 we
+  // wouldn't need these, as we could add type traits to the scalar
+  // unmarshaller.
+  status unmarshall (connection *, enum gcc_c_symbol_kind *);
+  status unmarshall (connection *, enum gcc_qualifiers *);
+  status unmarshall (connection *, enum gcc_c_oracle_request *);
+
+  // Send a string type marker followed by a string.
+  status marshall (connection *, const char *);
+
+  // Read a string type marker followed by a string.  The caller is
+  // responsible for freeing the resulting string using 'delete[]'.
+  status unmarshall (connection *, char **);
+
+  // Send a gcc_type_array marker followed by the array.
+  status marshall (connection *, const gcc_type_array *);
+
+  // Read a gcc_type_array marker, followed by a gcc_type_array.  The
+  // resulting array must be freed by the caller, using 'delete[]' on
+  // the elements, and 'delete' on the array object itself.
+  status unmarshall (connection *, struct gcc_type_array **);
+};
+
+#endif // CC1_PLUGIN_MARSHALL_HH
diff --git a/libcc1/names.cc b/libcc1/names.cc
new file mode 100644
index 0000000..5ddfa7b
--- /dev/null
+++ b/libcc1/names.cc
@@ -0,0 +1,46 @@
+/* String definitions.
+   Copyright (C) 2014 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>
+#include "names.hh"
+
+#define GCC_METHOD0(R, N) \
+  const char *cc1_plugin::N = # N;
+#define GCC_METHOD1(R, N, A) \
+  const char *cc1_plugin::N = # N;
+#define GCC_METHOD2(R, N, A, B) \
+  const char *cc1_plugin::N = # N;
+#define GCC_METHOD3(R, N, A, B, C) \
+  const char *cc1_plugin::N = # N;
+#define GCC_METHOD4(R, N, A, B, C, D) \
+  const char *cc1_plugin::N = # N;
+#define GCC_METHOD5(R, N, A, B, C, D, E) \
+  const char *cc1_plugin::N = # N;
+#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
+  const char *cc1_plugin::N = # N;
+
+#include "gcc-c-fe.def"
+
+#undef GCC_METHOD0
+#undef GCC_METHOD1
+#undef GCC_METHOD2
+#undef GCC_METHOD3
+#undef GCC_METHOD4
+#undef GCC_METHOD5
+#undef GCC_METHOD7
diff --git a/libcc1/names.hh b/libcc1/names.hh
new file mode 100644
index 0000000..9bda8d5
--- /dev/null
+++ b/libcc1/names.hh
@@ -0,0 +1,55 @@
+/* String declarations.
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_NAMES_HH
+#define CC1_PLUGIN_NAMES_HH
+
+namespace cc1_plugin
+{
+  // This code defines global string constants, one for each method in
+  // gcc-c-fe.def.  This is needed so that they can be used as
+  // template arguments elsewhere.
+
+#define GCC_METHOD0(R, N) \
+  extern const char *N;
+#define GCC_METHOD1(R, N, A) \
+  extern const char *N;
+#define GCC_METHOD2(R, N, A, B) \
+  extern const char *N;
+#define GCC_METHOD3(R, N, A, B, C) \
+  extern const char *N;
+#define GCC_METHOD4(R, N, A, B, C, D) \
+  extern const char *N;
+#define GCC_METHOD5(R, N, A, B, C, D, E) \
+  extern const char *N;
+#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
+  extern const char *N;
+
+#include "gcc-c-fe.def"
+
+#undef GCC_METHOD0
+#undef GCC_METHOD1
+#undef GCC_METHOD2
+#undef GCC_METHOD3
+#undef GCC_METHOD4
+#undef GCC_METHOD5
+#undef GCC_METHOD7
+};
+
+#endif // CC1_PLUGIN_NAMES_HH
diff --git a/libcc1/plugin.cc b/libcc1/plugin.cc
new file mode 100644
index 0000000..fbb49d3
--- /dev/null
+++ b/libcc1/plugin.cc
@@ -0,0 +1,919 @@
+/* Library interface to C front end
+   Copyright (C) 2014 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 "gcc-interface.h"
+#include "tree-core.h"
+#include "wide-int.h"
+#include "stor-layout.h"
+#include "c-tree.h"
+#include "toplev.h"
+#include "timevar.h"
+#include "hash-table.h"
+#include "tm.h"
+#include "c-family/c-pragma.h"
+#include "c-lang.h"
+#include "diagnostic.h"
+#include "langhooks.h"
+#include "langhooks-def.h"
+
+#include "callbacks.hh"
+#include "connection.hh"
+#include "rpc.hh"
+
+#include <string>
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+int plugin_is_GPL_compatible;
+#ifdef __GNUC__
+#pragma GCC visibility pop
+#endif
+
+\f
+
+// 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);
+}
+
+\f
+
+static unsigned long long
+convert_out (tree t)
+{
+  return (unsigned long long) (uintptr_t) t;
+}
+
+static tree
+convert_in (unsigned long long v)
+{
+  return (tree) (uintptr_t) v;
+}
+
+\f
+
+struct decl_addr_value
+{
+  tree decl;
+  tree address;
+};
+
+struct decl_addr_hasher : typed_free_remove<decl_addr_value>
+{
+  typedef decl_addr_value value_type;
+  typedef decl_addr_value compare_type;
+
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+decl_addr_hasher::hash (const value_type *e)
+{
+  return IDENTIFIER_HASH_VALUE (DECL_NAME (e->decl));
+}
+
+inline bool
+decl_addr_hasher::equal (const value_type *p1, const compare_type *p2)
+{
+  return p1->decl == p2->decl;
+}
+
+\f
+
+struct string_hasher : typed_noop_remove<char>
+{
+  typedef char value_type;
+  typedef char compare_type;
+
+  static inline hashval_t hash (const value_type *s)
+  {
+    return htab_hash_string (s);
+  }
+
+  static inline bool equal (const value_type *p1, const value_type *p2)
+  {
+    return strcmp (p1, p2) == 0;
+  }
+};
+
+\f
+
+// A wrapper for pushdecl that doesn't let gdb have a chance to
+// instantiate a symbol.
+
+static void
+pushdecl_safe (tree decl)
+{
+  void (*save) (enum c_oracle_request, tree identifier);
+
+  save = c_binding_oracle;
+  c_binding_oracle = NULL;
+  pushdecl (decl);
+  c_binding_oracle = save;
+}
+
+\f
+
+struct plugin_context : public cc1_plugin::connection
+{
+  plugin_context (int fd);
+
+  // Map decls to addresses.
+  hash_table<decl_addr_hasher> address_map;
+
+  // A collection of trees that are preserved for the GC.
+  hash_table< pointer_hash<tree_node> > preserved;
+
+  // File name cache.
+  hash_table<string_hasher> file_names;
+
+  // Perform GC marking.
+  void mark ();
+
+  // Preserve a tree during the plugin's operation.
+  tree preserve (tree t)
+  {
+    tree_node **slot = preserved.find_slot (t, INSERT);
+    *slot = t;
+    return t;
+  }
+
+  source_location get_source_location (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);
+    source_location loc = linemap_line_start (line_table, line_number, 0);
+    linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+    return loc;
+  }
+
+private:
+
+  // Add a file name to FILE_NAMES and return the canonical copy.
+  const char *intern_filename (const char *filename)
+  {
+    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;
+  }
+};
+
+static plugin_context *current_context;
+
+\f
+
+plugin_context::plugin_context (int fd)
+  : cc1_plugin::connection (fd),
+    address_map (),
+    preserved (),
+    file_names ()
+{
+  address_map.create (20);
+  preserved.create (20);
+  file_names.create (20);
+}
+
+void
+plugin_context::mark ()
+{
+  for (hash_table<decl_addr_hasher>::iterator it = address_map.begin ();
+       it != address_map.end ();
+       ++it)
+    {
+      ggc_mark ((*it).decl);
+      ggc_mark ((*it).address);
+    }
+
+  for (hash_table< pointer_hash<tree_node> >::iterator it = preserved.begin ();
+       it != preserved.end ();
+       ++it)
+    ggc_mark (&*it);
+}
+
+static void
+plugin_binding_oracle (enum c_oracle_request kind, tree identifier)
+{
+  enum gcc_c_oracle_request request;
+
+  gcc_assert (current_context != NULL);
+
+  switch (kind)
+    {
+    case C_ORACLE_SYMBOL:
+      request = GCC_C_ORACLE_SYMBOL;
+      break;
+    case C_ORACLE_TAG:
+      request = GCC_C_ORACLE_TAG;
+      break;
+    case C_ORACLE_LABEL:
+      request = GCC_C_ORACLE_LABEL;
+      break;
+    default:
+      abort ();
+    }
+
+  int ignore;
+  cc1_plugin::call (current_context, "binding_oracle", &ignore,
+		    request, IDENTIFIER_POINTER (identifier));
+}
+
+static void
+plugin_pragma_user_expression (cpp_reader *)
+{
+  c_binding_oracle = plugin_binding_oracle;
+}
+
+static void
+plugin_init_extra_pragmas (void *, void *)
+{
+  c_register_pragma ("GCC", "user_expression", plugin_pragma_user_expression);
+}
+
+\f
+
+// Maybe rewrite a decl to its address.
+static tree
+address_rewriter (tree *in, int *walk_subtrees, void *arg)
+{
+  plugin_context *ctx = (plugin_context *) arg;
+
+  if (!DECL_P (*in) || DECL_NAME (*in) == NULL_TREE)
+    return NULL_TREE;
+
+  decl_addr_value value;
+  value.decl = *in;
+  decl_addr_value *found_value = ctx->address_map.find (&value);
+  if (found_value != NULL)
+    {
+      // At this point we don't need VLA sizes for gdb-supplied
+      // variables, and having them here confuses later passes, so we
+      // drop them.
+      if (C_TYPE_VARIABLE_SIZE (TREE_TYPE (*in)))
+	{
+	  TREE_TYPE (*in)
+	    = build_array_type_nelts (TREE_TYPE (TREE_TYPE (*in)), 1);
+	  DECL_SIZE (*in) = TYPE_SIZE (TREE_TYPE (*in));
+	  DECL_SIZE_UNIT (*in) = TYPE_SIZE_UNIT (TREE_TYPE (*in));
+	}
+    }
+  else if (DECL_IS_BUILTIN (*in))
+    {
+      gcc_address address;
+
+      if (!cc1_plugin::call (ctx, "address_oracle", &address,
+			     IDENTIFIER_POINTER (DECL_NAME (*in))))
+	return NULL_TREE;
+      if (address == 0)
+	return NULL_TREE;
+
+      // Insert the decl into the address map in case it is referenced
+      // again.
+      value.address = build_int_cst_type (ptr_type_node, address);
+      decl_addr_value **slot = ctx->address_map.find_slot (&value, INSERT);
+      gcc_assert (*slot == NULL);
+      *slot
+	= static_cast<decl_addr_value *> (xmalloc (sizeof (decl_addr_value)));
+      **slot = value;
+      found_value = *slot;
+    }
+  else
+    return NULL_TREE;
+
+  if (found_value->address != error_mark_node)
+    {
+      // We have an address for the decl, so rewrite the tree.
+      tree ptr_type = build_pointer_type (TREE_TYPE (*in));
+      *in = fold_build1 (INDIRECT_REF, TREE_TYPE (*in),
+			 fold_build1 (CONVERT_EXPR, ptr_type,
+				      found_value->address));
+    }
+
+  *walk_subtrees = 0;
+
+  return NULL_TREE;
+}
+
+// When generating code for gdb, we want to be able to use absolute
+// addresses to refer to otherwise external objects that gdb knows
+// about.  gdb passes in these addresses when building decls, and then
+// before gimplification we go through the trees, rewriting uses to
+// the equivalent of "*(TYPE *) ADDR".
+static void
+rewrite_decls_to_addresses (void *function_in, void *)
+{
+  tree function = (tree) function_in;
+
+  // Do nothing if we're not in gdb.
+  if (current_context == NULL)
+    return;
+
+  walk_tree (&DECL_SAVED_TREE (function), address_rewriter, current_context,
+	     NULL);
+}
+
+\f
+
+gcc_decl
+plugin_build_decl (cc1_plugin::connection *self,
+		   const char *name,
+		   enum gcc_c_symbol_kind sym_kind,
+		   gcc_type sym_type_in,
+		   const char *substitution_name,
+		   gcc_address address,
+		   const char *filename,
+		   unsigned int line_number)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  tree identifier = get_identifier (name);
+  enum tree_code code;
+  tree decl;
+  tree sym_type = convert_in (sym_type_in);
+
+  switch (sym_kind)
+    {
+    case GCC_C_SYMBOL_FUNCTION:
+      code = FUNCTION_DECL;
+      break;
+
+    case GCC_C_SYMBOL_VARIABLE:
+      code = VAR_DECL;
+      break;
+
+    case GCC_C_SYMBOL_TYPEDEF:
+      code = TYPE_DECL;
+      break;
+
+    case GCC_C_SYMBOL_LABEL:
+      // FIXME: we aren't ready to handle labels yet.
+      // It isn't clear how to translate them properly
+      // and in any case a "goto" isn't likely to work.
+      return convert_out (error_mark_node);
+
+    default:
+      abort ();
+    }
+
+  source_location loc = ctx->get_source_location (filename, line_number);
+
+  decl = build_decl (loc, code, identifier, sym_type);
+  TREE_USED (decl) = 1;
+  TREE_ADDRESSABLE (decl) = 1;
+
+  if (sym_kind != GCC_C_SYMBOL_TYPEDEF)
+    {
+      decl_addr_value value;
+
+      value.decl = decl;
+      if (substitution_name != NULL)
+	{
+	  // If the translator gave us a name without a binding,
+	  // we can just substitute error_mark_node, since we know the
+	  // translator will be reporting an error anyhow.
+	  value.address
+	    = lookup_name (get_identifier (substitution_name));
+	  if (value.address == NULL_TREE)
+	    value.address = error_mark_node;
+	}
+      else
+	value.address = build_int_cst_type (ptr_type_node, address);
+      decl_addr_value **slot = ctx->address_map.find_slot (&value, INSERT);
+      gcc_assert (*slot == NULL);
+      *slot
+	= static_cast<decl_addr_value *> (xmalloc (sizeof (decl_addr_value)));
+      **slot = value;
+    }
+
+  return convert_out (ctx->preserve (decl));
+}
+
+int
+plugin_bind (cc1_plugin::connection *,
+	     gcc_decl decl_in, int is_global)
+{
+  tree decl = convert_in (decl_in);
+  c_bind (DECL_SOURCE_LOCATION (decl), decl, is_global);
+  rest_of_decl_compilation (decl, is_global, 0);
+  return 1;
+}
+
+int
+plugin_tagbind (cc1_plugin::connection *self,
+		const char *name, gcc_type tagged_type,
+		const char *filename, unsigned int line_number)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  c_pushtag (ctx->get_source_location (filename, line_number),
+	     get_identifier (name), convert_in (tagged_type));
+  return 1;
+}
+
+gcc_type
+plugin_build_pointer_type (cc1_plugin::connection *,
+			   gcc_type base_type)
+{
+  // No need to preserve a pointer type as the base type is preserved.
+  return convert_out (build_pointer_type (convert_in (base_type)));
+}
+
+gcc_type
+plugin_build_record_type (cc1_plugin::connection *self)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (make_node (RECORD_TYPE)));
+}
+
+gcc_type
+plugin_build_union_type (cc1_plugin::connection *self)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (make_node (UNION_TYPE)));
+}
+
+int
+plugin_build_add_field (cc1_plugin::connection *,
+			gcc_type record_or_union_type_in,
+			const char *field_name,
+			gcc_type field_type_in,
+			unsigned long bitsize,
+			unsigned long bitpos)
+{
+  tree record_or_union_type = convert_in (record_or_union_type_in);
+  tree field_type = convert_in (field_type_in);
+
+  gcc_assert (TREE_CODE (record_or_union_type) == RECORD_TYPE
+	      || TREE_CODE (record_or_union_type) == UNION_TYPE);
+
+  /* Note that gdb does not preserve the location of field decls, so
+     we can't provide a decent location here.  */
+  tree decl = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+			  get_identifier (field_name), field_type);
+  DECL_FIELD_CONTEXT (decl) = record_or_union_type;
+
+  if (TREE_CODE (field_type) == INTEGER_TYPE
+      && TYPE_PRECISION (field_type) != bitsize)
+    {
+      DECL_BIT_FIELD_TYPE (decl) = field_type;
+      TREE_TYPE (decl)
+	= c_build_bitfield_integer_type (bitsize, TYPE_UNSIGNED (field_type));
+    }
+
+  DECL_MODE (decl) = TYPE_MODE (TREE_TYPE (decl));
+
+  // There's no way to recover this from DWARF.
+  SET_DECL_OFFSET_ALIGN (decl, TYPE_PRECISION (pointer_sized_int_node));
+
+  tree pos = bitsize_int (bitpos);
+  pos_from_bit (&DECL_FIELD_OFFSET (decl), &DECL_FIELD_BIT_OFFSET (decl),
+		DECL_OFFSET_ALIGN (decl), pos);
+
+  DECL_SIZE (decl) = bitsize_int (bitsize);
+  DECL_SIZE_UNIT (decl) = size_int ((bitsize + BITS_PER_UNIT - 1)
+				    / BITS_PER_UNIT);
+
+  DECL_CHAIN (decl) = TYPE_FIELDS (record_or_union_type);
+  TYPE_FIELDS (record_or_union_type) = decl;
+
+  return 1;
+}
+
+int
+plugin_finish_record_or_union (cc1_plugin::connection *,
+			       gcc_type record_or_union_type_in,
+			       unsigned long size_in_bytes)
+{
+  tree record_or_union_type = convert_in (record_or_union_type_in);
+
+  gcc_assert (TREE_CODE (record_or_union_type) == RECORD_TYPE
+	      || TREE_CODE (record_or_union_type) == UNION_TYPE);
+
+  /* We built the field list in reverse order, so fix it now.  */
+  TYPE_FIELDS (record_or_union_type)
+    = nreverse (TYPE_FIELDS (record_or_union_type));
+
+  if (TREE_CODE (record_or_union_type) == UNION_TYPE)
+    {
+      /* Unions can just be handled by the generic code.  */
+      layout_type (record_or_union_type);
+    }
+  else
+    {
+      // FIXME there's no way to get this from DWARF,
+      // or even, it seems, a particularly good way to deduce it.
+      TYPE_ALIGN (record_or_union_type)
+	= TYPE_PRECISION (pointer_sized_int_node);
+
+      TYPE_SIZE (record_or_union_type) = bitsize_int (size_in_bytes
+						      * BITS_PER_UNIT);
+      TYPE_SIZE_UNIT (record_or_union_type) = size_int (size_in_bytes);
+
+      compute_record_mode (record_or_union_type);
+      finish_bitfield_layout (record_or_union_type);
+      // FIXME we have no idea about TYPE_PACKED
+    }
+
+  return 1;
+}
+
+gcc_type
+plugin_build_enum_type (cc1_plugin::connection *self,
+			gcc_type underlying_int_type_in)
+{
+  tree underlying_int_type = convert_in (underlying_int_type_in);
+
+  if (underlying_int_type == error_mark_node)
+    return convert_out (error_mark_node);
+
+  tree result = make_node (ENUMERAL_TYPE);
+
+  TYPE_PRECISION (result) = TYPE_PRECISION (underlying_int_type);
+  TYPE_UNSIGNED (result) = TYPE_UNSIGNED (underlying_int_type);
+
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (result));
+}
+
+int
+plugin_build_add_enum_constant (cc1_plugin::connection *,
+				gcc_type enum_type_in,
+				const char *name,
+				unsigned long value)
+{
+  tree cst, decl, cons;
+  tree enum_type = convert_in (enum_type_in);
+
+  gcc_assert (TREE_CODE (enum_type) == ENUMERAL_TYPE);
+
+  cst = build_int_cst (enum_type, value);
+  /* Note that gdb does not preserve the location of enum constants,
+     so we can't provide a decent location here.  */
+  decl = build_decl (BUILTINS_LOCATION, CONST_DECL,
+		     get_identifier (name), enum_type);
+  DECL_INITIAL (decl) = cst;
+  pushdecl_safe (decl);
+
+  cons = tree_cons (DECL_NAME (decl), cst, TYPE_VALUES (enum_type));
+  TYPE_VALUES (enum_type) = cons;
+
+  return 1;
+}
+
+int
+plugin_finish_enum_type (cc1_plugin::connection *,
+			 gcc_type enum_type_in)
+{
+  tree enum_type = convert_in (enum_type_in);
+  tree minnode, maxnode, iter;
+
+  iter = TYPE_VALUES (enum_type);
+  minnode = maxnode = TREE_VALUE (iter);
+  for (iter = TREE_CHAIN (iter);
+       iter != NULL_TREE;
+       iter = TREE_CHAIN (iter))
+    {
+      tree value = TREE_VALUE (iter);
+      if (tree_int_cst_lt (maxnode, value))
+	maxnode = value;
+      if (tree_int_cst_lt (value, minnode))
+	minnode = value;
+    }
+  TYPE_MIN_VALUE (enum_type) = minnode;
+  TYPE_MAX_VALUE (enum_type) = maxnode;
+
+  layout_type (enum_type);
+
+  return 1;
+}
+
+gcc_type
+plugin_build_function_type (cc1_plugin::connection *self,
+			    gcc_type return_type_in,
+			    const struct gcc_type_array *argument_types_in,
+			    int is_varargs)
+{
+  tree *argument_types;
+  tree return_type = convert_in (return_type_in);
+  tree result;
+
+  argument_types = new tree[argument_types_in->n_elements];
+  for (int i = 0; i < argument_types_in->n_elements; ++i)
+    argument_types[i] = convert_in (argument_types_in->elements[i]);
+
+  if (is_varargs)
+    result = build_varargs_function_type_array (return_type,
+						argument_types_in->n_elements,
+						argument_types);
+  else
+    result = build_function_type_array (return_type,
+					argument_types_in->n_elements,
+					argument_types);
+
+  delete[] argument_types;
+
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (result));
+}
+
+gcc_type
+plugin_int_type (cc1_plugin::connection *self,
+		 int is_unsigned, unsigned long size_in_bytes)
+{
+  tree result = c_common_type_for_size (BITS_PER_UNIT * size_in_bytes,
+					is_unsigned);
+  if (result == NULL_TREE)
+    result = error_mark_node;
+  else
+    {
+      plugin_context *ctx = static_cast<plugin_context *> (self);
+      ctx->preserve (result);
+    }
+  return convert_out (result);
+}
+
+gcc_type
+plugin_float_type (cc1_plugin::connection *,
+		   unsigned long size_in_bytes)
+{
+  if (BITS_PER_UNIT * size_in_bytes == TYPE_PRECISION (float_type_node))
+    return convert_out (float_type_node);
+  if (BITS_PER_UNIT * size_in_bytes == TYPE_PRECISION (double_type_node))
+    return convert_out (double_type_node);
+  if (BITS_PER_UNIT * size_in_bytes == TYPE_PRECISION (long_double_type_node))
+    return convert_out (long_double_type_node);
+  return convert_out (error_mark_node);
+}
+
+gcc_type
+plugin_void_type (cc1_plugin::connection *)
+{
+  return convert_out (void_type_node);
+}
+
+gcc_type
+plugin_bool_type (cc1_plugin::connection *)
+{
+  return convert_out (boolean_type_node);
+}
+
+gcc_type
+plugin_build_array_type (cc1_plugin::connection *self,
+			 gcc_type element_type_in, int num_elements)
+{
+  tree element_type = convert_in (element_type_in);
+  tree result;
+
+  if (num_elements == -1)
+    result = build_array_type (element_type, NULL_TREE);
+  else
+    result = build_array_type_nelts (element_type, num_elements);
+
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (result));
+}
+
+gcc_type
+plugin_build_vla_array_type (cc1_plugin::connection *self,
+			     gcc_type element_type_in,
+			     const char *upper_bound_name)
+{
+  tree element_type = convert_in (element_type_in);
+  tree upper_bound = lookup_name (get_identifier (upper_bound_name));
+  tree range = build_index_type (upper_bound);
+
+  tree result = build_array_type (element_type, range);
+  C_TYPE_VARIABLE_SIZE (result) = 1;
+
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (result));
+}
+
+gcc_type
+plugin_build_qualified_type (cc1_plugin::connection *,
+			     gcc_type unqualified_type_in,
+			     enum gcc_qualifiers qualifiers)
+{
+  tree unqualified_type = convert_in (unqualified_type_in);
+  int quals = 0;
+
+  if ((qualifiers & GCC_QUALIFIER_CONST) != 0)
+    quals |= TYPE_QUAL_CONST;
+  if ((qualifiers & GCC_QUALIFIER_VOLATILE) != 0)
+    quals |= TYPE_QUAL_VOLATILE;
+  if ((qualifiers & GCC_QUALIFIER_RESTRICT) != 0)
+    quals |= TYPE_QUAL_RESTRICT;
+
+  return convert_out (build_qualified_type (unqualified_type, quals));
+}
+
+gcc_type
+plugin_build_complex_type (cc1_plugin::connection *self,
+			   gcc_type base_type)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (build_complex_type (convert_in (base_type))));
+}
+
+gcc_type
+plugin_build_vector_type (cc1_plugin::connection *self,
+			  gcc_type base_type, int nunits)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  return convert_out (ctx->preserve (build_vector_type (convert_in (base_type),
+							nunits)));
+}
+
+int
+plugin_build_constant (cc1_plugin::connection *self, gcc_type type_in,
+		       const char *name, unsigned long value,
+		       const char *filename, unsigned int line_number)
+{
+  plugin_context *ctx = static_cast<plugin_context *> (self);
+  tree cst, decl;
+  tree type = convert_in (type_in);
+
+  cst = build_int_cst (type, value);
+  decl = build_decl (ctx->get_source_location (filename, line_number),
+		     CONST_DECL, get_identifier (name), type);
+  DECL_INITIAL (decl) = cst;
+  pushdecl_safe (decl);
+
+  return 1;
+}
+
+gcc_type
+plugin_error (cc1_plugin::connection *,
+	      const char *message)
+{
+  error ("%s", message);
+  return convert_out (error_mark_node);
+}
+
+\f
+
+// Perform GC marking.
+
+static void
+gc_mark (void *, void *)
+{
+  if (current_context != NULL)
+    current_context->mark ();
+}
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+	     struct plugin_gcc_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 ("%s: invalid file descriptor argument to plugin",
+			 plugin_info->base_name);
+	  break;
+	}
+    }
+  if (fd == -1)
+    fatal_error ("%s: required plugin argument %<fd%> is missing",
+		 plugin_info->base_name);
+
+  current_context = new plugin_context (fd);
+
+  // Handshake.
+  cc1_plugin::protocol_int version;
+  if (!current_context->require ('H')
+      || ! ::cc1_plugin::unmarshall (current_context, &version))
+    fatal_error ("%s: handshake failed", plugin_info->base_name);
+  if (version != GCC_C_FE_VERSION_0)
+    fatal_error ("%s: unknown version in handshake", plugin_info->base_name);
+
+  register_callback (plugin_info->base_name, PLUGIN_PRAGMAS,
+		     plugin_init_extra_pragmas, NULL);
+  register_callback (plugin_info->base_name, PLUGIN_PRE_GENERICIZE,
+		     rewrite_decls_to_addresses, NULL);
+  register_callback (plugin_info->base_name, PLUGIN_GGC_MARKING,
+		     gc_mark, NULL);
+
+  lang_hooks.print_error_function = plugin_print_error_function;
+
+#define GCC_METHOD0(R, N)			\
+  {						\
+    cc1_plugin::callback_ftype *fun		\
+      = cc1_plugin::callback<R, plugin_ ## N>;	\
+    current_context->add_callback (# N, fun);	\
+  }
+#define GCC_METHOD1(R, N, A)				\
+  {							\
+    cc1_plugin::callback_ftype *fun			\
+      = cc1_plugin::callback<R, A, plugin_ ## N>;	\
+    current_context->add_callback (# N, fun);		\
+  }
+#define GCC_METHOD2(R, N, A, B)				\
+  {							\
+    cc1_plugin::callback_ftype *fun			\
+      = cc1_plugin::callback<R, A, B, plugin_ ## N>;	\
+    current_context->add_callback (# N, fun);		\
+  }
+#define GCC_METHOD3(R, N, A, B, C)			\
+  {							\
+    cc1_plugin::callback_ftype *fun			\
+      = cc1_plugin::callback<R, A, B, C, plugin_ ## N>;	\
+    current_context->add_callback (# N, fun);		\
+  }
+#define GCC_METHOD4(R, N, A, B, C, D)		\
+  {						\
+    cc1_plugin::callback_ftype *fun		\
+      = cc1_plugin::callback<R, A, B, C, D,	\
+			     plugin_ ## N>;	\
+    current_context->add_callback (# N, fun);	\
+  }
+#define GCC_METHOD5(R, N, A, B, C, D, E)	\
+  {						\
+    cc1_plugin::callback_ftype *fun		\
+      = cc1_plugin::callback<R, A, B, C, D, E,	\
+			     plugin_ ## N>;	\
+    current_context->add_callback (# N, fun);	\
+  }
+#define GCC_METHOD7(R, N, A, B, C, D, E, F, G)		\
+  {							\
+    cc1_plugin::callback_ftype *fun			\
+      = cc1_plugin::callback<R, A, B, C, D, E, F, G,	\
+			     plugin_ ## N>;		\
+    current_context->add_callback (# N, fun);		\
+  }
+
+#include "gcc-c-fe.def"
+
+#undef GCC_METHOD0
+#undef GCC_METHOD1
+#undef GCC_METHOD2
+#undef GCC_METHOD3
+#undef GCC_METHOD4
+#undef GCC_METHOD5
+#undef GCC_METHOD7
+
+  return 0;
+}
diff --git a/libcc1/rpc.hh b/libcc1/rpc.hh
new file mode 100644
index 0000000..58758d3
--- /dev/null
+++ b/libcc1/rpc.hh
@@ -0,0 +1,486 @@
+/* RPC call and callback templates
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_RPC_HH
+#define CC1_PLUGIN_RPC_HH
+
+#include "status.hh"
+#include "marshall.hh"
+#include "connection.hh"
+
+namespace cc1_plugin
+{
+  // The plugin API may contain some "const" method parameters.
+  // However, when unmarshalling we cannot unmarshall into a const
+  // object; and furthermore we want to be able to deallocate pointers
+  // when finished with them.  This wrapper class lets us properly
+  // remove the "const" and handle deallocation from pointer types.
+
+  template<typename T>
+  class argument_wrapper
+  {
+  public:
+
+    argument_wrapper () { }
+    ~argument_wrapper () { }
+
+    operator T () const { return m_object; }
+
+    status unmarshall (connection *conn)
+    {
+      return ::cc1_plugin::unmarshall (conn, &m_object);
+    }
+
+  private:
+
+    T m_object;
+
+    // No copying or assignment allowed.
+    argument_wrapper (const argument_wrapper &);
+    argument_wrapper &operator= (const argument_wrapper &);
+  };
+
+  // Specialization for any kind of pointer.  This is declared but not
+  // defined to avoid bugs if a new pointer type is introduced into
+  // the API.  Instead you will just get a compilation error.
+  template<typename T>
+  class argument_wrapper<const T *>;
+
+  // Specialization for string types.
+  template<>
+  class argument_wrapper<const char *>
+  {
+  public:
+    argument_wrapper () : m_object (NULL) { }
+    ~argument_wrapper ()
+    {
+      delete[] m_object;
+    }
+
+    operator const char * () const
+    {
+      return m_object;
+    }
+
+    status unmarshall (connection *conn)
+    {
+      return ::cc1_plugin::unmarshall (conn, &m_object);
+    }
+
+  private:
+
+    char *m_object;
+
+    // No copying or assignment allowed.
+    argument_wrapper (const argument_wrapper &);
+    argument_wrapper &operator= (const argument_wrapper &);
+  };
+
+  // Specialization for gcc_type_array.
+  template<>
+  class argument_wrapper<const gcc_type_array *>
+  {
+  public:
+    argument_wrapper () : m_object (NULL) { }
+    ~argument_wrapper ()
+    {
+      // It would be nicer if gcc_type_array could have a destructor.
+      // But, it is in code shared with gdb and cannot.
+      if (m_object != NULL)
+	delete[] m_object->elements;
+      delete m_object;
+    }
+
+    operator const gcc_type_array * () const
+    {
+      return m_object;
+    }
+
+    status unmarshall (connection *conn)
+    {
+      return ::cc1_plugin::unmarshall (conn, &m_object);
+    }
+
+  private:
+
+    gcc_type_array *m_object;
+
+    // No copying or assignment allowed.
+    argument_wrapper (const argument_wrapper &);
+    argument_wrapper &operator= (const argument_wrapper &);
+  };
+
+  // There are two kinds of template functions here: "call" and
+  // "callback".  They are each repeated multiple times to handle
+  // different numbers of arguments.  (This would be improved with
+  // C++11, though applying a call is still tricky until C++14 can be
+  // used.)
+
+  // The "call" template is used for making a remote procedure call.
+  // It starts a query ('Q') packet, marshalls its arguments, waits
+  // for a result, and finally reads and returns the result via an
+  // "out" parameter.
+
+  // The "callback" template is used when receiving a remote procedure
+  // call.  This template function is suitable for use with the
+  // "callbacks" and "connection" classes.  It decodes incoming
+  // arguments, passes them to the wrapped function, and finally
+  // marshalls a reply packet.
+
+  template<typename R>
+  status
+  call (connection *conn, const char *method, R *result)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 0))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, R (*func) (connection *)>
+  status
+  callback (connection *conn)
+  {
+    R result;
+
+    if (!unmarshall_check (conn, 0))
+      return FAIL;
+    result = func (conn);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+
+  template<typename R, typename A>
+  status
+  call (connection *conn, const char *method, R *result, A arg)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 1))
+      return FAIL;
+    if (!marshall (conn, arg))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, typename A, R (*func) (connection *, A)>
+  status
+  callback (connection *conn)
+  {
+    argument_wrapper<A> arg;
+    R result;
+
+    if (!unmarshall_check (conn, 1))
+      return FAIL;
+    if (!arg.unmarshall (conn))
+      return FAIL;
+    result = func (conn, arg);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+
+  template<typename R, typename A1, typename A2>
+  status
+  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 2))
+      return FAIL;
+    if (!marshall (conn, arg1))
+      return FAIL;
+    if (!marshall (conn, arg2))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, typename A1, typename A2, R (*func) (connection *,
+							    A1, A2)>
+  status
+  callback (connection *conn)
+  {
+    argument_wrapper<A1> arg1;
+    argument_wrapper<A2> arg2;
+    R result;
+
+    if (!unmarshall_check (conn, 2))
+      return FAIL;
+    if (!arg1.unmarshall (conn))
+      return FAIL;
+    if (!arg2.unmarshall (conn))
+      return FAIL;
+    result = func (conn, arg1, arg2);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+
+  template<typename R, typename A1, typename A2, typename A3>
+  status
+  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
+	A3 arg3)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 3))
+      return FAIL;
+    if (!marshall (conn, arg1))
+      return FAIL;
+    if (!marshall (conn, arg2))
+      return FAIL;
+    if (!marshall (conn, arg3))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, typename A1, typename A2, typename A3,
+	   R (*func) (connection *, A1, A2, A3)>
+  status
+  callback (connection *conn)
+  {
+    argument_wrapper<A1> arg1;
+    argument_wrapper<A2> arg2;
+    argument_wrapper<A3> arg3;
+    R result;
+
+    if (!unmarshall_check (conn, 3))
+      return FAIL;
+    if (!arg1.unmarshall (conn))
+      return FAIL;
+    if (!arg2.unmarshall (conn))
+      return FAIL;
+    if (!arg3.unmarshall (conn))
+      return FAIL;
+    result = func (conn, arg1, arg2, arg3);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+
+  template<typename R, typename A1, typename A2, typename A3, typename A4>
+  status
+  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
+	A3 arg3, A4 arg4)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 4))
+      return FAIL;
+    if (!marshall (conn, arg1))
+      return FAIL;
+    if (!marshall (conn, arg2))
+      return FAIL;
+    if (!marshall (conn, arg3))
+      return FAIL;
+    if (!marshall (conn, arg4))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, typename A1, typename A2, typename A3, typename A4,
+	   R (*func) (connection *, A1, A2, A3, A4)>
+  status
+  callback (connection *conn)
+  {
+    argument_wrapper<A1> arg1;
+    argument_wrapper<A2> arg2;
+    argument_wrapper<A3> arg3;
+    argument_wrapper<A4> arg4;
+    R result;
+
+    if (!unmarshall_check (conn, 4))
+      return FAIL;
+    if (!arg1.unmarshall (conn))
+      return FAIL;
+    if (!arg2.unmarshall (conn))
+      return FAIL;
+    if (!arg3.unmarshall (conn))
+      return FAIL;
+    if (!arg4.unmarshall (conn))
+      return FAIL;
+    result = func (conn, arg1, arg2, arg3, arg4);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+
+  template<typename R, typename A1, typename A2, typename A3, typename A4,
+	   typename A5>
+  status
+  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
+	A3 arg3, A4 arg4, A5 arg5)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 5))
+      return FAIL;
+    if (!marshall (conn, arg1))
+      return FAIL;
+    if (!marshall (conn, arg2))
+      return FAIL;
+    if (!marshall (conn, arg3))
+      return FAIL;
+    if (!marshall (conn, arg4))
+      return FAIL;
+    if (!marshall (conn, arg5))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, typename A1, typename A2, typename A3, typename A4,
+	   typename A5, R (*func) (connection *, A1, A2, A3, A4, A5)>
+  status
+  callback (connection *conn)
+  {
+    argument_wrapper<A1> arg1;
+    argument_wrapper<A2> arg2;
+    argument_wrapper<A3> arg3;
+    argument_wrapper<A4> arg4;
+    argument_wrapper<A5> arg5;
+    R result;
+
+    if (!unmarshall_check (conn, 5))
+      return FAIL;
+    if (!arg1.unmarshall (conn))
+      return FAIL;
+    if (!arg2.unmarshall (conn))
+      return FAIL;
+    if (!arg3.unmarshall (conn))
+      return FAIL;
+    if (!arg4.unmarshall (conn))
+      return FAIL;
+    if (!arg5.unmarshall (conn))
+      return FAIL;
+    result = func (conn, arg1, arg2, arg3, arg4, arg5);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+
+  template<typename R, typename A1, typename A2, typename A3, typename A4,
+	   typename A5, typename A6, typename A7>
+  status
+  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
+	A3 arg3, A4 arg4, A5 arg5, A6 arg6, A7 arg7)
+  {
+    if (!conn->send ('Q'))
+      return FAIL;
+    if (!marshall (conn, method))
+      return FAIL;
+    if (!marshall (conn, 7))
+      return FAIL;
+    if (!marshall (conn, arg1))
+      return FAIL;
+    if (!marshall (conn, arg2))
+      return FAIL;
+    if (!marshall (conn, arg3))
+      return FAIL;
+    if (!marshall (conn, arg4))
+      return FAIL;
+    if (!marshall (conn, arg5))
+      return FAIL;
+    if (!marshall (conn, arg6))
+      return FAIL;
+    if (!marshall (conn, arg7))
+      return FAIL;
+    if (!conn->wait_for_result ())
+      return FAIL;
+    if (!unmarshall (conn, result))
+      return FAIL;
+    return OK;
+  }
+
+  template<typename R, typename A1, typename A2, typename A3, typename A4,
+	   typename A5, typename A6, typename A7,
+	   R (*func) (connection *, A1, A2, A3, A4, A5, A6, A7)>
+  status
+  callback (connection *conn)
+  {
+    argument_wrapper<A1> arg1;
+    argument_wrapper<A2> arg2;
+    argument_wrapper<A3> arg3;
+    argument_wrapper<A4> arg4;
+    argument_wrapper<A5> arg5;
+    argument_wrapper<A6> arg6;
+    argument_wrapper<A7> arg7;
+    R result;
+
+    if (!unmarshall_check (conn, 7))
+      return FAIL;
+    if (!arg1.unmarshall (conn))
+      return FAIL;
+    if (!arg2.unmarshall (conn))
+      return FAIL;
+    if (!arg3.unmarshall (conn))
+      return FAIL;
+    if (!arg4.unmarshall (conn))
+      return FAIL;
+    if (!arg5.unmarshall (conn))
+      return FAIL;
+    if (!arg6.unmarshall (conn))
+      return FAIL;
+    if (!arg7.unmarshall (conn))
+      return FAIL;
+    result = func (conn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    if (!conn->send ('R'))
+      return FAIL;
+    return marshall (conn, result);
+  }
+};
+
+#endif // CC1_PLUGIN_RPC_HH
diff --git a/libcc1/status.hh b/libcc1/status.hh
new file mode 100644
index 0000000..764c7ff
--- /dev/null
+++ b/libcc1/status.hh
@@ -0,0 +1,33 @@
+/* status type definition
+   Copyright (C) 2014 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/>.  */
+
+#ifndef CC1_PLUGIN_STATUS_HH
+#define CC1_PLUGIN_STATUS_HH
+
+namespace cc1_plugin
+{
+  // The status returned by various connection functions.
+  enum status
+  {
+    FAIL = 0,
+    OK = 1
+  };
+}
+
+#endif // CC1_PLUGIN_STATUS_HH

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 0/5] let gdb reuse gcc'c C compiler
  2014-06-19 20:42 ` [PATCH 0/5] let gdb reuse gcc'c C compiler Tom Tromey
@ 2014-07-30 16:28   ` Tom Tromey
  0 siblings, 0 replies; 101+ messages in thread
From: Tom Tromey @ 2014-07-30 16:28 UTC (permalink / raw)
  To: gcc-patches

Tom> This patch series is half of a project to let gdb reuse gcc (which
Tom> half depends on which list you are seeing this on), so that users can
Tom> compile small snippets of code and evaluate them in the current
Tom> context of the inferior.

[ ... later ... ]
Tom> I believe we've addressed all the review comments.

Ping.
I think at least the final patch has never been approved.

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-06-19 20:52   ` Tom Tromey
                       ` (2 preceding siblings ...)
  2014-07-18 19:00     ` Tom Tromey
@ 2014-07-31  4:49     ` Jeff Law
  2014-07-31  8:15       ` Richard Biener
                         ` (3 more replies)
  3 siblings, 4 replies; 101+ messages in thread
From: Jeff Law @ 2014-07-31  4:49 UTC (permalink / raw)
  To: Tom Tromey, gcc-patches

On 06/19/14 14:52, Tom Tromey wrote:
> Tom> I've edited this one down by removing the auto-generated stuff , and
> Tom> then compressed it.
>
> Here's a new version of patch #5.
> I've removed the generated code; let's see if it gets through without
> compression.
>
> I think this addresses all the reviews:
>
> * It uses gcc-plugin.m4 to disable the plugin
> * It does some configure checks for needed functionality, and disables
>    the plugin if they are not found
> * libcc1 and the plugin now do a protocol version handshake at
>    startup
> * The diagnostic overriding code is now in the plugin, not in gcc proper
> * gdb now tells libcc1 about the target triplet, and libcc1 uses
>    this to invoke the proper GCC.  This is done by (ewww) searching $PATH.
>
> Tom
>
> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
> 	    Tom Tromey  <tromey@redhat.com>
>
> 	* Makefile.def: Add libcc1 to host_modules.
> 	* configure.ac (host_tools): Add libcc1.
> 	* Makefile.in, configure: Rebuild.
>
> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> 	    Tom Tromey  <tromey@redhat.com>
>
> 	* aclocal.m4: New file.
> 	* callbacks.cc: New file.
> 	* callbacks.hh: New file.
> 	* cc1plugin-config.h.in: New file.
> 	* configure: New file.
> 	* configure.ac: New file.
> 	* connection.cc: New file.
> 	* connection.hh: New file.
> 	* findcomp.cc: New file.
> 	* findcomp.hh: New file.
> 	* libcc1.cc: New file.
> 	* libcc1plugin.sym: New file.
> 	* libcc1.sym: New file.
> 	* Makefile.am: New file.
> 	* Makefile.in: New file.
> 	* marshall.cc: New file.
> 	* marshall.hh: New file.
> 	* names.cc: New file.
> 	* names.hh: New file.
> 	* plugin.cc: New file.
> 	* rpc.hh: New file.
> 	* status.hh: New file.
So my biggest concern here is long term maintenance -- who's going to 
own care and feeding of these bits over time.

My inclination is to go ahead and approve, but explicitly note that if 
the bits do start to rot that we'll be fairly aggressive at 
disabling/removing them.

Now that my position is out there for everyone to see, give the other 
maintainers a few days (say until Monday) to chime in with any objections.

Obviously if there are no objections and you check in the change, please 
be on the lookout for any fallout.  I'm particularly concerned about 
AIX, Solaris and other non-linux platforms.

Does this deserve a mention in the news file?

Jeff

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31  4:49     ` Jeff Law
@ 2014-07-31  8:15       ` Richard Biener
  2014-07-31 10:53         ` Trevor Saunders
  2014-07-31 19:20         ` Tom Tromey
  2014-07-31 21:14       ` Mike Stump
                         ` (2 subsequent siblings)
  3 siblings, 2 replies; 101+ messages in thread
From: Richard Biener @ 2014-07-31  8:15 UTC (permalink / raw)
  To: Jeff Law; +Cc: Tom Tromey, GCC Patches

On Thu, Jul 31, 2014 at 6:47 AM, Jeff Law <law@redhat.com> wrote:
> On 06/19/14 14:52, Tom Tromey wrote:
>>
>> Tom> I've edited this one down by removing the auto-generated stuff , and
>> Tom> then compressed it.
>>
>> Here's a new version of patch #5.
>> I've removed the generated code; let's see if it gets through without
>> compression.
>>
>> I think this addresses all the reviews:
>>
>> * It uses gcc-plugin.m4 to disable the plugin
>> * It does some configure checks for needed functionality, and disables
>>    the plugin if they are not found
>> * libcc1 and the plugin now do a protocol version handshake at
>>    startup
>> * The diagnostic overriding code is now in the plugin, not in gcc proper
>> * gdb now tells libcc1 about the target triplet, and libcc1 uses
>>    this to invoke the proper GCC.  This is done by (ewww) searching $PATH.
>>
>> Tom
>>
>> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
>>             Tom Tromey  <tromey@redhat.com>
>>
>>         * Makefile.def: Add libcc1 to host_modules.
>>         * configure.ac (host_tools): Add libcc1.
>>         * Makefile.in, configure: Rebuild.
>>
>> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
>>             Jan Kratochvil  <jan.kratochvil@redhat.com>
>>             Tom Tromey  <tromey@redhat.com>
>>
>>         * aclocal.m4: New file.
>>         * callbacks.cc: New file.
>>         * callbacks.hh: New file.
>>         * cc1plugin-config.h.in: New file.
>>         * configure: New file.
>>         * configure.ac: New file.
>>         * connection.cc: New file.
>>         * connection.hh: New file.
>>         * findcomp.cc: New file.
>>         * findcomp.hh: New file.
>>         * libcc1.cc: New file.
>>         * libcc1plugin.sym: New file.
>>         * libcc1.sym: New file.
>>         * Makefile.am: New file.
>>         * Makefile.in: New file.
>>         * marshall.cc: New file.
>>         * marshall.hh: New file.
>>         * names.cc: New file.
>>         * names.hh: New file.
>>         * plugin.cc: New file.
>>         * rpc.hh: New file.
>>         * status.hh: New file.
>
> So my biggest concern here is long term maintenance -- who's going to own
> care and feeding of these bits over time.
>
> My inclination is to go ahead and approve, but explicitly note that if the
> bits do start to rot that we'll be fairly aggressive at disabling/removing
> them.
>
> Now that my position is out there for everyone to see, give the other
> maintainers a few days (say until Monday) to chime in with any objections.
>
> Obviously if there are no objections and you check in the change, please be
> on the lookout for any fallout.  I'm particularly concerned about AIX,
> Solaris and other non-linux platforms.
>
> Does this deserve a mention in the news file?

Can you briefly elaborate on how this relates to the JIT work from
David Malcom?

Also during the GCC Summit we talked about JIT and plugins and
I mentioned that the JIT API is actually a kind of "stable plugin API"
for IL creation.

We've also elaborated on why the JIT cannot be a "plugin" at the
moment - which is at least partly because we cannot have
"frontend plugins".  This is because compilation is currently
driven by the frontend which "owns" main() even though it immediately
calls into the middle-end and only gets control back via langhooks.
So a quite obvious cleanup of the program flow of GCC would be
to drive things from a middle-end main() - which would allow
a plugin to take over the frontend parts (and which would allow
making all frontends shared objects, aka "plugins" to a common
middle-end "driver").

Just throwing in my mental notes from the Summit here.  I really
wonder how libcc1 falls in into this picture and if it would stand
in the way of re-organizing main program flow and/or making
frontends shared objects.

[ideally both frontends and targets would be shared objects, but of
course even frontends have target dependencies pulled in via
target macros at the moment...]

Richard.

> Jeff
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31  8:15       ` Richard Biener
@ 2014-07-31 10:53         ` Trevor Saunders
  2014-07-31 11:28           ` Richard Biener
  2014-07-31 19:20         ` Tom Tromey
  1 sibling, 1 reply; 101+ messages in thread
From: Trevor Saunders @ 2014-07-31 10:53 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jeff Law, Tom Tromey, GCC Patches

On Thu, Jul 31, 2014 at 10:01:15AM +0200, Richard Biener wrote:
> On Thu, Jul 31, 2014 at 6:47 AM, Jeff Law <law@redhat.com> wrote:
> > On 06/19/14 14:52, Tom Tromey wrote:
> >>
> >> Tom> I've edited this one down by removing the auto-generated stuff , and
> >> Tom> then compressed it.
> >>
> >> Here's a new version of patch #5.
> >> I've removed the generated code; let's see if it gets through without
> >> compression.
> >>
> >> I think this addresses all the reviews:
> >>
> >> * It uses gcc-plugin.m4 to disable the plugin
> >> * It does some configure checks for needed functionality, and disables
> >>    the plugin if they are not found
> >> * libcc1 and the plugin now do a protocol version handshake at
> >>    startup
> >> * The diagnostic overriding code is now in the plugin, not in gcc proper
> >> * gdb now tells libcc1 about the target triplet, and libcc1 uses
> >>    this to invoke the proper GCC.  This is done by (ewww) searching $PATH.
> >>
> >> Tom
> >>
> >> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
> >>             Tom Tromey  <tromey@redhat.com>
> >>
> >>         * Makefile.def: Add libcc1 to host_modules.
> >>         * configure.ac (host_tools): Add libcc1.
> >>         * Makefile.in, configure: Rebuild.
> >>
> >> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
> >>             Jan Kratochvil  <jan.kratochvil@redhat.com>
> >>             Tom Tromey  <tromey@redhat.com>
> >>
> >>         * aclocal.m4: New file.
> >>         * callbacks.cc: New file.
> >>         * callbacks.hh: New file.
> >>         * cc1plugin-config.h.in: New file.
> >>         * configure: New file.
> >>         * configure.ac: New file.
> >>         * connection.cc: New file.
> >>         * connection.hh: New file.
> >>         * findcomp.cc: New file.
> >>         * findcomp.hh: New file.
> >>         * libcc1.cc: New file.
> >>         * libcc1plugin.sym: New file.
> >>         * libcc1.sym: New file.
> >>         * Makefile.am: New file.
> >>         * Makefile.in: New file.
> >>         * marshall.cc: New file.
> >>         * marshall.hh: New file.
> >>         * names.cc: New file.
> >>         * names.hh: New file.
> >>         * plugin.cc: New file.
> >>         * rpc.hh: New file.
> >>         * status.hh: New file.
> >
> > So my biggest concern here is long term maintenance -- who's going to own
> > care and feeding of these bits over time.
> >
> > My inclination is to go ahead and approve, but explicitly note that if the
> > bits do start to rot that we'll be fairly aggressive at disabling/removing
> > them.
> >
> > Now that my position is out there for everyone to see, give the other
> > maintainers a few days (say until Monday) to chime in with any objections.
> >
> > Obviously if there are no objections and you check in the change, please be
> > on the lookout for any fallout.  I'm particularly concerned about AIX,
> > Solaris and other non-linux platforms.
> >
> > Does this deserve a mention in the news file?
> 
> Can you briefly elaborate on how this relates to the JIT work from
> David Malcom?

I don't think the JIT work helps much here because this library wants to
feed gcc source not IL, so it needs a front end not just the back.

> Also during the GCC Summit we talked about JIT and plugins and
> I mentioned that the JIT API is actually a kind of "stable plugin API"
> for IL creation.

good point.

> We've also elaborated on why the JIT cannot be a "plugin" at the
> moment - which is at least partly because we cannot have
> "frontend plugins".  This is because compilation is currently
> driven by the frontend which "owns" main() even though it immediately
> calls into the middle-end and only gets control back via langhooks.
> So a quite obvious cleanup of the program flow of GCC would be
> to drive things from a middle-end main() - which would allow
> a plugin to take over the frontend parts (and which would allow
> making all frontends shared objects, aka "plugins" to a common
> middle-end "driver").

sounds nice

> Just throwing in my mental notes from the Summit here.  I really
> wonder how libcc1 falls in into this picture and if it would stand
> in the way of re-organizing main program flow and/or making
> frontends shared objects.

so the interesting bit of libcc1 is just a plugin, which means it won't
add any extra work past making plugins work.  On the other hand if you
could load a library that included the driver and front ends then you'd
basically have a much simpler libcc1, so I think that work would make
libcc1 a bit nicer.

Trev

> 
> [ideally both frontends and targets would be shared objects, but of
> course even frontends have target dependencies pulled in via
> target macros at the moment...]
> 
> Richard.
> 
> > Jeff
> >

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31 10:53         ` Trevor Saunders
@ 2014-07-31 11:28           ` Richard Biener
  2014-07-31 15:08             ` Joseph S. Myers
  0 siblings, 1 reply; 101+ messages in thread
From: Richard Biener @ 2014-07-31 11:28 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: Jeff Law, Tom Tromey, GCC Patches

On Thu, Jul 31, 2014 at 12:44 PM, Trevor Saunders <tsaunders@mozilla.com> wrote:
> On Thu, Jul 31, 2014 at 10:01:15AM +0200, Richard Biener wrote:
>> On Thu, Jul 31, 2014 at 6:47 AM, Jeff Law <law@redhat.com> wrote:
>> > On 06/19/14 14:52, Tom Tromey wrote:
>> >>
>> >> Tom> I've edited this one down by removing the auto-generated stuff , and
>> >> Tom> then compressed it.
>> >>
>> >> Here's a new version of patch #5.
>> >> I've removed the generated code; let's see if it gets through without
>> >> compression.
>> >>
>> >> I think this addresses all the reviews:
>> >>
>> >> * It uses gcc-plugin.m4 to disable the plugin
>> >> * It does some configure checks for needed functionality, and disables
>> >>    the plugin if they are not found
>> >> * libcc1 and the plugin now do a protocol version handshake at
>> >>    startup
>> >> * The diagnostic overriding code is now in the plugin, not in gcc proper
>> >> * gdb now tells libcc1 about the target triplet, and libcc1 uses
>> >>    this to invoke the proper GCC.  This is done by (ewww) searching $PATH.
>> >>
>> >> Tom
>> >>
>> >> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
>> >>             Tom Tromey  <tromey@redhat.com>
>> >>
>> >>         * Makefile.def: Add libcc1 to host_modules.
>> >>         * configure.ac (host_tools): Add libcc1.
>> >>         * Makefile.in, configure: Rebuild.
>> >>
>> >> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
>> >>             Jan Kratochvil  <jan.kratochvil@redhat.com>
>> >>             Tom Tromey  <tromey@redhat.com>
>> >>
>> >>         * aclocal.m4: New file.
>> >>         * callbacks.cc: New file.
>> >>         * callbacks.hh: New file.
>> >>         * cc1plugin-config.h.in: New file.
>> >>         * configure: New file.
>> >>         * configure.ac: New file.
>> >>         * connection.cc: New file.
>> >>         * connection.hh: New file.
>> >>         * findcomp.cc: New file.
>> >>         * findcomp.hh: New file.
>> >>         * libcc1.cc: New file.
>> >>         * libcc1plugin.sym: New file.
>> >>         * libcc1.sym: New file.
>> >>         * Makefile.am: New file.
>> >>         * Makefile.in: New file.
>> >>         * marshall.cc: New file.
>> >>         * marshall.hh: New file.
>> >>         * names.cc: New file.
>> >>         * names.hh: New file.
>> >>         * plugin.cc: New file.
>> >>         * rpc.hh: New file.
>> >>         * status.hh: New file.
>> >
>> > So my biggest concern here is long term maintenance -- who's going to own
>> > care and feeding of these bits over time.
>> >
>> > My inclination is to go ahead and approve, but explicitly note that if the
>> > bits do start to rot that we'll be fairly aggressive at disabling/removing
>> > them.
>> >
>> > Now that my position is out there for everyone to see, give the other
>> > maintainers a few days (say until Monday) to chime in with any objections.
>> >
>> > Obviously if there are no objections and you check in the change, please be
>> > on the lookout for any fallout.  I'm particularly concerned about AIX,
>> > Solaris and other non-linux platforms.
>> >
>> > Does this deserve a mention in the news file?
>>
>> Can you briefly elaborate on how this relates to the JIT work from
>> David Malcom?
>
> I don't think the JIT work helps much here because this library wants to
> feed gcc source not IL, so it needs a front end not just the back.

Ah, ok ...

>> Also during the GCC Summit we talked about JIT and plugins and
>> I mentioned that the JIT API is actually a kind of "stable plugin API"
>> for IL creation.
>
> good point.
>
>> We've also elaborated on why the JIT cannot be a "plugin" at the
>> moment - which is at least partly because we cannot have
>> "frontend plugins".  This is because compilation is currently
>> driven by the frontend which "owns" main() even though it immediately
>> calls into the middle-end and only gets control back via langhooks.
>> So a quite obvious cleanup of the program flow of GCC would be
>> to drive things from a middle-end main() - which would allow
>> a plugin to take over the frontend parts (and which would allow
>> making all frontends shared objects, aka "plugins" to a common
>> middle-end "driver").
>
> sounds nice

Actually after looking again I was wrong.  main.c and toplev.c
are the "driver".  So if we can make all frontends shared objects
with their only interface being their lang_hooks that would be nice
(of course the middle-end still needs to make gazillions of symbols
available to that "plugin").

Of course it won't really help libcc1 as libcc1 isn't a frontend
itself.

>> Just throwing in my mental notes from the Summit here.  I really
>> wonder how libcc1 falls in into this picture and if it would stand
>> in the way of re-organizing main program flow and/or making
>> frontends shared objects.
>
> so the interesting bit of libcc1 is just a plugin, which means it won't
> add any extra work past making plugins work.  On the other hand if you
> could load a library that included the driver and front ends then you'd
> basically have a much simpler libcc1, so I think that work would make
> libcc1 a bit nicer.
>
> Trev
>
>>
>> [ideally both frontends and targets would be shared objects, but of
>> course even frontends have target dependencies pulled in via
>> target macros at the moment...]
>>
>> Richard.
>>
>> > Jeff
>> >

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31 11:28           ` Richard Biener
@ 2014-07-31 15:08             ` Joseph S. Myers
  0 siblings, 0 replies; 101+ messages in thread
From: Joseph S. Myers @ 2014-07-31 15:08 UTC (permalink / raw)
  To: Richard Biener; +Cc: Trevor Saunders, Jeff Law, Tom Tromey, GCC Patches

On Thu, 31 Jul 2014, Richard Biener wrote:

> Actually after looking again I was wrong.  main.c and toplev.c
> are the "driver".  So if we can make all frontends shared objects
> with their only interface being their lang_hooks that would be nice
> (of course the middle-end still needs to make gazillions of symbols
> available to that "plugin").

As far as I know, the main non-lang-hook interface provided by front ends 
is the "convert" function (and there aren't that many places outside the 
front ends that still use it).  So it shouldn't be hard to get to the 
state where each front end is only used by its langhooks.  (That's a long 
way from any sort of independent buildability, though; everything still 
embeds global information about such things as command-line options for 
all available front ends, and tree codes likewise.)

I don't personally like the relics of other such magic-named functions in 
the form of langhooks-def.h defaulting to a langhook having a particular 
name that a front end can provide

#define LANG_HOOKS_GLOBAL_BINDINGS_P global_bindings_p
#define LANG_HOOKS_PUSHDECL     pushdecl
#define LANG_HOOKS_GETDECLS     getdecls

and think it would be better for each front end to have unique names for 
these, with no such default.

I think there are a few more cases where C and C++ provide different 
implementations of a function with the same name for use by c-family code 
(and ObjC / ObjC++ issues as well, of course).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31  8:15       ` Richard Biener
  2014-07-31 10:53         ` Trevor Saunders
@ 2014-07-31 19:20         ` Tom Tromey
  2014-07-31 19:21           ` Jakub Jelinek
  2014-07-31 19:51           ` Trevor Saunders
  1 sibling, 2 replies; 101+ messages in thread
From: Tom Tromey @ 2014-07-31 19:20 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jeff Law, GCC Patches

Richard> Can you briefly elaborate on how this relates to the JIT work from
Richard> David Malcom?

I think Trevor answered this bit well but I had a bit more to add...

Richard> Just throwing in my mental notes from the Summit here.  I really
Richard> wonder how libcc1 falls in into this picture and if it would stand
Richard> in the way of re-organizing main program flow and/or making
Richard> frontends shared objects.

FWIW the plugin is really quite small.  It uses just a few things from
the C front end.  Earlier patches in the series also add a couple of ad
hoc hooks to the C front end so that the plugin can insert itself.
However it really isn't much -- primarily I think due to the simplicity
of C; I expect hooking into g++ will be trickier.

I don't think this plugin will be much of a barrier to anything in gcc.
It hooks in to gcc in the same way as any other plugin (aside from those
ad hoc hooks).  You can look through plugin.cc in the patch to see what
parts of gcc's internals uses.

One way of looking at it is -- if gcc changes break this plugin, they'll
probably break every plugin.  So it's a good thing :)

Richard> [ideally both frontends and targets would be shared objects, but of
Richard> course even frontends have target dependencies pulled in via
Richard> target macros at the moment...]

We actually started development with this approach.  Our first working
version of this project was based on David Malcolm's JIT branch.  We
turned cc1 into a .so and had gdb dlopen it.  Then we did the
compilation parts in-process.

We ended up going with the plugin approach because it has better fault
tolerance.  With the cc1.so approach, if we could provoke a crash -- not
uncommon given that we were calling gcc internals in a new and exciting
way -- then the whole debug session came down.

Using a plugin avoids this.  If gcc crashes, gdb can report an error and
continue on.  This is much friendlier for users, making it worth the
extra effort of dealing with multiple processes, RPC, etc.  Also, our
fears about the performance of this approach were unfounded, I imagine
because we're generally dealing with very small inputs.

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31 19:20         ` Tom Tromey
@ 2014-07-31 19:21           ` Jakub Jelinek
  2014-07-31 19:51           ` Trevor Saunders
  1 sibling, 0 replies; 101+ messages in thread
From: Jakub Jelinek @ 2014-07-31 19:21 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Richard Biener, Jeff Law, GCC Patches

On Thu, Jul 31, 2014 at 01:12:54PM -0600, Tom Tromey wrote:
> Richard> [ideally both frontends and targets would be shared objects, but of
> Richard> course even frontends have target dependencies pulled in via
> Richard> target macros at the moment...]
> 
> We actually started development with this approach.  Our first working
> version of this project was based on David Malcolm's JIT branch.  We
> turned cc1 into a .so and had gdb dlopen it.  Then we did the
> compilation parts in-process.
> 
> We ended up going with the plugin approach because it has better fault
> tolerance.  With the cc1.so approach, if we could provoke a crash -- not
> uncommon given that we were calling gcc internals in a new and exciting
> way -- then the whole debug session came down.
> 
> Using a plugin avoids this.  If gcc crashes, gdb can report an error and
> continue on.  This is much friendlier for users, making it worth the
> extra effort of dealing with multiple processes, RPC, etc.  Also, our
> fears about the performance of this approach were unfounded, I imagine
> because we're generally dealing with very small inputs.

Given that what GDB wants is not a JIT, but reuse the C (and later on C++)
FEs, I think the plugin approach is just fine for this.

	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31 19:20         ` Tom Tromey
  2014-07-31 19:21           ` Jakub Jelinek
@ 2014-07-31 19:51           ` Trevor Saunders
  2014-07-31 20:07             ` Tom Tromey
  1 sibling, 1 reply; 101+ messages in thread
From: Trevor Saunders @ 2014-07-31 19:51 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Richard Biener, Jeff Law, GCC Patches

On Thu, Jul 31, 2014 at 01:12:54PM -0600, Tom Tromey wrote:
> Richard> Can you briefly elaborate on how this relates to the JIT work from
> Richard> David Malcom?
> 
> I think Trevor answered this bit well but I had a bit more to add...
> 
> Richard> Just throwing in my mental notes from the Summit here.  I really
> Richard> wonder how libcc1 falls in into this picture and if it would stand
> Richard> in the way of re-organizing main program flow and/or making
> Richard> frontends shared objects.
> 
> FWIW the plugin is really quite small.  It uses just a few things from
> the C front end.  Earlier patches in the series also add a couple of ad
> hoc hooks to the C front end so that the plugin can insert itself.
> However it really isn't much -- primarily I think due to the simplicity
> of C; I expect hooking into g++ will be trickier.
> 
> I don't think this plugin will be much of a barrier to anything in gcc.
> It hooks in to gcc in the same way as any other plugin (aside from those
> ad hoc hooks).  You can look through plugin.cc in the patch to see what
> parts of gcc's internals uses.

the plugin part seems fine, but I do find my self wondering if there's a
better way of doing the hooks into C, if they can be more genrally
useful.  I'm not complaining about them at all it just seems like its
worth thinking about what they tell us we should make better in the
future.

> One way of looking at it is -- if gcc changes break this plugin, they'll
> probably break every plugin.  So it's a good thing :)
> 
> Richard> [ideally both frontends and targets would be shared objects, but of
> Richard> course even frontends have target dependencies pulled in via
> Richard> target macros at the moment...]
> 
> We actually started development with this approach.  Our first working
> version of this project was based on David Malcolm's JIT branch.  We
> turned cc1 into a .so and had gdb dlopen it.  Then we did the
> compilation parts in-process.
> 
> We ended up going with the plugin approach because it has better fault
> tolerance.  With the cc1.so approach, if we could provoke a crash -- not
> uncommon given that we were calling gcc internals in a new and exciting
> way -- then the whole debug session came down.

out of process seems very reasonable, but I do hope we'll fix the
crashes since there's any number of other uses for cc1 as a library.

Trev

> Using a plugin avoids this.  If gcc crashes, gdb can report an error and
> continue on.  This is much friendlier for users, making it worth the
> extra effort of dealing with multiple processes, RPC, etc.  Also, our
> fears about the performance of this approach were unfounded, I imagine
> because we're generally dealing with very small inputs.
> 
> Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31 19:51           ` Trevor Saunders
@ 2014-07-31 20:07             ` Tom Tromey
  2014-08-01  2:18               ` Trevor Saunders
  0 siblings, 1 reply; 101+ messages in thread
From: Tom Tromey @ 2014-07-31 20:07 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: Richard Biener, Jeff Law, GCC Patches

>>>>> "Trevor" == Trevor Saunders <tsaunders@mozilla.com> writes:

Trevor> the plugin part seems fine, but I do find my self wondering if there's a
Trevor> better way of doing the hooks into C, if they can be more genrally
Trevor> useful.

There's just one now, the binding oracle.
(There used to be two but we reimplemented the second one by overriding
a langhook from the plugin.)

The binding oracle could perhaps be redone as an ordinary plugin event.
It didn't seem that worthwhile to me, but if someone else has a use, it
seems doable.

Trevor> out of process seems very reasonable, but I do hope we'll fix the
Trevor> crashes since there's any number of other uses for cc1 as a library.

The ones I recall were all things like the plugin making a tree
incorrectly.  This could still be an issue but it is one unlikely to be
hit in ordinary uses of the compiler.  I agree any such things are bugs
though.

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31  4:49     ` Jeff Law
  2014-07-31  8:15       ` Richard Biener
@ 2014-07-31 21:14       ` Mike Stump
  2014-08-04 14:23         ` Tom Tromey
  2014-08-05 19:34       ` Tom Tromey
  2014-10-09  9:07       ` [PATCH 5/5] add libcc1 Phil Muldoon
  3 siblings, 1 reply; 101+ messages in thread
From: Mike Stump @ 2014-07-31 21:14 UTC (permalink / raw)
  To: Jeff Law; +Cc: Tom Tromey, gcc-patches

On Jul 30, 2014, at 9:47 PM, Jeff Law <law@redhat.com> wrote:
> So my biggest concern here is long term maintenance -- who's going to own care and feeding of these bits over time.
> 
> My inclination is to go ahead and approve, but explicitly note that if the bits do start to rot that we'll be fairly aggressive at disabling/removing them.

So the normal way to do this would be to make the plugin front-end non-default and then never gate any release decisions upon the state of the that front-end.  If it works, ship it, if it doesn’t ship it.  If people want it to build, the contribute patches, if they don’t care, oh well…

That said, changes that ripple across front-ends generally need to be built with all (really all) built and are generally rejected if they break the build.

Given my experience with lessor front-ends (Objective-C and Objective-C++), I think we do a good job and the maintenance is fairly low.  Others can disabuse me of this opinion if they want.  My expectation is that this frontend will be easy to maintain and will be a non-issue.  Everyone and then someone won’t test with it, they will break it, someone will notice, someone will contribute the 2 line patch that also makes it work, and life goes on.  This is my experience with Objective-C++ (a non-default language).

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31 20:07             ` Tom Tromey
@ 2014-08-01  2:18               ` Trevor Saunders
  0 siblings, 0 replies; 101+ messages in thread
From: Trevor Saunders @ 2014-08-01  2:18 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Richard Biener, Jeff Law, GCC Patches

On Thu, Jul 31, 2014 at 01:51:45PM -0600, Tom Tromey wrote:
> >>>>> "Trevor" == Trevor Saunders <tsaunders@mozilla.com> writes:
> 
> Trevor> the plugin part seems fine, but I do find my self wondering if there's a
> Trevor> better way of doing the hooks into C, if they can be more genrally
> Trevor> useful.
> 
> There's just one now, the binding oracle.

ah, that seems reasonable enough.

> (There used to be two but we reimplemented the second one by overriding
> a langhook from the plugin.)

hm, I think langhooks should eventually become an interface with virtual
functions to help seperate front ends, and that may be interesting with
plugins that over ride lang hooks from the front end, but we need to
cross that bridge anyway I guess.

> The binding oracle could perhaps be redone as an ordinary plugin event.
> It didn't seem that worthwhile to me, but if someone else has a use, it
> seems doable.
> 
> Trevor> out of process seems very reasonable, but I do hope we'll fix the
> Trevor> crashes since there's any number of other uses for cc1 as a library.
> 
> The ones I recall were all things like the plugin making a tree
> incorrectly.  This could still be an issue but it is one unlikely to be
> hit in ordinary uses of the compiler.  I agree any such things are bugs
> though.

Then that seems fine.

So as far as I'm concerned please lets go forward with this and clean up
later as needed.

Trev

> 
> Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31 21:14       ` Mike Stump
@ 2014-08-04 14:23         ` Tom Tromey
  0 siblings, 0 replies; 101+ messages in thread
From: Tom Tromey @ 2014-08-04 14:23 UTC (permalink / raw)
  To: Mike Stump; +Cc: Jeff Law, gcc-patches

>>>>> "Mike" == Mike Stump <mikestump@comcast.net> writes:

Mike> So the normal way to do this would be to make the plugin front-end
Mike> non-default and then never gate any release decisions upon the state
Mike> of the that front-end.

Not sure if this is overly pedantic, but the plugin is just a library,
not a front end.  It works with the existing C front end.

I think the main issue arising here is that the plugin doesn't have any
in-tree tests.  You have to have gdb to test it.

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31  4:49     ` Jeff Law
  2014-07-31  8:15       ` Richard Biener
  2014-07-31 21:14       ` Mike Stump
@ 2014-08-05 19:34       ` Tom Tromey
  2014-08-08 12:15         ` [PATCH 5/5] add libcc1 [gcc-5/changes.html] Jan Kratochvil
  2014-10-09  9:07       ` [PATCH 5/5] add libcc1 Phil Muldoon
  3 siblings, 1 reply; 101+ messages in thread
From: Tom Tromey @ 2014-08-05 19:34 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches

>>>>> "Jeff" == Jeff Law <law@redhat.com> writes:

Jeff> Obviously if there are no objections and you check in the change,
Jeff> please be on the lookout for any fallout.  I'm particularly concerned
Jeff> about AIX, Solaris and other non-linux platforms.

I did a build on the AIX box (gcc111) in the compile farm and didn't
have any issues.  The plugin isn't built there as plugin support seems
to be disabled.

Jeff> Does this deserve a mention in the news file?

I suppose so, I will get someone here to write it.

Tom

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1 [gcc-5/changes.html]
  2014-08-05 19:34       ` Tom Tromey
@ 2014-08-08 12:15         ` Jan Kratochvil
  2014-08-31 15:12           ` Gerald Pfeifer
  0 siblings, 1 reply; 101+ messages in thread
From: Jan Kratochvil @ 2014-08-08 12:15 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches, Tom Tromey

[-- Attachment #1: Type: text/plain, Size: 265 bytes --]

On Tue, 05 Aug 2014 21:34:00 +0200, Tom Tromey wrote:
> >>>>> "Jeff" == Jeff Law <law@redhat.com> writes:
> Jeff> Does this deserve a mention in the news file?
> 
> I suppose so, I will get someone here to write it.

Attached (based on Tom's PATCH 0/5 mail).


Jan

[-- Attachment #2: c.diff --]
[-- Type: text/plain, Size: 1142 bytes --]

Index: htdocs/gcc-5/changes.html
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/gcc-5/changes.html,v
retrieving revision 1.2
diff -u -p -r1.2 changes.html
--- htdocs/gcc-5/changes.html	30 Jul 2014 18:02:31 -0000	1.2
+++ htdocs/gcc-5/changes.html	8 Aug 2014 12:10:46 -0000
@@ -20,7 +20,25 @@
 
 <!-- h3 id="ada">Ada</h3 -->
 <!-- h3 id="c-family">C family</h3 -->
-<!-- h3 id="c">C</h3-->
+
+<h3 id="c">C</h3>
+  <ul>
+    <li>GDB evaluation of a block of source code is now provided by new GCC
+    plugin.<br />
+    For example:
+    <pre>
+      (gdb) compile code int i; for (i = 0; i < 3; ++i) printf ("#%d\n", i)
+      #0
+      #1
+      #2
+    </pre>
+    A user can compile a code snippet and it will be inserted into the inferior
+    and evaluated.  Declarations needed by the snippet are supplied by GDB, and
+    there is a GDB--GCC interface so that the snippets can refer to local
+    variables in the current inferior frame.
+    </li>
+  </ul>
+
 <!-- h3 id="cxx">C++</h3-->
   <!-- h4 id="libstdcxx">Runtime Library (libstdc++)</h4-->
 <h3 id="fortran">Fortran</h3>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1 [gcc-5/changes.html]
  2014-08-08 12:15         ` [PATCH 5/5] add libcc1 [gcc-5/changes.html] Jan Kratochvil
@ 2014-08-31 15:12           ` Gerald Pfeifer
  2014-09-14 15:07             ` Manuel López-Ibáñez
  0 siblings, 1 reply; 101+ messages in thread
From: Gerald Pfeifer @ 2014-08-31 15:12 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: Jeff Law, gcc-patches, Tom Tromey

Hi Jan,

On Fri, 8 Aug 2014, Jan Kratochvil wrote:
>>>>>>> "Jeff" == Jeff Law <law@redhat.com> writes:
>>> Does this deserve a mention in the news file?
> Attached (based on Tom's PATCH 0/5 mail).

Index: htdocs/gcc-5/changes.html
===================================================================
+<h3 id="c">C</h3>
+  <ul>
+    <li>GDB evaluation of a block of source code is now provided by new GCC
+    plugin.<br />

How does one obtain/install/trigger this plugin?  Where are more details
documented?  This is information I'd add here.

+    A user can compile a code snippet and it will be inserted into the inferior
+    and evaluated.  Declarations needed by the snippet are supplied by GDB, and
+    there is a GDB--GCC interface so that the snippets can refer to local
+    variables in the current inferior frame.

The validator probably is going to complain that this needs to be within
<p>...</p> markers.

In HTML, I'd just say GDB-GCC (one dash).

I'm good with this patch modulo these suggestion, but perhaps Jeff or
Tom have some further input?

Gerald

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1 [gcc-5/changes.html]
  2014-08-31 15:12           ` Gerald Pfeifer
@ 2014-09-14 15:07             ` Manuel López-Ibáñez
  2014-09-17 14:14               ` Jan Kratochvil
  0 siblings, 1 reply; 101+ messages in thread
From: Manuel López-Ibáñez @ 2014-09-14 15:07 UTC (permalink / raw)
  To: Gerald Pfeifer; +Cc: Jan Kratochvil, Jeff Law, Gcc Patch List, Tom Tromey

What happened with this? I don't see any libcc1 in the gcc repository
and this patch was never committed.

Cheers,

Manuel.


On 31 August 2014 17:12, Gerald Pfeifer <gerald@pfeifer.com> wrote:
> Hi Jan,
>
> On Fri, 8 Aug 2014, Jan Kratochvil wrote:
>>>>>>>> "Jeff" == Jeff Law <law@redhat.com> writes:
>>>> Does this deserve a mention in the news file?
>> Attached (based on Tom's PATCH 0/5 mail).
>
> Index: htdocs/gcc-5/changes.html
> ===================================================================
> +<h3 id="c">C</h3>
> +  <ul>
> +    <li>GDB evaluation of a block of source code is now provided by new GCC
> +    plugin.<br />
>
> How does one obtain/install/trigger this plugin?  Where are more details
> documented?  This is information I'd add here.
>
> +    A user can compile a code snippet and it will be inserted into the inferior
> +    and evaluated.  Declarations needed by the snippet are supplied by GDB, and
> +    there is a GDB--GCC interface so that the snippets can refer to local
> +    variables in the current inferior frame.
>
> The validator probably is going to complain that this needs to be within
> <p>...</p> markers.
>
> In HTML, I'd just say GDB-GCC (one dash).
>
> I'm good with this patch modulo these suggestion, but perhaps Jeff or
> Tom have some further input?
>
> Gerald

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1 [gcc-5/changes.html]
  2014-09-14 15:07             ` Manuel López-Ibáñez
@ 2014-09-17 14:14               ` Jan Kratochvil
  0 siblings, 0 replies; 101+ messages in thread
From: Jan Kratochvil @ 2014-09-17 14:14 UTC (permalink / raw)
  To: Manuel López-Ibáñez
  Cc: Gerald Pfeifer, Jeff Law, Gcc Patch List, Tom Tromey

On Sun, 14 Sep 2014 17:07:05 +0200, Manuel López-Ibáñez wrote:
> What happened with this? I don't see any libcc1 in the gcc repository
> and this patch was never committed.

It was discussed internally and the patches are going to be updated, rebased
and later checked in.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-07-31  4:49     ` Jeff Law
                         ` (2 preceding siblings ...)
  2014-08-05 19:34       ` Tom Tromey
@ 2014-10-09  9:07       ` Phil Muldoon
  2014-10-09  9:12         ` Jakub Jelinek
                           ` (2 more replies)
  3 siblings, 3 replies; 101+ messages in thread
From: Phil Muldoon @ 2014-10-09  9:07 UTC (permalink / raw)
  To: Jeff Law; +Cc: Tom Tromey, tom, gcc-patches

On 31/07/14 05:47, Jeff Law wrote:
> On 06/19/14 14:52, Tom Tromey wrote:
>> Here's a new version of patch #5.
>> I've removed the generated code; let's see if it gets through without
>> compression.
>>
>> I think this addresses all the reviews:
>>
>> * It uses gcc-plugin.m4 to disable the plugin
>> * It does some configure checks for needed functionality, and disables
>>    the plugin if they are not found
>> * libcc1 and the plugin now do a protocol version handshake at
>>    startup
>> * The diagnostic overriding code is now in the plugin, not in gcc proper
>> * gdb now tells libcc1 about the target triplet, and libcc1 uses
>>    this to invoke the proper GCC.  This is done by (ewww) searching $PATH.
>>
>> Tom
>>
>> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
>>         Tom Tromey  <tromey@redhat.com>

> So my biggest concern here is long term maintenance -- who's going to own care and feeding of these bits over time.

Sorry for taking so long to reply.  We've talked, on irc and elsewhere
a little (some at the Cauldron too!).  I think the consensus is as
nobody has explicitly mentioned anything, this is OK to go in?  So to
be a pain, I think we should get an archivable "OK to check-in" and
that I, or other members of the Red Hat team (or anyone else that
comes along that is interested), will maintain this.  FWIW, I don't
really see bit-rot as an issue because 1) I'll be around and so will
other hackers working on this -- I think it is very important to GDB;
2) It's not really a patch-set I think is horribly susceptible to bit
rot anyway.

> My inclination is to go ahead and approve, but explicitly note that if the bits do start to rot that we'll be fairly aggressive at disabling/removing them.

That's a fair condition and I can happily live with that. Agreed on
the conditional here.

> Now that my position is out there for everyone to see, give the other maintainers a few days (say until Monday) to chime in with any objections.

Well it's been a few  months, so Monday has long gone ;)

> Obviously if there are no objections and you check in the change, please be on the lookout for any fallout.  I'm particularly concerned about AIX, Solaris and other non-linux platforms.

Noted.

> Does this deserve a mention in the news file?

I am not sure.  All the interface to this is really through GDB.
I'll let someone else tell me yes or no for news.  The patch set I have on my
desk is ready to go, and I believe all alterations have been approved
in previous email threads.

Cheers,

Phil

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-09  9:07       ` [PATCH 5/5] add libcc1 Phil Muldoon
@ 2014-10-09  9:12         ` Jakub Jelinek
  2014-10-09  9:18         ` Phil Muldoon
  2014-10-10 22:31         ` Jeff Law
  2 siblings, 0 replies; 101+ messages in thread
From: Jakub Jelinek @ 2014-10-09  9:12 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Jeff Law, Tom Tromey, tom, gcc-patches

On Thu, Oct 09, 2014 at 10:07:23AM +0100, Phil Muldoon wrote:
> >> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
> >>         Tom Tromey  <tromey@redhat.com>
> 
> > So my biggest concern here is long term maintenance -- who's going to own care and feeding of these bits over time.
> 
> Sorry for taking so long to reply.  We've talked, on irc and elsewhere
> a little (some at the Cauldron too!).  I think the consensus is as
> nobody has explicitly mentioned anything, this is OK to go in?  So to
> be a pain, I think we should get an archivable "OK to check-in" and
> that I, or other members of the Red Hat team (or anyone else that

The series is ok for trunk.  Please retest it before checking in.

> > Does this deserve a mention in the news file?
> 
> I am not sure.  All the interface to this is really through GDB.
> I'll let someone else tell me yes or no for news.  The patch set I have on my
> desk is ready to go, and I believe all alterations have been approved
> in previous email threads.

Yeah, I think it belongs into GDB news file probably, because that is the
place where it is user visible. 

	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-09  9:07       ` [PATCH 5/5] add libcc1 Phil Muldoon
  2014-10-09  9:12         ` Jakub Jelinek
@ 2014-10-09  9:18         ` Phil Muldoon
  2014-10-10 22:31         ` Jeff Law
  2 siblings, 0 replies; 101+ messages in thread
From: Phil Muldoon @ 2014-10-09  9:18 UTC (permalink / raw)
  To: gcc-patches; +Cc: Tom Tromey, tom, gcc-patches

On 31/07/14 05:47, Jeff Law wrote:
> On 06/19/14 14:52, Tom Tromey wrote:
>> Here's a new version of patch #5.
>> I've removed the generated code; let's see if it gets through without
>> compression.
>>
>> I think this addresses all the reviews:
>>
>> * It uses gcc-plugin.m4 to disable the plugin
>> * It does some configure checks for needed functionality, and disables
>>    the plugin if they are not found
>> * libcc1 and the plugin now do a protocol version handshake at
>>    startup
>> * The diagnostic overriding code is now in the plugin, not in gcc proper
>> * gdb now tells libcc1 about the target triplet, and libcc1 uses
>>    this to invoke the proper GCC.  This is done by (ewww) searching $PATH.
>>
>> Tom
>>
>> 2014-06-19  Phil Muldoon  <pmuldoon@redhat.com>
>>         Tom Tromey  <tromey@redhat.com>

> So my biggest concern here is long term maintenance -- who's going to own care and feeding of these bits over time.

Sorry for taking so long to reply.  We've talked, on irc and elsewhere
a little (some at the Cauldron too!).  I think the consensus is as
nobody has explicitly mentioned anything, this is OK to go in?  So to
be a pain, I think we should get an archivable "OK to check-in" and
that I, or other members of the Red Hat team (or anyone else that
comes along that is interested), will maintain this.  FWIW, I don't
really see bit-rot as an issue because 1) I'll be around and so will
other hackers working on this -- I think it is very important to GDB;
2) It's not really a patch-set I think is horribly susceptible to bit
rot anyway.

> My inclination is to go ahead and approve, but explicitly note that if the bits do start to rot that we'll be fairly aggressive at disabling/removing them.

That's a fair condition and I can happily live with that. Agreed on
the conditional here.

> Now that my position is out there for everyone to see, give the other maintainers a few days (say until Monday) to chime in with any objections.

Well it's been a few  months, so Monday has long gone ;)

> Obviously if there are no objections and you check in the change, please be on the lookout for any fallout.  I'm particularly concerned about AIX, Solaris and other non-linux platforms.

Noted.

> Does this deserve a mention in the news file?

I am not sure.  All the interface to this is really through GDB.
I'll let someone else tell me yes or no for news.  The patch set I have on my
desk is ready to go, and I believe all alterations have been approved
in previous email threads.

Cheers,

Phil


^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-09  9:07       ` [PATCH 5/5] add libcc1 Phil Muldoon
  2014-10-09  9:12         ` Jakub Jelinek
  2014-10-09  9:18         ` Phil Muldoon
@ 2014-10-10 22:31         ` Jeff Law
  2014-10-24  7:43           ` Phil Muldoon
  2 siblings, 1 reply; 101+ messages in thread
From: Jeff Law @ 2014-10-10 22:31 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Tom Tromey, tom, gcc-patches

On 10/09/14 03:07, Phil Muldoon wrote:
>
> Sorry for taking so long to reply.  We've talked, on irc and elsewhere
> a little (some at the Cauldron too!).  I think the consensus is as
> nobody has explicitly mentioned anything, this is OK to go in?
Yes, please go ahead and check it in.  You'll be the first contact point 
if something goes wrong :-)

Given the length of time since the original post and now, can you please 
do sanity bootstrap to make sure nothing's bitrotted before you commit?
>
>> Does this deserve a mention in the news file?
>
> I am not sure.  All the interface to this is really through GDB.
> I'll let someone else tell me yes or no for news.  The patch set I have on my
> desk is ready to go, and I believe all alterations have been approved
> in previous email threads.
>
I think someone mentioned it really deserved a news file mention in 
gdb's new file rather than gcc's.  That makes sense to me.
jeff

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-10 22:31         ` Jeff Law
@ 2014-10-24  7:43           ` Phil Muldoon
  2014-10-24  7:53             ` Jakub Jelinek
  2014-10-24 16:47             ` Jeff Law
  0 siblings, 2 replies; 101+ messages in thread
From: Phil Muldoon @ 2014-10-24  7:43 UTC (permalink / raw)
  To: Jeff Law; +Cc: Tom Tromey, tom, gcc-patches

On 10/10/14 22:58, Jeff Law wrote:
> On 10/09/14 03:07, Phil Muldoon wrote:
>>
>> Sorry for taking so long to reply.  We've talked, on irc and elsewhere
>> a little (some at the Cauldron too!).  I think the consensus is as
>> nobody has explicitly mentioned anything, this is OK to go in?
> Yes, please go ahead and check it in.  You'll be the first contact point if something goes wrong :-)
>
> Given the length of time since the original post and now, can you please do sanity bootstrap to make sure nothing's bitrotted before you commit?

I rebased the patch on top of GCC head (from the git repository),
updated the ChangeLogs, etc from two days ago (it takes two days to do
a full rebase, pristine and patched bootstrap and testrun on my poor
laptop ;).

I've built both pristine and patched branches with bootstrap enabled.
I ran both testsuites and used contrib/compare_tests to make sure
everything was as it should be.  compare_tests reports everything as
fine.  One minor change I found, was due to some ongoing work on
hash_tables.  It seems to parameterless constructor call for a new
hash table has been removed.  This was trivially fixed with the patch
attached.  Even though (to me) it is obvious, what do you think?

Cheers

Phil

--

diff --git a/libcc1/plugin.cc b/libcc1/plugin.cc
index fbb49d3..5cdd19d 100644
--- a/libcc1/plugin.cc
+++ b/libcc1/plugin.cc
@@ -220,13 +220,10 @@ static plugin_context *current_context;
 
 plugin_context::plugin_context (int fd)
   : cc1_plugin::connection (fd),
-    address_map (),
-    preserved (),
-    file_names ()
+    address_map (30),
+    preserved (30),
+    file_names (30)
 {
-  address_map.create (20);
-  preserved.create (20);
-  file_names.create (20);
 }
 
 void
@@ -236,8 +233,8 @@ plugin_context::mark ()
        it != address_map.end ();
        ++it)
     {
-      ggc_mark ((*it).decl);
-      ggc_mark ((*it).address);
+      ggc_mark ((*it)->decl);
+      ggc_mark ((*it)->address);
     }
 
   for (hash_table< pointer_hash<tree_node> >::iterator it = preserved.begin ();

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-24  7:43           ` Phil Muldoon
@ 2014-10-24  7:53             ` Jakub Jelinek
  2014-10-24 16:47             ` Jeff Law
  1 sibling, 0 replies; 101+ messages in thread
From: Jakub Jelinek @ 2014-10-24  7:53 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Jeff Law, Tom Tromey, tom, gcc-patches

On Fri, Oct 24, 2014 at 08:15:36AM +0100, Phil Muldoon wrote:
> On 10/10/14 22:58, Jeff Law wrote:
> > On 10/09/14 03:07, Phil Muldoon wrote:
> >>
> >> Sorry for taking so long to reply.  We've talked, on irc and elsewhere
> >> a little (some at the Cauldron too!).  I think the consensus is as
> >> nobody has explicitly mentioned anything, this is OK to go in?
> > Yes, please go ahead and check it in.  You'll be the first contact point if something goes wrong :-)
> >
> > Given the length of time since the original post and now, can you please do sanity bootstrap to make sure nothing's bitrotted before you commit?
> 
> I rebased the patch on top of GCC head (from the git repository),
> updated the ChangeLogs, etc from two days ago (it takes two days to do
> a full rebase, pristine and patched bootstrap and testrun on my poor
> laptop ;).
> 
> I've built both pristine and patched branches with bootstrap enabled.
> I ran both testsuites and used contrib/compare_tests to make sure
> everything was as it should be.  compare_tests reports everything as
> fine.  One minor change I found, was due to some ongoing work on
> hash_tables.  It seems to parameterless constructor call for a new
> hash table has been removed.  This was trivially fixed with the patch
> attached.  Even though (to me) it is obvious, what do you think?

> --- a/libcc1/plugin.cc
> +++ b/libcc1/plugin.cc
> @@ -220,13 +220,10 @@ static plugin_context *current_context;
>  
>  plugin_context::plugin_context (int fd)
>    : cc1_plugin::connection (fd),
> -    address_map (),
> -    preserved (),
> -    file_names ()
> +    address_map (30),
> +    preserved (30),
> +    file_names (30)
>  {
> -  address_map.create (20);
> -  preserved.create (20);
> -  file_names.create (20);

This is http://gcc.gnu.org/r211936 , i.e.
https://gcc.gnu.org/ml/gcc-patches/2014-06/msg01598.html
so the changes are fine.

>  }
>  
>  void
> @@ -236,8 +233,8 @@ plugin_context::mark ()
>         it != address_map.end ();
>         ++it)
>      {
> -      ggc_mark ((*it).decl);
> -      ggc_mark ((*it).address);
> +      ggc_mark ((*it)->decl);
> +      ggc_mark ((*it)->address);
>      }

And this is http://gcc.gnu.org/r211937 , i.e.
https://gcc.gnu.org/ml/gcc-patches/2014-06/msg01599.html
in action. 

>    for (hash_table< pointer_hash<tree_node> >::iterator it = preserved.begin ();

So, if these are the only non-obvious changes you needed, please go ahead
and commit.

	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-24  7:43           ` Phil Muldoon
  2014-10-24  7:53             ` Jakub Jelinek
@ 2014-10-24 16:47             ` Jeff Law
  2014-10-27 20:03               ` Phil Muldoon
  1 sibling, 1 reply; 101+ messages in thread
From: Jeff Law @ 2014-10-24 16:47 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Tom Tromey, tom, gcc-patches

On 10/24/14 01:15, Phil Muldoon wrote:
> On 10/10/14 22:58, Jeff Law wrote:
>> On 10/09/14 03:07, Phil Muldoon wrote:
>>>
>>> Sorry for taking so long to reply.  We've talked, on irc and elsewhere
>>> a little (some at the Cauldron too!).  I think the consensus is as
>>> nobody has explicitly mentioned anything, this is OK to go in?
>> Yes, please go ahead and check it in.  You'll be the first contact point if something goes wrong :-)
>>
>> Given the length of time since the original post and now, can you please do sanity bootstrap to make sure nothing's bitrotted before you commit?
>
> I rebased the patch on top of GCC head (from the git repository),
> updated the ChangeLogs, etc from two days ago (it takes two days to do
> a full rebase, pristine and patched bootstrap and testrun on my poor
> laptop ;).
Get a new laptop :-)  The process for getting one from corporate isn't 
bad.  In fact, I just got my refreshed laptop last week.

>
> I've built both pristine and patched branches with bootstrap enabled.
> I ran both testsuites and used contrib/compare_tests to make sure
> everything was as it should be.  compare_tests reports everything as
> fine.  One minor change I found, was due to some ongoing work on
> hash_tables.  It seems to parameterless constructor call for a new
> hash table has been removed.  This was trivially fixed with the patch
> attached.  Even though (to me) it is obvious, what do you think?
Looks fine to me.

jeff

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-24 16:47             ` Jeff Law
@ 2014-10-27 20:03               ` Phil Muldoon
  2014-10-28 13:29                 ` Joseph S. Myers
  0 siblings, 1 reply; 101+ messages in thread
From: Phil Muldoon @ 2014-10-27 20:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: Jeff Law, jakub, Tom Tromey, tom


> On 10/10/14 22:58, Jeff Law wrote:
>> On 10/09/14 03:07, Phil Muldoon wrote:

> Given the length of time since the original post and now, can you please do sanity bootstrap to make sure nothing's bitrotted before you commit?

>> I've built both pristine and patched branches with bootstrap enabled.
>> I ran both testsuites and used contrib/compare_tests to make sure
>> everything was as it should be.  compare_tests reports everything as
>> fine.  One minor change I found, was due to some ongoing work on
>> hash_tables.  It seems to parameterless constructor call for a new
>> hash table has been removed.  This was trivially fixed with the patch
>> attached.  Even though (to me) it is obvious, what do you think?

> Looks fine to me.
>
> jeff

> On 24/10/14 08:43, Jakub Jelinek wrote:

> So, if these are the only non-obvious changes you needed, please go
> ahead and commit.

>    Jakub

Thanks.  This patch has now been committed.  Bootstrap and
testsuite pre and post are as expected.  Thanks for your help
in getting this patch-series committed.

Cheers

Phil

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-27 20:03               ` Phil Muldoon
@ 2014-10-28 13:29                 ` Joseph S. Myers
  2014-10-28 18:00                   ` Phil Muldoon
  0 siblings, 1 reply; 101+ messages in thread
From: Joseph S. Myers @ 2014-10-28 13:29 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: gcc-patches

I'm seeing a different bootstrap failure from those already discussed:

In file included from 
/scratch/jmyers/fsf/gcc-mainline/libcc1/../gcc/gcc-plugin.h:28:0,
                 from 
/scratch/jmyers/fsf/gcc-mainline/libcc1/plugin.cc:34:
/scratch/jmyers/fsf/gcc-mainline/libcc1/../gcc/system.h:653:17: fatal error: gmp.h: No such file or directory

It appears the build is ignoring the --with-gmp option passed to 
configure.  Since <gmp.h> is included in system.h, if you include system.h 
you have to pass the right -I option corresponding to --with-gmp / 
--with-gmp-include.  (There are several other such configure options for 
MPFR, MPC, CLooG, ISL, libiconv at least - whether they are relevant 
depends on whether your code ends up including the relevant headers.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28 13:29                 ` Joseph S. Myers
@ 2014-10-28 18:00                   ` Phil Muldoon
  2014-10-29  3:32                     ` Joseph S. Myers
  2014-10-29 10:29                     ` Jakub Jelinek
  0 siblings, 2 replies; 101+ messages in thread
From: Phil Muldoon @ 2014-10-28 18:00 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches

On 28/10/14 13:19, Joseph S. Myers wrote:
> I'm seeing a different bootstrap failure from those already discussed:
>
> In file included from
> /scratch/jmyers/fsf/gcc-mainline/libcc1/../gcc/gcc-plugin.h:28:0,
>                  from
> /scratch/jmyers/fsf/gcc-mainline/libcc1/plugin.cc:34:
> /scratch/jmyers/fsf/gcc-mainline/libcc1/../gcc/system.h:653:17: fatal error: gmp.h: No such file or directory
>
> It appears the build is ignoring the --with-gmp option passed to
> configure.  Since <gmp.h> is included in system.h, if you include system.h
> you have to pass the right -I option corresponding to --with-gmp /
> --with-gmp-include.  (There are several other such configure options for
> MPFR, MPC, CLooG, ISL, libiconv at least - whether they are relevant
> depends on whether your code ends up including the relevant headers.)

Joseph,

Hi, sorry for the troubles! I am having difficulty seeing this fail on
my system.  I built gmp from upstream, installed it, and pointed to
the install location with --with-gmp. Which stage does your build fail
at?

I am actually not totally sure how to respect the -with-gmp argument
in libcc1.  auto* tools are not my strongest skill. ;)

I notice gcc/configure.ac I think just exports the variables to
Makefile.in from the main configure script.  That what we should do in
this case?

Cheers

Phil


^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28 18:00                   ` Phil Muldoon
@ 2014-10-29  3:32                     ` Joseph S. Myers
  2014-10-29 10:29                     ` Jakub Jelinek
  1 sibling, 0 replies; 101+ messages in thread
From: Joseph S. Myers @ 2014-10-29  3:32 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: gcc-patches

On Tue, 28 Oct 2014, Phil Muldoon wrote:

> Joseph,
> 
> Hi, sorry for the troubles! I am having difficulty seeing this fail on
> my system.  I built gmp from upstream, installed it, and pointed to
> the install location with --with-gmp. Which stage does your build fail
> at?

To get the failure you need not to have GMP installed somewhere the 
bootstrap compiler would otherwise find (e.g. uninstall your system GMP 
package before testing).  The failure is building stage 1.

> I am actually not totally sure how to respect the -with-gmp argument
> in libcc1.  auto* tools are not my strongest skill. ;)
> 
> I notice gcc/configure.ac I think just exports the variables to
> Makefile.in from the main configure script.  That what we should do in
> this case?

Toplevel passes GMPINC down to subdirectories.  I think you should

(a) copy

AC_ARG_VAR(GMPINC,[How to find GMP include files])

from gcc/configure.ac;

(b) copy

GMPINC = @GMPINC@

from gcc/Makefile.in;

(c) add $(GMPINC) to AM_CPPFLAGS.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28 18:00                   ` Phil Muldoon
  2014-10-29  3:32                     ` Joseph S. Myers
@ 2014-10-29 10:29                     ` Jakub Jelinek
  2014-10-29 10:45                       ` Paolo Bonzini
  2014-10-30  5:37                       ` Jeff Law
  1 sibling, 2 replies; 101+ messages in thread
From: Jakub Jelinek @ 2014-10-29 10:29 UTC (permalink / raw)
  To: Phil Muldoon, Paolo Bonzini, DJ Delorie, Alexandre Oliva,
	Ralf Wildenhues
  Cc: Joseph S. Myers, gcc-patches

On Tue, Oct 28, 2014 at 05:36:50PM +0000, Phil Muldoon wrote:
> On 28/10/14 13:19, Joseph S. Myers wrote:
> > I'm seeing a different bootstrap failure from those already discussed:
> >
> > In file included from
> > /scratch/jmyers/fsf/gcc-mainline/libcc1/../gcc/gcc-plugin.h:28:0,
> >                  from
> > /scratch/jmyers/fsf/gcc-mainline/libcc1/plugin.cc:34:
> > /scratch/jmyers/fsf/gcc-mainline/libcc1/../gcc/system.h:653:17: fatal error: gmp.h: No such file or directory
> >
> > It appears the build is ignoring the --with-gmp option passed to
> > configure.  Since <gmp.h> is included in system.h, if you include system.h
> > you have to pass the right -I option corresponding to --with-gmp /
> > --with-gmp-include.  (There are several other such configure options for
> > MPFR, MPC, CLooG, ISL, libiconv at least - whether they are relevant
> > depends on whether your code ends up including the relevant headers.)
> 
> Hi, sorry for the troubles! I am having difficulty seeing this fail on
> my system.  I built gmp from upstream, installed it, and pointed to
> the install location with --with-gmp. Which stage does your build fail
> at?
> 
> I am actually not totally sure how to respect the -with-gmp argument
> in libcc1.  auto* tools are not my strongest skill. ;)
> 
> I notice gcc/configure.ac I think just exports the variables to
> Makefile.in from the main configure script.  That what we should do in
> this case?

Here is a patch I'm bootstrapping/regtesting now (but, with system gmp
installed).  I've verified that with this patch stage1 libcc1 is built
without -Werror in flags, while stage2 libcc1 is built with -Werror.

If this passes bootstrap/regtest, is it ok for trunk (should fix
two bootstrap issues)?  Is the
https://gcc.gnu.org/ml/gcc-patches/2014-10/msg02936.html
patch ok too (that one already tested; another bootstrap issue)?

2014-10-29  Jakub Jelinek  <jakub@redhat.com>
	    Phil Muldoon  <pmuldoon@redhat.com>

	* configure.ac: Remove -Werror addition to WARN_FLAGS.  Add
	ACX_PROG_CC_WARNINGS_ARE_ERRORS and AC_ARG_VAR for GMPINC.
	* Makefile.am (AM_CPPFLAGS): Add $(GMPINC).
	(WERROR_FLAG): Remove.
	(AM_CXXFLAGS): Use $(WERROR) instead of $(WERROR_FLAG).
	* configure: Regenerated.
	* Makefile.in: Regenerated.

--- libcc1/configure.ac.jj	2014-10-28 14:39:52.000000000 +0100
+++ libcc1/configure.ac	2014-10-29 10:01:36.515497687 +0100
@@ -52,8 +52,10 @@ gcc_version=`cat $srcdir/../gcc/BASE-VER
 AC_SUBST(gcc_version)
 
 ACX_PROG_CC_WARNING_OPTS([-W -Wall], [WARN_FLAGS])
-WARN_FLAGS="$WARN_FLAGS -Werror"
 AC_SUBST(WARN_FLAGS)
+ACX_PROG_CC_WARNINGS_ARE_ERRORS([manual])
+
+AC_ARG_VAR(GMPINC,[How to find GMP include files])
 
 libsuffix=
 if test "$GXX" = yes; then
--- libcc1/Makefile.am.jj	2014-10-29 09:53:00.000000000 +0100
+++ libcc1/Makefile.am	2014-10-29 10:02:08.481885746 +0100
@@ -21,9 +21,8 @@ gcc_build_dir = ../$(host_subdir)/gcc
 AM_CPPFLAGS = -I $(srcdir)/../include -I $(srcdir)/../libgcc \
 	-I $(gcc_build_dir) -I$(srcdir)/../gcc \
 	-I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
-	-I $(srcdir)/../libcpp/include
-WERROR_FLAG = -Werror
-AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
+	-I $(srcdir)/../libcpp/include $(GMPINC)
+AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR) $(visibility)
 override CXXFLAGS := $(filter-out -fsanitize=address,$(CXXFLAGS))
 override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
 # Can be simplified when libiberty becomes a normal convenience library.
--- libcc1/configure.jj	2014-10-28 14:39:52.000000000 +0100
+++ libcc1/configure	2014-10-29 10:02:32.957419099 +0100
@@ -605,6 +605,8 @@ LIBOBJS
 ENABLE_PLUGIN_FALSE
 ENABLE_PLUGIN_TRUE
 libsuffix
+GMPINC
+WERROR
 WARN_FLAGS
 gcc_version
 visibility
@@ -743,6 +745,7 @@ with_pic
 enable_fast_install
 with_gnu_ld
 enable_libtool_lock
+enable_werror_always
 enable_plugin
 '
       ac_precious_vars='build_alias
@@ -757,7 +760,8 @@ CPP
 CXX
 CXXFLAGS
 CCC
-CXXCPP'
+CXXCPP
+GMPINC'
 
 
 # Initialize some variables set by options.
@@ -1387,6 +1391,7 @@ Optional Features:
   --enable-fast-install[=PKGS]
                           optimize for fast installation [default=yes]
   --disable-libtool-lock  avoid locking (might break parallel builds)
+  --enable-werror-always  enable -Werror despite compiler version
   --enable-plugin         enable plugin support
 
 Optional Packages:
@@ -1409,6 +1414,7 @@ Some influential environment variables:
   CXX         C++ compiler command
   CXXFLAGS    C++ compiler flags
   CXXCPP      C++ preprocessor
+  GMPINC      How to find GMP include files
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -10530,7 +10536,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 10533 "configure"
+#line 10539 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10636,7 +10642,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 10639 "configure"
+#line 10645 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -14342,7 +14348,21 @@ fi
   done
 CFLAGS="$save_CFLAGS"
 
-WARN_FLAGS="$WARN_FLAGS -Werror"
+
+WERROR=
+# Check whether --enable-werror-always was given.
+if test "${enable_werror_always+set}" = set; then :
+  enableval=$enable_werror_always;
+else
+  enable_werror_always=no
+fi
+
+if test $enable_werror_always = yes; then :
+  WERROR="$WERROR${WERROR:+ }-Werror"
+fi
+
+
+
 
 
 libsuffix=
--- libcc1/Makefile.in.jj	2014-10-29 09:53:00.000000000 +0100
+++ libcc1/Makefile.in	2014-10-29 10:02:35.739365984 +0100
@@ -140,6 +140,7 @@ ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
+GMPINC = @GMPINC@
 GREP = @GREP@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
@@ -178,6 +179,7 @@ SHELL = @SHELL@
 STRIP = @STRIP@
 VERSION = @VERSION@
 WARN_FLAGS = @WARN_FLAGS@
+WERROR = @WERROR@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -247,10 +249,9 @@ gcc_build_dir = ../$(host_subdir)/gcc
 AM_CPPFLAGS = -I $(srcdir)/../include -I $(srcdir)/../libgcc \
 	-I $(gcc_build_dir) -I$(srcdir)/../gcc \
 	-I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
-	-I $(srcdir)/../libcpp/include
+	-I $(srcdir)/../libcpp/include $(GMPINC)
 
-WERROR_FLAG = -Werror
-AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
+AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR) $(visibility)
 # Can be simplified when libiberty becomes a normal convenience library.
 libiberty_normal = ../libiberty/libiberty.a
 libiberty_noasan = ../libiberty/noasan/libiberty.a


	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-29 10:29                     ` Jakub Jelinek
@ 2014-10-29 10:45                       ` Paolo Bonzini
  2014-10-29 10:58                         ` Jakub Jelinek
  2014-10-30  5:37                       ` Jeff Law
  1 sibling, 1 reply; 101+ messages in thread
From: Paolo Bonzini @ 2014-10-29 10:45 UTC (permalink / raw)
  To: Jakub Jelinek, Phil Muldoon, DJ Delorie, Alexandre Oliva,
	Ralf Wildenhues
  Cc: Joseph S. Myers, gcc-patches



On 10/29/2014 11:28 AM, Jakub Jelinek wrote:
> If this passes bootstrap/regtest, is it ok for trunk (should fix
> two bootstrap issues)?  Is the
> https://gcc.gnu.org/ml/gcc-patches/2014-10/msg02936.html
> patch ok too (that one already tested; another bootstrap issue)?

Both seem okay, though I'd have to look at the whole thread to
understand what libcc1 is. :)

Just two questions:

1) what's the issue that you need to disable asan for?

2) why is GMPLIB not handled in the same way?

Paolo

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-29 10:45                       ` Paolo Bonzini
@ 2014-10-29 10:58                         ` Jakub Jelinek
  2014-10-29 10:59                           ` Paolo Bonzini
  0 siblings, 1 reply; 101+ messages in thread
From: Jakub Jelinek @ 2014-10-29 10:58 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Phil Muldoon, DJ Delorie, Alexandre Oliva, Ralf Wildenhues,
	Joseph S. Myers, gcc-patches

On Wed, Oct 29, 2014 at 11:37:42AM +0100, Paolo Bonzini wrote:
> 
> 
> On 10/29/2014 11:28 AM, Jakub Jelinek wrote:
> > If this passes bootstrap/regtest, is it ok for trunk (should fix
> > two bootstrap issues)?  Is the
> > https://gcc.gnu.org/ml/gcc-patches/2014-10/msg02936.html
> > patch ok too (that one already tested; another bootstrap issue)?
> 
> Both seem okay, though I'd have to look at the whole thread to
> understand what libcc1 is. :)

It is a library for communication between the debugger and
a GCC plugin (and the plugin itself).  So, the library is
dlopened into GDB and the plugin that links against that library
is dlopened by GCC when GDB asks the library it dlopened to
run the compiler with the plugin.

> Just two questions:
> 
> 1) what's the issue that you need to disable asan for?

-fsanitize=address generally doesn't work or doesn't work too well,
if the binary is not built with -fsanitize=address, but shared library
dlopened into it is.  So, we want to avoid instrumenting plugins
that way (we already don't instrument lto-plugin for that reason,
because ld might not be asan instrumented, and libcc1 is similar case,
when gdb dlopens the library, it might not be instrumented either).

> 2) why is GMPLIB not handled in the same way?

The only problem is that system.h includes gmp.h, so we need a way
to find that header.  I think libcc1 doesn't use any functions from gmp
itself, so if gmp.h can be included, GMPLIB isn't really needed.

	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-29 10:58                         ` Jakub Jelinek
@ 2014-10-29 10:59                           ` Paolo Bonzini
  2014-10-29 11:03                             ` Jakub Jelinek
                                               ` (2 more replies)
  0 siblings, 3 replies; 101+ messages in thread
From: Paolo Bonzini @ 2014-10-29 10:59 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Phil Muldoon, DJ Delorie, Alexandre Oliva, Ralf Wildenhues,
	Joseph S. Myers, gcc-patches



On 10/29/2014 11:51 AM, Jakub Jelinek wrote:
> On Wed, Oct 29, 2014 at 11:37:42AM +0100, Paolo Bonzini wrote:
>>
>>
>> On 10/29/2014 11:28 AM, Jakub Jelinek wrote:
>>> If this passes bootstrap/regtest, is it ok for trunk (should fix
>>> two bootstrap issues)?  Is the
>>> https://gcc.gnu.org/ml/gcc-patches/2014-10/msg02936.html
>>> patch ok too (that one already tested; another bootstrap issue)?
>>
>> Both seem okay, though I'd have to look at the whole thread to
>> understand what libcc1 is. :)
> 
> It is a library for communication between the debugger and
> a GCC plugin (and the plugin itself).  So, the library is
> dlopened into GDB and the plugin that links against that library
> is dlopened by GCC when GDB asks the library it dlopened to
> run the compiler with the plugin.
> 
>> Just two questions:
>>
>> 1) what's the issue that you need to disable asan for?
> 
> -fsanitize=address generally doesn't work or doesn't work too well,
> if the binary is not built with -fsanitize=address, but shared library
> dlopened into it is.  So, we want to avoid instrumenting plugins
> that way (we already don't instrument lto-plugin for that reason,
> because ld might not be asan instrumented, and libcc1 is similar case,
> when gdb dlopens the library, it might not be instrumented either).

Thanks for explaining.  I can see intuitively why that could be a problem...

>> 2) why is GMPLIB not handled in the same way?
> 
> The only problem is that system.h includes gmp.h, so we need a way
> to find that header.  I think libcc1 doesn't use any functions from gmp
> itself, so if gmp.h can be included, GMPLIB isn't really needed.

Ah, got it.  Is it hard to move the inclusion to the actual users?

Paolo

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-29 10:59                           ` Paolo Bonzini
@ 2014-10-29 11:03                             ` Jakub Jelinek
  2014-10-29 15:00                               ` Paolo Bonzini
  2014-10-29 11:10                             ` Phil Muldoon
  2014-10-29 11:42                             ` Phil Muldoon
  2 siblings, 1 reply; 101+ messages in thread
From: Jakub Jelinek @ 2014-10-29 11:03 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Phil Muldoon, DJ Delorie, Alexandre Oliva, Ralf Wildenhues,
	Joseph S. Myers, gcc-patches

On Wed, Oct 29, 2014 at 11:53:28AM +0100, Paolo Bonzini wrote:
> >> 2) why is GMPLIB not handled in the same way?
> > 
> > The only problem is that system.h includes gmp.h, so we need a way
> > to find that header.  I think libcc1 doesn't use any functions from gmp
> > itself, so if gmp.h can be included, GMPLIB isn't really needed.
> 
> Ah, got it.  Is it hard to move the inclusion to the actual users?

I think it is hard.  I think it has been moved to system.h very much
intentionally, as including gmp.h only in selected headers was causing lots
of troubles, e.g. because of #pragma GCC poison at the end of system.h,
I believe some gmp.h versions were using some poisoned symbols.
system.h doesn't include gmp.h if -DGENERATOR_FILE, but libcc1 is not a
generator, so that is not appropriate, it can use various other GCC headers
that are not suitable for generators.  GMPINC has been suggested by Joseph,
I'd think if we ever need also GMPLIB, we'd clearly see it as link failures
of libcc1 first and could add it only when really needed.

	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-29 10:59                           ` Paolo Bonzini
  2014-10-29 11:03                             ` Jakub Jelinek
@ 2014-10-29 11:10                             ` Phil Muldoon
  2014-10-29 11:42                             ` Phil Muldoon
  2 siblings, 0 replies; 101+ messages in thread
From: Phil Muldoon @ 2014-10-29 11:10 UTC (permalink / raw)
  To: Paolo Bonzini, Jakub Jelinek
  Cc: DJ Delorie, Alexandre Oliva, Ralf Wildenhues, Joseph S. Myers,
	gcc-patches

On 29/10/14 10:53, Paolo Bonzini wrote:
>>> 2) why is GMPLIB not handled in the same way?
>>
>> The only problem is that system.h includes gmp.h, so we need a way
>> to find that header.  I think libcc1 doesn't use any functions from gmp
>> itself, so if gmp.h can be included, GMPLIB isn't really needed.
>
> Ah, got it.  Is it hard to move the inclusion to the actual users?

We don't, I was looking at this issue today.  It is just as Jakub
explains.

Cheers

Phil

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-29 10:59                           ` Paolo Bonzini
  2014-10-29 11:03                             ` Jakub Jelinek
  2014-10-29 11:10                             ` Phil Muldoon
@ 2014-10-29 11:42                             ` Phil Muldoon
  2 siblings, 0 replies; 101+ messages in thread
From: Phil Muldoon @ 2014-10-29 11:42 UTC (permalink / raw)
  To: Paolo Bonzini, Jakub Jelinek
  Cc: DJ Delorie, Alexandre Oliva, Ralf Wildenhues, Joseph S. Myers,
	gcc-patches

On 29/10/14 10:53, Paolo Bonzini wrote:
>
>
> On 10/29/2014 11:51 AM, Jakub Jelinek wrote:
>> On Wed, Oct 29, 2014 at 11:37:42AM +0100, Paolo Bonzini wrote:
>>>
>>>
>>> On 10/29/2014 11:28 AM, Jakub Jelinek wrote:
>>>> If this passes bootstrap/regtest, is it ok for trunk (should fix
>>>> two bootstrap issues)?  Is the
>>>> https://gcc.gnu.org/ml/gcc-patches/2014-10/msg02936.html
>>>> patch ok too (that one already tested; another bootstrap issue)?
>>>
>>> Both seem okay, though I'd have to look at the whole thread to
>>> understand what libcc1 is. :)
>>
>> It is a library for communication between the debugger and
>> a GCC plugin (and the plugin itself).  So, the library is
>> dlopened into GDB and the plugin that links against that library
>> is dlopened by GCC when GDB asks the library it dlopened to
>> run the compiler with the plugin.
>>

Adding on to what Jakub said, it allows GDB access to GCC's parser.
There are a number of reasons why, but right now that means we can
compile code snippets in GDB (without the source of the current
inferior), allow access to symbols of that inferior in that source
snippet, etc.  We then inject and execute it.

We are currently writing a wiki article about it.  Not required reading
or anything, but more information for the curious.

https://sourceware.org/gdb/wiki/GCCCompileAndExecute

(That is a work in progress).  There is also a video of a presentation
I did at Cauldron somewhere.

Cheers

Phil

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-29 11:03                             ` Jakub Jelinek
@ 2014-10-29 15:00                               ` Paolo Bonzini
  0 siblings, 0 replies; 101+ messages in thread
From: Paolo Bonzini @ 2014-10-29 15:00 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Phil Muldoon, DJ Delorie, Alexandre Oliva, Ralf Wildenhues,
	Joseph S. Myers, gcc-patches

On 10/29/2014 11:59 AM, Jakub Jelinek wrote:
>> > Ah, got it.  Is it hard to move the inclusion to the actual users?
> I think it is hard.  I think it has been moved to system.h very much
> intentionally, as including gmp.h only in selected headers was causing lots
> of troubles, e.g. because of #pragma GCC poison at the end of system.h,
> I believe some gmp.h versions were using some poisoned symbols.
> system.h doesn't include gmp.h if -DGENERATOR_FILE, but libcc1 is not a
> generator, so that is not appropriate, it can use various other GCC headers
> that are not suitable for generators.  GMPINC has been suggested by Joseph,
> I'd think if we ever need also GMPLIB, we'd clearly see it as link failures
> of libcc1 first and could add it only when really needed.

Fair enough, thanks!

Paolo

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-29 10:29                     ` Jakub Jelinek
  2014-10-29 10:45                       ` Paolo Bonzini
@ 2014-10-30  5:37                       ` Jeff Law
  1 sibling, 0 replies; 101+ messages in thread
From: Jeff Law @ 2014-10-30  5:37 UTC (permalink / raw)
  To: Jakub Jelinek, Phil Muldoon, Paolo Bonzini, DJ Delorie,
	Alexandre Oliva, Ralf Wildenhues
  Cc: Joseph S. Myers, gcc-patches

On 10/29/14 04:28, Jakub Jelinek wrote:
> On Tue, Oct 28, 2014 at 05:36:50PM +0000, Phil Muldoon wrote:
>> On 28/10/14 13:19, Joseph S. Myers wrote:
>>> I'm seeing a different bootstrap failure from those already discussed:
>>>
>>> In file included from
>>> /scratch/jmyers/fsf/gcc-mainline/libcc1/../gcc/gcc-plugin.h:28:0,
>>>                   from
>>> /scratch/jmyers/fsf/gcc-mainline/libcc1/plugin.cc:34:
>>> /scratch/jmyers/fsf/gcc-mainline/libcc1/../gcc/system.h:653:17: fatal error: gmp.h: No such file or directory
>>>
>>> It appears the build is ignoring the --with-gmp option passed to
>>> configure.  Since <gmp.h> is included in system.h, if you include system.h
>>> you have to pass the right -I option corresponding to --with-gmp /
>>> --with-gmp-include.  (There are several other such configure options for
>>> MPFR, MPC, CLooG, ISL, libiconv at least - whether they are relevant
>>> depends on whether your code ends up including the relevant headers.)
>>
>> Hi, sorry for the troubles! I am having difficulty seeing this fail on
>> my system.  I built gmp from upstream, installed it, and pointed to
>> the install location with --with-gmp. Which stage does your build fail
>> at?
>>
>> I am actually not totally sure how to respect the -with-gmp argument
>> in libcc1.  auto* tools are not my strongest skill. ;)
>>
>> I notice gcc/configure.ac I think just exports the variables to
>> Makefile.in from the main configure script.  That what we should do in
>> this case?
>
> Here is a patch I'm bootstrapping/regtesting now (but, with system gmp
> installed).  I've verified that with this patch stage1 libcc1 is built
> without -Werror in flags, while stage2 libcc1 is built with -Werror.
>
> If this passes bootstrap/regtest, is it ok for trunk (should fix
> two bootstrap issues)?  Is the
> https://gcc.gnu.org/ml/gcc-patches/2014-10/msg02936.html
> patch ok too (that one already tested; another bootstrap issue)?
>
> 2014-10-29  Jakub Jelinek  <jakub@redhat.com>
> 	    Phil Muldoon  <pmuldoon@redhat.com>
>
> 	* configure.ac: Remove -Werror addition to WARN_FLAGS.  Add
> 	ACX_PROG_CC_WARNINGS_ARE_ERRORS and AC_ARG_VAR for GMPINC.
> 	* Makefile.am (AM_CPPFLAGS): Add $(GMPINC).
> 	(WERROR_FLAG): Remove.
> 	(AM_CXXFLAGS): Use $(WERROR) instead of $(WERROR_FLAG).
> 	* configure: Regenerated.
> 	* Makefile.in: Regenerated.
So is this still relevant if we stop bootstrapping libcc1?

The patch is OK if it's still needed.

Thanks,
Jeff


^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-30  8:56               ` Jakub Jelinek
@ 2014-10-30 10:43                 ` Thomas Schwinge
  0 siblings, 0 replies; 101+ messages in thread
From: Thomas Schwinge @ 2014-10-30 10:43 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Uros Bizjak, gcc-patches, Tom Tromey, Jeff Law, Phil Muldoon

[-- Attachment #1: Type: text/plain, Size: 5105 bytes --]

Hi!

On Thu, 30 Oct 2014 09:51:59 +0100, Jakub Jelinek <jakub@redhat.com> wrote:
> On Thu, Oct 30, 2014 at 09:33:08AM +0100, Thomas Schwinge wrote:
> > Here is a patch that I'm testing; OK?  I didn't understand what the
> > conditions are that libcc1 might not be built as a shared library: is it
> > always built as one -- but is that really supported on all systems?  If
> 
> It is not unconditionally supported, libcc1/configure.ac uses
> GCC_ENABLE_PLUGINS and doesn't compile anything if gcc doesn't support
> plugins (one of the several tests of that is that -fPIC -shared is
> supported.

Ah, now I see.  Conceptually, as I understand it, that should be done in
the top-level build system, so that libcc1 (and, in case, the shared host
libiberty) isn't even attempted to be built if not supported.  But then,
I don't personally have to deal with hosts that don't support plugins.

> Your patch is ok with proper ChangeLog entry.

Committed in r216912:

commit 944792ef24b74c2b6f5e5d0763b7e5a4a361c3d4
Author: tschwinge <tschwinge@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Thu Oct 30 10:06:37 2014 +0000

    Build a shared host libiberty also for libcc1's benefit.
    
    	* configure.ac (extra_host_libiberty_configure_flags): Add
    	--enable-shared also for libcc1's benefit.
    	* configure: Regenerate.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@216912 138bc75d-0d04-0410-961f-82ee72b054a4
---
 ChangeLog    |  6 ++++++
 configure    | 16 ++++++++++++----
 configure.ac | 14 +++++++++++---
 3 files changed, 29 insertions(+), 7 deletions(-)

diff --git ChangeLog ChangeLog
index e3636c6..ebcae80 100644
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,9 @@
+2014-10-30  Thomas Schwinge  <thomas@codesourcery.com>
+
+	* configure.ac (extra_host_libiberty_configure_flags): Add
+	--enable-shared also for libcc1's benefit.
+	* configure: Regenerate.
+
 2014-10-29  Tristan Gingold  <gingold@adacore.com>
 
 	* MAINTAINERS: Change my email address.
diff --git configure configure
index 149acf6..3eab122 100755
--- configure
+++ configure
@@ -642,8 +642,8 @@ CXXFLAGS_FOR_TARGET
 CFLAGS_FOR_TARGET
 DEBUG_PREFIX_CFLAGS_FOR_TARGET
 SYSROOT_CFLAGS_FOR_TARGET
-stage1_languages
 extra_host_libiberty_configure_flags
+stage1_languages
 extra_linker_plugin_flags
 extra_linker_plugin_configure_flags
 clooginc
@@ -6259,7 +6259,6 @@ if test -d ${srcdir}/gcc; then
   new_enable_languages=,c,
 
   # If LTO is enabled, add the LTO front end.
-  extra_host_libiberty_configure_flags=
   if test "$enable_lto" = "yes" ; then
     case ,${enable_languages}, in
       *,lto,*) ;;
@@ -6267,11 +6266,9 @@ if test -d ${srcdir}/gcc; then
     esac
     if test "${build_lto_plugin}" = "yes" ; then
       configdirs="$configdirs lto-plugin"
-      extra_host_libiberty_configure_flags=--enable-shared
     fi
   fi
 
-
   missing_languages=`echo ",$enable_languages," | sed -e s/,all,/,/ -e s/,c,/,/ `
   potential_languages=,c,
 
@@ -6584,6 +6581,17 @@ then
   esac
 fi
 
+# Sometimes we have special requirements for the host libiberty.
+extra_host_libiberty_configure_flags=
+case " $configdirs " in
+  *" lto-plugin "* | *" libcc1 "*)
+    # When these are to be built as shared libraries, the same applies to
+    # libiberty.
+    extra_host_libiberty_configure_flags=--enable-shared
+    ;;
+esac
+
+
 # Produce a warning message for the subdirs we can't configure.
 # This isn't especially interesting in the Cygnus tree, but in the individual
 # FSF releases, it's important to let people know when their machine isn't
diff --git configure.ac configure.ac
index b62af38..d8262f8 100644
--- configure.ac
+++ configure.ac
@@ -1852,7 +1852,6 @@ if test -d ${srcdir}/gcc; then
   new_enable_languages=,c,
 
   # If LTO is enabled, add the LTO front end.
-  extra_host_libiberty_configure_flags=
   if test "$enable_lto" = "yes" ; then
     case ,${enable_languages}, in
       *,lto,*) ;;
@@ -1860,10 +1859,8 @@ if test -d ${srcdir}/gcc; then
     esac
     if test "${build_lto_plugin}" = "yes" ; then
       configdirs="$configdirs lto-plugin"
-      extra_host_libiberty_configure_flags=--enable-shared
     fi
   fi
-  AC_SUBST(extra_host_libiberty_configure_flags)
 
   missing_languages=`echo ",$enable_languages," | sed -e s/,all,/,/ -e s/,c,/,/ `
   potential_languages=,c,
@@ -2177,6 +2174,17 @@ then
   esac
 fi
 
+# Sometimes we have special requirements for the host libiberty.
+extra_host_libiberty_configure_flags=
+case " $configdirs " in
+  *" lto-plugin "* | *" libcc1 "*)
+    # When these are to be built as shared libraries, the same applies to
+    # libiberty.
+    extra_host_libiberty_configure_flags=--enable-shared
+    ;;
+esac
+AC_SUBST(extra_host_libiberty_configure_flags)
+
 # Produce a warning message for the subdirs we can't configure.
 # This isn't especially interesting in the Cygnus tree, but in the individual
 # FSF releases, it's important to let people know when their machine isn't


Grüße,
 Thomas

[-- Attachment #2: Type: application/pgp-signature, Size: 472 bytes --]

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-30  8:50             ` Thomas Schwinge
@ 2014-10-30  8:56               ` Jakub Jelinek
  2014-10-30 10:43                 ` Thomas Schwinge
  0 siblings, 1 reply; 101+ messages in thread
From: Jakub Jelinek @ 2014-10-30  8:56 UTC (permalink / raw)
  To: Thomas Schwinge
  Cc: Uros Bizjak, gcc-patches, Tom Tromey, Jeff Law, Phil Muldoon

On Thu, Oct 30, 2014 at 09:33:08AM +0100, Thomas Schwinge wrote:
> Here is a patch that I'm testing; OK?  I didn't understand what the
> conditions are that libcc1 might not be built as a shared library: is it
> always built as one -- but is that really supported on all systems?  If

It is not unconditionally supported, libcc1/configure.ac uses
GCC_ENABLE_PLUGINS and doesn't compile anything if gcc doesn't support
plugins (one of the several tests of that is that -fPIC -shared is
supported.

> that's indeed true, then this could be further simplified, and
> --enable-shared passed to the host libiberty unconditionally.

Your patch is ok with proper ChangeLog entry.

> --- configure.ac
> +++ configure.ac
> @@ -1865,7 +1865,6 @@ if test -d ${srcdir}/gcc; then
>    new_enable_languages=,c,
>  
>    # If LTO is enabled, add the LTO front end.
> -  extra_host_libiberty_configure_flags=
>    if test "$enable_lto" = "yes" ; then
>      case ,${enable_languages}, in
>        *,lto,*) ;;
> @@ -1873,10 +1872,8 @@ if test -d ${srcdir}/gcc; then
>      esac
>      if test "${build_lto_plugin}" = "yes" ; then
>        configdirs="$configdirs lto-plugin"
> -      extra_host_libiberty_configure_flags=--enable-shared
>      fi
>    fi
> -  AC_SUBST(extra_host_libiberty_configure_flags)
>  
>    missing_languages=`echo ",$enable_languages," | sed -e s/,all,/,/ -e s/,c,/,/ `
>    potential_languages=,c,
> @@ -2190,6 +2187,17 @@ then
>    esac
>  fi
>  
> +# Sometimes we have special requirements for the host libiberty.
> +extra_host_libiberty_configure_flags=
> +case " $configdirs " in
> +  *" lto-plugin "* | *" libcc1 "*)
> +    # When these are to be built as shared libraries, the same applies to
> +    # libiberty.
> +    extra_host_libiberty_configure_flags=--enable-shared
> +    ;;
> +esac
> +AC_SUBST(extra_host_libiberty_configure_flags)
> +
>  # Produce a warning message for the subdirs we can't configure.
>  # This isn't especially interesting in the Cygnus tree, but in the individual
>  # FSF releases, it's important to let people know when their machine isn't
> 
> 
> Grüße,
>  Thomas



	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28 12:24           ` Jakub Jelinek
  2014-10-30  5:16             ` Jeff Law
@ 2014-10-30  8:50             ` Thomas Schwinge
  2014-10-30  8:56               ` Jakub Jelinek
  1 sibling, 1 reply; 101+ messages in thread
From: Thomas Schwinge @ 2014-10-30  8:50 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Uros Bizjak, gcc-patches, Tom Tromey, Jeff Law, Phil Muldoon

[-- Attachment #1: Type: text/plain, Size: 4498 bytes --]

Hi!

On Tue, 28 Oct 2014 13:23:50 +0100, Jakub Jelinek <jakub@redhat.com> wrote:
> On Tue, Oct 28, 2014 at 11:47:31AM +0000, Phil Muldoon wrote:
> > I think I have a solution.  Though my automake fu is very weak.  Does
> > this patch work for you?  I'm really not sure how to deal with the
> > three possible versions of libiberty any other way.
> 
> That is insufficient,
> a) you don't filter away -fsanitize=address, which would make it
> unusable in gdb
> b) without the -Wc, stuff, you get the ugly libtool warnings
> c) the LTLDFLAGS mess is needed for libtool not eating the -Wc, stuff

> So I'm proposing my patch (which is modeled after lto-plugin changes by
> myself and others), [...]

(Maybe we should now turn that into generic infrastructure?)

> 2014-10-28  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* Makefile.am (CXXFLAGS, LDFLAGS): Filter out -fsanitize=address.
> 	(libiberty_normal, libiberty_noasan, libiberty_pic, libiberty_dep):
> 	New variables.
> 	(libiberty): Set to -Wc, followed by the first existing noasan/,
> 	pic/ or . libiberty.a.
> 	(libcc1plugin_la_DEPENDENCIES, libcc1plugin_la_LINK,
> 	libcc1_la_DEPENDENCIES, libcc1_la_LINK, LTLDFLAGS): New variables.
> 	* Makefile.in: Regenerated.

;-) To re-use your words: »That is insufficient«, d) in a configuration
where there is no lto-plugin built, we now try to link the shared libcc1
against a static libiberty:

    /bin/bash ./libtool --tag=CXX   --mode=link g++ -m64 [...] -module -export-symbols [...]/source-gcc/libcc1/libcc1.sym  -Xcompiler '-static-libstdc++' -Xcompiler '-static-libgcc' -o libcc1.la -rpath /lib/../lib64 findcomp.lo libcc1.lo names.lo callbacks.lo connection.lo marshall.lo   -Wc,../libiberty/libiberty.a 
    libtool: link: g++ -m64 [...] -shared -nostdlib [...]/crti.o [...]/crtbeginS.o  .libs/findcomp.o .libs/libcc1.o .libs/names.o .libs/callbacks.o .libs/connection.o .libs/marshall.o [...] -lstdc++ -lm -lc -lgcc_s [...]/crtendS.o [...]/crtn.o  -m64 [...] -static-libstdc++ -static-libgcc ../libiberty/libiberty.a   -Wl,-soname -Wl,libcc1.so.0 -Wl,-retain-symbols-file -Wl,[...]/source-gcc/libcc1/libcc1.sym -o .libs/libcc1.so.0.0.0
    [...]/ld: ../libiberty/libiberty.a(regex.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
    ../libiberty/libiberty.a: error adding symbols: Bad value
    collect2: error: ld returned 1 exit status
    make[3]: *** [libcc1.la] Error 1
    make[3]: Leaving directory `[...]/build-gcc/libcc1'
    make[2]: *** [all] Error 2
    make[2]: Leaving directory `[...]/build-gcc/libcc1'
    make[1]: *** [all-libcc1] Error 2
    make[1]: Leaving directory `[...]/build-gcc'
    make: *** [all] Error 2

Here is a patch that I'm testing; OK?  I didn't understand what the
conditions are that libcc1 might not be built as a shared library: is it
always built as one -- but is that really supported on all systems?  If
that's indeed true, then this could be further simplified, and
--enable-shared passed to the host libiberty unconditionally.

--- configure.ac
+++ configure.ac
@@ -1865,7 +1865,6 @@ if test -d ${srcdir}/gcc; then
   new_enable_languages=,c,
 
   # If LTO is enabled, add the LTO front end.
-  extra_host_libiberty_configure_flags=
   if test "$enable_lto" = "yes" ; then
     case ,${enable_languages}, in
       *,lto,*) ;;
@@ -1873,10 +1872,8 @@ if test -d ${srcdir}/gcc; then
     esac
     if test "${build_lto_plugin}" = "yes" ; then
       configdirs="$configdirs lto-plugin"
-      extra_host_libiberty_configure_flags=--enable-shared
     fi
   fi
-  AC_SUBST(extra_host_libiberty_configure_flags)
 
   missing_languages=`echo ",$enable_languages," | sed -e s/,all,/,/ -e s/,c,/,/ `
   potential_languages=,c,
@@ -2190,6 +2187,17 @@ then
   esac
 fi
 
+# Sometimes we have special requirements for the host libiberty.
+extra_host_libiberty_configure_flags=
+case " $configdirs " in
+  *" lto-plugin "* | *" libcc1 "*)
+    # When these are to be built as shared libraries, the same applies to
+    # libiberty.
+    extra_host_libiberty_configure_flags=--enable-shared
+    ;;
+esac
+AC_SUBST(extra_host_libiberty_configure_flags)
+
 # Produce a warning message for the subdirs we can't configure.
 # This isn't especially interesting in the Cygnus tree, but in the individual
 # FSF releases, it's important to let people know when their machine isn't


Grüße,
 Thomas

[-- Attachment #2: Type: application/pgp-signature, Size: 472 bytes --]

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28 12:24           ` Jakub Jelinek
@ 2014-10-30  5:16             ` Jeff Law
  2014-10-30  8:50             ` Thomas Schwinge
  1 sibling, 0 replies; 101+ messages in thread
From: Jeff Law @ 2014-10-30  5:16 UTC (permalink / raw)
  To: Jakub Jelinek, Phil Muldoon; +Cc: Uros Bizjak, gcc-patches, Tom Tromey

On 10/28/14 06:23, Jakub Jelinek wrote:
> On Tue, Oct 28, 2014 at 11:47:31AM +0000, Phil Muldoon wrote:
>> I think I have a solution.  Though my automake fu is very weak.  Does
>> this patch work for you?  I'm really not sure how to deal with the
>> three possible versions of libiberty any other way.
>
> That is insufficient,
> a) you don't filter away -fsanitize=address, which would make it
> unusable in gdb
> b) without the -Wc, stuff, you get the ugly libtool warnings
> c) the LTLDFLAGS mess is needed for libtool not eating the -Wc, stuff
>
> I've in the mean time successfully bootstrapped/regtested my patch on
> i686-linux (--with-build-config=bootstrap-ubsan), that was build without
> ada, on x86_64-linux the build failed because of some recent ada vs.
> bootstrap-ubsan incompatibilities unrelated to libcc1 (but libcc1 built
> fine).
>
> So I'm proposing my patch (which is modeled after lto-plugin changes by
> myself and others), with the -Werror stuff handled separately as follow-up.
> Ok for trunk?
>
> 2014-10-28  Jakub Jelinek  <jakub@redhat.com>
>
> 	* Makefile.am (CXXFLAGS, LDFLAGS): Filter out -fsanitize=address.
> 	(libiberty_normal, libiberty_noasan, libiberty_pic, libiberty_dep):
> 	New variables.
> 	(libiberty): Set to -Wc, followed by the first existing noasan/,
> 	pic/ or . libiberty.a.
> 	(libcc1plugin_la_DEPENDENCIES, libcc1plugin_la_LINK,
> 	libcc1_la_DEPENDENCIES, libcc1_la_LINK, LTLDFLAGS): New variables.
> 	* Makefile.in: Regenerated.
Ick.    But OK I guess.

jeff


^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28 11:53         ` Phil Muldoon
@ 2014-10-28 12:24           ` Jakub Jelinek
  2014-10-30  5:16             ` Jeff Law
  2014-10-30  8:50             ` Thomas Schwinge
  0 siblings, 2 replies; 101+ messages in thread
From: Jakub Jelinek @ 2014-10-28 12:24 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Uros Bizjak, gcc-patches, Tom Tromey, Jeff Law

On Tue, Oct 28, 2014 at 11:47:31AM +0000, Phil Muldoon wrote:
> I think I have a solution.  Though my automake fu is very weak.  Does
> this patch work for you?  I'm really not sure how to deal with the
> three possible versions of libiberty any other way.

That is insufficient,
a) you don't filter away -fsanitize=address, which would make it
unusable in gdb
b) without the -Wc, stuff, you get the ugly libtool warnings
c) the LTLDFLAGS mess is needed for libtool not eating the -Wc, stuff

I've in the mean time successfully bootstrapped/regtested my patch on
i686-linux (--with-build-config=bootstrap-ubsan), that was build without
ada, on x86_64-linux the build failed because of some recent ada vs.
bootstrap-ubsan incompatibilities unrelated to libcc1 (but libcc1 built
fine).

So I'm proposing my patch (which is modeled after lto-plugin changes by
myself and others), with the -Werror stuff handled separately as follow-up.
Ok for trunk?

2014-10-28  Jakub Jelinek  <jakub@redhat.com>

	* Makefile.am (CXXFLAGS, LDFLAGS): Filter out -fsanitize=address.
	(libiberty_normal, libiberty_noasan, libiberty_pic, libiberty_dep):
	New variables.
	(libiberty): Set to -Wc, followed by the first existing noasan/,
	pic/ or . libiberty.a.
	(libcc1plugin_la_DEPENDENCIES, libcc1plugin_la_LINK,
	libcc1_la_DEPENDENCIES, libcc1_la_LINK, LTLDFLAGS): New variables.
	* Makefile.in: Regenerated.

--- libcc1/Makefile.am.jj	2014-10-27 19:41:13.000000000 +0100
+++ libcc1/Makefile.am	2014-10-28 09:07:57.443711725 +0100
@@ -24,8 +24,17 @@ AM_CPPFLAGS = -I $(srcdir)/../include -I
 	-I $(srcdir)/../libcpp/include
 WERROR_FLAG = -Werror
 AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
-libiberty = ../libiberty/pic/libiberty.a
-
+override CXXFLAGS := $(filter-out -fsanitize=address,$(CXXFLAGS))
+override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
+# Can be simplified when libiberty becomes a normal convenience library.
+libiberty_normal = ../libiberty/libiberty.a
+libiberty_noasan = ../libiberty/noasan/libiberty.a
+libiberty_pic = ../libiberty/pic/libiberty.a
+Wc=-Wc,
+libiberty = $(if $(wildcard $(libiberty_noasan)),$(Wc)$(libiberty_noasan), \
+	    $(if $(wildcard $(libiberty_pic)),$(Wc)$(libiberty_pic), \
+	    $(Wc)$(libiberty_normal)))
+libiberty_dep = $(patsubst $(Wc)%,%,$(libiberty))
 
 plugindir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/plugin
 cc1libdir = $(libdir)/$(libsuffix)
@@ -49,7 +58,16 @@ shared_source = callbacks.cc callbacks.h
 libcc1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1plugin.sym
 libcc1plugin_la_SOURCES = plugin.cc $(shared_source)
 libcc1plugin_la_LIBADD = $(libiberty)
+libcc1plugin_la_DEPENDENCIES = $(libiberty_dep)
+libcc1plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(libcc1plugin_la_LDFLAGS) $(LTLDFLAGS) -o $@
 
+LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
 libcc1_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1.sym
 libcc1_la_SOURCES = findcomp.cc libcc1.cc names.cc names.hh $(shared_source)
 libcc1_la_LIBADD = $(libiberty)
+libcc1_la_DEPENDENCIES = $(libiberty_dep)
+libcc1_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(libcc1_la_LDFLAGS) $(LTLDFLAGS) -o $@
--- libcc1/Makefile.in.jj	2014-10-27 19:41:13.000000000 +0100
+++ libcc1/Makefile.in	2014-10-28 09:08:01.689922599 +0100
@@ -81,20 +81,12 @@ am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
 am__installdirs = "$(DESTDIR)$(cc1libdir)" "$(DESTDIR)$(plugindir)"
 LTLIBRARIES = $(cc1lib_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libcc1_la_DEPENDENCIES = $(libiberty)
 am__objects_1 = callbacks.lo connection.lo marshall.lo
 am_libcc1_la_OBJECTS = findcomp.lo libcc1.lo names.lo $(am__objects_1)
 libcc1_la_OBJECTS = $(am_libcc1_la_OBJECTS)
-libcc1_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
-	$(CXXFLAGS) $(libcc1_la_LDFLAGS) $(LDFLAGS) -o $@
 @ENABLE_PLUGIN_TRUE@am_libcc1_la_rpath = -rpath $(cc1libdir)
-libcc1plugin_la_DEPENDENCIES = $(libiberty)
 am_libcc1plugin_la_OBJECTS = plugin.lo $(am__objects_1)
 libcc1plugin_la_OBJECTS = $(am_libcc1plugin_la_OBJECTS)
-libcc1plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
-	$(CXXFLAGS) $(libcc1plugin_la_LDFLAGS) $(LDFLAGS) -o $@
 @ENABLE_PLUGIN_TRUE@am_libcc1plugin_la_rpath = -rpath $(plugindir)
 DEFAULT_INCLUDES = -I.@am__isrc@
 depcomp = $(SHELL) $(top_srcdir)/../depcomp
@@ -259,7 +251,16 @@ AM_CPPFLAGS = -I $(srcdir)/../include -I
 
 WERROR_FLAG = -Werror
 AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
-libiberty = ../libiberty/pic/libiberty.a
+# Can be simplified when libiberty becomes a normal convenience library.
+libiberty_normal = ../libiberty/libiberty.a
+libiberty_noasan = ../libiberty/noasan/libiberty.a
+libiberty_pic = ../libiberty/pic/libiberty.a
+Wc = -Wc,
+libiberty = $(if $(wildcard $(libiberty_noasan)),$(Wc)$(libiberty_noasan), \
+	    $(if $(wildcard $(libiberty_pic)),$(Wc)$(libiberty_pic), \
+	    $(Wc)$(libiberty_normal)))
+
+libiberty_dep = $(patsubst $(Wc)%,%,$(libiberty))
 plugindir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/plugin
 cc1libdir = $(libdir)/$(libsuffix)
 @ENABLE_PLUGIN_TRUE@plugin_LTLIBRARIES = libcc1plugin.la
@@ -271,9 +272,20 @@ shared_source = callbacks.cc callbacks.h
 libcc1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1plugin.sym
 libcc1plugin_la_SOURCES = plugin.cc $(shared_source)
 libcc1plugin_la_LIBADD = $(libiberty)
+libcc1plugin_la_DEPENDENCIES = $(libiberty_dep)
+libcc1plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(libcc1plugin_la_LDFLAGS) $(LTLDFLAGS) -o $@
+
+LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
 libcc1_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1.sym
 libcc1_la_SOURCES = findcomp.cc libcc1.cc names.cc names.hh $(shared_source)
 libcc1_la_LIBADD = $(libiberty)
+libcc1_la_DEPENDENCIES = $(libiberty_dep)
+libcc1_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(libcc1_la_LDFLAGS) $(LTLDFLAGS) -o $@
+
 all: $(BUILT_SOURCES) cc1plugin-config.h
 	$(MAKE) $(AM_MAKEFLAGS) all-am
 
@@ -619,6 +631,8 @@ uninstall-am: uninstall-cc1libLTLIBRARIE
 	pdf pdf-am ps ps-am tags uninstall uninstall-am \
 	uninstall-cc1libLTLIBRARIES uninstall-pluginLTLIBRARIES
 
+override CXXFLAGS := $(filter-out -fsanitize=address,$(CXXFLAGS))
+override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
 
 # Put this in a header so we don't run sed for each compilation.  This
 # is also simpler to debug as one can easily see the constant.


	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28 10:56       ` Uros Bizjak
  2014-10-28 11:16         ` Phil Muldoon
@ 2014-10-28 11:53         ` Phil Muldoon
  2014-10-28 12:24           ` Jakub Jelinek
  1 sibling, 1 reply; 101+ messages in thread
From: Phil Muldoon @ 2014-10-28 11:53 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: Jakub Jelinek, gcc-patches, Tom Tromey, Jeff Law

On 28/10/14 10:51, Uros Bizjak wrote:
> On Tue, Oct 28, 2014 at 11:35 AM, Phil Muldoon <pmuldoon@redhat.com> wrote:
>
>>>>>> This patch has now been committed.
>>>>>
>>>>> Also breaks bootstap on x86_64-linux-gnu, CentOS 5.11:
>>>>
>>>> For -Werror, I'd think that should fix that, WARN_FLAGS should
>>>> already contain -Werror during stage2/stage3 unless --disable-werror.
>>>> Untested though.
>>>
>>> No, it still fails, although with one -Werror less in the compile flags:
>>
>> Does removing it from configure.ac and regenerating configure work?
>>
>> I don't have access to a system compiler of the version you have, so I
>> am unable to test.
>
> Yes, this patch allows bootstrap to pass stage1, although with a new warning:
>
> *** Warning: Linking the shared library libcc1.la against the
> *** static library ../libiberty/pic/libiberty.a is not portable!
>
> Thanks,
> Uros.

I think I have a solution.  Though my automake fu is very weak.  Does
this patch work for you?  I'm really not sure how to deal with the
three possible versions of libiberty any other way.

Cheers

Phil

--



Index: Makefile.in
===================================================================
--- Makefile.in    (revision 216776)
+++ Makefile.in    (working copy)
@@ -81,7 +81,8 @@
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
 am__installdirs = "$(DESTDIR)$(cc1libdir)" "$(DESTDIR)$(plugindir)"
 LTLIBRARIES = $(cc1lib_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libcc1_la_DEPENDENCIES = $(libiberty)
+libcc1_la_DEPENDENCIES = $(if $(wildcard $(libiberty_noasan)),, $(if \
+    $(wildcard $(libiberty_pic)),,$(libiberty)))
 am__objects_1 = callbacks.lo connection.lo marshall.lo
 am_libcc1_la_OBJECTS = findcomp.lo libcc1.lo names.lo $(am__objects_1)
 libcc1_la_OBJECTS = $(am_libcc1_la_OBJECTS)
@@ -89,7 +90,8 @@
     $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
     $(CXXFLAGS) $(libcc1_la_LDFLAGS) $(LDFLAGS) -o $@
 @ENABLE_PLUGIN_TRUE@am_libcc1_la_rpath = -rpath $(cc1libdir)
-libcc1plugin_la_DEPENDENCIES = $(libiberty)
+libcc1plugin_la_DEPENDENCIES = $(if $(wildcard $(libiberty_noasan)),, \
+    $(if $(wildcard $(libiberty_pic)),,$(libiberty)))
 am_libcc1plugin_la_OBJECTS = plugin.lo $(am__objects_1)
 libcc1plugin_la_OBJECTS = $(am_libcc1plugin_la_OBJECTS)
 libcc1plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
@@ -257,9 +259,10 @@
     -I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
     -I $(srcdir)/../libcpp/include
 
-WERROR_FLAG = -Werror
-AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
-libiberty = ../libiberty/pic/libiberty.a
+AM_CXXFLAGS = $(WARN_FLAGS) $(visibility)
+libiberty = ../libiberty/libiberty.a
+libiberty_noasan = ../libiberty/noasan/libiberty.a
+libiberty_pic = ../libiberty/pic/libiberty.a
 plugindir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/plugin
 cc1libdir = $(libdir)/$(libsuffix)
 @ENABLE_PLUGIN_TRUE@plugin_LTLIBRARIES = libcc1plugin.la
@@ -270,10 +273,16 @@
 
 libcc1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1plugin.sym
 libcc1plugin_la_SOURCES = plugin.cc $(shared_source)
-libcc1plugin_la_LIBADD = $(libiberty)
+libcc1plugin_la_LIBADD = \
+    $(if $(wildcard $(libiberty_noasan)),, \
+    $(if $(wildcard $(libiberty_pic)),,$(libiberty)))
+
 libcc1_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1.sym
 libcc1_la_SOURCES = findcomp.cc libcc1.cc names.cc names.hh $(shared_source)
-libcc1_la_LIBADD = $(libiberty)
+libcc1_la_LIBADD = \
+    $(if $(wildcard $(libiberty_noasan)),, \
+    $(if $(wildcard $(libiberty_pic)),,$(libiberty)))
+
 all: $(BUILT_SOURCES) cc1plugin-config.h
     $(MAKE) $(AM_MAKEFLAGS) all-am
 
Index: Makefile.am
===================================================================
--- Makefile.am    (revision 216776)
+++ Makefile.am    (working copy)
@@ -22,10 +22,11 @@
     -I $(gcc_build_dir) -I$(srcdir)/../gcc \
     -I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
     -I $(srcdir)/../libcpp/include
-WERROR_FLAG = -Werror
-AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
-libiberty = ../libiberty/pic/libiberty.a
+AM_CXXFLAGS = $(WARN_FLAGS) $(visibility)
 
+libiberty = ../libiberty/libiberty.a
+libiberty_noasan = ../libiberty/noasan/libiberty.a
+libiberty_pic = ../libiberty/pic/libiberty.a
 
 plugindir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/plugin
 cc1libdir = $(libdir)/$(libsuffix)
@@ -48,8 +49,13 @@
 
 libcc1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1plugin.sym
 libcc1plugin_la_SOURCES = plugin.cc $(shared_source)
-libcc1plugin_la_LIBADD = $(libiberty)
+libcc1plugin_la_LIBADD = \
+    $(if $(wildcard $(libiberty_noasan)),, \
+    $(if $(wildcard $(libiberty_pic)),,$(libiberty)))
 
 libcc1_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1.sym
 libcc1_la_SOURCES = findcomp.cc libcc1.cc names.cc names.hh $(shared_source)
-libcc1_la_LIBADD = $(libiberty)
+libcc1_la_LIBADD = \
+    $(if $(wildcard $(libiberty_noasan)),, \
+    $(if $(wildcard $(libiberty_pic)),,$(libiberty)))
+

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28 10:56       ` Uros Bizjak
@ 2014-10-28 11:16         ` Phil Muldoon
  2014-10-28 11:53         ` Phil Muldoon
  1 sibling, 0 replies; 101+ messages in thread
From: Phil Muldoon @ 2014-10-28 11:16 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: Jakub Jelinek, gcc-patches, Tom Tromey, Jeff Law

On 28/10/14 10:51, Uros Bizjak wrote:
> On Tue, Oct 28, 2014 at 11:35 AM, Phil Muldoon <pmuldoon@redhat.com> wrote:
>
>>>>>> This patch has now been committed.
>>>>> Also breaks bootstap on x86_64-linux-gnu, CentOS 5.11:
>>>> For -Werror, I'd think that should fix that, WARN_FLAGS should
>>>> already contain -Werror during stage2/stage3 unless --disable-werror.
>>>> Untested though.
>>> No, it still fails, although with one -Werror less in the compile flags:
>> Does removing it from configure.ac and regenerating configure work?
>>
>> I don't have access to a system compiler of the version you have, so I
>> am unable to test.
> Yes, this patch allows bootstrap to pass stage1, although with a new warning:
>
> *** Warning: Linking the shared library libcc1.la against the
> *** static library ../libiberty/pic/libiberty.a is not portable!
>
> Thanks,
> Uros.

Yeah there is a separate issue with the way we link libiberty in Makefile.am.  I am investigating and attempting to fix this right now.

Cheers

Phil

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28 10:51     ` Phil Muldoon
@ 2014-10-28 10:56       ` Uros Bizjak
  2014-10-28 11:16         ` Phil Muldoon
  2014-10-28 11:53         ` Phil Muldoon
  0 siblings, 2 replies; 101+ messages in thread
From: Uros Bizjak @ 2014-10-28 10:56 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Jakub Jelinek, gcc-patches, Tom Tromey, Jeff Law

On Tue, Oct 28, 2014 at 11:35 AM, Phil Muldoon <pmuldoon@redhat.com> wrote:

>>>>> This patch has now been committed.
>>>>
>>>> Also breaks bootstap on x86_64-linux-gnu, CentOS 5.11:
>>>
>>> For -Werror, I'd think that should fix that, WARN_FLAGS should
>>> already contain -Werror during stage2/stage3 unless --disable-werror.
>>> Untested though.
>>
>> No, it still fails, although with one -Werror less in the compile flags:
>
> Does removing it from configure.ac and regenerating configure work?
>
> I don't have access to a system compiler of the version you have, so I
> am unable to test.

Yes, this patch allows bootstrap to pass stage1, although with a new warning:

*** Warning: Linking the shared library libcc1.la against the
*** static library ../libiberty/pic/libiberty.a is not portable!

Thanks,
Uros.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28  9:58   ` Uros Bizjak
@ 2014-10-28 10:51     ` Phil Muldoon
  2014-10-28 10:56       ` Uros Bizjak
  0 siblings, 1 reply; 101+ messages in thread
From: Phil Muldoon @ 2014-10-28 10:51 UTC (permalink / raw)
  To: Uros Bizjak, Jakub Jelinek; +Cc: gcc-patches, Tom Tromey, Jeff Law

On 28/10/14 09:57, Uros Bizjak wrote:
> On Tue, Oct 28, 2014 at 10:35 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Tue, Oct 28, 2014 at 09:36:45AM +0100, Uros Bizjak wrote:
>>>> This patch has now been committed.
>>>
>>> Also breaks bootstap on x86_64-linux-gnu, CentOS 5.11:
>>
>> For -Werror, I'd think that should fix that, WARN_FLAGS should
>> already contain -Werror during stage2/stage3 unless --disable-werror.
>> Untested though.
>
> No, it still fails, although with one -Werror less in the compile flags:

Does removing it from configure.ac and regenerating configure work?

I don't have access to a system compiler of the version you have, so I
am unable to test.

Cheers

Phil

--

Index: Makefile.am
===================================================================
--- Makefile.am    (revision 216776)
+++ Makefile.am    (working copy)
@@ -22,8 +22,7 @@
     -I $(gcc_build_dir) -I$(srcdir)/../gcc \
     -I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
     -I $(srcdir)/../libcpp/include
-WERROR_FLAG = -Werror
-AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
+AM_CXXFLAGS = $(WARN_FLAGS) $(visibility)
 libiberty = ../libiberty/pic/libiberty.a
 
 
Index: Makefile.in
===================================================================
--- Makefile.in    (revision 216776)
+++ Makefile.in    (working copy)
@@ -257,8 +257,7 @@
     -I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
     -I $(srcdir)/../libcpp/include
 
-WERROR_FLAG = -Werror
-AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
+AM_CXXFLAGS = $(WARN_FLAGS) $(visibility)
 libiberty = ../libiberty/pic/libiberty.a
 plugindir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/plugin
 cc1libdir = $(libdir)/$(libsuffix)

Index: configure
===================================================================
--- configure    (revision 216776)
+++ configure    (working copy)
@@ -14342,7 +14342,7 @@
   done
 CFLAGS="$save_CFLAGS"
 
-WARN_FLAGS="$WARN_FLAGS -Werror"
+WARN_FLAGS="$WARN_FLAGS"
 
 
 libsuffix=

Index: configure.ac
===================================================================
--- configure.ac    (revision 216776)
+++ configure.ac    (working copy)
@@ -52,7 +52,7 @@
 AC_SUBST(gcc_version)
 
 ACX_PROG_CC_WARNING_OPTS([-W -Wall], [WARN_FLAGS])
-WARN_FLAGS="$WARN_FLAGS -Werror"
+WARN_FLAGS="$WARN_FLAGS"
 AC_SUBST(WARN_FLAGS)
 
 libsuffix=


^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28  9:36 ` Jakub Jelinek
@ 2014-10-28  9:58   ` Uros Bizjak
  2014-10-28 10:51     ` Phil Muldoon
  0 siblings, 1 reply; 101+ messages in thread
From: Uros Bizjak @ 2014-10-28  9:58 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches, Tom Tromey, Jeff Law, Phil Muldoon

On Tue, Oct 28, 2014 at 10:35 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Tue, Oct 28, 2014 at 09:36:45AM +0100, Uros Bizjak wrote:
>> > This patch has now been committed.
>>
>> Also breaks bootstap on x86_64-linux-gnu, CentOS 5.11:
>
> For -Werror, I'd think that should fix that, WARN_FLAGS should
> already contain -Werror during stage2/stage3 unless --disable-werror.
> Untested though.

No, it still fails, although with one -Werror less in the compile flags:

gmake[4]: Entering directory `/home/uros/gcc-build/libcc1'
/bin/sh ./libtool --tag=CXX   --mode=compile g++ -DHAVE_CONFIG_H -I.
-I../../gcc-svn/trunk/libcc1  -I ../../gcc-svn/trunk/libcc1/../include
-I ../../gcc-svn/trunk/libcc1/../libgcc -I .././gcc
-I../../gcc-svn/trunk/libcc1/../gcc -I
../../gcc-svn/trunk/libcc1/../gcc/c -I
../../gcc-svn/trunk/libcc1/../gcc/c-family -I
../../gcc-svn/trunk/libcc1/../libcpp/include  -W -Wall -Werror
-fvisibility=hidden -g -MT plugin.lo -MD -MP -MF .deps/plugin.Tpo -c
-o plugin.lo ../../gcc-svn/trunk/libcc1/plugin.cc
libtool: compile:  g++ -DHAVE_CONFIG_H -I.
-I../../gcc-svn/trunk/libcc1 -I ../../gcc-svn/trunk/libcc1/../include
-I ../../gcc-svn/trunk/libcc1/../libgcc -I .././gcc
-I../../gcc-svn/trunk/libcc1/../gcc -I
../../gcc-svn/trunk/libcc1/../gcc/c -I
../../gcc-svn/trunk/libcc1/../gcc/c-family -I
../../gcc-svn/trunk/libcc1/../libcpp/include -W -Wall -Werror
-fvisibility=hidden -g -MT plugin.lo -MD -MP -MF .deps/plugin.Tpo -c
../../gcc-svn/trunk/libcc1/plugin.cc  -fPIC -DPIC -o .libs/plugin.o
cc1plus: warnings being treated as errors
../../gcc-svn/trunk/libcc1/../gcc/hash-table.h: In instantiation of
‘hash_table<pointer_hash<tree_node>, xcallocator, true>’:
../../gcc-svn/trunk/libcc1/plugin.cc:171:   instantiated from here
../../gcc-svn/trunk/libcc1/../gcc/hash-table.h:1161: warning: lowering
visibility of ‘void gt_ggc_mx(hash_table<T, xcallocator,
storage_tester<T,void>::value>*) [with T = T, Descriptor =
pointer_hash<tree_node>, Allocator = xcallocator]’ to match its type
../../gcc-svn/trunk/libcc1/../gcc/hash-table.h:1162: warning: lowering
visibility of ‘void gt_pch_nx(hash_table<T, xcallocator,
storage_tester<T,void>::value>*) [with T = T, Descriptor =
pointer_hash<tree_node>, Allocator = xcallocator]’ to match its type
../../gcc-svn/trunk/libcc1/../gcc/hash-table.h:1166: warning: lowering
visibility of ‘void gt_pch_nx(hash_map<T, U, V>*, void (*)(void*,
void*), void*) [with T = T, U = U, V = V, Descriptor =
pointer_hash<tree_node>, Allocator = xcallocator]’ to match its type
../../gcc-svn/trunk/libcc1/../gcc/hash-table.h:1169: warning: lowering
visibility of ‘void gt_pch_nx(hash_set<T, U>*, void (*)(void*, void*),
void*) [with T = T, U = U, Descriptor = pointer_hash<tree_node>,
Allocator = xcallocator]’ to match its type
../../gcc-svn/trunk/libcc1/../gcc/hash-table.h:1171: warning: lowering
visibility of ‘void gt_pch_nx(hash_table<T, xcallocator,
storage_tester<T,void>::value>*, void (*)(void*, void*), void*) [with
T = T, Descriptor = pointer_hash<tree_node>, Allocator = xcallocator]’
to match its type
gmake[4]: *** [plugin.lo] Error 1
gmake[4]: Leaving directory `/home/uros/gcc-build/libcc1'
gmake[3]: *** [all] Error 2
gmake[3]: Leaving directory `/home/uros/gcc-build/libcc1'
gmake[2]: *** [all-stage1-libcc1] Error 2
gmake[2]: Leaving directory `/home/uros/gcc-build'
gmake[1]: *** [stage1-bubble] Error 2
gmake[1]: Leaving directory `/home/uros/gcc-build'
gmake: *** [all] Error 2

I wonder if at this point just compiled gcc/xg++ and not system
compiler should be used?

Uros.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28  8:43 Uros Bizjak
  2014-10-28  8:55 ` Phil Muldoon
@ 2014-10-28  9:36 ` Jakub Jelinek
  2014-10-28  9:58   ` Uros Bizjak
  1 sibling, 1 reply; 101+ messages in thread
From: Jakub Jelinek @ 2014-10-28  9:36 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches, Tom Tromey, Jeff Law, pmuldoon

On Tue, Oct 28, 2014 at 09:36:45AM +0100, Uros Bizjak wrote:
> > This patch has now been committed.
> 
> Also breaks bootstap on x86_64-linux-gnu, CentOS 5.11:

For -Werror, I'd think that should fix that, WARN_FLAGS should
already contain -Werror during stage2/stage3 unless --disable-werror.
Untested though.

--- libcc1/Makefile.am	2014-10-28 09:07:57.443711725 +0100
+++ libcc1/Makefile.am	2014-10-28 10:32:09.712135034 +0100
@@ -22,8 +22,7 @@ AM_CPPFLAGS = -I $(srcdir)/../include -I
 	-I $(gcc_build_dir) -I$(srcdir)/../gcc \
 	-I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
 	-I $(srcdir)/../libcpp/include
-WERROR_FLAG = -Werror
-AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
+AM_CXXFLAGS = $(WARN_FLAGS) $(visibility)
 override CXXFLAGS := $(filter-out -fsanitize=address,$(CXXFLAGS))
 override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
 # Can be simplified when libiberty becomes a normal convenience library.
--- libcc1/Makefile.in	2014-10-28 09:08:01.689922599 +0100
+++ libcc1/Makefile.in	2014-10-28 10:32:21.376918921 +0100
@@ -249,8 +249,7 @@ AM_CPPFLAGS = -I $(srcdir)/../include -I
 	-I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
 	-I $(srcdir)/../libcpp/include
 
-WERROR_FLAG = -Werror
-AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
+AM_CXXFLAGS = $(WARN_FLAGS) $(visibility)
 # Can be simplified when libiberty becomes a normal convenience library.
 libiberty_normal = ../libiberty/libiberty.a
 libiberty_noasan = ../libiberty/noasan/libiberty.a


	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28  8:55 ` Phil Muldoon
@ 2014-10-28  9:21   ` Uros Bizjak
  0 siblings, 0 replies; 101+ messages in thread
From: Uros Bizjak @ 2014-10-28  9:21 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: gcc-patches, Tom Tromey, Jakub Jelinek, Jeff Law

On Tue, Oct 28, 2014 at 9:50 AM, Phil Muldoon <pmuldoon@redhat.com> wrote:
> On 28/10/14 08:36, Uros Bizjak wrote:
>>> This patch has now been committed.
>> Also breaks bootstap on x86_64-linux-gnu, CentOS 5.11:
>>
>> gmake[4]: Entering directory `/home/uros/gcc-build/libcc1'
>> /bin/sh ./libtool --tag=CXX   --mode=compile g++ -DHAVE_CONFIG_H -I.
>> -I../../gcc-svn/trunk/libcc1  -I ../../gcc-svn/trunk/libcc1/../include
>> -I ../../gcc-svn/trunk/libcc1/../libgcc -I .././gcc
>> -I../../gcc-svn/trunk/libcc1/../gcc -I
>
> Weird, I bootstrapped my build on x8664 Fedora 20 and saw no issues.  Can you please
> provide me your build/configure parameters?

This failure is in stage1 due to -Werror in combination with default
CentOS gcc-4.1.x compiler:

gcc version 4.1.2 20080704 (Red Hat 4.1.2-55)

Stage1 libraries should not be compiled with -Werror, since the
default system compiler can have issues with warnings.

Uros.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28  8:46   ` Phil Muldoon
  2014-10-28  8:50     ` Christophe Lyon
@ 2014-10-28  9:09     ` Jakub Jelinek
  1 sibling, 0 replies; 101+ messages in thread
From: Jakub Jelinek @ 2014-10-28  9:09 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Dominique Dhumieres, gcc-patches, tromey, law

On Tue, Oct 28, 2014 at 08:43:35AM +0000, Phil Muldoon wrote:
> On 28/10/14 08:13, Jakub Jelinek wrote:
> > On Tue, Oct 28, 2014 at 01:05:00AM +0100, Dominique Dhumieres wrote:
> >>> This patch has now been committed.
> >> It breaks bootstap on x86_64-apple-darwin14:
> >>
> >> ...
> >> make[3]: Entering directory `/opt/gcc/p_build/libcc1'
> >> make  all-am
> >> make[4]: Entering directory `/opt/gcc/p_build/libcc1'
> >> make[4]: *** No rule to make target `../libiberty/pic/libiberty.a', needed by `libcc1.la'.  Stop.
> >> make[4]: Leaving directory `/opt/gcc/p_build/libcc1'
> >> make[3]: *** [all] Error 2
> >> make[3]: Leaving directory `/opt/gcc/p_build/libcc1'
> >> make[2]: *** [all-stage1-libcc1] Error 2
> >> make[2]: Leaving directory `/opt/gcc/p_build'
> >> make[1]: *** [stage1-bubble] Error 2
> >> make[1]: Leaving directory `/opt/gcc/p_build'
> >> make: *** [all] Error 2
> > There are other issues related to --with-build-config=bootstrap-{a,ub}san
> > in there too, my current WIP patch is but didn't get to test it yet.
> 
> Apologies.  I am investigating the issue, though I am not entirely sure of why the issue with libiberty occurs.

I think I have the libiberty issues solved in my patch, just hit another
issue (visibility related) in my -fsanitize=vptr patch which I've been
bootstrapping it with, so had to fix that and am now trying again.

The thing with libiberty is that we have one to 3 versions of libiberty,
e.g. on targets where there is no pic support or where -fpic is on by
default libiberty doesn't build the pic/ version, and the noasan/ version
is built for --with-build-config=bootstrap-asan builds, so that one can
choose libiberty instrumented -fsanitize=address (the normal one or pic if
the latter exists) and pic non-instrumented one (for use in lto-plugin and
supposedly libcc1 too), anything that can be loaded into some other program
than gcc should not be asan instrumented, because it requires the executable
to be linked that way too (e.g. linker or gdb).

	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28  8:43 Uros Bizjak
@ 2014-10-28  8:55 ` Phil Muldoon
  2014-10-28  9:21   ` Uros Bizjak
  2014-10-28  9:36 ` Jakub Jelinek
  1 sibling, 1 reply; 101+ messages in thread
From: Phil Muldoon @ 2014-10-28  8:55 UTC (permalink / raw)
  To: Uros Bizjak, gcc-patches; +Cc: Tom Tromey, Jakub Jelinek, Jeff Law

On 28/10/14 08:36, Uros Bizjak wrote:
>> This patch has now been committed.
> Also breaks bootstap on x86_64-linux-gnu, CentOS 5.11:
>
> gmake[4]: Entering directory `/home/uros/gcc-build/libcc1'
> /bin/sh ./libtool --tag=CXX   --mode=compile g++ -DHAVE_CONFIG_H -I.
> -I../../gcc-svn/trunk/libcc1  -I ../../gcc-svn/trunk/libcc1/../include
> -I ../../gcc-svn/trunk/libcc1/../libgcc -I .././gcc
> -I../../gcc-svn/trunk/libcc1/../gcc -I

Weird, I bootstrapped my build on x8664 Fedora 20 and saw no issues.  Can you please
provide me your build/configure parameters?

Cheers

Phil

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28  8:46   ` Phil Muldoon
@ 2014-10-28  8:50     ` Christophe Lyon
  2014-10-28  9:09     ` Jakub Jelinek
  1 sibling, 0 replies; 101+ messages in thread
From: Christophe Lyon @ 2014-10-28  8:50 UTC (permalink / raw)
  To: Phil Muldoon
  Cc: Jakub Jelinek, Dominique Dhumieres, gcc-patches, tromey, Jeff Law

On 28 October 2014 09:43, Phil Muldoon <pmuldoon@redhat.com> wrote:
> On 28/10/14 08:13, Jakub Jelinek wrote:
>> On Tue, Oct 28, 2014 at 01:05:00AM +0100, Dominique Dhumieres wrote:
>>>> This patch has now been committed.
>>> It breaks bootstap on x86_64-apple-darwin14:
>>>
>>> ...
>>> make[3]: Entering directory `/opt/gcc/p_build/libcc1'
>>> make  all-am
>>> make[4]: Entering directory `/opt/gcc/p_build/libcc1'
>>> make[4]: *** No rule to make target `../libiberty/pic/libiberty.a', needed by `libcc1.la'.  Stop.
>>> make[4]: Leaving directory `/opt/gcc/p_build/libcc1'
>>> make[3]: *** [all] Error 2
>>> make[3]: Leaving directory `/opt/gcc/p_build/libcc1'
>>> make[2]: *** [all-stage1-libcc1] Error 2
>>> make[2]: Leaving directory `/opt/gcc/p_build'
>>> make[1]: *** [stage1-bubble] Error 2
>>> make[1]: Leaving directory `/opt/gcc/p_build'
>>> make: *** [all] Error 2
>> There are other issues related to --with-build-config=bootstrap-{a,ub}san
>> in there too, my current WIP patch is but didn't get to test it yet.
>
> Apologies.  I am investigating the issue, though I am not entirely sure of why the issue with libiberty occurs.
>

I also breaks the build of cross compilers for arm* and aarch64*
targets (host RHEL5/x86_64):
cc1plus: warnings being treated as errors
/tmp/76611_16.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libcc1/../gcc/hash-table.h:
In instantiation of ‘hash_table<pointer_hash<tree_node>, xcallocator,
true>’:
/tmp/76611_16.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libcc1/plugin.cc:171:
  instantiated from here
/tmp/76611_16.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libcc1/../gcc/hash-table.h:1161:
warning: lowering visibility of ‘void gt_ggc_mx(hash_table<T,
xcallocator, storage_test
er<T,void>::value>*) [with T = T, Descriptor =
pointer_hash<tree_node>, Allocator = xcallocator]’ to match its type
/tmp/76611_16.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libcc1/../gcc/hash-table.h:1162:
warning: lowering visibility of ‘void gt_pch_nx(hash_table<T,
xcallocator, storage_test
er<T,void>::value>*) [with T = T, Descriptor =
pointer_hash<tree_node>, Allocator = xcallocator]’ to match its type
/tmp/76611_16.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libcc1/../gcc/hash-table.h:1166:
warning: lowering visibility of ‘void gt_pch_nx(hash_map<T, U, V>*,
void (*)(void*, void*), void*) [with T = T, U = U, V = V, Descriptor =
pointer_hash<tree_node>, Allocator = xcallocator]’ to match its type
/tmp/76611_16.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libcc1/../gcc/hash-table.h:1169:
warning: lowering visibility of ‘void gt_pch_nx(hash_set<T, U>*, void
(*)(void*, void*), void*) [with T = T, U = U, Descriptor =
pointer_hash<tree_node>, Allocator = xcallocator]’ to match its type
/tmp/76611_16.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libcc1/../gcc/hash-table.h:1171:
warning: lowering visibility of ‘void gt_pch_nx(hash_table<T,
xcallocator, storage_tester<T,void>::value>*, void (*)(void*, void*),
void*) [with T = T, Descriptor = pointer_hash<tree_node>, Allocator =
xcallocator]’ to match its type
make[3]: *** [plugin.lo] Error 1

> Cheers
>
> Phil
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28  8:36 ` Jakub Jelinek
@ 2014-10-28  8:46   ` Phil Muldoon
  2014-10-28  8:50     ` Christophe Lyon
  2014-10-28  9:09     ` Jakub Jelinek
  0 siblings, 2 replies; 101+ messages in thread
From: Phil Muldoon @ 2014-10-28  8:46 UTC (permalink / raw)
  To: Jakub Jelinek, Dominique Dhumieres; +Cc: gcc-patches, tromey, law

On 28/10/14 08:13, Jakub Jelinek wrote:
> On Tue, Oct 28, 2014 at 01:05:00AM +0100, Dominique Dhumieres wrote:
>>> This patch has now been committed.
>> It breaks bootstap on x86_64-apple-darwin14:
>>
>> ...
>> make[3]: Entering directory `/opt/gcc/p_build/libcc1'
>> make  all-am
>> make[4]: Entering directory `/opt/gcc/p_build/libcc1'
>> make[4]: *** No rule to make target `../libiberty/pic/libiberty.a', needed by `libcc1.la'.  Stop.
>> make[4]: Leaving directory `/opt/gcc/p_build/libcc1'
>> make[3]: *** [all] Error 2
>> make[3]: Leaving directory `/opt/gcc/p_build/libcc1'
>> make[2]: *** [all-stage1-libcc1] Error 2
>> make[2]: Leaving directory `/opt/gcc/p_build'
>> make[1]: *** [stage1-bubble] Error 2
>> make[1]: Leaving directory `/opt/gcc/p_build'
>> make: *** [all] Error 2
> There are other issues related to --with-build-config=bootstrap-{a,ub}san
> in there too, my current WIP patch is but didn't get to test it yet.

Apologies.  I am investigating the issue, though I am not entirely sure of why the issue with libiberty occurs.

Cheers

Phil

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
@ 2014-10-28  8:43 Uros Bizjak
  2014-10-28  8:55 ` Phil Muldoon
  2014-10-28  9:36 ` Jakub Jelinek
  0 siblings, 2 replies; 101+ messages in thread
From: Uros Bizjak @ 2014-10-28  8:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: Tom Tromey, Jakub Jelinek, Jeff Law, pmuldoon

> This patch has now been committed.

Also breaks bootstap on x86_64-linux-gnu, CentOS 5.11:

gmake[4]: Entering directory `/home/uros/gcc-build/libcc1'
/bin/sh ./libtool --tag=CXX   --mode=compile g++ -DHAVE_CONFIG_H -I.
-I../../gcc-svn/trunk/libcc1  -I ../../gcc-svn/trunk/libcc1/../include
-I ../../gcc-svn/trunk/libcc1/../libgcc -I .././gcc
-I../../gcc-svn/trunk/libcc1/../gcc -I
../../gcc-svn/trunk/libcc1/../gcc/c -I
../../gcc-svn/trunk/libcc1/../gcc/c-family -I
../../gcc-svn/trunk/libcc1/../libcpp/include  -W -Wall -Werror -Werror
-fvisibility=hidden -g -MT plugin.lo -MD -MP -MF .deps/plugin.Tpo -c
-o plugin.lo ../../gcc-svn/trunk/libcc1/plugin.cc
libtool: compile:  g++ -DHAVE_CONFIG_H -I.
-I../../gcc-svn/trunk/libcc1 -I ../../gcc-svn/trunk/libcc1/../include
-I ../../gcc-svn/trunk/libcc1/../libgcc -I .././gcc
-I../../gcc-svn/trunk/libcc1/../gcc -I
../../gcc-svn/trunk/libcc1/../gcc/c -I
../../gcc-svn/trunk/libcc1/../gcc/c-family -I
../../gcc-svn/trunk/libcc1/../libcpp/include -W -Wall -Werror -Werror
-fvisibility=hidden -g -MT plugin.lo -MD -MP -MF .deps/plugin.Tpo -c
../../gcc-svn/trunk/libcc1/plugin.cc  -fPIC -DPIC -o .libs/plugin.o
cc1plus: warnings being treated as errors
../../gcc-svn/trunk/libcc1/../gcc/hash-table.h: In instantiation of
‘hash_table<pointer_hash<tree_node>, xcallocator, true>’:
../../gcc-svn/trunk/libcc1/plugin.cc:171:   instantiated from here
../../gcc-svn/trunk/libcc1/../gcc/hash-table.h:1161: warning: lowering
visibility of ‘void gt_ggc_mx(hash_table<T, xcallocator,
storage_tester<T,void>::value>*) [with T = T, Descriptor =
pointer_hash<tree_node>, Allocator = xcallocator]’ to match its type
../../gcc-svn/trunk/libcc1/../gcc/hash-table.h:1162: warning: lowering
visibility of ‘void gt_pch_nx(hash_table<T, xcallocator,
storage_tester<T,void>::value>*) [with T = T, Descriptor =
pointer_hash<tree_node>, Allocator = xcallocator]’ to match its type
../../gcc-svn/trunk/libcc1/../gcc/hash-table.h:1166: warning: lowering
visibility of ‘void gt_pch_nx(hash_map<T, U, V>*, void (*)(void*,
void*), void*) [with T = T, U = U, V = V, Descriptor =
pointer_hash<tree_node>, Allocator = xcallocator]’ to match its type
../../gcc-svn/trunk/libcc1/../gcc/hash-table.h:1169: warning: lowering
visibility of ‘void gt_pch_nx(hash_set<T, U>*, void (*)(void*, void*),
void*) [with T = T, U = U, Descriptor = pointer_hash<tree_node>,
Allocator = xcallocator]’ to match its type
../../gcc-svn/trunk/libcc1/../gcc/hash-table.h:1171: warning: lowering
visibility of ‘void gt_pch_nx(hash_table<T, xcallocator,
storage_tester<T,void>::value>*, void (*)(void*, void*), void*) [with
T = T, Descriptor = pointer_hash<tree_node>, Allocator = xcallocator]’
to match its type
gmake[4]: *** [plugin.lo] Error 1
gmake[4]: Leaving directory `/home/uros/gcc-build/libcc1'
gmake[3]: *** [all] Error 2
gmake[3]: Leaving directory `/home/uros/gcc-build/libcc1'
gmake[2]: *** [all-stage1-libcc1] Error 2
gmake[2]: Leaving directory `/home/uros/gcc-build'
gmake[1]: *** [stage1-bubble] Error 2
gmake[1]: Leaving directory `/home/uros/gcc-build'
gmake: *** [all] Error 2

Uros.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
  2014-10-28  3:19 [PATCH 5/5] add libcc1 Dominique Dhumieres
@ 2014-10-28  8:36 ` Jakub Jelinek
  2014-10-28  8:46   ` Phil Muldoon
  0 siblings, 1 reply; 101+ messages in thread
From: Jakub Jelinek @ 2014-10-28  8:36 UTC (permalink / raw)
  To: Dominique Dhumieres; +Cc: gcc-patches, tromey, law, pmuldoon

On Tue, Oct 28, 2014 at 01:05:00AM +0100, Dominique Dhumieres wrote:
> > This patch has now been committed.
> 
> It breaks bootstap on x86_64-apple-darwin14:
> 
> ...
> make[3]: Entering directory `/opt/gcc/p_build/libcc1'
> make  all-am
> make[4]: Entering directory `/opt/gcc/p_build/libcc1'
> make[4]: *** No rule to make target `../libiberty/pic/libiberty.a', needed by `libcc1.la'.  Stop.
> make[4]: Leaving directory `/opt/gcc/p_build/libcc1'
> make[3]: *** [all] Error 2
> make[3]: Leaving directory `/opt/gcc/p_build/libcc1'
> make[2]: *** [all-stage1-libcc1] Error 2
> make[2]: Leaving directory `/opt/gcc/p_build'
> make[1]: *** [stage1-bubble] Error 2
> make[1]: Leaving directory `/opt/gcc/p_build'
> make: *** [all] Error 2

There are other issues related to --with-build-config=bootstrap-{a,ub}san
in there too, my current WIP patch is but didn't get to test it yet.

--- libcc1/Makefile.am.jj	2014-10-27 19:41:13.000000000 +0100
+++ libcc1/Makefile.am	2014-10-28 09:07:57.443711725 +0100
@@ -24,8 +24,17 @@ AM_CPPFLAGS = -I $(srcdir)/../include -I
 	-I $(srcdir)/../libcpp/include
 WERROR_FLAG = -Werror
 AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
-libiberty = ../libiberty/pic/libiberty.a
-
+override CXXFLAGS := $(filter-out -fsanitize=address,$(CXXFLAGS))
+override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
+# Can be simplified when libiberty becomes a normal convenience library.
+libiberty_normal = ../libiberty/libiberty.a
+libiberty_noasan = ../libiberty/noasan/libiberty.a
+libiberty_pic = ../libiberty/pic/libiberty.a
+Wc=-Wc,
+libiberty = $(if $(wildcard $(libiberty_noasan)),$(Wc)$(libiberty_noasan), \
+	    $(if $(wildcard $(libiberty_pic)),$(Wc)$(libiberty_pic), \
+	    $(Wc)$(libiberty_normal)))
+libiberty_dep = $(patsubst $(Wc)%,%,$(libiberty))
 
 plugindir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/plugin
 cc1libdir = $(libdir)/$(libsuffix)
@@ -49,7 +58,16 @@ shared_source = callbacks.cc callbacks.h
 libcc1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1plugin.sym
 libcc1plugin_la_SOURCES = plugin.cc $(shared_source)
 libcc1plugin_la_LIBADD = $(libiberty)
+libcc1plugin_la_DEPENDENCIES = $(libiberty_dep)
+libcc1plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(libcc1plugin_la_LDFLAGS) $(LTLDFLAGS) -o $@
 
+LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
 libcc1_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1.sym
 libcc1_la_SOURCES = findcomp.cc libcc1.cc names.cc names.hh $(shared_source)
 libcc1_la_LIBADD = $(libiberty)
+libcc1_la_DEPENDENCIES = $(libiberty_dep)
+libcc1_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(libcc1_la_LDFLAGS) $(LTLDFLAGS) -o $@
--- libcc1/Makefile.in.jj	2014-10-27 19:41:13.000000000 +0100
+++ libcc1/Makefile.in	2014-10-28 09:08:01.689922599 +0100
@@ -81,20 +81,12 @@ am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
 am__installdirs = "$(DESTDIR)$(cc1libdir)" "$(DESTDIR)$(plugindir)"
 LTLIBRARIES = $(cc1lib_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libcc1_la_DEPENDENCIES = $(libiberty)
 am__objects_1 = callbacks.lo connection.lo marshall.lo
 am_libcc1_la_OBJECTS = findcomp.lo libcc1.lo names.lo $(am__objects_1)
 libcc1_la_OBJECTS = $(am_libcc1_la_OBJECTS)
-libcc1_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
-	$(CXXFLAGS) $(libcc1_la_LDFLAGS) $(LDFLAGS) -o $@
 @ENABLE_PLUGIN_TRUE@am_libcc1_la_rpath = -rpath $(cc1libdir)
-libcc1plugin_la_DEPENDENCIES = $(libiberty)
 am_libcc1plugin_la_OBJECTS = plugin.lo $(am__objects_1)
 libcc1plugin_la_OBJECTS = $(am_libcc1plugin_la_OBJECTS)
-libcc1plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
-	$(CXXFLAGS) $(libcc1plugin_la_LDFLAGS) $(LDFLAGS) -o $@
 @ENABLE_PLUGIN_TRUE@am_libcc1plugin_la_rpath = -rpath $(plugindir)
 DEFAULT_INCLUDES = -I.@am__isrc@
 depcomp = $(SHELL) $(top_srcdir)/../depcomp
@@ -259,7 +251,16 @@ AM_CPPFLAGS = -I $(srcdir)/../include -I
 
 WERROR_FLAG = -Werror
 AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR_FLAG) $(visibility)
-libiberty = ../libiberty/pic/libiberty.a
+# Can be simplified when libiberty becomes a normal convenience library.
+libiberty_normal = ../libiberty/libiberty.a
+libiberty_noasan = ../libiberty/noasan/libiberty.a
+libiberty_pic = ../libiberty/pic/libiberty.a
+Wc = -Wc,
+libiberty = $(if $(wildcard $(libiberty_noasan)),$(Wc)$(libiberty_noasan), \
+	    $(if $(wildcard $(libiberty_pic)),$(Wc)$(libiberty_pic), \
+	    $(Wc)$(libiberty_normal)))
+
+libiberty_dep = $(patsubst $(Wc)%,%,$(libiberty))
 plugindir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/plugin
 cc1libdir = $(libdir)/$(libsuffix)
 @ENABLE_PLUGIN_TRUE@plugin_LTLIBRARIES = libcc1plugin.la
@@ -271,9 +272,20 @@ shared_source = callbacks.cc callbacks.h
 libcc1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1plugin.sym
 libcc1plugin_la_SOURCES = plugin.cc $(shared_source)
 libcc1plugin_la_LIBADD = $(libiberty)
+libcc1plugin_la_DEPENDENCIES = $(libiberty_dep)
+libcc1plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(libcc1plugin_la_LDFLAGS) $(LTLDFLAGS) -o $@
+
+LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
 libcc1_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1.sym
 libcc1_la_SOURCES = findcomp.cc libcc1.cc names.cc names.hh $(shared_source)
 libcc1_la_LIBADD = $(libiberty)
+libcc1_la_DEPENDENCIES = $(libiberty_dep)
+libcc1_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(libcc1_la_LDFLAGS) $(LTLDFLAGS) -o $@
+
 all: $(BUILT_SOURCES) cc1plugin-config.h
 	$(MAKE) $(AM_MAKEFLAGS) all-am
 
@@ -619,6 +631,8 @@ uninstall-am: uninstall-cc1libLTLIBRARIE
 	pdf pdf-am ps ps-am tags uninstall uninstall-am \
 	uninstall-cc1libLTLIBRARIES uninstall-pluginLTLIBRARIES
 
+override CXXFLAGS := $(filter-out -fsanitize=address,$(CXXFLAGS))
+override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
 
 # Put this in a header so we don't run sed for each compilation.  This
 # is also simpler to debug as one can easily see the constant.


	Jakub

^ permalink raw reply	[flat|nested] 101+ messages in thread

* Re: [PATCH 5/5] add libcc1
@ 2014-10-28  3:19 Dominique Dhumieres
  2014-10-28  8:36 ` Jakub Jelinek
  0 siblings, 1 reply; 101+ messages in thread
From: Dominique Dhumieres @ 2014-10-28  3:19 UTC (permalink / raw)
  To: gcc-patches; +Cc: tromey, jakub, law, pmuldoon

> This patch has now been committed.

It breaks bootstap on x86_64-apple-darwin14:

...
make[3]: Entering directory `/opt/gcc/p_build/libcc1'
make  all-am
make[4]: Entering directory `/opt/gcc/p_build/libcc1'
make[4]: *** No rule to make target `../libiberty/pic/libiberty.a', needed by `libcc1.la'.  Stop.
make[4]: Leaving directory `/opt/gcc/p_build/libcc1'
make[3]: *** [all] Error 2
make[3]: Leaving directory `/opt/gcc/p_build/libcc1'
make[2]: *** [all-stage1-libcc1] Error 2
make[2]: Leaving directory `/opt/gcc/p_build'
make[1]: *** [stage1-bubble] Error 2
make[1]: Leaving directory `/opt/gcc/p_build'
make: *** [all] Error 2

TIA

Dominique

^ permalink raw reply	[flat|nested] 101+ messages in thread

end of thread, other threads:[~2014-10-30 10:11 UTC | newest]

Thread overview: 101+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-16 15:26 [PATCH 0/5] let gdb reuse gcc'c C compiler Tom Tromey
2014-05-16 15:26 ` [PATCH 1/5] export finish_bitfield_layout from stor-layout Tom Tromey
2014-05-16 18:27   ` Jeff Law
2014-05-16 15:27 ` [PATCH 2/5] c_diagnostic_ignored_function hack Tom Tromey
2014-05-16 16:05   ` Joseph S. Myers
2014-06-19 20:46     ` Tom Tromey
2014-05-16 18:33   ` Jeff Law
2014-05-16 18:42     ` Tom Tromey
2014-05-16 15:27 ` [PATCH 3/5] introduce the binding oracle Tom Tromey
2014-05-16 19:12   ` Jeff Law
2014-06-05 15:31     ` Tom Tromey
2014-06-19 20:43     ` Tom Tromey
2014-05-16 15:27 ` [PATCH 4/5] add gcc/gdb interface files Tom Tromey
2014-05-22 12:52   ` Jeff Law
2014-05-22 13:16     ` Jakub Jelinek
2014-05-22 15:13       ` Jeff Law
2014-06-04 20:39       ` Tom Tromey
2014-06-05 19:23         ` Jeff Law
2014-06-05 19:30           ` Jakub Jelinek
2014-06-06  1:54             ` Tom Tromey
2014-06-06  5:35               ` Jakub Jelinek
2014-06-09 17:09               ` Jeff Law
2014-06-19 20:45                 ` Tom Tromey
2014-05-16 16:29 ` [PATCH 0/5] let gdb reuse gcc'c C compiler Mike Stump
2014-05-16 18:48 ` [PATCH 5/5] add libcc1 Tom Tromey
2014-05-16 20:29   ` Joseph S. Myers
2014-05-16 21:03     ` Tom Tromey
2014-06-18 21:07     ` Tom Tromey
2014-06-19 20:47     ` Tom Tromey
2014-05-16 21:36   ` Mike Stump
2014-05-16 22:17   ` Mike Stump
2014-06-05 19:34     ` Tom Tromey
2014-06-05 21:35       ` Mike Stump
2014-06-19 20:52   ` Tom Tromey
2014-06-19 21:45     ` Jakub Jelinek
2014-06-19 22:22       ` Tom Tromey
2014-06-20  3:11     ` Trevor Saunders
2014-06-20 15:34       ` Tom Tromey
2014-06-23 19:09         ` Jeff Law
2014-06-24  3:13           ` Trevor Saunders
2014-06-24 17:12             ` Tom Tromey
2014-06-24 18:10               ` Trevor Saunders
2014-07-18 19:00     ` Tom Tromey
2014-07-31  4:49     ` Jeff Law
2014-07-31  8:15       ` Richard Biener
2014-07-31 10:53         ` Trevor Saunders
2014-07-31 11:28           ` Richard Biener
2014-07-31 15:08             ` Joseph S. Myers
2014-07-31 19:20         ` Tom Tromey
2014-07-31 19:21           ` Jakub Jelinek
2014-07-31 19:51           ` Trevor Saunders
2014-07-31 20:07             ` Tom Tromey
2014-08-01  2:18               ` Trevor Saunders
2014-07-31 21:14       ` Mike Stump
2014-08-04 14:23         ` Tom Tromey
2014-08-05 19:34       ` Tom Tromey
2014-08-08 12:15         ` [PATCH 5/5] add libcc1 [gcc-5/changes.html] Jan Kratochvil
2014-08-31 15:12           ` Gerald Pfeifer
2014-09-14 15:07             ` Manuel López-Ibáñez
2014-09-17 14:14               ` Jan Kratochvil
2014-10-09  9:07       ` [PATCH 5/5] add libcc1 Phil Muldoon
2014-10-09  9:12         ` Jakub Jelinek
2014-10-09  9:18         ` Phil Muldoon
2014-10-10 22:31         ` Jeff Law
2014-10-24  7:43           ` Phil Muldoon
2014-10-24  7:53             ` Jakub Jelinek
2014-10-24 16:47             ` Jeff Law
2014-10-27 20:03               ` Phil Muldoon
2014-10-28 13:29                 ` Joseph S. Myers
2014-10-28 18:00                   ` Phil Muldoon
2014-10-29  3:32                     ` Joseph S. Myers
2014-10-29 10:29                     ` Jakub Jelinek
2014-10-29 10:45                       ` Paolo Bonzini
2014-10-29 10:58                         ` Jakub Jelinek
2014-10-29 10:59                           ` Paolo Bonzini
2014-10-29 11:03                             ` Jakub Jelinek
2014-10-29 15:00                               ` Paolo Bonzini
2014-10-29 11:10                             ` Phil Muldoon
2014-10-29 11:42                             ` Phil Muldoon
2014-10-30  5:37                       ` Jeff Law
2014-06-19 20:42 ` [PATCH 0/5] let gdb reuse gcc'c C compiler Tom Tromey
2014-07-30 16:28   ` Tom Tromey
2014-10-28  3:19 [PATCH 5/5] add libcc1 Dominique Dhumieres
2014-10-28  8:36 ` Jakub Jelinek
2014-10-28  8:46   ` Phil Muldoon
2014-10-28  8:50     ` Christophe Lyon
2014-10-28  9:09     ` Jakub Jelinek
2014-10-28  8:43 Uros Bizjak
2014-10-28  8:55 ` Phil Muldoon
2014-10-28  9:21   ` Uros Bizjak
2014-10-28  9:36 ` Jakub Jelinek
2014-10-28  9:58   ` Uros Bizjak
2014-10-28 10:51     ` Phil Muldoon
2014-10-28 10:56       ` Uros Bizjak
2014-10-28 11:16         ` Phil Muldoon
2014-10-28 11:53         ` Phil Muldoon
2014-10-28 12:24           ` Jakub Jelinek
2014-10-30  5:16             ` Jeff Law
2014-10-30  8:50             ` Thomas Schwinge
2014-10-30  8:56               ` Jakub Jelinek
2014-10-30 10:43                 ` Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).