]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
C++-ify compile/.
authorKeith Seitz <keiths@redhat.com>
Tue, 21 Feb 2017 21:32:58 +0000 (13:32 -0800)
committerKeith Seitz <keiths@redhat.com>
Tue, 21 Feb 2017 21:32:58 +0000 (13:32 -0800)
gdb/c-lang.h
gdb/compile/compile-c-support.c
gdb/compile/compile-c-symbols.c
gdb/compile/compile-c-types.c
gdb/compile/compile-c.h [new file with mode: 0644]
gdb/compile/compile-internal.h
gdb/compile/compile-loc2c.c
gdb/compile/compile.c
gdb/language.h

index c4b19ecfef610584a1c716fff0d802495c379be0..58a81b01fce8acf294dd44f3393b940375ea583a 100644 (file)
@@ -150,7 +150,7 @@ extern int c_textual_element_type (struct type *, char);
    exception on failure.  This is suitable for use as the
    la_get_compile_instance language method.  */
 
-extern struct compile_instance *c_get_compile_context (void);
+extern compile::compile_instance *c_get_compile_context (void);
 
 /* This takes the user-supplied text and returns a new bit of code to
    compile.
@@ -158,7 +158,7 @@ extern struct compile_instance *c_get_compile_context (void);
    This is used as the la_compute_program language method; see that
    for a description of the arguments.  */
 
-extern std::string c_compute_program (struct compile_instance *inst,
+extern std::string c_compute_program (compile::compile_instance *inst,
                                      const char *input,
                                      struct gdbarch *gdbarch,
                                      const struct block *expr_block,
index 7ad0a872f23162430a6f26daa2a037a7b4e266cb..ead2bddf210616111784b38c83a7d896ce4ece9f 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "defs.h"
 #include "compile-internal.h"
+#include "compile-c.h"
 #include "compile.h"
 #include "gdb-dlfcn.h"
 #include "c-lang.h"
@@ -62,57 +63,71 @@ c_get_range_decl_name (const struct dynamic_prop *prop)
   return xstrprintf ("__gdb_prop_%s", host_address_to_string (prop));
 }
 
-\f
-
 #define STR(x) #x
 #define STRINGIFY(x) STR(x)
 
-/* Helper function for c_get_compile_context.  Open the GCC front-end
-   shared library and return the symbol specified by the current
-   GCC_C_FE_CONTEXT.  */
+/* Load the plug-in library FE_LIBCC and return the initialization function
+   FE_CONTEXT.  */
 
-static gcc_c_fe_context_function *
-load_libcc (void)
+template <typename FUNCTYPE>
+FUNCTYPE *
+load_libcompile (const char *fe_libcc, const char *fe_context)
 {
   void *handle;
-  gcc_c_fe_context_function *func;
+  FUNCTYPE *func;
 
-   /* gdb_dlopen will call error () on an error, so no need to check
-      value.  */
-  handle = gdb_dlopen (STRINGIFY (GCC_C_FE_LIBCC));
-  func = (gcc_c_fe_context_function *) gdb_dlsym (handle,
-                                                 STRINGIFY (GCC_C_FE_CONTEXT));
+  /* gdb_dlopen will call error () on an error, so no need to check
+     value.  */
+  handle = gdb_dlopen (fe_libcc);
+  func = (FUNCTYPE *) (gdb_dlsym (handle, fe_context));
 
   if (func == NULL)
-    error (_("could not find symbol %s in library %s"),
-          STRINGIFY (GCC_C_FE_CONTEXT),
-          STRINGIFY (GCC_C_FE_LIBCC));
+    error (_("could not find symbol %s in library %s"), fe_context, fe_libcc);
   return func;
 }
 
 /* Return the compile instance associated with the current context.
-   This function calls the symbol returned from the load_libcc
-   function.  This will provide the gcc_c_context.  */
-
-struct compile_instance *
-c_get_compile_context (void)
+   This function calls the symbol returned from the load_libcompile
+   function.  FE_LIBCC is the library to load.  BASE_VERSION is the
+   base compile plug-in version we support.  API_VERSION is the
+   API version supported.  */
+
+template <typename INSTTYPE, typename FUNCTYPE, typename CTXTYPE,
+         typename BASE_VERSION_TYPE, typename API_VERSION_TYPE>
+compile::compile_instance *
+get_compile_context (const char *fe_libcc, const char *fe_context,
+                    BASE_VERSION_TYPE base_version,
+                    API_VERSION_TYPE api_version)
 {
-  static gcc_c_fe_context_function *func;
-
-  struct gcc_c_context *context;
+  static FUNCTYPE *func;
+  static CTXTYPE *context;
 
   if (func == NULL)
     {
-      func = load_libcc ();
+      func = load_libcompile<FUNCTYPE> (fe_libcc, fe_context);
       gdb_assert (func != NULL);
     }
 
-  context = (*func) (GCC_FE_VERSION_0, GCC_C_FE_VERSION_0);
+  context = (*func) (base_version, api_version);
   if (context == NULL)
     error (_("The loaded version of GCC does not support the required version "
             "of the API."));
 
-  return new_compile_instance (context);
+  return new INSTTYPE (context);
+}
+
+/* A C-language implementation of get_compile_context.  */
+
+compile::compile_instance *
+c_get_compile_context (void)
+{
+  using namespace compile;
+
+  return get_compile_context
+    <compile_c_instance, gcc_c_fe_context_function, gcc_c_context,
+    gcc_base_api_version, gcc_c_api_version>
+    (STRINGIFY (GCC_C_FE_LIBCC), STRINGIFY (GCC_C_FE_CONTEXT),
+     GCC_FE_VERSION_0, GCC_C_FE_VERSION_0);
 }
 
 \f
@@ -171,71 +186,6 @@ write_macro_definitions (const struct block *block, CORE_ADDR pc,
     macro_for_each_in_scope (scope->file, scope->line, print_one_macro, file);
 }
 
-/* Helper function to construct a header scope for a block of code.
-   Takes a scope argument which selects the correct header to
-   insert into BUF.  */
-
-static void
-add_code_header (enum compile_i_scope_types type, struct ui_file *buf)
-{
-  switch (type)
-    {
-    case COMPILE_I_SIMPLE_SCOPE:
-      fputs_unfiltered ("void "
-                       GCC_FE_WRAPPER_FUNCTION
-                       " (struct "
-                       COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
-                       " *"
-                       COMPILE_I_SIMPLE_REGISTER_ARG_NAME
-                       ") {\n",
-                       buf);
-      break;
-    case COMPILE_I_PRINT_ADDRESS_SCOPE:
-    case COMPILE_I_PRINT_VALUE_SCOPE:
-      /* <string.h> is needed for a memcpy call below.  */
-      fputs_unfiltered ("#include <string.h>\n"
-                       "void "
-                       GCC_FE_WRAPPER_FUNCTION
-                       " (struct "
-                       COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
-                       " *"
-                       COMPILE_I_SIMPLE_REGISTER_ARG_NAME
-                       ", "
-                       COMPILE_I_PRINT_OUT_ARG_TYPE
-                       " "
-                       COMPILE_I_PRINT_OUT_ARG
-                       ") {\n",
-                       buf);
-      break;
-
-    case COMPILE_I_RAW_SCOPE:
-      break;
-    default:
-      gdb_assert_not_reached (_("Unknown compiler scope reached."));
-    }
-}
-
-/* Helper function to construct a footer scope for a block of code.
-   Takes a scope argument which selects the correct footer to
-   insert into BUF.  */
-
-static void
-add_code_footer (enum compile_i_scope_types type, struct ui_file *buf)
-{
-  switch (type)
-    {
-    case COMPILE_I_SIMPLE_SCOPE:
-    case COMPILE_I_PRINT_ADDRESS_SCOPE:
-    case COMPILE_I_PRINT_VALUE_SCOPE:
-      fputs_unfiltered ("}\n", buf);
-      break;
-    case COMPILE_I_RAW_SCOPE:
-      break;
-    default:
-      gdb_assert_not_reached (_("Unknown compiler scope reached."));
-    }
-}
-
 /* Generate a structure holding all the registers used by the function
    we're generating.  */
 
@@ -318,114 +268,289 @@ generate_register_struct (struct ui_file *stream, struct gdbarch *gdbarch,
   fputs_unfiltered ("};\n\n", stream);
 }
 
-/* Take the source code provided by the user with the 'compile'
-   command, and compute the additional wrapping, macro, variable and
-   register operations needed.  INPUT is the source code derived from
-   the 'compile' command, GDBARCH is the architecture to use when
-   computing above, EXPR_BLOCK denotes the block relevant contextually
-   to the inferior when the expression was created, and EXPR_PC
-   indicates the value of $PC.  */
+/* C-language policy to emit a push user expression pragma into BUF.  */
 
-std::string
-c_compute_program (struct compile_instance *inst,
-                  const char *input,
-                  struct gdbarch *gdbarch,
-                  const struct block *expr_block,
-                  CORE_ADDR expr_pc)
+struct c_push_user_expression
 {
-  struct compile_c_instance *context = (struct compile_c_instance *) inst;
+  void push_user_expression (struct ui_file *buf)
+  {
+    fputs_unfiltered ("#pragma GCC user_expression\n", buf);
+  }
+};
 
-  string_file buf;
-  string_file var_stream;
+/* C-language policy to emit a pop user expression pragma into BUF.
+   For C, this is a nop.  */
 
-  write_macro_definitions (expr_block, expr_pc, &buf);
+struct pop_user_expression_nop
+{
+  void pop_user_expression (struct ui_file *buf)
+  {
+    /* Nothing to do.  */
+  }
+};
+
+/* C-language policy to construct a code header for a block of code.
+   Takes a scope TYPE argument which selects the correct header to
+   insert into BUF.  */
 
-  /* Do not generate local variable information for "raw"
-     compilations.  In this case we aren't emitting our own function
-     and the user's code may only refer to globals.  */
-  if (inst->scope != COMPILE_I_RAW_SCOPE)
-    {
-      unsigned char *registers_used;
-      int i;
+struct c_add_code_header
+{
+  void add_code_header (enum compile_i_scope_types type, struct ui_file *buf)
+  {
+    switch (type)
+      {
+      case COMPILE_I_SIMPLE_SCOPE:
+       fputs_unfiltered ("void "
+                         GCC_FE_WRAPPER_FUNCTION
+                         " (struct "
+                         COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
+                         " *"
+                         COMPILE_I_SIMPLE_REGISTER_ARG_NAME
+                         ") {\n",
+                         buf);
+       break;
+
+      case COMPILE_I_PRINT_ADDRESS_SCOPE:
+      case COMPILE_I_PRINT_VALUE_SCOPE:
+       /* <string.h> is needed for a memcpy call below.  */
+       fputs_unfiltered ("#include <string.h>\n"
+                         "void "
+                         GCC_FE_WRAPPER_FUNCTION
+                         " (struct "
+                         COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
+                         " *"
+                         COMPILE_I_SIMPLE_REGISTER_ARG_NAME
+                         ", "
+                         COMPILE_I_PRINT_OUT_ARG_TYPE
+                         " "
+                         COMPILE_I_PRINT_OUT_ARG
+                         ") {\n",
+                         buf);
+       break;
+
+      case COMPILE_I_RAW_SCOPE:
+       break;
+
+      default:
+       gdb_assert_not_reached (_("Unknown compiler scope reached."));
+      }
+  }
+};
 
-      /* Generate the code to compute variable locations, but do it
-        before generating the function header, so we can define the
-        register struct before the function body.  This requires a
-        temporary stream.  */
-      registers_used = generate_c_for_variable_locations (context,
-                                                         var_stream, gdbarch,
-                                                         expr_block, expr_pc);
-      make_cleanup (xfree, registers_used);
-
-      buf.puts ("typedef unsigned int"
-               " __attribute__ ((__mode__(__pointer__)))"
-               " __gdb_uintptr;\n");
-      buf.puts ("typedef int"
-               " __attribute__ ((__mode__(__pointer__)))"
-               " __gdb_intptr;\n");
-
-      /* Iterate all log2 sizes in bytes supported by c_get_mode_for_size.  */
-      for (i = 0; i < 4; ++i)
-       {
-         const char *mode = c_get_mode_for_size (1 << i);
+/* C-language policy to construct a code footer for a block of code.
+   Takes a scope TYPE which selects the correct footer to insert into BUF.  */
 
-         gdb_assert (mode != NULL);
-         buf.printf ("typedef int"
-                     " __attribute__ ((__mode__(__%s__)))"
-                     " __gdb_int_%s;\n",
-                     mode, mode);
-       }
+struct c_add_code_footer
+{
+  void add_code_footer (enum compile_i_scope_types type, struct ui_file *buf)
+  {
+    switch (type)
+      {
+      case COMPILE_I_SIMPLE_SCOPE:
+      case COMPILE_I_PRINT_ADDRESS_SCOPE:
+      case COMPILE_I_PRINT_VALUE_SCOPE:
+       fputs_unfiltered ("}\n", buf);
+       break;
 
-      generate_register_struct (&buf, gdbarch, registers_used);
-    }
+      case COMPILE_I_RAW_SCOPE:
+       break;
 
-  add_code_header (inst->scope, &buf);
+      default:
+       gdb_assert_not_reached (_("Unknown compiler scope reached."));
+      }
+  }
+};
 
-  if (inst->scope == COMPILE_I_SIMPLE_SCOPE
-      || inst->scope == COMPILE_I_PRINT_ADDRESS_SCOPE
-      || inst->scope == COMPILE_I_PRINT_VALUE_SCOPE)
-    {
-      buf.write (var_stream.c_str (), var_stream.size ());
-      buf.puts ("#pragma GCC user_expression\n");
-    }
+/* C-language policy to emit the user code snippet INPUT into BUF based on the
+   scope TYPE.  */
 
-  /* The user expression has to be in its own scope, so that "extern"
-     works properly.  Otherwise gcc thinks that the "extern"
-     declaration is in the same scope as the declaration provided by
-     gdb.  */
-  if (inst->scope != COMPILE_I_RAW_SCOPE)
-    buf.puts ("{\n");
+struct c_add_input
+{
+  void add_input (enum compile_i_scope_types type, const char *input,
+                 struct ui_file *buf)
+  {
+    switch (type)
+      {
+      case COMPILE_I_PRINT_ADDRESS_SCOPE:
+      case COMPILE_I_PRINT_VALUE_SCOPE:
+       fprintf_unfiltered (buf,
+                           "__auto_type " COMPILE_I_EXPR_VAL " = %s;\n"
+                           "typeof (%s) *" COMPILE_I_EXPR_PTR_TYPE ";\n"
+                           "memcpy (" COMPILE_I_PRINT_OUT_ARG ", %s"
+                           COMPILE_I_EXPR_VAL ",\n"
+                           "sizeof (*" COMPILE_I_EXPR_PTR_TYPE "));\n"
+                           , input, input,
+                           (type == COMPILE_I_PRINT_ADDRESS_SCOPE
+                            ? "&" : ""));
+       break;
+
+      default:
+       fputs_unfiltered (input, buf);
+       break;
+      }
+    fputs_unfiltered ("\n", buf);
+  }
+};
 
-  buf.puts ("#line 1 \"gdb command line\"\n");
+/* A host class representing a compile program.
 
-  switch (inst->scope)
-    {
-    case COMPILE_I_PRINT_ADDRESS_SCOPE:
-    case COMPILE_I_PRINT_VALUE_SCOPE:
-      buf.printf (
-"__auto_type " COMPILE_I_EXPR_VAL " = %s;\n"
-"typeof (%s) *" COMPILE_I_EXPR_PTR_TYPE ";\n"
-"memcpy (" COMPILE_I_PRINT_OUT_ARG ", %s" COMPILE_I_EXPR_VAL ",\n"
-        "sizeof (*" COMPILE_I_EXPR_PTR_TYPE "));\n"
-                         , input, input,
-                         (inst->scope == COMPILE_I_PRINT_ADDRESS_SCOPE
-                          ? "&" : ""));
-      break;
-    default:
-      buf.puts (input);
-      break;
-    }
+   CompileInstanceType is the type of the compile_instance for the
+   langauge.
+
+   PushUserExpressionPolicy and PopUserExpressionPolicy are used to
+   push and pop user expression pragmas to the compile plug-in.
+
+   AddCodeHeaderPolicy and AddCodeFooterPolicy are used to add the appropriate
+   code header and footer, respectively.
+
+   AddInputPolicy adds the actual user code.  */
+
+template <class CompileInstanceType, class PushUserExpressionPolicy,
+         class PopUserExpressionPolicy, class AddCodeHeaderPolicy,
+         class AddCodeFooterPolicy, class AddInputPolicy>
+class compile_program
+  : private PushUserExpressionPolicy, private PopUserExpressionPolicy,
+    private AddCodeHeaderPolicy, private AddCodeFooterPolicy,
+    private AddInputPolicy
+{
+  using PushUserExpressionPolicy::push_user_expression;
+  using PopUserExpressionPolicy::pop_user_expression;
+  using AddCodeHeaderPolicy::add_code_header;
+  using AddCodeFooterPolicy::add_code_footer;
+  using AddInputPolicy::add_input;
+
+public:
+
+  /* Construct a compile_program using the compiler instance INST
+     using the architecture given by GDBARCH.  */
+
+  compile_program (CompileInstanceType *inst, struct gdbarch *gdbarch)
+    : m_instance (inst), m_arch (gdbarch)
+  {
+  }
+
+  /* Take the source code provided by the user with the 'compile'
+     command and compute the additional wrapping, macro, variable and
+     register operations needed.  INPUT is the source code derived from
+     the 'compile' command, EXPR_BLOCK denotes the block relevant contextually
+     to the inferior when the expression was created, and EXPR_PC
+     indicates the value of $PC.
+
+     Returns the text of the program to compile.  This must be free'd by
+     the caller.  */
+
+  std::string compute (const char *input, const struct block *expr_block,
+                      CORE_ADDR expr_pc)
+  {
+    string_file var_stream;
+    string_file buf;
+
+    /* Do not generate local variable information for "raw"
+       compilations.  In this case we aren't emitting our own function
+       and the user's code may only refer to globals.  */
+    if (m_instance->scope () != COMPILE_I_RAW_SCOPE)
+      {
+       /* Generate the code to compute variable locations, but do it
+          before generating the function header, so we can define the
+          register struct before the function body.  This requires a
+          temporary stream.  */
+       unsigned char *registers_used
+         = generate_c_for_variable_locations (m_instance, var_stream, m_arch,
+                                              expr_block, expr_pc);
+       make_cleanup (xfree, registers_used);
+
+       buf.puts ("typedef unsigned int"
+                 " __attribute__ ((__mode__(__pointer__)))"
+                 " __gdb_uintptr;\n");
+       buf.puts ("typedef int"
+                 " __attribute__ ((__mode__(__pointer__)))"
+                 " __gdb_intptr;\n");
+
+       /* Iterate all log2 sizes in bytes supported by c_get_mode_for_size.  */
+       for (int i = 0; i < 4; ++i)
+         {
+           const char *mode = c_get_mode_for_size (1 << i);
+
+           gdb_assert (mode != NULL);
+           buf.printf ("typedef int"
+                       " __attribute__ ((__mode__(__%s__)))"
+                       " __gdb_int_%s;\n",
+                       mode, mode);
+         }
+
+       generate_register_struct (&buf, m_arch, registers_used);
+      }
+
+    add_code_header (m_instance->scope (), &buf);
+
+    if (m_instance->scope () == COMPILE_I_SIMPLE_SCOPE
+       || m_instance->scope () == COMPILE_I_PRINT_ADDRESS_SCOPE
+       || m_instance->scope () == COMPILE_I_PRINT_VALUE_SCOPE)
+      {
+       buf.write (var_stream.c_str (), var_stream.size ());
+       push_user_expression (&buf);
+      }
+
+    write_macro_definitions (expr_block, expr_pc, &buf);
+
+    /* The user expression has to be in its own scope, so that "extern"
+       works properly.  Otherwise gcc thinks that the "extern"
+       declaration is in the same scope as the declaration provided by
+       gdb.  */
+    if (m_instance->scope () != COMPILE_I_RAW_SCOPE)
+      buf.puts ("{\n");
+
+    buf.puts ("#line 1 \"gdb command line\"\n");
+
+    add_input (m_instance->scope (), input, &buf);
+
+    /* For larger user expressions the automatic semicolons may be
+       confusing.  */
+    if (strchr (input, '\n') == NULL)
+      buf.puts (";\n");
+
+    if (m_instance->scope () != COMPILE_I_RAW_SCOPE)
+      buf.puts ("}\n");
+
+    if (m_instance->scope () == COMPILE_I_SIMPLE_SCOPE
+       || m_instance->scope () == COMPILE_I_PRINT_ADDRESS_SCOPE
+       || m_instance->scope () == COMPILE_I_PRINT_VALUE_SCOPE)
+      pop_user_expression (&buf);
 
-  buf.puts ("\n");
+    add_code_footer (m_instance->scope (), &buf);
+    return std::move (buf.string ());
+  }
 
-  /* For larger user expressions the automatic semicolons may be
-     confusing.  */
-  if (strchr (input, '\n') == NULL)
-    buf.puts (";\n");
+private:
+
+  /* The compile instance to be used for compilation and
+     type-conversion.  */
+  CompileInstanceType *m_instance;
+
+  /* The architecture to be used.  */
+  struct gdbarch *m_arch;
+};
+
+/* Type used for C program computations.  */
+
+typedef compile_program<compile::compile_c_instance, c_push_user_expression,
+                       pop_user_expression_nop, c_add_code_header,
+                       c_add_code_footer,
+                       c_add_input> c_compile_program;
+
+/* The la_compute_program method for C.  */
+
+std::string
+c_compute_program (compile::compile_instance *inst,
+                  const char *input,
+                  struct gdbarch *gdbarch,
+                  const struct block *expr_block,
+                  CORE_ADDR expr_pc)
+{
+  using namespace compile;
 
-  if (inst->scope != COMPILE_I_RAW_SCOPE)
-    buf.puts ("}\n");
+  compile_c_instance *c_inst = static_cast<compile_c_instance *> (inst);
+  c_compile_program program (c_inst, gdbarch);
 
-  add_code_footer (inst->scope, &buf);
-  return std::move (buf.string ());
+  return program.compute (input, expr_block, expr_pc);
 }
index 9282cfc02515447f8c4ea67848c8d06b4512bbbd..e5023af7281dc703a3ab60fc84576c4873e444cd 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "defs.h"
 #include "compile-internal.h"
+#include "compile-c.h"
 #include "symtab.h"
 #include "parser-defs.h"
 #include "block.h"
 
 \f
 
-/* Object of this type are stored in the compiler's symbol_err_map.  */
+using namespace compile;
 
-struct symbol_error
-{
-  /* The symbol.  */
-
-  const struct symbol *sym;
-
-  /* The error message to emit.  This is malloc'd and owned by the
-     hash table.  */
+/* See description in compile-c.h.  */
 
-  char *message;
-};
-
-/* Hash function for struct symbol_error.  */
-
-static hashval_t
-hash_symbol_error (const void *a)
-{
-  const struct symbol_error *se = (const struct symbol_error *) a;
-
-  return htab_hash_pointer (se->sym);
-}
-
-/* Equality function for struct symbol_error.  */
-
-static int
-eq_symbol_error (const void *a, const void *b)
-{
-  const struct symbol_error *sea = (const struct symbol_error *) a;
-  const struct symbol_error *seb = (const struct symbol_error *) b;
-
-  return sea->sym == seb->sym;
-}
-
-/* Deletion function for struct symbol_error.  */
-
-static void
-del_symbol_error (void *a)
-{
-  struct symbol_error *se = (struct symbol_error *) a;
-
-  xfree (se->message);
-  xfree (se);
-}
-
-/* Associate SYMBOL with some error text.  */
-
-static void
-insert_symbol_error (htab_t hash, const struct symbol *sym, const char *text)
-{
-  struct symbol_error e;
-  void **slot;
-
-  e.sym = sym;
-  slot = htab_find_slot (hash, &e, INSERT);
-  if (*slot == NULL)
-    {
-      struct symbol_error *e = XNEW (struct symbol_error);
-
-      e->sym = sym;
-      e->message = xstrdup (text);
-      *slot = e;
-    }
-}
-
-/* Emit the error message corresponding to SYM, if one exists, and
-   arrange for it not to be emitted again.  */
-
-static void
-error_symbol_once (struct compile_c_instance *context,
-                  const struct symbol *sym)
-{
-  struct symbol_error search;
-  struct symbol_error *err;
-  char *message;
-
-  if (context->symbol_err_map == NULL)
-    return;
-
-  search.sym = sym;
-  err = (struct symbol_error *) htab_find (context->symbol_err_map, &search);
-  if (err == NULL || err->message == NULL)
-    return;
-
-  message = err->message;
-  err->message = NULL;
-  make_cleanup (xfree, message);
-  error (_("%s"), message);
-}
-
-\f
-
-/* Compute the name of the pointer representing a local symbol's
-   address.  */
-
-static char *
-symbol_substitution_name (struct symbol *sym)
+char *
+c_symbol_substitution_name (struct symbol *sym)
 {
   return concat ("__", SYMBOL_NATURAL_NAME (sym), "_ptr", (char *) NULL);
 }
@@ -142,7 +51,7 @@ symbol_substitution_name (struct symbol *sym)
    scope.)  */
 
 static void
-convert_one_symbol (struct compile_c_instance *context,
+convert_one_symbol (compile_c_instance *context,
                    struct block_symbol sym,
                    int is_global,
                    int is_local)
@@ -151,19 +60,18 @@ convert_one_symbol (struct compile_c_instance *context,
   const char *filename = symbol_symtab (sym.symbol)->filename;
   unsigned short line = SYMBOL_LINE (sym.symbol);
 
-  error_symbol_once (context, sym.symbol);
+  context->error_symbol_once (sym.symbol);
 
   if (SYMBOL_CLASS (sym.symbol) == LOC_LABEL)
     sym_type = 0;
   else
-    sym_type = convert_type (context, SYMBOL_TYPE (sym.symbol));
+    sym_type = context->convert_type (SYMBOL_TYPE (sym.symbol));
 
   if (SYMBOL_DOMAIN (sym.symbol) == STRUCT_DOMAIN)
     {
       /* Binding a tag, so we don't need to build a decl.  */
-      C_CTX (context)->c_ops->tagbind (C_CTX (context),
-                                      SYMBOL_NATURAL_NAME (sym.symbol),
-                                      sym_type, filename, line);
+      context->tagbind (SYMBOL_NATURAL_NAME (sym.symbol),
+                       sym_type, filename, line);
     }
   else
     {
@@ -196,9 +104,8 @@ convert_one_symbol (struct compile_c_instance *context,
              /* Already handled by convert_enum.  */
              return;
            }
-         C_CTX (context)->c_ops->build_constant
-           (C_CTX (context),
-            sym_type, SYMBOL_NATURAL_NAME (sym.symbol),
+         context->build_constant
+           (sym_type, SYMBOL_NATURAL_NAME (sym.symbol),
             SYMBOL_VALUE (sym.symbol),
             filename, line);
          return;
@@ -267,7 +174,7 @@ convert_one_symbol (struct compile_c_instance *context,
        case LOC_LOCAL:
        substitution:
          kind = GCC_C_SYMBOL_VARIABLE;
-         symbol_name = symbol_substitution_name (sym.symbol);
+         symbol_name = c_symbol_substitution_name (sym.symbol);
          break;
 
        case LOC_STATIC:
@@ -282,18 +189,17 @@ convert_one_symbol (struct compile_c_instance *context,
        }
 
       /* Don't emit local variable decls for a raw expression.  */
-      if (context->base.scope != COMPILE_I_RAW_SCOPE
+      if (context->scope () != COMPILE_I_RAW_SCOPE
          || symbol_name == NULL)
        {
-         decl = C_CTX (context)->c_ops->build_decl
-           (C_CTX (context),
-            SYMBOL_NATURAL_NAME (sym.symbol),
+         decl = context->build_decl
+           (SYMBOL_NATURAL_NAME (sym.symbol),
             kind,
             sym_type,
             symbol_name, addr,
             filename, line);
 
-         C_CTX (context)->c_ops->bind (C_CTX (context), decl, is_global);
+         context->bind (decl, is_global);
        }
 
       xfree (symbol_name);
@@ -305,7 +211,7 @@ convert_one_symbol (struct compile_c_instance *context,
    itself, and DOMAIN is the domain which was searched.  */
 
 static void
-convert_symbol_sym (struct compile_c_instance *context, const char *identifier,
+convert_symbol_sym (compile_c_instance *context, const char *identifier,
                    struct block_symbol sym, domain_enum domain)
 {
   const struct block *static_block;
@@ -355,7 +261,7 @@ convert_symbol_sym (struct compile_c_instance *context, const char *identifier,
    to use and BMSYM is the minimal symbol to convert.  */
 
 static void
-convert_symbol_bmsym (struct compile_c_instance *context,
+convert_symbol_bmsym (compile_c_instance *context,
                      struct bound_minimal_symbol bmsym)
 {
   struct minimal_symbol *msym = bmsym.minsym;
@@ -405,12 +311,10 @@ convert_symbol_bmsym (struct compile_c_instance *context,
       break;
     }
 
-  sym_type = convert_type (context, type);
-  decl = C_CTX (context)->c_ops->build_decl (C_CTX (context),
-                                            MSYMBOL_NATURAL_NAME (msym),
-                                            kind, sym_type, NULL, addr,
-                                            NULL, 0);
-  C_CTX (context)->c_ops->bind (C_CTX (context), decl, 1 /* is_global */);
+  sym_type = context->convert_type (type);
+  decl = context->build_decl (MSYMBOL_NATURAL_NAME (msym),
+                             kind, sym_type, NULL, addr, NULL, 0);
+  context->bind (decl, true /* is_global */);
 }
 
 /* See compile-internal.h.  */
@@ -421,7 +325,7 @@ gcc_convert_symbol (void *datum,
                    enum gcc_c_oracle_request request,
                    const char *identifier)
 {
-  struct compile_c_instance *context = (struct compile_c_instance *) datum;
+  compile_c_instance *context = static_cast<compile_c_instance *> (datum);
   domain_enum domain;
   int found = 0;
 
@@ -446,7 +350,7 @@ gcc_convert_symbol (void *datum,
     {
       struct block_symbol sym;
 
-      sym = lookup_symbol (identifier, context->base.block, domain, NULL);
+      sym = lookup_symbol (identifier, context->block (), domain, NULL);
       if (sym.symbol != NULL)
        {
          convert_symbol_sym (context, identifier, sym, domain);
@@ -467,7 +371,7 @@ gcc_convert_symbol (void *datum,
 
   CATCH (e, RETURN_MASK_ALL)
     {
-      C_CTX (context)->c_ops->error (C_CTX (context), e.message);
+      context->error (e.message);
     }
   END_CATCH
 
@@ -484,7 +388,7 @@ gcc_address
 gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context,
                    const char *identifier)
 {
-  struct compile_c_instance *context = (struct compile_c_instance *) datum;
+  compile_c_instance *context = static_cast<compile_c_instance *> (datum);
   gcc_address result = 0;
   int found = 0;
 
@@ -529,7 +433,7 @@ gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context,
 
   CATCH (e, RETURN_MASK_ERROR)
     {
-      C_CTX (context)->c_ops->error (C_CTX (context), e.message);
+      context->error (e.message);
     }
   END_CATCH
 
@@ -583,7 +487,7 @@ symbol_seen (htab_t hashtab, struct symbol *sym)
 /* Generate C code to compute the length of a VLA.  */
 
 static void
-generate_vla_size (struct compile_c_instance *compiler,
+generate_vla_size (compile_instance *compiler,
                   string_file &stream,
                   struct gdbarch *gdbarch,
                   unsigned char *registers_used,
@@ -639,7 +543,7 @@ generate_vla_size (struct compile_c_instance *compiler,
 /* Generate C code to compute the address of SYM.  */
 
 static void
-generate_c_for_for_one_variable (struct compile_c_instance *compiler,
+generate_c_for_for_one_variable (compile_instance *compiler,
                                 string_file &stream,
                                 struct gdbarch *gdbarch,
                                 unsigned char *registers_used,
@@ -663,7 +567,7 @@ generate_c_for_for_one_variable (struct compile_c_instance *compiler,
 
       if (SYMBOL_COMPUTED_OPS (sym) != NULL)
        {
-         char *generated_name = symbol_substitution_name (sym);
+         char *generated_name = c_symbol_substitution_name (sym);
          struct cleanup *cleanup = make_cleanup (xfree, generated_name);
          /* We need to emit to a temporary buffer in case an error
             occurs in the middle.  */
@@ -702,22 +606,15 @@ generate_c_for_for_one_variable (struct compile_c_instance *compiler,
 
   CATCH (e, RETURN_MASK_ERROR)
     {
-      if (compiler->symbol_err_map == NULL)
-       compiler->symbol_err_map = htab_create_alloc (10,
-                                                     hash_symbol_error,
-                                                     eq_symbol_error,
-                                                     del_symbol_error,
-                                                     xcalloc,
-                                                     xfree);
-      insert_symbol_error (compiler->symbol_err_map, sym, e.message);
+      compiler->insert_symbol_error (sym, e.message);
     }
   END_CATCH
 }
 
-/* See compile-internal.h.  */
+/* See compile-c.h.  */
 
 unsigned char *
-generate_c_for_variable_locations (struct compile_c_instance *compiler,
+generate_c_for_variable_locations (compile_instance *compiler,
                                   string_file &stream,
                                   struct gdbarch *gdbarch,
                                   const struct block *block,
index 5ce4cdef06a9611b259c71dfcfc55593891b3280..47a1925b1ac4127a2727fe03c56373b4f503f6ab 100644 (file)
 #include "defs.h"
 #include "gdbtypes.h"
 #include "compile-internal.h"
-/* An object that maps a gdb type to a gcc type.  */
+#include "compile-c.h"
 
-struct type_map_instance
-{
-  /* The gdb type.  */
-
-  struct type *type;
-
-  /* The corresponding gcc type handle.  */
-
-  gcc_type gcc_type_handle;
-};
-
-/* Hash a type_map_instance.  */
-
-static hashval_t
-hash_type_map_instance (const void *p)
-{
-  const struct type_map_instance *inst = (const struct type_map_instance *) p;
-
-  return htab_hash_pointer (inst->type);
-}
-
-/* Check two type_map_instance objects for equality.  */
-
-static int
-eq_type_map_instance (const void *a, const void *b)
-{
-  const struct type_map_instance *insta = (const struct type_map_instance *) a;
-  const struct type_map_instance *instb = (const struct type_map_instance *) b;
-
-  return insta->type == instb->type;
-}
-
-\f
-
-/* Insert an entry into the type map associated with CONTEXT that maps
-   from the gdb type TYPE to the gcc type GCC_TYPE.  It is ok for a
-   given type to be inserted more than once, provided that the exact
-   same association is made each time.  This simplifies how type
-   caching works elsewhere in this file -- see how struct type caching
-   is handled.  */
-
-static void
-insert_type (struct compile_c_instance *context, struct type *type,
-            gcc_type gcc_type)
-{
-  struct type_map_instance inst, *add;
-  void **slot;
-
-  inst.type = type;
-  inst.gcc_type_handle = gcc_type;
-  slot = htab_find_slot (context->type_map, &inst, INSERT);
-
-  add = (struct type_map_instance *) *slot;
-  /* The type might have already been inserted in order to handle
-     recursive types.  */
-  if (add != NULL && add->gcc_type_handle != gcc_type)
-    error (_("Unexpected type id from GCC, check you use recent enough GCC."));
-
-  if (add == NULL)
-    {
-      add = XNEW (struct type_map_instance);
-      *add = inst;
-      *slot = add;
-    }
-}
+using namespace compile;
 
 /* Convert a pointer type to its gcc representation.  */
 
 static gcc_type
-convert_pointer (struct compile_c_instance *context, struct type *type)
+convert_pointer (compile_c_instance *context, struct type *type)
 {
-  gcc_type target = convert_type (context, TYPE_TARGET_TYPE (type));
+  gcc_type target = context->convert_type (TYPE_TARGET_TYPE (type));
 
-  return C_CTX (context)->c_ops->build_pointer_type (C_CTX (context),
-                                                    target);
+  return context->build_pointer_type (target);
 }
 
 /* Convert an array type to its gcc representation.  */
 
 static gcc_type
-convert_array (struct compile_c_instance *context, struct type *type)
+convert_array (compile_c_instance *context, struct type *type)
 {
   gcc_type element_type;
   struct type *range = TYPE_INDEX_TYPE (type);
 
-  element_type = convert_type (context, TYPE_TARGET_TYPE (type));
+  element_type = context->convert_type (TYPE_TARGET_TYPE (type));
 
   if (TYPE_LOW_BOUND_KIND (range) != PROP_CONST)
-    return C_CTX (context)->c_ops->error (C_CTX (context),
-                                         _("array type with non-constant"
-                                           " lower bound is not supported"));
+    return context->error (_("array type with non-constant"
+                            " lower bound is not supported"));
   if (TYPE_LOW_BOUND (range) != 0)
-    return C_CTX (context)->c_ops->error (C_CTX (context),
-                                         _("cannot convert array type with "
-                                           "non-zero lower bound to C"));
+    return context->error (_("cannot convert array type with "
+                            "non-zero lower bound to C"));
 
   if (TYPE_HIGH_BOUND_KIND (range) == PROP_LOCEXPR
       || TYPE_HIGH_BOUND_KIND (range) == PROP_LOCLIST)
@@ -126,14 +59,11 @@ convert_array (struct compile_c_instance *context, struct type *type)
       char *upper_bound;
 
       if (TYPE_VECTOR (type))
-       return C_CTX (context)->c_ops->error (C_CTX (context),
-                                             _("variably-sized vector type"
-                                               " is not supported"));
+       return context->error (_("variably-sized vector type"
+                                " is not supported"));
 
       upper_bound = c_get_range_decl_name (&TYPE_RANGE_DATA (range)->high);
-      result = C_CTX (context)->c_ops->build_vla_array_type (C_CTX (context),
-                                                            element_type,
-                                                            upper_bound);
+      result = context->build_vla_array_type (element_type, upper_bound);
       xfree (upper_bound);
       return result;
     }
@@ -150,18 +80,15 @@ convert_array (struct compile_c_instance *context, struct type *type)
        }
 
       if (TYPE_VECTOR (type))
-       return C_CTX (context)->c_ops->build_vector_type (C_CTX (context),
-                                                         element_type,
-                                                         count);
-      return C_CTX (context)->c_ops->build_array_type (C_CTX (context),
-                                                      element_type, count);
+       return context->build_vector_type (element_type, count);
+      return context->build_array_type (element_type, count);
     }
 }
 
 /* Convert a struct or union type to its gcc representation.  */
 
 static gcc_type
-convert_struct_or_union (struct compile_c_instance *context, struct type *type)
+convert_struct_or_union (compile_c_instance *context, struct type *type)
 {
   int i;
   gcc_type result;
@@ -169,63 +96,53 @@ convert_struct_or_union (struct compile_c_instance *context, struct type *type)
   /* First we create the resulting type and enter it into our hash
      table.  This lets recursive types work.  */
   if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
-    result = C_CTX (context)->c_ops->build_record_type (C_CTX (context));
+    result = context->build_record_type ();
   else
     {
       gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
-      result = C_CTX (context)->c_ops->build_union_type (C_CTX (context));
+      result = context->build_union_type ();
     }
-  insert_type (context, type, result);
+  context->insert_type (type, result);
 
   for (i = 0; i < TYPE_NFIELDS (type); ++i)
     {
       gcc_type field_type;
       unsigned long bitsize = TYPE_FIELD_BITSIZE (type, i);
 
-      field_type = convert_type (context, TYPE_FIELD_TYPE (type, i));
+      field_type = context->convert_type (TYPE_FIELD_TYPE (type, i));
       if (bitsize == 0)
        bitsize = 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (type, i));
-      C_CTX (context)->c_ops->build_add_field (C_CTX (context), result,
-                                              TYPE_FIELD_NAME (type, i),
-                                              field_type,
-                                              bitsize,
-                                              TYPE_FIELD_BITPOS (type, i));
+      context->build_add_field (result, TYPE_FIELD_NAME (type, i),
+                               field_type, bitsize,
+                               TYPE_FIELD_BITPOS (type, i));
     }
 
-  C_CTX (context)->c_ops->finish_record_or_union (C_CTX (context), result,
-                                                 TYPE_LENGTH (type));
+  context->finish_record_or_union (result, TYPE_LENGTH (type));
   return result;
 }
 
 /* Convert an enum type to its gcc representation.  */
 
 static gcc_type
-convert_enum (struct compile_c_instance *context, struct type *type)
+convert_enum (compile_c_instance *context, struct type *type)
 {
   gcc_type int_type, result;
   int i;
-  struct gcc_c_context *ctx = C_CTX (context);
 
-  if (C_CTX (context)->c_ops->c_version >= GCC_C_FE_VERSION_1)
-    int_type = ctx->c_ops->int_type (ctx,
-                                    TYPE_UNSIGNED (type),
-                                    TYPE_LENGTH (type),
-                                    NULL);
+  if (context->c_version () >= GCC_C_FE_VERSION_1)
+    int_type = context->int_type (TYPE_UNSIGNED (type), TYPE_LENGTH (type),
+                                 NULL);
   else
-    int_type = ctx->c_ops->int_type_v0 (ctx,
-                                       TYPE_UNSIGNED (type),
-                                       TYPE_LENGTH (type));
+    int_type = context->int_type (TYPE_UNSIGNED (type), TYPE_LENGTH (type));
 
-  result = ctx->c_ops->build_enum_type (ctx, int_type);
+  result = context->build_enum_type (int_type);
   for (i = 0; i < TYPE_NFIELDS (type); ++i)
     {
-      ctx->c_ops->build_add_enum_constant (ctx,
-                                          result,
-                                          TYPE_FIELD_NAME (type, i),
-                                          TYPE_FIELD_ENUMVAL (type, i));
+      context->build_add_enum_constant (result, TYPE_FIELD_NAME (type, i),
+                                       TYPE_FIELD_ENUMVAL (type, i));
     }
 
-  ctx->c_ops->finish_enum_type (ctx, result);
+  context->finish_enum_type (result);
 
   return result;
 }
@@ -233,7 +150,7 @@ convert_enum (struct compile_c_instance *context, struct type *type)
 /* Convert a function type to its gcc representation.  */
 
 static gcc_type
-convert_func (struct compile_c_instance *context, struct type *type)
+convert_func (compile_c_instance *context, struct type *type)
 {
   int i;
   gcc_type result, return_type;
@@ -242,16 +159,14 @@ convert_func (struct compile_c_instance *context, struct type *type)
 
   /* This approach means we can't make self-referential function
      types.  Those are impossible in C, though.  */
-  return_type = convert_type (context, TYPE_TARGET_TYPE (type));
+  return_type = context->convert_type (TYPE_TARGET_TYPE (type));
 
   array.n_elements = TYPE_NFIELDS (type);
   array.elements = XNEWVEC (gcc_type, TYPE_NFIELDS (type));
   for (i = 0; i < TYPE_NFIELDS (type); ++i)
-    array.elements[i] = convert_type (context, TYPE_FIELD_TYPE (type, i));
+    array.elements[i] = context->convert_type (TYPE_FIELD_TYPE (type, i));
 
-  result = C_CTX (context)->c_ops->build_function_type (C_CTX (context),
-                                                       return_type,
-                                                       &array, is_varargs);
+  result = context->build_function_type (return_type, &array, is_varargs);
   xfree (array.elements);
 
   return result;
@@ -260,66 +175,59 @@ convert_func (struct compile_c_instance *context, struct type *type)
 /* Convert an integer type to its gcc representation.  */
 
 static gcc_type
-convert_int (struct compile_c_instance *context, struct type *type)
+convert_int (compile_c_instance *context, struct type *type)
 {
-  if (C_CTX (context)->c_ops->c_version >= GCC_C_FE_VERSION_1)
+  if (context->c_version () >= GCC_C_FE_VERSION_1)
     {
       if (TYPE_NOSIGN (type))
        {
          gdb_assert (TYPE_LENGTH (type) == 1);
-         return C_CTX (context)->c_ops->char_type (C_CTX (context));
+         return context->char_type ();
        }
-      return C_CTX (context)->c_ops->int_type (C_CTX (context),
-                                              TYPE_UNSIGNED (type),
-                                              TYPE_LENGTH (type),
-                                              TYPE_NAME (type));
+      return context->int_type (TYPE_UNSIGNED (type), TYPE_LENGTH (type),
+                               TYPE_NAME (type));
     }
   else
-    return C_CTX (context)->c_ops->int_type_v0 (C_CTX (context),
-                                               TYPE_UNSIGNED (type),
-                                               TYPE_LENGTH (type));
+    return context->int_type (TYPE_UNSIGNED (type), TYPE_LENGTH (type));
 }
 
 /* Convert a floating-point type to its gcc representation.  */
 
 static gcc_type
-convert_float (struct compile_c_instance *context, struct type *type)
+convert_float (compile_c_instance *context, struct type *type)
 {
-  if (C_CTX (context)->c_ops->c_version >= GCC_C_FE_VERSION_1)
-    return C_CTX (context)->c_ops->float_type (C_CTX (context),
-                                              TYPE_LENGTH (type),
-                                              TYPE_NAME (type));
+  if (context->c_version () >= GCC_C_FE_VERSION_1)
+    return context->float_type (TYPE_LENGTH (type), TYPE_NAME (type));
   else
-    return C_CTX (context)->c_ops->float_type_v0 (C_CTX (context),
-                                                 TYPE_LENGTH (type));
+    return context->float_type (TYPE_LENGTH (type));
 }
 
 /* Convert the 'void' type to its gcc representation.  */
 
 static gcc_type
-convert_void (struct compile_c_instance *context, struct type *type)
+convert_void (compile_c_instance *context, struct type *type)
 {
-  return C_CTX (context)->c_ops->void_type (C_CTX (context));
+  return context->void_type ();
 }
 
 /* Convert a boolean type to its gcc representation.  */
 
 static gcc_type
-convert_bool (struct compile_c_instance *context, struct type *type)
+convert_bool (compile_c_instance *context, struct type *type)
 {
-  return C_CTX (context)->c_ops->bool_type (C_CTX (context));
+  return context->bool_type ();
 }
 
 /* Convert a qualified type to its gcc representation.  */
 
 static gcc_type
-convert_qualified (struct compile_c_instance *context, struct type *type)
+convert_qualified (compile_c_instance *context, struct type *type)
 {
   struct type *unqual = make_unqualified_type (type);
   gcc_type unqual_converted;
   gcc_qualifiers_flags quals = 0;
 
-  unqual_converted = convert_type (context, unqual);
+  unqual_converted = context->convert_type (unqual);
 
   if (TYPE_CONST (type))
     quals |= GCC_QUALIFIER_CONST;
@@ -328,19 +236,17 @@ convert_qualified (struct compile_c_instance *context, struct type *type)
   if (TYPE_RESTRICT (type))
     quals |= GCC_QUALIFIER_RESTRICT;
 
-  return C_CTX (context)->c_ops->build_qualified_type (C_CTX (context),
-                                                      unqual_converted,
-                                                      quals);
+  return context->build_qualified_type (unqual_converted, quals);
 }
 
 /* Convert a complex type to its gcc representation.  */
 
 static gcc_type
-convert_complex (struct compile_c_instance *context, struct type *type)
+convert_complex (compile_c_instance *context, struct type *type)
 {
-  gcc_type base = convert_type (context, TYPE_TARGET_TYPE (type));
+  gcc_type base = context->convert_type (TYPE_TARGET_TYPE (type));
 
-  return C_CTX (context)->c_ops->build_complex_type (C_CTX (context), base);
+  return context->build_complex_type (base);
 }
 
 /* A helper function which knows how to convert most types from their
@@ -349,7 +255,7 @@ convert_complex (struct compile_c_instance *context, struct type *type)
    returns the gcc type.  */
 
 static gcc_type
-convert_type_basic (struct compile_c_instance *context, struct type *type)
+convert_type_basic (compile_c_instance *context, struct type *type)
 {
   /* If we are converting a qualified type, first convert the
      unqualified type and then apply the qualifiers.  */
@@ -392,70 +298,219 @@ convert_type_basic (struct compile_c_instance *context, struct type *type)
       return convert_complex (context, type);
     }
 
-  return C_CTX (context)->c_ops->error (C_CTX (context),
-                                       _("cannot convert gdb type "
-                                         "to gcc type"));
+  return context->error (_("cannot convert gdb type to gcc type"));
 }
 
-/* See compile-internal.h.  */
+/* Default compile flags for C.  */
+
+const char *compile_c_instance::m_default_cflags = "-std=gnu11"
+  /* Otherwise the .o file may need
+     "_Unwind_Resume" and
+     "__gcc_personality_v0".  */
+  " -fno-exceptions"
+  " -Wno-implicit-function-declaration";
 
 gcc_type
-convert_type (struct compile_c_instance *context, struct type *type)
+compile_c_instance::convert_type (struct type *type)
 {
-  struct type_map_instance inst, *found;
-  gcc_type result;
-
   /* We don't ever have to deal with typedefs in this code, because
      those are only needed as symbols by the C compiler.  */
   type = check_typedef (type);
 
-  inst.type = type;
-  found = (struct type_map_instance *) htab_find (context->type_map, &inst);
-  if (found != NULL)
-    return found->gcc_type_handle;
+  type_map_t::iterator pos = m_type_map.find (type);
+  if (pos != m_type_map.end ())
+    return pos->second;
 
-  result = convert_type_basic (context, type);
-  insert_type (context, type, result);
+  gcc_type result = convert_type_basic (this, type);
+  insert_type (type, result);
   return result;
 }
 
-\f
+#define FORWARD(OP,...) (m_context->c_ops->OP (m_context, ##__VA_ARGS__))
+
+unsigned int
+compile_c_instance::c_version () const
+{
+  return m_context->c_ops->c_version;
+}
+
+bool
+compile_c_instance::tagbind (const char *name, gcc_type tagged_type,
+                            const char *filename, unsigned int line_number)
+{
+  return FORWARD (tagbind, name, tagged_type, filename, line_number);
+}
+
+bool
+compile_c_instance::build_constant (gcc_type type, const char *name,
+                                   unsigned long value, const char *filename,
+                                   unsigned int line_number)
+{
+  return FORWARD (build_constant, type, name, value, filename, line_number);
+}
+
+gcc_decl
+compile_c_instance::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)
+{
+  return FORWARD (build_decl, name, sym_kind, sym_type, substitution_name,
+                 address, filename, line_number);
+}
+
+bool
+compile_c_instance::bind (gcc_decl decl, bool is_global)
+{
+  return FORWARD (bind, decl, is_global);
+}
+
+gcc_type
+compile_c_instance::error (const char *message)
+{
+  return FORWARD (error, message);
+}
+
+gcc_type
+compile_c_instance::build_pointer_type (gcc_type base_type)
+{
+  return FORWARD (build_pointer_type, base_type);
+}
+
+gcc_type
+compile_c_instance::build_vla_array_type (gcc_type element_type,
+                                         const char *upper_bound_name)
+{
+  return FORWARD (build_vla_array_type, element_type, upper_bound_name);
+}
+
+gcc_type
+compile_c_instance::build_vector_type (gcc_type element_type, int num_elements)
+{
+  return FORWARD (build_vector_type, element_type, num_elements);
+}
+
+gcc_type
+compile_c_instance::build_array_type (gcc_type element_type, int num_elements)
+{
+  return FORWARD (build_array_type, element_type, num_elements);
+}
 
-/* Delete the compiler instance C.  */
+gcc_type
+compile_c_instance::build_record_type ()
+{
+  return FORWARD (build_record_type);
+}
 
-static void
-delete_instance (struct compile_instance *c)
+gcc_type
+compile_c_instance::build_union_type ()
 {
-  struct compile_c_instance *context = (struct compile_c_instance *) c;
+  return FORWARD (build_union_type);
+}
 
-  context->base.fe->ops->destroy (context->base.fe);
-  htab_delete (context->type_map);
-  if (context->symbol_err_map != NULL)
-    htab_delete (context->symbol_err_map);
-  xfree (context);
+bool
+compile_c_instance::build_add_field (gcc_type record_or_union_type,
+                                    const char *field_name,
+                                    gcc_type field_type, unsigned long bitsize,
+                                    unsigned long bitpos)
+{
+  return FORWARD (build_add_field, record_or_union_type, field_name,
+                 field_type, bitsize, bitpos);
 }
 
-/* See compile-internal.h.  */
+bool
+compile_c_instance::finish_record_or_union (gcc_type record_or_union_type,
+                                           unsigned long size_in_bytes)
+{
+  return FORWARD (finish_record_or_union, record_or_union_type, size_in_bytes);
+}
 
-struct compile_instance *
-new_compile_instance (struct gcc_c_context *fe)
+gcc_type
+compile_c_instance::int_type (bool is_unsigned, unsigned long size_in_bytes,
+                             const char *builtin_name)
 {
-  struct compile_c_instance *result = XCNEW (struct compile_c_instance);
+  return FORWARD (int_type, is_unsigned, size_in_bytes, builtin_name);
+}
 
-  result->base.fe = &fe->base;
-  result->base.destroy = delete_instance;
-  result->base.gcc_target_options = ("-std=gnu11"
-                                    /* Otherwise the .o file may need
-                                       "_Unwind_Resume" and
-                                       "__gcc_personality_v0".  */
-                                    " -fno-exceptions");
+gcc_type
+compile_c_instance::int_type (bool is_unsigned, unsigned long size_in_bytes)
+{
+  return FORWARD (int_type_v0, is_unsigned, size_in_bytes);
+}
+
+gcc_type
+compile_c_instance::build_enum_type (gcc_type underlying_int_type)
+{
+  return FORWARD (build_enum_type, underlying_int_type);
+}
 
-  result->type_map = htab_create_alloc (10, hash_type_map_instance,
-                                       eq_type_map_instance,
-                                       xfree, xcalloc, xfree);
+bool
+compile_c_instance::build_add_enum_constant (gcc_type enum_type,
+                                            const char *name,
+                                            unsigned long value)
+{
+  return FORWARD (build_add_enum_constant, enum_type, name, value);
+}
 
-  fe->c_ops->set_callbacks (fe, gcc_convert_symbol,
-                           gcc_symbol_address, result);
+bool
+compile_c_instance::finish_enum_type (gcc_type enum_type)
+{
+  return FORWARD (finish_enum_type, enum_type);
+}
 
-  return &result->base;
+gcc_type
+compile_c_instance::build_function_type (gcc_type return_value,
+                                        const struct gcc_type_array *argument_types,
+                                        bool is_varargs)
+{
+  return FORWARD (build_function_type, return_value, argument_types,
+                 is_varargs);
 }
+
+gcc_type
+compile_c_instance::char_type ()
+{
+  return FORWARD (char_type);
+}
+
+gcc_type
+compile_c_instance::float_type (unsigned long size_in_bytes,
+                               const char *builtin_name)
+{
+  return FORWARD (float_type, size_in_bytes, builtin_name);
+}
+
+gcc_type
+compile_c_instance::float_type (unsigned long size_in_bytes)
+{
+  return FORWARD (float_type_v0, size_in_bytes);
+}
+
+gcc_type
+compile_c_instance::void_type ()
+{
+  return FORWARD (void_type);
+}
+
+gcc_type
+compile_c_instance::bool_type ()
+{
+  return FORWARD (bool_type);
+}
+
+gcc_type
+compile_c_instance::build_qualified_type (gcc_type unqualified_type,
+                                         enum gcc_qualifiers qualifiers)
+{
+  return FORWARD (build_qualified_type, unqualified_type, qualifiers);
+}
+
+gcc_type
+compile_c_instance::build_complex_type (gcc_type element_type)
+{
+  return FORWARD (build_complex_type, element_type);
+}
+
+#undef FORWARD
diff --git a/gdb/compile/compile-c.h b/gdb/compile/compile-c.h
new file mode 100644 (file)
index 0000000..fd2b380
--- /dev/null
@@ -0,0 +1,176 @@
+/* Header file for GDB compile C-language support.
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+   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 GDB_COMPILE_C_H
+#define GDB_COMPILE_C_H
+
+#include "common/enum-flags.h"
+
+/* enum-flags wrapper.  */
+DEF_ENUM_FLAGS_TYPE (enum gcc_qualifiers, gcc_qualifiers_flags);
+
+/* A callback suitable for use as the GCC C symbol oracle.  */
+
+extern gcc_c_oracle_function gcc_convert_symbol;
+
+/* A callback suitable for use as the GCC C address oracle.  */
+
+extern gcc_c_symbol_address_function gcc_symbol_address;
+
+namespace compile
+{
+
+  /* A subclass of compile_instance that is specific to the C front
+     end.  */
+
+  class compile_c_instance
+    : public compile_instance
+  {
+  public:
+
+    compile_c_instance (struct gcc_base_context *base, const char *options)
+      : compile_instance (base, options)
+    {
+    }
+
+    explicit compile_c_instance (struct gcc_c_context *gcc_c)
+      : compile_instance (&gcc_c->base, m_default_cflags), m_context (gcc_c)
+    {
+      m_context->c_ops->set_callbacks (m_context, gcc_convert_symbol,
+                                      gcc_symbol_address, this);
+    }
+
+    ~compile_c_instance ()
+    {
+      m_gcc_fe->ops->destroy (m_gcc_fe);
+    }
+
+    /* Convert a gdb type, TYPE, to a GCC type.
+
+       The new GCC type is returned.  */
+
+    gcc_type convert_type (struct type *type);
+
+    /* Plug-in forwards  */
+
+    unsigned int c_version () const;
+
+    bool tagbind (const char *name, gcc_type tagged_type, const char *filename,
+                 unsigned int line_number);
+
+    bool build_constant (gcc_type type, const char *name, unsigned long value,
+                        const char *filename, unsigned int line_number);
+
+    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);
+
+    bool bind (gcc_decl decl, bool is_global);
+
+    gcc_type error (const char *message);
+
+    gcc_type build_pointer_type (gcc_type base_type);
+
+    gcc_type build_vla_array_type (gcc_type element_type,
+                                  const char *upper_bound_name);
+
+    gcc_type build_vector_type (gcc_type element_type, int num_elements);
+
+    gcc_type build_array_type (gcc_type element_type, int num_elements);
+
+    gcc_type build_record_type ();
+
+    gcc_type build_union_type ();
+
+    bool build_add_field (gcc_type record_or_union_type, const char *field_name,
+                         gcc_type field_type, unsigned long bitsize,
+                         unsigned long bitpos);
+
+    bool finish_record_or_union (gcc_type record_or_union_type,
+                                unsigned long size_in_bytes);
+
+    gcc_type int_type (bool is_unsigned, unsigned long size_in_bytes,
+                      const char *builtin_name);
+
+    gcc_type int_type (bool is_unsigned, unsigned long size_in_bytes);
+
+    gcc_type build_enum_type (gcc_type underlying_int_type);
+
+    bool build_add_enum_constant (gcc_type enum_type, const char *name,
+                                 unsigned long value);
+
+    bool finish_enum_type (gcc_type enum_type);
+
+    gcc_type build_function_type (gcc_type return_value,
+                                 const struct gcc_type_array *argument_types,
+                                 bool is_varargs);
+
+    gcc_type char_type ();
+
+    gcc_type float_type (unsigned long size_in_bytes, const char *builtin_name);
+
+    gcc_type float_type (unsigned long size_in_bytes);
+
+    gcc_type void_type ();
+
+    gcc_type bool_type ();
+
+    gcc_type build_qualified_type (gcc_type unqualified_type,
+                                  enum gcc_qualifiers qualifiers);
+
+    gcc_type build_complex_type (gcc_type element_type);
+
+  private:
+
+    /* Default compiler flags for C.  */
+    static const char *m_default_cflags;
+
+    /* The GCC C context.  */
+    struct gcc_c_context *m_context;
+  };
+};
+
+/* Emit code to compute the address for all the local variables in
+   scope at PC in BLOCK.  Returns a malloc'd vector, indexed by gdb
+   register number, where each element indicates if the corresponding
+   register is needed to compute a local variable.  */
+
+extern unsigned char *generate_c_for_variable_locations
+     (compile::compile_instance *compiler,
+      string_file &stream,
+      struct gdbarch *gdbarch,
+      const struct block *block,
+      CORE_ADDR pc);
+
+/* Get the GCC mode attribute value for a given type size.  */
+
+extern const char *c_get_mode_for_size (int size);
+
+/* Given a dynamic property, return an xmallocd name that is used to
+   represent its size.  The result must be freed by the caller.  The
+   contents of the resulting string will be the same each time for
+   each call with the same argument.  */
+
+struct dynamic_prop;
+extern char *c_get_range_decl_name (const struct dynamic_prop *prop);
+
+/* Compute the name of the pointer representing a local symbol's
+   address.  */
+
+extern char *c_symbol_substitution_name (struct symbol *sym);
+
+#endif /* GDB_COMPILE_C_H  */
index 0c53f8c443298bd211674d034ed110a73ac34e33..292282e65501bd2bd907fd9864765c339104d894 100644 (file)
 #ifndef GDB_COMPILE_INTERNAL_H
 #define GDB_COMPILE_INTERNAL_H
 
-#include "hashtab.h"
+#include "defs.h"
 #include "gcc-c-interface.h"
-#include "common/enum-flags.h"
 
-/* enum-flags wrapper.  */
-DEF_ENUM_FLAGS_TYPE (enum gcc_qualifiers, gcc_qualifiers_flags);
+#include <string>
+#include <unordered_map>
 
 /* Debugging flag for the "compile" family of commands.  */
 
@@ -30,57 +29,153 @@ extern int compile_debug;
 
 struct block;
 
-/* An object of this type holds state associated with a given
-   compilation job.  */
-
-struct compile_instance
+namespace compile
 {
-  /* The GCC front end.  */
+  /* An object of this type holds state associated with a given
+     compilation job.  */
 
-  struct gcc_base_context *fe;
+  class compile_instance
+  {
+  public:
 
-  /* The "scope" of this compilation.  */
+    compile_instance (struct gcc_base_context *gcc_fe, const char *options)
+      : m_gcc_fe (gcc_fe), m_gcc_target_options (options)
+    {
+    }
 
-  enum compile_i_scope_types scope;
+    virtual ~compile_instance ()
+    {
+    }
 
-  /* The block in which an expression is being parsed.  */
+    /* Returns the GCC options to be passed during compilation.  */
 
-  const struct block *block;
+    const std::string &gcc_target_options () const
+    {
+      return m_gcc_target_options;
+    }
 
-  /* Specify "-std=gnu11", "-std=gnu++11" or similar.  These options are put
-     after CU's DW_AT_producer compilation options to override them.  */
+    /* Insert GCC_TYPE into the type cache for TYPE.
 
-  const char *gcc_target_options;
+       It is ok for a given type to be inserted more than once, provided that
+       the exact same association is made each time.  */
 
-  /* How to destroy this object.  */
+    void insert_type (struct type *type, gcc_type gcc_type);
 
-  void (*destroy) (struct compile_instance *);
-};
+    /* Associate SYMBOL with some error text.  */
 
-/* A subclass of compile_instance that is specific to the C front
-   end.  */
-struct compile_c_instance
-{
-  /* Base class.  Note that the base class vtable actually points to a
-     gcc_c_fe_vtable.  */
+    void insert_symbol_error (const struct symbol *sym, std::string text);
 
-  struct compile_instance base;
+    /* Emit the error message corresponding to SYM, if one exists, and
+       arrange for it not to be emitted again.  */
 
-  /* Map from gdb types to gcc types.  */
+    void error_symbol_once (const struct symbol *sym);
 
-  htab_t type_map;
+    /* These currently just forward to the underlying ops
+       vtable.  */
 
-  /* Map from gdb symbols to gcc error messages to emit.  */
+    /* Set the plug-in print callback.  */
 
-  htab_t symbol_err_map;
-};
+    void set_print_callback (void (*print_function) (void *, const char *),
+                            void *datum);
+
+    /* Return the plug-in's front-end version.  */
+
+    unsigned int version () const;
+
+    /* Set the plug-in's verbosity level.  */
+
+    void set_verbose (int level);
+
+    /* Set the plug-in driver program.  */
+
+    void set_driver_filename (const char *filename);
+
+    /* Set the regular expression used to match the configury triplet
+       prefix to the compiler.  */
+
+    void set_triplet_regexp (const char *regexp);
+
+    /* Set compilation arguments.  */
+
+    char *set_arguments (int argc, char **argv);
+
+    /* As above for protocol version 0.  */
+
+    char *set_arguments (const char *regexp, int argc, char **argv);
+
+    /* Set the filename of the program to compile.  */
+
+    void set_source_file (const char *filename);
+
+    /* Compile the previously specified source file to FILENAME.  */
+
+    bool compile (const char *filename);
+
+    /* Same as above, but for earlier protocol versions.  */
+
+    bool compile (const char *filename, int verbose_level);
+
+    /* Set the scope type for this compile.  */
+
+    void set_scope (enum compile_i_scope_types scope)
+    {
+      m_scope = scope;
+    }
+
+    /* Return the scope type.  */
+
+    enum compile_i_scope_types scope () const
+    {
+      return m_scope;
+    }
+
+    /* Set the block to be used for symbol searches.  */
 
-/* A helper macro that takes a compile_c_instance and returns its
-   corresponding gcc_c_context.  */
+    void set_block (const struct block *block)
+    {
+      m_block = block;
+    }
 
-#define C_CTX(I) ((struct gcc_c_context *) ((I)->base.fe))
+    /* Return the search block.  */
 
-/* Define header and footers for different scopes.  */
+    const struct block *block () const
+    {
+      return m_block;
+    }
+
+  protected:
+
+    /* Map types used by the compile instance for caching type conversions.
+       and error tracking.  */
+
+    typedef std::pair<struct type *, gcc_type> type_map_item_t;
+    typedef std::unordered_map<struct type *, gcc_type> type_map_t;
+    typedef std::pair<const struct symbol *, std::string> symbol_err_map_item_t;
+    typedef std::unordered_map<const struct symbol *, std::string>
+    symbol_err_map_t;
+
+    /* The GCC front end.  */
+    struct gcc_base_context *m_gcc_fe;
+
+    /* The "scope" of this compilation.  */
+    enum compile_i_scope_types m_scope;
+
+    /* The block in which an expression is being parsed.  */
+    const struct block *m_block;
+
+    /* Specify "-std=gnu11", "-std=gnu++11" or similar.  These options are put
+       after CU's DW_AT_producer compilation options to override them.  */
+    std::string m_gcc_target_options;
+
+    /* Map from gdb types to gcc types.  */
+    type_map_t m_type_map;
+
+    /* Map from gdb symbols to gcc error messages to emit.  */
+    symbol_err_map_t m_symbol_err_map;
+  };
+};
+
+/* Define the headers and footers for different scopes.  */
 
 /* A simple scope just declares a function named "_gdb_expr", takes no
    arguments and returns no value.  */
@@ -93,6 +188,10 @@ struct compile_c_instance
 #define COMPILE_I_EXPR_VAL "__gdb_expr_val"
 #define COMPILE_I_EXPR_PTR_TYPE "__gdb_expr_ptr_type"
 
+/* A "type" to indicate a NULL type.  */
+
+const gcc_type GCC_TYPE_NONE = (gcc_type) -1;
+
 /* Call gdbarch_register_name (GDBARCH, REGNUM) and convert its result
    to a form suitable for the compiler source.  The register names
    should not clash with inferior defined macros.  Returned pointer is
@@ -108,50 +207,6 @@ extern char *compile_register_name_mangled (struct gdbarch *gdbarch,
 extern int compile_register_name_demangle (struct gdbarch *gdbarch,
                                           const char *reg_name);
 
-/* Convert a gdb type, TYPE, to a GCC type.  CONTEXT is used to do the
-   actual conversion.  The new GCC type is returned.  */
-
-struct type;
-extern gcc_type convert_type (struct compile_c_instance *context,
-                             struct type *type);
-
-/* A callback suitable for use as the GCC C symbol oracle.  */
-
-extern gcc_c_oracle_function gcc_convert_symbol;
-
-/* A callback suitable for use as the GCC C address oracle.  */
-
-extern gcc_c_symbol_address_function gcc_symbol_address;
-
-/* Instantiate a GDB object holding state for the GCC context FE.  The
-   new object is returned.  */
-
-extern struct compile_instance *new_compile_instance (struct gcc_c_context *fe);
-
-/* Emit code to compute the address for all the local variables in
-   scope at PC in BLOCK.  Returns a malloc'd vector, indexed by gdb
-   register number, where each element indicates if the corresponding
-   register is needed to compute a local variable.  */
-
-extern unsigned char *generate_c_for_variable_locations
-     (struct compile_c_instance *compiler,
-      string_file &stream,
-      struct gdbarch *gdbarch,
-      const struct block *block,
-      CORE_ADDR pc);
-
-/* Get the GCC mode attribute value for a given type size.  */
-
-extern const char *c_get_mode_for_size (int size);
-
-/* Given a dynamic property, return an xmallocd name that is used to
-   represent its size.  The result must be freed by the caller.  The
-   contents of the resulting string will be the same each time for
-   each call with the same argument.  */
-
-struct dynamic_prop;
-extern char *c_get_range_decl_name (const struct dynamic_prop *prop);
-
 /* Type used to hold and pass around the source and object file names
    to use for compilation.  */
 class compile_file_names
index f1296e8304ec6c4a80250000964b96d7b81ee027..aab50e93571c8f8432689b983926dab92e5b2df5 100644 (file)
@@ -24,6 +24,7 @@
 #include "ui-file.h"
 #include "utils.h"
 #include "compile-internal.h"
+#include "compile-c.h"
 #include "compile.h"
 #include "block.h"
 #include "dwarf2-frame.h"
index 8d57cc980848383fc0e18d351a9c9f7aa6505cfe..b9a3d3419f939d115a21d40c00ee8c77e96db8fb 100644 (file)
@@ -420,8 +420,8 @@ filter_args (int *argcp, char **argv)
    generated above.  */
 
 static void
-get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch,
-         int *argcp, char ***argvp)
+get_args (const compile::compile_instance *compiler,
+         struct gdbarch *gdbarch, int *argcp, char ***argvp)
 {
   const char *cs_producer_options;
   int argc_compiler;
@@ -442,7 +442,7 @@ get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch,
       freeargv (argv_producer);
     }
 
-  build_argc_argv (compiler->gcc_target_options,
+  build_argc_argv (compiler->gcc_target_options ().c_str (),
                   &argc_compiler, &argv_compiler);
   append_args (argcp, argvp, argc_compiler, argv_compiler);
   freeargv (argv_compiler);
@@ -450,14 +450,15 @@ get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch,
   append_args (argcp, argvp, compile_args_argc, compile_args_argv);
 }
 
-/* A cleanup function to destroy a gdb_gcc_instance.  */
+/* A cleanup function to destroy a compile_instance.  */
 
 static void
 cleanup_compile_instance (void *arg)
 {
-  struct compile_instance *inst = (struct compile_instance *) arg;
+  compile::compile_instance *inst
+    = static_cast<compile::compile_instance *> (arg);
 
-  inst->destroy (inst);
+  delete inst;
 }
 
 /* A cleanup function to unlink a file.  */
@@ -487,16 +488,16 @@ static compile_file_names
 compile_to_object (struct command_line *cmd, const char *cmd_string,
                   enum compile_i_scope_types scope)
 {
-  struct compile_instance *compiler;
+  compile::compile_instance *compiler;
   struct cleanup *cleanup, *inner_cleanup;
   const struct block *expr_block;
   CORE_ADDR trash_pc, expr_pc;
   int argc;
   char **argv;
-  int ok;
+  bool ok;
   FILE *src;
   struct gdbarch *gdbarch = get_current_arch ();
-  char *triplet_rx;
+  char *triplet_rx = NULL;
   char *error_message;
 
   if (!target_has_execution)
@@ -513,10 +514,9 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
   compiler = current_language->la_get_compile_instance ();
   cleanup = make_cleanup (cleanup_compile_instance, compiler);
 
-  compiler->fe->ops->set_print_callback (compiler->fe, print_callback, NULL);
-
-  compiler->scope = scope;
-  compiler->block = expr_block;
+  compiler->set_print_callback (print_callback, NULL);
+  compiler->set_scope (scope);
+  compiler->set_block (expr_block);
 
   /* From the provided expression, build a scope to pass to the
      compiler.  */
@@ -547,16 +547,16 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
   if (compile_debug)
     fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code.c_str ());
 
-  if (compiler->fe->ops->version >= GCC_FE_VERSION_1)
-    compiler->fe->ops->set_verbose (compiler->fe, compile_debug);
+  if (compiler->version () >= GCC_FE_VERSION_1)
+    compiler->set_verbose (compile_debug);
 
   if (compile_gcc[0] != 0)
     {
-      if (compiler->fe->ops->version < GCC_FE_VERSION_1)
+      if (compiler->version () < GCC_FE_VERSION_1)
        error (_("Command 'set compile-gcc' requires GCC version 6 or higher "
                 "(libcc1 interface version 1 or higher)"));
 
-      compiler->fe->ops->set_driver_filename (compiler->fe, compile_gcc);
+      compiler->set_driver_filename (compile_gcc);
     }
   else
     {
@@ -567,19 +567,18 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
       triplet_rx = concat (arch_rx, "(-[^-]*)?-", os_rx, (char *) NULL);
       make_cleanup (xfree, triplet_rx);
 
-      if (compiler->fe->ops->version >= GCC_FE_VERSION_1)
-       compiler->fe->ops->set_triplet_regexp (compiler->fe, triplet_rx);
+      if (compiler->version () >= GCC_FE_VERSION_1)
+       compiler->set_triplet_regexp (triplet_rx);
     }
 
   /* Set compiler command-line arguments.  */
   get_args (compiler, gdbarch, &argc, &argv);
   make_cleanup_freeargv (argv);
 
-  if (compiler->fe->ops->version >= GCC_FE_VERSION_1)
-    error_message = compiler->fe->ops->set_arguments (compiler->fe, argc, argv);
+  if (compiler->version ()>= GCC_FE_VERSION_1)
+    error_message = compiler->set_arguments (argc, argv);
   else
-    error_message = compiler->fe->ops->set_arguments_v0 (compiler->fe, triplet_rx,
-                                                        argc, argv);
+    error_message = compiler->set_arguments (triplet_rx, argc, argv);
   if (error_message != NULL)
     {
       make_cleanup (xfree, error_message);
@@ -612,13 +611,12 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
                        fnames.source_file ());
 
   /* Call the compiler and start the compilation process.  */
-  compiler->fe->ops->set_source_file (compiler->fe, fnames.source_file ());
+  compiler->set_source_file (fnames.source_file ());
 
-  if (compiler->fe->ops->version >= GCC_FE_VERSION_1)
-    ok = compiler->fe->ops->compile (compiler->fe, fnames.object_file ());
+  if (compiler->version () >= GCC_FE_VERSION_1)
+    ok = compiler->compile (fnames.object_file ());
   else
-    ok = compiler->fe->ops->compile_v0 (compiler->fe, fnames.object_file (),
-                                       compile_debug);
+    ok = compiler->compile (fnames.object_file (), compile_debug);
   if (!ok)
     error (_("Compilation failed."));
 
@@ -697,6 +695,140 @@ compile_register_name_demangle (struct gdbarch *gdbarch,
   error (_("Cannot find gdbarch register \"%s\"."), regname);
 }
 
+/* See description in compile-internal.h.  */
+
+void
+compile::compile_instance::insert_type (struct type *type, gcc_type gcc_type)
+{
+  type_map_t::iterator pos = m_type_map.find (type);
+
+  if (pos != m_type_map.end ())
+    {
+      /* The type might have already been inserted in order to handle
+        recursive types.  */
+      if (pos->second != gcc_type)
+       error (_("Unexpected type id from GCC, check you use recent "
+                "enough GCC."));
+    }
+  else
+    m_type_map.insert (std::make_pair (type, gcc_type));
+}
+
+/* See description in compile-internal.h.  */
+
+void
+compile::compile_instance::insert_symbol_error (const struct symbol *sym,
+                                               std::string text)
+{
+  symbol_err_map_t::iterator pos = m_symbol_err_map.find (sym);
+
+  if (pos == m_symbol_err_map.end ())
+    m_symbol_err_map.insert (std::make_pair (sym, text));
+}
+
+/* See description in compile-internal.h.  */
+
+void
+compile::compile_instance::error_symbol_once (const struct symbol *sym)
+{
+  symbol_err_map_t::iterator pos = m_symbol_err_map.find (sym);
+  if (pos == m_symbol_err_map.end () || pos->second.length () == 0)
+    return;
+
+  std::string message (pos->second);
+  pos->second.clear ();
+  ::error (_("%s"), message.c_str ());
+}
+
+/* Forwards to the plug-in.  */
+
+#define FORWARD(OP,...) (m_gcc_fe->ops->OP (m_gcc_fe, ##__VA_ARGS__))
+
+/* Set the plug-in print callback.  */
+
+void
+compile::compile_instance::set_print_callback
+  (void (*print_function) (void *, const char *), void *datum)
+{
+  FORWARD (set_print_callback, print_function, datum);
+}
+
+/* Return the plug-in's front-end version.  */
+
+unsigned int
+compile::compile_instance::version () const
+{
+  return m_gcc_fe->ops->version;
+}
+
+/* Set the plug-in's verbosity level.  */
+
+void
+compile::compile_instance::set_verbose (int level)
+{
+  FORWARD (set_verbose, level);
+}
+
+/* Set the plug-in driver program.  */
+
+void
+compile::compile_instance::set_driver_filename (const char *filename)
+{
+  FORWARD (set_driver_filename, filename);
+}
+
+/* Set the regular expression used to match the configury triplet
+   prefix to the compiler.  */
+
+void
+compile::compile_instance::set_triplet_regexp (const char *regexp)
+{
+  FORWARD (set_triplet_regexp, regexp);
+}
+
+/* Set compilation arguments.  */
+
+char *
+compile::compile_instance::set_arguments (int argc, char **argv)
+{
+  return FORWARD (set_arguments, argc, argv);
+}
+
+/* As above, for protocol version 0.  */
+
+char *
+compile::compile_instance::set_arguments (const char *regexp, int argc, char
+                                         **argv)
+{
+  return FORWARD (set_arguments_v0, regexp, argc, argv);
+}
+
+/* Set the filename of the program to compile.  */
+
+void
+compile::compile_instance::set_source_file (const char *filename)
+{
+  FORWARD (set_source_file, filename);
+}
+
+/* Compile the previously specified source file to FILENAME.  */
+
+bool
+compile::compile_instance::compile (const char *filename)
+{
+  return FORWARD (compile, filename);
+}
+
+/* As above, but for an earlier compile protocol.  */
+
+bool
+compile::compile_instance::compile (const char *filename, int verbose_level)
+{
+  return FORWARD (compile_v0, filename, verbose_level);
+}
+
+#undef FORWARD
+
 extern initialize_file_ftype _initialize_compile;
 
 void
index 2bf677c43e7ef4ed1e7a441b9703921ffd33f6d9..4c4468d52b8d5563acc605d07f0471cc7e68ddca 100644 (file)
@@ -35,7 +35,11 @@ struct value_print_options;
 struct type_print_options;
 struct lang_varobj_ops;
 struct parser_state;
-struct compile_instance;
+
+namespace compile
+{
+  class compile_instance;
+};
 
 #define MAX_FORTRAN_DIMS  7    /* Maximum number of F77 array dims.  */
 
@@ -400,7 +404,7 @@ struct language_defn
        instance is owned by its caller and must be deallocated by
        calling its 'destroy' method.  */
 
-    struct compile_instance *(*la_get_compile_instance) (void);
+    compile::compile_instance *(*la_get_compile_instance) (void);
 
     /* This method must be defined if 'la_get_gcc_context' is defined.
        If 'la_get_gcc_context' is not defined, then this method is
@@ -416,7 +420,7 @@ struct language_defn
        parsed.
        EXPR_PC is the PC at which the expression is being parsed.  */
 
-    std::string (*la_compute_program) (struct compile_instance *inst,
+    std::string (*la_compute_program) (compile::compile_instance *inst,
                                       const char *input,
                                       struct gdbarch *gdbarch,
                                       const struct block *expr_block,