This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: (Doc ping [for news and manual]) -- [PATCH 14/14] the "compile" command


On 16/05/14 16:26, Tom Tromey wrote:
> This final patch adds the new "compile" command and subcommands, and
> all the machinery needed to make it work.
>
> A shared library supplied by gcc is used for all communications with
> gcc.  Types and most aspects of symbols are provided directly by gdb
> to the compiler using this library.
>
> gdb provides some information about the user's code using plain text.
> Macros are emitted this way, and DWARF location expressions (and
> bounds for VLA) are compiled to C code.
>
> This hybrid approach was taken because, on the one hand, it is better
> to provide global declarations and such on demand; but on the other
> hand, for local variables, translating DWARF location expressions to C
> was much simpler than exporting a full compiler API to gdb -- the same
> result, only easier to implement, understand, and debug.
>
> In the ordinary mode, the user's expression is wrapped in a dummy
> function.  After compilation, gdb inserts the resulting object code
> into the inferior, then calls this function.
>
> Access to local variables is provided by noting which registers are
> used by location expressions, and passing a structure of register
> values into the function.  Writes to registers are supported by
> copying out these values after the function returns.
>
> This approach was taken so that we could eventually implement other
> more interesting features based on this same infrastructure; for
> example, we're planning to investigate inferior-side breakpoint
> conditions.
>
> 2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> 	    Tom Tromey  <tromey@redhat.com>
>
> 	* NEWS: Update.
> 	* symtab.h (struct symbol_computed_ops) <generate_c_location>: New
> 	field.
> 	* p-lang.c (pascal_language_defn): Update.
> 	* opencl-lang.c (opencl_language_defn): Update.
> 	* objc-lang.c (objc_language_defn): Update.
> 	* m2-lang.c (m2_language_defn): Update.
> 	* language.h (struct language_defn) <la_get_compile_instance,
> 	la_compute_program>: New fields.
> 	* language.c (unknown_language_defn, auto_language_defn)
> 	(local_language_defn): Update.
> 	* jv-lang.c (java_language_defn): Update.
> 	* go-lang.c (go_language_defn): Update.
> 	* f-lang.c (f_language_defn): Update.
> 	* dwarf2loc.h (dwarf2_compile_property_to_c): Declare.
> 	* dwarf2loc.c (dwarf2_compile_property_to_c)
> 	(locexpr_generate_c_location, loclist_generate_c_location): New
> 	functions.
> 	(dwarf2_locexpr_funcs, dwarf2_loclist_funcs): Update.
> 	* defs.h (enum compile_i_scope_types): New.
> 	(enum command_control_type) <compile_control>: New constant.
> 	(struct command_line) <control_u>: New field.
> 	* d-lang.c (d_language_defn): Update.
> 	* compile/compile.c: New file.
> 	* compile/compile-c-support.c: New file.
> 	* compile/compile-c-symbols.c: New file.
> 	* compile/compile-c-types.c: New file.
> 	* compile/compile.h: New file.
> 	* compile/compile-internal.h: New file.
> 	* compile/compile-loc2c.c: New file.
> 	* compile/compile-object-load.c: New file.
> 	* compile/compile-object-load.h: New file.
> 	* compile/compile-object-run.c: New file.
> 	* compile/compile-object-run.h: New file.
> 	* cli/cli-script.c (multi_line_command_p, print_command_lines)
> 	(execute_control_command, process_next_line)
> 	(recurse_read_control_structure): Handle compile_control.
> 	* c-lang.h (c_get_compile_context, c_compute_program): Declare.
> 	* c-lang.c (c_language_defn, cplus_language_defn)
> 	(asm_language_defn, minimal_language_defn): Update.
> 	* ada-lang.c (ada_language_defn): Update.
> 	* Makefile.in (SUBDIR_GCC_COMPILE_OBS, SUBDIR_GCC_COMPILE_SRCS):
> 	New variables.
> 	(SFILES): Add SUBDIR_GCC_COMPILE_SRCS.
> 	(HFILES_NO_SRCDIR): Add compile.h.
> 	(COMMON_OBS): Add SUBDIR_GCC_COMPILE_OBS.
> 	(INIT_FILES): Add SUBDIR_GCC_COMPILE_SRCS.
> 	(compile.o, compile-c-types.o, compile-c-symbols.o)
> 	(compile-object-load.o, compile-object-run.o, compile-loc2c.o)
> 	(compile-c-support.o): New targets.
>
> 2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
>
> 	* gdb.texinfo (Altering): Update.
> 	(Compiling and Injecting Code): New node.
>
> 2014-05-16  Phil Muldoon  <pmuldoon@redhat.com>
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> 	    Tom Tromey  <tromey@redhat.com>
>
> 	* gdb.dwarf2/compile-ops.exp: New file.
> 	* gdb.threads/compile-tls.c: New file.
> 	* gdb.threads/compile-tls.exp: New file.
> 	* gdb.base/compile-constvar.S: New file.
> 	* gdb.base/compile-constvar.c: New file.
> 	* gdb.base/compile-mod.c: New file.
> 	* gdb.base/compile-nodebug.c: New file.
> 	* gdb.base/compile-setjmp-mod.c: New file.
> 	* gdb.base/compile-setjmp.c: New file.
> 	* gdb.base/compile-setjmp.exp: New file.
> 	* gdb.base/compile-shlib.c: New file.
> 	* gdb.base/compile.c: New file.
> 	* gdb.base/compile.exp: New file.
> 	* lib/gdb.exp (skip_compile_feature_tests): New proc.
> ---
>  gdb/ChangeLog                               |   55 ++
>  gdb/Makefile.in                             |   61 +-
>  gdb/NEWS                                    |   32 +
>  gdb/ada-lang.c                              |    2 +
>  gdb/c-lang.c                                |    8 +
>  gdb/c-lang.h                                |   19 +
>  gdb/cli/cli-script.c                        |   31 +-
>  gdb/compile/compile-c-support.c             |  396 +++++++++
>  gdb/compile/compile-c-symbols.c             |  759 ++++++++++++++++++
>  gdb/compile/compile-c-types.c               |  438 ++++++++++
>  gdb/compile/compile-internal.h              |  147 ++++
>  gdb/compile/compile-loc2c.c                 | 1147 +++++++++++++++++++++++++++
>  gdb/compile/compile-object-load.c           |  570 +++++++++++++
>  gdb/compile/compile-object-load.h           |   39 +
>  gdb/compile/compile-object-run.c            |  138 ++++
>  gdb/compile/compile-object-run.h            |   24 +
>  gdb/compile/compile.c                       |  623 +++++++++++++++
>  gdb/compile/compile.h                       |  102 +++
>  gdb/d-lang.c                                |    2 +
>  gdb/defs.h                                  |   28 +
>  gdb/doc/ChangeLog                           |    5 +
>  gdb/doc/gdb.texinfo                         |  242 ++++++
>  gdb/dwarf2loc.c                             |   86 +-
>  gdb/dwarf2loc.h                             |   21 +
>  gdb/f-lang.c                                |    2 +
>  gdb/go-lang.c                               |    2 +
>  gdb/jv-lang.c                               |    2 +
>  gdb/language.c                              |    6 +
>  gdb/language.h                              |   31 +
>  gdb/m2-lang.c                               |    2 +
>  gdb/objc-lang.c                             |    2 +
>  gdb/opencl-lang.c                           |    2 +
>  gdb/p-lang.c                                |    2 +
>  gdb/symtab.h                                |   15 +
>  gdb/testsuite/ChangeLog                     |   19 +
>  gdb/testsuite/gdb.base/compile-constvar.S   |   95 +++
>  gdb/testsuite/gdb.base/compile-constvar.c   |   18 +
>  gdb/testsuite/gdb.base/compile-mod.c        |   26 +
>  gdb/testsuite/gdb.base/compile-nodebug.c    |   24 +
>  gdb/testsuite/gdb.base/compile-setjmp-mod.c |   46 ++
>  gdb/testsuite/gdb.base/compile-setjmp.c     |   24 +
>  gdb/testsuite/gdb.base/compile-setjmp.exp   |   34 +
>  gdb/testsuite/gdb.base/compile-shlib.c      |   26 +
>  gdb/testsuite/gdb.base/compile.c            |  130 +++
>  gdb/testsuite/gdb.base/compile.exp          |  357 +++++++++
>  gdb/testsuite/gdb.dwarf2/compile-ops.exp    |  424 ++++++++++
>  gdb/testsuite/gdb.threads/compile-tls.c     |   40 +
>  gdb/testsuite/gdb.threads/compile-tls.exp   |   42 +
>  gdb/testsuite/lib/gdb.exp                   |   17 +
>  49 files changed, 6356 insertions(+), 7 deletions(-)
>  create mode 100644 gdb/compile/compile-c-support.c
>  create mode 100644 gdb/compile/compile-c-symbols.c
>  create mode 100644 gdb/compile/compile-c-types.c
>  create mode 100644 gdb/compile/compile-internal.h
>  create mode 100644 gdb/compile/compile-loc2c.c
>  create mode 100644 gdb/compile/compile-object-load.c
>  create mode 100644 gdb/compile/compile-object-load.h
>  create mode 100644 gdb/compile/compile-object-run.c
>  create mode 100644 gdb/compile/compile-object-run.h
>  create mode 100644 gdb/compile/compile.c
>  create mode 100644 gdb/compile/compile.h
>  create mode 100644 gdb/testsuite/gdb.base/compile-constvar.S
>  create mode 100644 gdb/testsuite/gdb.base/compile-constvar.c
>  create mode 100644 gdb/testsuite/gdb.base/compile-mod.c
>  create mode 100644 gdb/testsuite/gdb.base/compile-nodebug.c
>  create mode 100644 gdb/testsuite/gdb.base/compile-setjmp-mod.c
>  create mode 100644 gdb/testsuite/gdb.base/compile-setjmp.c
>  create mode 100644 gdb/testsuite/gdb.base/compile-setjmp.exp
>  create mode 100644 gdb/testsuite/gdb.base/compile-shlib.c
>  create mode 100644 gdb/testsuite/gdb.base/compile.c
>  create mode 100644 gdb/testsuite/gdb.base/compile.exp
>  create mode 100644 gdb/testsuite/gdb.dwarf2/compile-ops.exp
>  create mode 100644 gdb/testsuite/gdb.threads/compile-tls.c
>  create mode 100644 gdb/testsuite/gdb.threads/compile-tls.exp
>
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index 3efedc8..30cee39 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -280,6 +280,24 @@ SUBDIR_TUI_LDFLAGS=
>  SUBDIR_TUI_CFLAGS= \
>  	-DTUI=1
>  
> +#
> +# GCC Compile support sub-directory definitions
> +#
> +SUBDIR_GCC_COMPILE_OBS = \
> +	compile.o compile-c-symbols.o compile-c-types.o \
> +	compile-object-load.o compile-object-run.o \
> +	compile-loc2c.o compile-c-support.o
> +SUBDIR_GCC_COMPILE_SRCS = \
> +	compile/compile.c \
> +	compile/compile-c-symbols.c \
> +	compile/compile-c-types.c \
> +	compile/compile-object-load.c \
> +	compile/compile-object-load.h \
> +	compile/compile-object-run.c \
> +	compile/compile-object-run.h \
> +	compile/compile-loc2c.c \
> +	compile/compile-c-support.c
> +
>  # Guile sub directory definitons for guile support.
>  
>  SUBDIR_GUILE_OBS = \
> @@ -840,7 +858,8 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
>  	common/gdb_vecs.c common/common-utils.c common/xml-utils.c \
>  	common/ptid.c common/buffer.c gdb-dlfcn.c common/agent.c \
>  	common/format.c common/filestuff.c btrace.c record-btrace.c ctf.c \
> -	target/waitstatus.c common/print-utils.c common/rsp-low.c
> +	target/waitstatus.c common/print-utils.c common/rsp-low.c \
> +	$(SUBDIR_GCC_COMPILE_SRCS)
>  
>  LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
>  
> @@ -861,7 +880,7 @@ ia64-tdep.h ada-lang.h varobj.h frv-tdep.h nto-tdep.h serial.h \
>  c-lang.h d-lang.h go-lang.h frame.h event-loop.h block.h cli/cli-setshow.h \
>  cli/cli-decode.h cli/cli-cmds.h cli/cli-utils.h \
>  cli/cli-script.h macrotab.h symtab.h common/version.h \
> -gnulib/import/string.in.h gnulib/import/str-two-way.h \
> +compile/compile.h gnulib/import/string.in.h gnulib/import/str-two-way.h \
>  gnulib/import/stdint.in.h remote.h remote-notif.h gdb.h sparc-nat.h \
>  gdbthread.h dwarf2-frame.h dwarf2-frame-tailcall.h nbsd-nat.h dcache.h \
>  amd64-nat.h s390-linux-tdep.h arm-linux-tdep.h exceptions.h macroscope.h \
> @@ -1022,7 +1041,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
>  	gdb_vecs.o jit.o progspace.o skip.o probe.o \
>  	common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o \
>  	format.o registry.o btrace.o record-btrace.o waitstatus.o \
> -	print-utils.o rsp-low.o
> +	print-utils.o rsp-low.o \
> +	$(SUBDIR_GCC_COMPILE_OBS)
>  
>  TSOBS = inflow.o
>  
> @@ -1257,7 +1277,7 @@ test-cp-name-parser$(EXEEXT): test-cp-name-parser.o $(LIBIBERTY)
>  # duplicates.  Files in the gdb/ directory can end up appearing in
>  # COMMON_OBS (as a .o file) and CONFIG_SRCS (as a .c file).
>  
> -INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS)
> +INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS) $(SUBDIR_GCC_COMPILE_SRCS)
>  init.c: $(INIT_FILES)
>  	@echo Making init.c
>  	@rm -f init.c-tmp init.l-tmp
> @@ -1890,6 +1910,39 @@ cli-utils.o: $(srcdir)/cli/cli-utils.c
>  	$(COMPILE) $(srcdir)/cli/cli-utils.c
>  	$(POSTCOMPILE)
>  
> +# GCC Compile support dependencies
> +#
> +# Need to explicitly specify the compile rule as make will do nothing
> +# or try to compile the object file into the sub-directory.
> +
> +compile.o: $(srcdir)/compile/compile.c
> +	$(COMPILE) $(srcdir)/compile/compile.c
> +	$(POSTCOMPILE)
> +
> +compile-c-types.o: $(srcdir)/compile/compile-c-types.c
> +	$(COMPILE) $(srcdir)/compile/compile-c-types.c
> +	$(POSTCOMPILE)
> +
> +compile-c-symbols.o: $(srcdir)/compile/compile-c-symbols.c
> +	$(COMPILE) $(srcdir)/compile/compile-c-symbols.c
> +	$(POSTCOMPILE)
> +
> +compile-object-load.o: $(srcdir)/compile/compile-object-load.c
> +	$(COMPILE) $(srcdir)/compile/compile-object-load.c
> +	$(POSTCOMPILE)
> +
> +compile-object-run.o: $(srcdir)/compile/compile-object-run.c
> +	$(COMPILE) $(srcdir)/compile/compile-object-run.c
> +	$(POSTCOMPILE)
> +
> +compile-loc2c.o: $(srcdir)/compile/compile-loc2c.c
> +	$(COMPILE) $(srcdir)/compile/compile-loc2c.c
> +	$(POSTCOMPILE)
> +
> +compile-c-support.o: $(srcdir)/compile/compile-c-support.c
> +	$(COMPILE) $(srcdir)/compile/compile-c-support.c
> +	$(POSTCOMPILE)
> +
>  
>  #
>  # GDBTK sub-directory
> diff --git a/gdb/NEWS b/gdb/NEWS
> index d0c44ea..6829f5b 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -3,6 +3,16 @@
>  
>  *** Changes since GDB 7.7
>  
> +* GDB now supports the compilation and injection of source code into
> +  the inferior.  GDB will use a feature-capable compiler to compile
> +  the source code to object code, and if successful, inject and
> +  execute that code within the current context of the inferior.
> +  Currently the "C" language is supported.  The commands used to
> +  interface with this new feature are:
> +
> +     compile code [-raw|-r] [--] [source code]
> +     compile file [-raw|-r] filename
> +
>  * GDB supports printing and modifying of variable length automatic arrays
>    as specified in ISO C99.
>  
> @@ -26,6 +36,28 @@ guile-repl
>  gr
>    Start a Guile interactive prompt (or "repl" for "read-eval-print loop").
>  
> +compile code [-r|-raw] [--] [source code]
> +  Compile and inject into the inferior the executable object code
> +  produced by compiling the provided source code.  This resulting
> +  object code will be executed within the current context of the
> +  inferior, allowing access to variables, types and other elements
> +  that are currently within scope.  The -raw option will prevent GDB
> +  automatically wrapping the source code into a callable scope (this
> +  will have to be provided in the source code, and is considered
> +  expert level usage).  The "--" option indicates that all text to the
> +  right of the "--" is to be considered as source code, and will not
> +  be considered for option parsing.
> +
> +compile file [-r|-raw] filename
> +  Compile and inject into the inferior the executable object code
> +  produced by compiling the source code stored in the filename
> +  provided.  This resulting object code will be executed within the
> +  current context of the inferior, allowing access to variables, types
> +  and other elements that are currently within scope.  The -raw option
> +  will prevent GDB automatically wrapping the source code into a
> +  callable scope (this will have to be provided in the source code,
> +  and is considered expert level usage).
> +
>  info auto-load guile-scripts [regexp]
>    Print the list of automatically loaded Guile scripts.
>  
> diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
> index 38972c6..95fe14f 100644
> --- a/gdb/ada-lang.c
> +++ b/gdb/ada-lang.c
> @@ -13521,6 +13521,8 @@ const struct language_defn ada_language_defn = {
>    ada_get_symbol_name_cmp,	/* la_get_symbol_name_cmp */
>    ada_iterate_over_symbols,
>    &ada_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> diff --git a/gdb/c-lang.c b/gdb/c-lang.c
> index 765a6b0..078b170 100644
> --- a/gdb/c-lang.c
> +++ b/gdb/c-lang.c
> @@ -868,6 +868,8 @@ const struct language_defn c_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &c_varobj_ops,
> +  c_get_compile_context,
> +  c_compute_program,
>    LANG_MAGIC
>  };
>  
> @@ -993,6 +995,8 @@ const struct language_defn cplus_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &cplus_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> @@ -1036,6 +1040,8 @@ const struct language_defn asm_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &default_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> @@ -1084,6 +1090,8 @@ const struct language_defn minimal_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &default_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> diff --git a/gdb/c-lang.h b/gdb/c-lang.h
> index 76bd426..5a2f878 100644
> --- a/gdb/c-lang.h
> +++ b/gdb/c-lang.h
> @@ -141,5 +141,24 @@ extern int cp_is_vtbl_member (struct type *);
>  
>  extern int c_textual_element_type (struct type *, char);
>  
> +/* Create a new instance of the C compiler and return it.  The new
> +   compiler is owned by the caller and must be freed using the destroy
> +   method.  This function never returns NULL, but rather throws an
> +   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);
> +
> +/* This takes the user-supplied text and returns a newly malloc'd bit
> +   of code to compile.
> +
> +   This is used as the la_compute_program language method; see that
> +   for a description of the arguments.  */
> +
> +extern char *c_compute_program (struct compile_instance *inst,
> +				const char *input,
> +				struct gdbarch *gdbarch,
> +				const struct block *expr_block,
> +				CORE_ADDR expr_pc);
>  
>  #endif /* !defined (C_LANG_H) */
> diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
> index 7dc1ba4..5e473b2 100644
> --- a/gdb/cli/cli-script.c
> +++ b/gdb/cli/cli-script.c
> @@ -34,6 +34,7 @@
>  
>  #include "extension.h"
>  #include "interps.h"
> +#include "compile/compile.h"
>  
>  /* Prototypes for local functions.  */
>  
> @@ -90,6 +91,7 @@ multi_line_command_p (enum command_control_type type)
>      case while_control:
>      case while_stepping_control:
>      case commands_control:
> +    case compile_control:
>      case python_control:
>      case guile_control:
>        return 1;
> @@ -275,6 +277,19 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd,
>  	  continue;
>  	}
>  
> +      if (list->control_type == compile_control)
> +	{
> +	  ui_out_field_string (uiout, NULL, "compile expression");
> +	  ui_out_text (uiout, "\n");
> +	  print_command_lines (uiout, *list->body_list, 0);
> +	  if (depth)
> +	    ui_out_spaces (uiout, 2 * depth);
> +	  ui_out_field_string (uiout, NULL, "end");
> +	  ui_out_text (uiout, "\n");
> +	  list = list->next;
> +	  continue;
> +	}
> +
>        if (list->control_type == guile_control)
>  	{
>  	  ui_out_field_string (uiout, NULL, "guile");
> @@ -602,6 +617,11 @@ execute_control_command (struct command_line *cmd)
>  	break;
>        }
>  
> +    case compile_control:
> +      eval_compile_command (cmd, NULL, cmd->control_u.compile.scope);
> +      ret = simple_control;
> +      break;
> +
>      case python_control:
>      case guile_control:
>        {
> @@ -1043,6 +1063,14 @@ process_next_line (char *p, struct command_line **command, int parse_commands,
>  	     here.  */
>  	  *command = build_command_line (python_control, "");
>  	}
> +      else if (p_end - p == 6 && !strncmp (p, "compile", 7))
> +	{
> +	  /* Note that we ignore the inline "compile command" form
> +	     here.  */
> +	  *command = build_command_line (compile_control, "");
> +	  (*command)->control_u.compile.scope = COMPILE_I_INVALID_SCOPE;
> +	}
> +
>        else if (p_end - p == 5 && !strncmp (p, "guile", 5))
>  	{
>  	  /* Note that we ignore the inline "guile command" form here.  */
> @@ -1136,7 +1164,8 @@ recurse_read_control_structure (char * (*read_next_line_func) (void),
>        next = NULL;
>        val = process_next_line (read_next_line_func (), &next, 
>  			       current_cmd->control_type != python_control
> -			       && current_cmd->control_type != guile_control,
> +			       && current_cmd->control_type != guile_control
> +			       && current_cmd->control_type != compile_control,
>  			       validator, closure);
>  
>        /* Just skip blanks and comments.  */
> diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
> new file mode 100644
> index 0000000..f0fa999
> --- /dev/null
> +++ b/gdb/compile/compile-c-support.c
> @@ -0,0 +1,396 @@
> +/* C language support for compilation.
> +
> +   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/>.  */
> +
> +#include "defs.h"
> +#include "compile-internal.h"
> +#include "compile.h"
> +#include "gdb-dlfcn.h"
> +#include "c-lang.h"
> +#include "macrotab.h"
> +#include "macroscope.h"
> +#include "regcache.h"
> +
> +/* See compile-internal.h.  */
> +
> +const char *
> +c_get_mode_for_size (int size)
> +{
> +  const char *mode = NULL;
> +
> +  switch (size)
> +    {
> +    case 1:
> +      mode = "QI";
> +      break;
> +    case 2:
> +      mode = "HI";
> +      break;
> +    case 4:
> +      mode = "SI";
> +      break;
> +    case 8:
> +      mode = "DI";
> +      break;
> +    }
> +
> +  return mode;
> +}
> +
> +/* See compile-internal.h.  */
> +
> +char *
> +c_get_range_decl_name (const struct dynamic_prop *prop)
> +{
> +  return xstrprintf ("__gdb_prop_%s", host_address_to_string (prop));
> +}
> +
> +
> +
> +#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.  */
> +
> +static gcc_c_fe_context_function *
> +load_libcc (void)
> +{
> +  void *handle;
> +  gcc_c_fe_context_function *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));
> +
> +  if (func == NULL)
> +    error (_("could not find symbol %s in library %s"),
> +	   STRINGIFY (GCC_C_FE_CONTEXT),
> +	   STRINGIFY (GCC_C_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)
> +{
> +  static gcc_c_fe_context_function *func;
> +
> +  struct gcc_c_context *context;
> +
> +  if (func == NULL)
> +    {
> +      func = load_libcc ();
> +      gdb_assert (func != NULL);
> +    }
> +
> +  context = (*func) (GCC_FE_VERSION_0, GCC_C_FE_VERSION_0);
> +  if (context == NULL)
> +    error (_("The loaded version of GCC does not support the required version "
> +	     "of the API."));
> +
> +  return new_compile_instance (context);
> +}
> +
> +
> +
> +/* Write one macro definition.  */
> +
> +static void
> +print_one_macro (const char *name, const struct macro_definition *macro,
> +		 struct macro_source_file *source, int line,
> +		 void *user_data)
> +{
> +  struct ui_file *file = user_data;
> +
> +  /* Don't print command-line defines.  They will be supplied another
> +     way.  */
> +  if (line == 0)
> +    return;
> +
> +  fprintf_filtered (file, "#define %s", name);
> +
> +  if (macro->kind == macro_function_like)
> +    {
> +      int i;
> +
> +      fputs_filtered ("(", file);
> +      for (i = 0; i < macro->argc; i++)
> +	{
> +	  fputs_filtered (macro->argv[i], file);
> +	  if (i + 1 < macro->argc)
> +	    fputs_filtered (", ", file);
> +	}
> +      fputs_filtered (")", file);
> +    }
> +
> +  fprintf_filtered (file, " %s\n", macro->replacement);
> +}
> +
> +/* Write macro definitions at PC to FILE.  */
> +
> +static void
> +write_macro_definitions (const struct block *block, CORE_ADDR pc,
> +			 struct ui_file *file)
> +{
> +  struct macro_scope *scope;
> +
> +  if (block != NULL)
> +    scope = sal_macro_scope (find_pc_line (pc, 0));
> +  else
> +    scope = default_macro_scope ();
> +  if (scope == NULL)
> +    scope = user_macro_scope ();
> +
> +  if (scope != NULL && scope->file != NULL && scope->file->table != NULL)
> +    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_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:
> +      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.  */
> +
> +static void
> +generate_register_struct (struct ui_file *stream, struct gdbarch *gdbarch,
> +			  const unsigned char *registers_used)
> +{
> +  int i;
> +  int seen = 0;
> +
> +  fputs_unfiltered ("struct " COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG " {\n",
> +		    stream);
> +
> +  if (registers_used != NULL)
> +    for (i = 0; i < gdbarch_num_regs (gdbarch); ++i)
> +      {
> +	if (registers_used[i])
> +	  {
> +	    struct type *regtype = check_typedef (register_type (gdbarch, i));
> +	    char *regname = compile_register_name_mangled (gdbarch, i);
> +	    struct cleanup *cleanups = make_cleanup (xfree, regname);
> +
> +	    seen = 1;
> +
> +	    /* You might think we could use type_print here.  However,
> +	       target descriptions often use types with names like
> +	       "int64_t", which may not be defined in the inferior
> +	       (and in any case would not be looked up due to the
> +	       #pragma business).  So, we take a much simpler
> +	       approach: for pointer- or integer-typed registers, emit
> +	       the field in the most direct way; and for other
> +	       register types (typically flags or vectors), emit a
> +	       maximally-aligned array of the correct size.  */
> +
> +	    fputs_unfiltered ("  ", stream);
> +	    switch (TYPE_CODE (regtype))
> +	      {
> +	      case TYPE_CODE_PTR:
> +		fprintf_filtered (stream, "void *%s", regname);
> +		break;
> +
> +	      case TYPE_CODE_INT:
> +		{
> +		  const char *mode
> +		    = c_get_mode_for_size (TYPE_LENGTH (regtype));
> +
> +		  if (mode != NULL)
> +		    {
> +		      if (TYPE_UNSIGNED (regtype))
> +			fputs_unfiltered ("unsigned ", stream);
> +		      fprintf_unfiltered (stream,
> +					  "int %s"
> +					  " __attribute__ ((__mode__(__%s__)))",
> +					  regname,
> +					  mode);
> +		      break;
> +		    }
> +		}
> +
> +		/* Fall through.  */
> +
> +	      default:
> +		fprintf_unfiltered (stream,
> +				    "  unsigned char %s[%d]"
> +				    " __attribute__((__aligned__("
> +				    "__BIGGEST_ALIGNMENT__)))",
> +				    regname,
> +				    TYPE_LENGTH (regtype));
> +	      }
> +	    fputs_unfiltered (";\n", stream);
> +
> +	    do_cleanups (cleanups);
> +	  }
> +      }
> +
> +  if (!seen)
> +    fputs_unfiltered ("  char " COMPILE_I_SIMPLE_REGISTER_DUMMY ";\n",
> +		      stream);
> +
> +  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.  */
> +
> +char *
> +c_compute_program (struct compile_instance *inst,
> +		   const char *input,
> +		   struct gdbarch *gdbarch,
> +		   const struct block *expr_block,
> +		   CORE_ADDR expr_pc)
> +{
> +  struct ui_file *buf, *var_stream = NULL;
> +  char *code;
> +  struct cleanup *cleanup;
> +  struct compile_c_instance *context = (struct compile_c_instance *) inst;
> +
> +  buf = mem_fileopen ();
> +  cleanup = make_cleanup_ui_file_delete (buf);
> +
> +  write_macro_definitions (expr_block, expr_pc, 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;
> +
> +      /* 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.  */
> +      var_stream = mem_fileopen ();
> +      make_cleanup_ui_file_delete (var_stream);
> +      registers_used = generate_c_for_variable_locations (context,
> +							  var_stream, gdbarch,
> +							  expr_block, expr_pc);
> +      make_cleanup (xfree, registers_used);
> +
> +      generate_register_struct (buf, gdbarch, registers_used);
> +
> +      fputs_unfiltered ("typedef unsigned int"
> +			" __attribute__ ((__mode__(__pointer__)))"
> +			" __gdb_uintptr;\n",
> +			buf);
> +      fputs_unfiltered ("typedef int"
> +			" __attribute__ ((__mode__(__pointer__)))"
> +			" __gdb_intptr;\n",
> +			buf);
> +
> +      for (i = 0; i < 4; ++i)
> +	{
> +	  const char *mode = c_get_mode_for_size (1 << i);
> +
> +	  gdb_assert (mode != NULL);
> +	  fprintf_unfiltered (buf,
> +			      "typedef int"
> +			      " __attribute__ ((__mode__(__%s__)))"
> +			      " __gdb_int_%s;\n",
> +			      mode, mode);
> +	}
> +    }
> +
> +  add_code_header (inst->scope, buf);
> +
> +  if (inst->scope == COMPILE_I_SIMPLE_SCOPE)
> +    {
> +      ui_file_put (var_stream, ui_file_write_for_put, buf);
> +      fputs_unfiltered ("#pragma GCC user_expression\n", 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 (inst->scope != COMPILE_I_RAW_SCOPE)
> +    fputs_unfiltered ("{\n", buf);
> +
> +  fputs_unfiltered ("#line 1 \"gdb command line\"\n", buf);
> +  fputs_unfiltered (input, buf);
> +  fputs_unfiltered ("\n", buf);
> +
> +  /* For larger user expressions the automatic semicolons may be
> +     confusing.  */
> +  if (strchr (input, '\n') == NULL)
> +    fputs_unfiltered (";\n", buf);
> +
> +  if (inst->scope != COMPILE_I_RAW_SCOPE)
> +    fputs_unfiltered ("}\n", buf);
> +
> +  add_code_footer (inst->scope, buf);
> +  code = ui_file_xstrdup (buf, NULL);
> +  do_cleanups (cleanup);
> +  return code;
> +}
> diff --git a/gdb/compile/compile-c-symbols.c b/gdb/compile/compile-c-symbols.c
> new file mode 100644
> index 0000000..a9e381f
> --- /dev/null
> +++ b/gdb/compile/compile-c-symbols.c
> @@ -0,0 +1,759 @@
> +/* Convert symbols from GDB to GCC
> +
> +   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/>.  */
> +
> +
> +#include "defs.h"
> +#include "compile-internal.h"
> +#include "gdb_assert.h"
> +#include "symtab.h"
> +#include "parser-defs.h"
> +#include "block.h"
> +#include "objfiles.h"
> +#include "compile.h"
> +#include "value.h"
> +#include "exceptions.h"
> +#include "gdbtypes.h"
> +#include "dwarf2loc.h"
> +
> +
> +
> +/* Object of this type are stored in the compiler's symbol_err_map.  */
> +
> +struct symbol_error
> +{
> +  /* The symbol.  */
> +
> +  const struct symbol *sym;
> +
> +  /* The error message to emit.  This is malloc'd and owned by the
> +     hash table.  */
> +
> +  char *message;
> +};
> +
> +/* Hash function for struct symbol_error.  */
> +
> +static hashval_t
> +hash_symbol_error (const void *a)
> +{
> +  const struct symbol_error *se = 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 = a;
> +  const struct symbol_error *seb = b;
> +
> +  return sea->sym == seb->sym;
> +}
> +
> +/* Deletion function for struct symbol_error.  */
> +
> +static void
> +del_symbol_error (void *a)
> +{
> +  struct symbol_error *se = 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 = 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);
> +}
> +
> +
> +
> +/* Compute the name of the pointer representing a local symbol's
> +   address.  */
> +
> +static char *
> +symbol_substitution_name (struct symbol *sym)
> +{
> +  return concat ("__", SYMBOL_NATURAL_NAME (sym), "_ptr", (char *) NULL);
> +}
> +
> +/* Convert a given symbol, SYM, to the compiler's representation.
> +   CONTEXT is the compiler instance.  IS_GLOBAL is true if the
> +   symbol came from the global scope.  IS_LOCAL is true if the symbol
> +   came from a local scope.  (Note that the two are not strictly
> +   inverses because the symbol might have come from the static
> +   scope.)  */
> +
> +static void
> +convert_one_symbol (struct compile_c_instance *context,
> +		    struct symbol *sym,
> +		    int is_global,
> +		    int is_local)
> +{
> +  gcc_type sym_type;
> +  const char *filename = SYMBOL_SYMTAB (sym)->filename;
> +  unsigned short line = SYMBOL_LINE (sym);
> +
> +  error_symbol_once (context, sym);
> +
> +  if (SYMBOL_CLASS (sym) == LOC_LABEL)
> +    sym_type = 0;
> +  else
> +    sym_type = convert_type (context, SYMBOL_TYPE (sym));
> +
> +  if (SYMBOL_DOMAIN (sym) == 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),
> +				       sym_type, filename, line);
> +    }
> +  else
> +    {
> +      gcc_decl decl;
> +      enum gcc_c_symbol_kind kind;
> +      CORE_ADDR addr = 0;
> +      char *symbol_name = NULL;
> +
> +      switch (SYMBOL_CLASS (sym))
> +	{
> +	case LOC_TYPEDEF:
> +	  kind = GCC_C_SYMBOL_TYPEDEF;
> +	  break;
> +
> +	case LOC_LABEL:
> +	  kind = GCC_C_SYMBOL_LABEL;
> +	  addr = SYMBOL_VALUE_ADDRESS (sym);
> +	  break;
> +
> +	case LOC_BLOCK:
> +	  kind = GCC_C_SYMBOL_FUNCTION;
> +	  addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
> +	  break;
> +
> +	case LOC_CONST:
> +	  if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM)
> +	    {
> +	      /* Already handled by convert_enum.  */
> +	      return;
> +	    }
> +	  C_CTX (context)->c_ops->build_constant (C_CTX (context), sym_type,
> +						  SYMBOL_NATURAL_NAME (sym),
> +						  SYMBOL_VALUE (sym),
> +						  filename, line);
> +	  return;
> +
> +	case LOC_CONST_BYTES:
> +	  error (_("Unsupported LOC_CONST_BYTES for symbol \"%s\"."),
> +		 SYMBOL_PRINT_NAME (sym));
> +
> +	case LOC_UNDEF:
> +	  internal_error (__FILE__, __LINE__, _("LOC_UNDEF found for \"%s\"."),
> +			  SYMBOL_PRINT_NAME (sym));
> +
> +	case LOC_COMMON_BLOCK:
> +	  error (_("Fortran common block is unsupported for compilation "
> +		   "evaluaton of symbol \"%s\"."),
> +		 SYMBOL_PRINT_NAME (sym));
> +
> +	case LOC_OPTIMIZED_OUT:
> +	  error (_("Symbol \"%s\" cannot be used for compilation evaluation "
> +		   "as it is optimized out."),
> +		 SYMBOL_PRINT_NAME (sym));
> +
> +	case LOC_COMPUTED:
> +	  if (is_local)
> +	    goto substitution;
> +	  /* Probably TLS here.  */
> +	  warning (_("Symbol \"%s\" is thread-local and currently can only "
> +		     "be referenced from the current thread in "
> +		     "compiled code."),
> +		   SYMBOL_PRINT_NAME (sym));
> +	  /* FALLTHROUGH */
> +	case LOC_UNRESOLVED:
> +	  /* 'symbol_name' cannot be used here as that one is used only for
> +	     local variables from compile_dwarf_expr_to_c.
> +	     Global variables can be accessed by GCC only by their address, not
> +	     by their name.  */
> +	  {
> +	    struct value *val;
> +	    struct frame_info *frame = NULL;
> +
> +	    if (symbol_read_needs_frame (sym))
> +	      {
> +		frame = get_selected_frame (NULL);
> +		if (frame == NULL)
> +		  error (_("Symbol \"%s\" cannot be used because "
> +			   "there is no selected frame"),
> +			 SYMBOL_PRINT_NAME (sym));
> +	      }
> +
> +	    val = read_var_value (sym, frame);
> +	    if (VALUE_LVAL (val) != lval_memory)
> +	      error (_("Symbol \"%s\" cannot be used for compilation "
> +		       "evaluation as its address has not been found."),
> +		     SYMBOL_PRINT_NAME (sym));
> +
> +	    kind = GCC_C_SYMBOL_VARIABLE;
> +	    addr = value_address (val);
> +	  }
> +	  break;
> +
> +
> +	case LOC_REGISTER:
> +	case LOC_ARG:
> +	case LOC_REF_ARG:
> +	case LOC_REGPARM_ADDR:
> +	case LOC_LOCAL:
> +	substitution:
> +	  kind = GCC_C_SYMBOL_VARIABLE;
> +	  symbol_name = symbol_substitution_name (sym);
> +	  break;
> +
> +	case LOC_STATIC:
> +	  kind = GCC_C_SYMBOL_VARIABLE;
> +	  addr = SYMBOL_VALUE_ADDRESS (sym);
> +	  break;
> +
> +	case LOC_FINAL_VALUE:
> +	default:
> +	  gdb_assert_not_reached ("Unreachable case in convert_one_symbol.");
> +
> +	}
> +
> +      /* Don't emit local variable decls for a raw expression.  */
> +      if (context->base.scope != COMPILE_I_RAW_SCOPE
> +	  || symbol_name == NULL)
> +	{
> +	  decl = C_CTX (context)->c_ops->build_decl (C_CTX (context),
> +						     SYMBOL_NATURAL_NAME (sym),
> +						     kind,
> +						     sym_type,
> +						     symbol_name, addr,
> +						     filename, line);
> +
> +	  C_CTX (context)->c_ops->bind (C_CTX (context), decl, is_global);
> +	}
> +
> +      xfree (symbol_name);
> +    }
> +}
> +
> +/* Convert a full symbol to its gcc form.  CONTEXT is the compiler to
> +   use, IDENTIFIER is the name of the symbol, SYM is the symbol
> +   itself, and DOMAIN is the domain which was searched.  */
> +
> +static void
> +convert_symbol_sym (struct compile_c_instance *context, const char *identifier,
> +		    struct symbol *sym, domain_enum domain)
> +{
> +  const struct block *static_block, *found_block;
> +  int is_local_symbol;
> +
> +  found_block = block_found;
> +
> +  /* If we found a symbol and it is not in the  static or global
> +     scope, then we should first convert any static or global scope
> +     symbol of the same name.  This lets this unusual case work:
> +
> +     int x; // Global.
> +     int func(void)
> +     {
> +     int x;
> +     // At this spot, evaluate "extern int x; x"
> +     }
> +  */
> +
> +  static_block = block_static_block (found_block);
> +  /* STATIC_BLOCK is NULL if FOUND_BLOCK is the global block.  */
> +  is_local_symbol = (found_block != static_block && static_block != NULL);
> +  if (is_local_symbol)
> +    {
> +      struct symbol *global_sym;
> +
> +      global_sym = lookup_symbol (identifier, NULL, domain, NULL);
> +      /* If the outer symbol is in the static block, we ignore it, as
> +	 it cannot be referenced.  */
> +      if (global_sym != NULL
> +	  && block_found != block_static_block (block_found))
> +	{
> +	  if (compile_debug)
> +	    fprintf_unfiltered (gdb_stdout,
> +				"gcc_convert_symbol \"%s\": global symbol\n",
> +				identifier);
> +	  convert_one_symbol (context, global_sym, 1, 0);
> +	}
> +    }
> +
> +  if (compile_debug)
> +    fprintf_unfiltered (gdb_stdout,
> +			"gcc_convert_symbol \"%s\": local symbol\n",
> +			identifier);
> +  convert_one_symbol (context, sym, 0, is_local_symbol);
> +}
> +
> +/* Convert a minimal symbol to its gcc form.  CONTEXT is the compiler
> +   to use and BMSYM is the minimal symbol to convert.  */
> +
> +static void
> +convert_symbol_bmsym (struct compile_c_instance *context,
> +		      struct bound_minimal_symbol bmsym)
> +{
> +  struct minimal_symbol *msym = bmsym.minsym;
> +  struct objfile *objfile = bmsym.objfile;
> +  struct type *type;
> +  enum gcc_c_symbol_kind kind;
> +  gcc_type sym_type;
> +  gcc_decl decl;
> +  CORE_ADDR addr;
> +
> +  /* Conversion copied from write_exp_msymbol.  */
> +  switch (MSYMBOL_TYPE (msym))
> +    {
> +    case mst_text:
> +    case mst_file_text:
> +    case mst_solib_trampoline:
> +      type = objfile_type (objfile)->nodebug_text_symbol;
> +      kind = GCC_C_SYMBOL_FUNCTION;
> +      break;
> +
> +    case mst_text_gnu_ifunc:
> +      type = objfile_type (objfile)->nodebug_text_gnu_ifunc_symbol;
> +      kind = GCC_C_SYMBOL_FUNCTION;
> +      break;
> +
> +    case mst_data:
> +    case mst_file_data:
> +    case mst_bss:
> +    case mst_file_bss:
> +      type = objfile_type (objfile)->nodebug_data_symbol;
> +      kind = GCC_C_SYMBOL_VARIABLE;
> +      break;
> +
> +    case mst_slot_got_plt:
> +      type = objfile_type (objfile)->nodebug_got_plt_symbol;
> +      kind = GCC_C_SYMBOL_FUNCTION;
> +      break;
> +
> +    default:
> +      type = objfile_type (objfile)->nodebug_unknown_symbol;
> +      kind = GCC_C_SYMBOL_VARIABLE;
> +      break;
> +    }
> +
> +  sym_type = convert_type (context, type);
> +  addr = MSYMBOL_VALUE_ADDRESS (objfile, msym);
> +  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 */);
> +}
> +
> +/* See compile-internal.h.  */
> +
> +void
> +gcc_convert_symbol (void *datum,
> +		    struct gcc_c_context *gcc_context,
> +		    enum gcc_c_oracle_request request,
> +		    const char *identifier)
> +{
> +  struct compile_c_instance *context = datum;
> +  domain_enum domain;
> +  volatile struct gdb_exception e;
> +  int found = 0;
> +
> +  switch (request)
> +    {
> +    case GCC_C_ORACLE_SYMBOL:
> +      domain = VAR_DOMAIN;
> +      break;
> +    case GCC_C_ORACLE_TAG:
> +      domain = STRUCT_DOMAIN;
> +      break;
> +    case GCC_C_ORACLE_LABEL:
> +      domain = LABEL_DOMAIN;
> +      break;
> +    default:
> +      gdb_assert_not_reached ("Unrecognized oracle request.");
> +    }
> +
> +  /* We can't allow exceptions to escape out of this callback.  Safest
> +     is to simply emit a gcc error.  */
> +  TRY_CATCH (e, RETURN_MASK_ERROR)
> +    {
> +      struct symbol *sym;
> +
> +      sym = lookup_symbol (identifier, context->base.block, domain, NULL);
> +      if (sym != NULL)
> +	{
> +	  convert_symbol_sym (context, identifier, sym, domain);
> +	  found = 1;
> +	}
> +      else if (domain == VAR_DOMAIN)
> +	{
> +	  struct bound_minimal_symbol bmsym;
> +
> +	  bmsym = lookup_minimal_symbol (identifier, NULL, NULL);
> +	  if (bmsym.minsym != NULL)
> +	    {
> +	      convert_symbol_bmsym (context, bmsym);
> +	      found = 1;
> +	    }
> +	}
> +    }
> +
> +  if (e.reason < 0)
> +    C_CTX (context)->c_ops->error (C_CTX (context), e.message);
> +
> +  if (compile_debug && !found)
> +    fprintf_unfiltered (gdb_stdout,
> +			"gcc_convert_symbol \"%s\": lookup_symbol failed\n",
> +			identifier);
> +  return;
> +}
> +
> +/* See compile-internal.h.  */
> +
> +gcc_address
> +gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context,
> +		    const char *identifier)
> +{
> +  struct compile_c_instance *context = datum;
> +  volatile struct gdb_exception e;
> +  gcc_address result = 0;
> +  int found = 0;
> +
> +  /* We can't allow exceptions to escape out of this callback.  Safest
> +     is to simply emit a gcc error.  */
> +  TRY_CATCH (e, RETURN_MASK_ERROR)
> +    {
> +      struct symbol *sym;
> +
> +      /* We only need global functions here.  */
> +      sym = lookup_symbol (identifier, NULL, VAR_DOMAIN, NULL);
> +      if (sym != NULL && SYMBOL_CLASS (sym) == LOC_BLOCK)
> +	{
> +	  if (compile_debug)
> +	    fprintf_unfiltered (gdb_stdout,
> +				"gcc_symbol_address \"%s\": full symbol\n",
> +				identifier);
> +	  result = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
> +	  found = 1;
> +	}
> +      else
> +	{
> +	  struct bound_minimal_symbol msym;
> +
> +	  msym = lookup_bound_minimal_symbol (identifier);
> +	  if (msym.minsym != NULL)
> +	    {
> +	      if (compile_debug)
> +		fprintf_unfiltered (gdb_stdout,
> +				    "gcc_symbol_address \"%s\": minimal "
> +				    "symbol\n",
> +				    identifier);
> +	      result = BMSYMBOL_VALUE_ADDRESS (msym);
> +	      found = 1;
> +	    }
> +	}
> +    }
> +
> +  if (e.reason < 0)
> +    C_CTX (context)->c_ops->error (C_CTX (context), e.message);
> +
> +  if (compile_debug && !found)
> +    fprintf_unfiltered (gdb_stdout,
> +			"gcc_symbol_address \"%s\": failed\n",
> +			identifier);
> +  return result;
> +}
> +
> +
> +
> +/* A hash function for symbol names.  */
> +
> +static hashval_t
> +hash_symname (const void *a)
> +{
> +  const struct symbol *sym = a;
> +
> +  return htab_hash_string (SYMBOL_NATURAL_NAME (sym));
> +}
> +
> +/* A comparison function for hash tables that just looks at symbol
> +   names.  */
> +
> +static int
> +eq_symname (const void *a, const void *b)
> +{
> +  const struct symbol *syma = a;
> +  const struct symbol *symb = b;
> +
> +  return strcmp (SYMBOL_NATURAL_NAME (syma), SYMBOL_NATURAL_NAME (symb)) == 0;
> +}
> +
> +/* If a symbol with the same name as SYM is already in HASHTAB, return
> +   1.  Otherwise, add SYM to HASHTAB and return 0.  */
> +
> +static int
> +symbol_seen (htab_t hashtab, struct symbol *sym)
> +{
> +  void **slot;
> +
> +  slot = htab_find_slot (hashtab, sym, INSERT);
> +  if (*slot != NULL)
> +    return 1;
> +
> +  *slot = sym;
> +  return 0;
> +}
> +
> +/* Generate C code to compute the length of a VLA.  */
> +
> +static void
> +generate_vla_size (struct compile_c_instance *compiler,
> +		   struct ui_file *stream,
> +		   struct gdbarch *gdbarch,
> +		   unsigned char *registers_used,
> +		   CORE_ADDR pc,
> +		   struct type *type,
> +		   struct symbol *sym)
> +{
> +  type = check_typedef (type);
> +
> +  if (TYPE_CODE (type) == TYPE_CODE_REF)
> +    type = check_typedef (TYPE_TARGET_TYPE (type));
> +
> +  switch (TYPE_CODE (type))
> +    {
> +    case TYPE_CODE_RANGE:
> +      {
> +	if (TYPE_HIGH_BOUND_KIND (type) == PROP_LOCEXPR
> +	    || TYPE_HIGH_BOUND_KIND (type) == PROP_LOCLIST)
> +	  {
> +	    const struct dynamic_prop *prop = &TYPE_RANGE_DATA (type)->high;
> +	    char *name = c_get_range_decl_name (prop);
> +	    struct cleanup *cleanup = make_cleanup (xfree, name);
> +
> +	    dwarf2_compile_property_to_c (stream, name,
> +					  gdbarch, registers_used,
> +					  prop, pc, sym);
> +	    do_cleanups (cleanup);
> +	  }
> +      }
> +      break;
> +
> +    case TYPE_CODE_ARRAY:
> +      generate_vla_size (compiler, stream, gdbarch, registers_used, pc,
> +			 TYPE_INDEX_TYPE (type), sym);
> +      generate_vla_size (compiler, stream, gdbarch, registers_used, pc,
> +			 TYPE_TARGET_TYPE (type), sym);
> +      break;
> +
> +    case TYPE_CODE_UNION:
> +    case TYPE_CODE_STRUCT:
> +      {
> +	int i;
> +
> +	for (i = 0; i < TYPE_NFIELDS (type); ++i)
> +	  if (!field_is_static (&TYPE_FIELD (type, i)))
> +	    generate_vla_size (compiler, stream, gdbarch, registers_used, pc,
> +			       TYPE_FIELD_TYPE (type, i), sym);
> +      }
> +      break;
> +    }
> +}
> +
> +/* Generate C code to compute the address of SYM.  */
> +
> +static void
> +generate_c_for_for_one_variable (struct compile_c_instance *compiler,
> +				 struct ui_file *stream,
> +				 struct gdbarch *gdbarch,
> +				 unsigned char *registers_used,
> +				 CORE_ADDR pc,
> +				 struct symbol *sym)
> +{
> +  volatile struct gdb_exception e;
> +
> +  TRY_CATCH (e, RETURN_MASK_ERROR)
> +    {
> +      if (is_dynamic_type (SYMBOL_TYPE (sym)))
> +	{
> +	  struct ui_file *size_file = mem_fileopen ();
> +	  struct cleanup *cleanup = make_cleanup_ui_file_delete (size_file);
> +
> +	  generate_vla_size (compiler, size_file, gdbarch, registers_used, pc,
> +			     SYMBOL_TYPE (sym), sym);
> +	  ui_file_put (size_file, ui_file_write_for_put, stream);
> +
> +	  do_cleanups (cleanup);
> +	}
> +
> +      if (SYMBOL_COMPUTED_OPS (sym) != NULL)
> +	{
> +	  char *generated_name = 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.  */
> +	  struct ui_file *local_file = mem_fileopen ();
> +
> +	  make_cleanup_ui_file_delete (local_file);
> +	  SYMBOL_COMPUTED_OPS (sym)->generate_c_location (sym, local_file,
> +							  gdbarch,
> +							  registers_used,
> +							  pc, generated_name);
> +	  ui_file_put (local_file, ui_file_write_for_put, stream);
> +
> +	  do_cleanups (cleanup);
> +	}
> +      else
> +	{
> +	  switch (SYMBOL_CLASS (sym))
> +	    {
> +	    case LOC_REGISTER:
> +	    case LOC_ARG:
> +	    case LOC_REF_ARG:
> +	    case LOC_REGPARM_ADDR:
> +	    case LOC_LOCAL:
> +	      error (_("Local symbol unhandled when generating C code."));
> +
> +	    case LOC_COMPUTED:
> +	      gdb_assert_not_reached (_("LOC_COMPUTED variable "
> +					"missing a method."));
> +
> +	    default:
> +	      /* Nothing to do for all other cases, as they don't represent
> +		 local variables.  */
> +	      break;
> +	    }
> +	}
> +    }
> +
> +  if (e.reason >= 0)
> +    return;
> +
> +  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);
> +}
> +
> +/* See compile-internal.h.  */
> +
> +unsigned char *
> +generate_c_for_variable_locations (struct compile_c_instance *compiler,
> +				   struct ui_file *stream,
> +				   struct gdbarch *gdbarch,
> +				   const struct block *block,
> +				   CORE_ADDR pc)
> +{
> +  struct cleanup *cleanup, *outer;
> +  htab_t symhash;
> +  const struct block *static_block = block_static_block (block);
> +  unsigned char *registers_used;
> +
> +  /* If we're already in the static or global block, there is nothing
> +     to write.  */
> +  if (static_block == NULL || block == static_block)
> +    return NULL;
> +
> +  registers_used = XCNEWVEC (unsigned char, gdbarch_num_regs (gdbarch));
> +  outer = make_cleanup (xfree, registers_used);
> +
> +  /* Ensure that a given name is only entered once.  This reflects the
> +     reality of shadowing.  */
> +  symhash = htab_create_alloc (1, hash_symname, eq_symname, NULL,
> +			       xcalloc, xfree);
> +  cleanup = make_cleanup_htab_delete (symhash);
> +
> +  while (1)
> +    {
> +      struct symbol *sym;
> +      struct block_iterator iter;
> +
> +      /* Iterate over symbols in this block, generating code to
> +	 compute the location of each local variable.  */
> +      for (sym = block_iterator_first (block, &iter);
> +	   sym != NULL;
> +	   sym = block_iterator_next (&iter))
> +	{
> +	  if (!symbol_seen (symhash, sym))
> +	    generate_c_for_for_one_variable (compiler, stream, gdbarch,
> +					     registers_used, pc, sym);
> +	}
> +
> +      /* If we just finished the outermost block of a function, we're
> +	 done.  */
> +      if (BLOCK_FUNCTION (block) != NULL)
> +	break;
> +      block = BLOCK_SUPERBLOCK (block);
> +    }
> +
> +  do_cleanups (cleanup);
> +  discard_cleanups (outer);
> +  return registers_used;
> +}
> diff --git a/gdb/compile/compile-c-types.c b/gdb/compile/compile-c-types.c
> new file mode 100644
> index 0000000..78ae9a8
> --- /dev/null
> +++ b/gdb/compile/compile-c-types.c
> @@ -0,0 +1,438 @@
> +/* Convert types from GDB to GCC
> +
> +   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/>.  */
> +
> +
> +#include "defs.h"
> +#include "gdbtypes.h"
> +#include "compile-internal.h"
> +#include "gdb_assert.h"
> +
> +/* An object that maps a gdb type to a gcc type.  */
> +
> +struct type_map_instance
> +{
> +  /* The gdb type.  */
> +
> +  struct type *type;
> +
> +  /* The corresponding gcc type handle.  */
> +
> +  gcc_type gcc_type;
> +};
> +
> +/* Hash a type_map_instance.  */
> +
> +static hashval_t
> +hash_type_map_instance (const void *p)
> +{
> +  const struct type_map_instance *inst = 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 = a;
> +  const struct type_map_instance *instb = b;
> +
> +  return insta->type == instb->type;
> +}
> +
> +
> +
> +/* 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 = gcc_type;
> +  slot = htab_find_slot (context->type_map, &inst, INSERT);
> +
> +  add = *slot;
> +  /* The type might have already been inserted in order to handle
> +     recursive types.  */
> +  gdb_assert (add == NULL || add->gcc_type == gcc_type);
> +
> +  if (add == NULL)
> +    {
> +      add = XNEW (struct type_map_instance);
> +      *add = inst;
> +      *slot = add;
> +    }
> +}
> +
> +/* Convert a pointer type to its gcc representation.  */
> +
> +static gcc_type
> +convert_pointer (struct compile_c_instance *context, struct type *type)
> +{
> +  gcc_type target = convert_type (context, TYPE_TARGET_TYPE (type));
> +
> +  return C_CTX (context)->c_ops->build_pointer_type (C_CTX (context),
> +						     target);
> +}
> +
> +/* Convert an array type to its gcc representation.  */
> +
> +static gcc_type
> +convert_array (struct 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));
> +
> +  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"));
> +  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"));
> +
> +  if (TYPE_HIGH_BOUND_KIND (range) == PROP_LOCEXPR
> +      || TYPE_HIGH_BOUND_KIND (range) == PROP_LOCLIST)
> +    {
> +      gcc_type result;
> +      char *upper_bound;
> +
> +      if (TYPE_VECTOR (type))
> +	return C_CTX (context)->c_ops->error (C_CTX (context),
> +					      _("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);
> +      xfree (upper_bound);
> +      return result;
> +    }
> +  else
> +    {
> +      LONGEST low_bound, high_bound, count;
> +
> +      if (get_array_bounds (type, &low_bound, &high_bound) == 0)
> +	count = -1;
> +      else
> +	{
> +	  gdb_assert (low_bound == 0); /* Ensured above.  */
> +	  count = high_bound + 1;
> +	}
> +
> +      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);
> +    }
> +}
> +
> +/* 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)
> +{
> +  int i;
> +  gcc_type result;
> +
> +  /* 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));
> +  else
> +    {
> +      gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
> +      result = C_CTX (context)->c_ops->build_union_type (C_CTX (context));
> +    }
> +  insert_type (context, 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));
> +      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));
> +    }
> +
> +  C_CTX (context)->c_ops->finish_record_or_union (C_CTX (context), 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)
> +{
> +  gcc_type int_type, result;
> +  int i;
> +  struct gcc_c_context *ctx = C_CTX (context);
> +
> +  int_type = ctx->c_ops->int_type (ctx,
> +				   TYPE_UNSIGNED (type),
> +				   TYPE_LENGTH (type));
> +
> +  result = ctx->c_ops->build_enum_type (ctx, 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));
> +    }
> +
> +  ctx->c_ops->finish_enum_type (ctx, result);
> +
> +  return result;
> +}
> +
> +/* Convert a function type to its gcc representation.  */
> +
> +static gcc_type
> +convert_func (struct compile_c_instance *context, struct type *type)
> +{
> +  int i;
> +  gcc_type result, return_type;
> +  struct gcc_type_array array;
> +  int is_varargs = TYPE_VARARGS (type) || !TYPE_PROTOTYPED (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));
> +
> +  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));
> +
> +  result = C_CTX (context)->c_ops->build_function_type (C_CTX (context),
> +							return_type,
> +							&array, is_varargs);
> +  xfree (array.elements);
> +
> +  return result;
> +}
> +
> +/* Convert an integer type to its gcc representation.  */
> +
> +static gcc_type
> +convert_int (struct compile_c_instance *context, struct type *type)
> +{
> +  return C_CTX (context)->c_ops->int_type (C_CTX (context),
> +					   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)
> +{
> +  return C_CTX (context)->c_ops->float_type (C_CTX (context),
> +					     TYPE_LENGTH (type));
> +}
> +
> +/* Convert the 'void' type to its gcc representation.  */
> +
> +static gcc_type
> +convert_void (struct compile_c_instance *context, struct type *type)
> +{
> +  return C_CTX (context)->c_ops->void_type (C_CTX (context));
> +}
> +
> +/* Convert a boolean type to its gcc representation.  */
> +
> +static gcc_type
> +convert_bool (struct compile_c_instance *context, struct type *type)
> +{
> +  return C_CTX (context)->c_ops->bool_type (C_CTX (context));
> +}
> +
> +/* Convert a qualified type to its gcc representation.  */
> +
> +static gcc_type
> +convert_qualified (struct compile_c_instance *context, struct type *type)
> +{
> +  struct type *unqual = make_unqualified_type (type);
> +  gcc_type unqual_converted;
> +  int quals = 0;
> +
> +  unqual_converted = convert_type (context, unqual);
> +
> +  if (TYPE_CONST (type))
> +    quals |= GCC_QUALIFIER_CONST;
> +  if (TYPE_VOLATILE (type))
> +    quals |= GCC_QUALIFIER_VOLATILE;
> +  if (TYPE_RESTRICT (type))
> +    quals |= GCC_QUALIFIER_RESTRICT;
> +
> +  return C_CTX (context)->c_ops->build_qualified_type (C_CTX (context),
> +						       unqual_converted,
> +						       quals);
> +}
> +
> +/* Convert a complex type to its gcc representation.  */
> +
> +static gcc_type
> +convert_complex (struct compile_c_instance *context, struct type *type)
> +{
> +  gcc_type base = convert_type (context, TYPE_TARGET_TYPE (type));
> +
> +  return C_CTX (context)->c_ops->build_complex_type (C_CTX (context), base);
> +}
> +
> +/* A helper function which knows how to convert most types from their
> +   gdb representation to the corresponding gcc form.  This examines
> +   the TYPE and dispatches to the appropriate conversion function.  It
> +   returns the gcc type.  */
> +
> +static gcc_type
> +convert_type_basic (struct compile_c_instance *context, struct type *type)
> +{
> +  /* If we are converting a qualified type, first convert the
> +     unqualified type and then apply the qualifiers.  */
> +  if ((TYPE_INSTANCE_FLAGS (type) & (TYPE_INSTANCE_FLAG_CONST
> +				     | TYPE_INSTANCE_FLAG_VOLATILE
> +				     | TYPE_INSTANCE_FLAG_RESTRICT)) != 0)
> +    return convert_qualified (context, type);
> +
> +  switch (TYPE_CODE (type))
> +    {
> +    case TYPE_CODE_PTR:
> +      return convert_pointer (context, type);
> +
> +    case TYPE_CODE_ARRAY:
> +      return convert_array (context, type);
> +
> +    case TYPE_CODE_STRUCT:
> +    case TYPE_CODE_UNION:
> +      return convert_struct_or_union (context, type);
> +
> +    case TYPE_CODE_ENUM:
> +      return convert_enum (context, type);
> +
> +    case TYPE_CODE_FUNC:
> +      return convert_func (context, type);
> +
> +    case TYPE_CODE_INT:
> +      return convert_int (context, type);
> +
> +    case TYPE_CODE_FLT:
> +      return convert_float (context, type);
> +
> +    case TYPE_CODE_VOID:
> +      return convert_void (context, type);
> +
> +    case TYPE_CODE_BOOL:
> +      return convert_bool (context, type);
> +
> +    case TYPE_CODE_COMPLEX:
> +      return convert_complex (context, type);
> +    }
> +
> +  return C_CTX (context)->c_ops->error (C_CTX (context),
> +					_("cannot convert gdb type "
> +					  "to gcc type"));
> +}
> +
> +/* See compile-internal.h.  */
> +
> +gcc_type
> +convert_type (struct compile_c_instance *context, 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.  */
> +  CHECK_TYPEDEF (type);
> +
> +  inst.type = type;
> +  found = htab_find (context->type_map, &inst);
> +  if (found != NULL)
> +    return found->gcc_type;
> +
> +  result = convert_type_basic (context, type);
> +  insert_type (context, type, result);
> +  return result;
> +}
> +
> +
> +
> +/* Delete the compiler instance C.  */
> +
> +static void
> +delete_instance (struct compile_instance *c)
> +{
> +  struct compile_c_instance *context = (struct compile_c_instance *) c;
> +
> +  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);
> +}
> +
> +/* See compile-internal.h.  */
> +
> +struct compile_instance *
> +new_compile_instance (struct gcc_c_context *fe)
> +{
> +  struct compile_c_instance *result = XCNEW (struct compile_c_instance);
> +
> +  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");
> +
> +  result->type_map = htab_create_alloc (10, hash_type_map_instance,
> +					eq_type_map_instance,
> +					xfree, xcalloc, xfree);
> +
> +  fe->c_ops->set_callbacks (fe, gcc_convert_symbol,
> +			    gcc_symbol_address, result);
> +
> +  return &result->base;
> +}
> diff --git a/gdb/compile/compile-internal.h b/gdb/compile/compile-internal.h
> new file mode 100644
> index 0000000..cb8d3d1
> --- /dev/null
> +++ b/gdb/compile/compile-internal.h
> @@ -0,0 +1,147 @@
> +/* Header file for GDB compile command and supporting functions.
> +   Copyright (C) 2014 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_INTERNAL_H
> +#define GDB_COMPILE_INTERNAL_H
> +
> +#include "hashtab.h"
> +#include "gcc-c-interface.h"
> +
> +/* Debugging flag for the "compile" family of commands.  */
> +
> +extern int compile_debug;
> +
> +struct block;
> +
> +/* An object of this type holds state associated with a given
> +   compilation job.  */
> +
> +struct compile_instance
> +{
> +  /* The GCC front end.  */
> +
> +  struct gcc_base_context *fe;
> +
> +  /* The "scope" of this compilation.  */
> +
> +  enum compile_i_scope_types scope;
> +
> +  /* The block in which an expression is being parsed.  */
> +
> +  const struct block *block;
> +
> +  /* Specify "-std=gnu11", "-std=gnu++11" or similar.  These options are put
> +     after CU's DW_AT_producer compilation options to override them.  */
> +
> +  const char *gcc_target_options;
> +
> +  /* How to destroy this object.  */
> +
> +  void (*destroy) (struct compile_instance *);
> +};
> +
> +/* 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.  */
> +
> +  struct compile_instance base;
> +
> +  /* Map from gdb types to gcc types.  */
> +
> +  htab_t type_map;
> +
> +  /* Map from gdb symbols to gcc error messages to emit.  */
> +
> +  htab_t symbol_err_map;
> +};
> +
> +/* A helper macro that takes a compile_c_instance and returns its
> +   corresponding gcc_c_context.  */
> +
> +#define C_CTX(I) ((struct gcc_c_context *) ((I)->base.fe))
> +
> +/* Define header and footers for different scopes.  */
> +
> +/* A simple scope just declares a function named "_gdb_expr", takes no
> +   arguments and returns no value.  */
> +
> +#define COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG "__gdb_regs"
> +#define COMPILE_I_SIMPLE_REGISTER_ARG_NAME "__regs"
> +#define COMPILE_I_SIMPLE_REGISTER_DUMMY "_dummy"
> +
> +/* 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
> +   never NULL.  Returned pointer needs to be deallocated by xfree.  */
> +
> +extern char *compile_register_name_mangled (struct gdbarch *gdbarch,
> +					    int regnum);
> +
> +/* Convert compiler source register name to register number of
> +   GDBARCH.  Returned value is always >= 0, function throws an error
> +   for non-matching REG_NAME.  */
> +
> +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,
> +      struct ui_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);
> +
> +#endif /* GDB_COMPILE_INTERNAL_H */
> diff --git a/gdb/compile/compile-loc2c.c b/gdb/compile/compile-loc2c.c
> new file mode 100644
> index 0000000..9cfb5fb
> --- /dev/null
> +++ b/gdb/compile/compile-loc2c.c
> @@ -0,0 +1,1147 @@
> +/* Convert a DWARF location expression to 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/>.  */
> +
> +#include "defs.h"
> +#include "dwarf2.h"
> +#include "dwarf2expr.h"
> +#include "dwarf2loc.h"
> +#include "ui-file.h"
> +#include "utils.h"
> +#include "compile-internal.h"
> +#include "compile.h"
> +#include "block.h"
> +#include "dwarf2-frame.h"
> +#include "gdb_vecs.h"
> +#include "value.h"
> +
> +
> +
> +/* Information about a given instruction.  */
> +
> +struct insn_info
> +{
> +  /* Stack depth at entry.  */
> +
> +  unsigned int depth;
> +
> +  /* Whether this instruction has been visited.  */
> +
> +  unsigned int visited : 1;
> +
> +  /* Whether this instruction needs a label.  */
> +
> +  unsigned int label : 1;
> +
> +  /* Whether this instruction is DW_OP_GNU_push_tls_address.  This is
> +     a hack until we can add a feature to glibc to let us properly
> +     generate code for TLS.  */
> +
> +  unsigned int is_tls : 1;
> +};
> +
> +/* A helper function for compute_stack_depth that does the work.  This
> +   examines the DWARF expression starting from START and computes
> +   stack effects.
> +
> +   NEED_TEMPVAR is an out parameter which is set if this expression
> +   needs a special temporary variable to be emitted (see the code
> +   generator).
> +   INFO is an array of insn_info objects, indexed by offset from the
> +   start of the DWARF expression.
> +   TO_DO is a list of bytecodes which must be examined; it may be
> +   added to by this function.
> +   BYTE_ORDER and ADDR_SIZE describe this bytecode in the obvious way.
> +   OP_PTR and OP_END are the bounds of the DWARF expression.  */
> +
> +static void
> +compute_stack_depth_worker (int start, int *need_tempvar,
> +			    struct insn_info *info,
> +			    VEC (int) **to_do,
> +			    enum bfd_endian byte_order, unsigned int addr_size,
> +			    const gdb_byte *op_ptr, const gdb_byte *op_end)
> +{
> +  const gdb_byte * const base = op_ptr;
> +  int stack_depth;
> +
> +  op_ptr += start;
> +  gdb_assert (info[start].visited);
> +  stack_depth = info[start].depth;
> +
> +  while (op_ptr < op_end)
> +    {
> +      enum dwarf_location_atom op = *op_ptr;
> +      uint64_t reg;
> +      int64_t offset;
> +      int ndx = op_ptr - base;
> +
> +#define SET_CHECK_DEPTH(WHERE)				\
> +      if (info[WHERE].visited)				\
> +	{						\
> +	  if (info[WHERE].depth != stack_depth)		\
> +	    error (_("inconsistent stack depths"));	\
> +	}						\
> +      else						\
> +	{						\
> +	  /* Stack depth not set, so set it.  */	\
> +	  info[WHERE].visited = 1;			\
> +	  info[WHERE].depth = stack_depth;		\
> +	}
> +
> +      SET_CHECK_DEPTH (ndx);
> +
> +      ++op_ptr;
> +
> +      switch (op)
> +	{
> +	case DW_OP_lit0:
> +	case DW_OP_lit1:
> +	case DW_OP_lit2:
> +	case DW_OP_lit3:
> +	case DW_OP_lit4:
> +	case DW_OP_lit5:
> +	case DW_OP_lit6:
> +	case DW_OP_lit7:
> +	case DW_OP_lit8:
> +	case DW_OP_lit9:
> +	case DW_OP_lit10:
> +	case DW_OP_lit11:
> +	case DW_OP_lit12:
> +	case DW_OP_lit13:
> +	case DW_OP_lit14:
> +	case DW_OP_lit15:
> +	case DW_OP_lit16:
> +	case DW_OP_lit17:
> +	case DW_OP_lit18:
> +	case DW_OP_lit19:
> +	case DW_OP_lit20:
> +	case DW_OP_lit21:
> +	case DW_OP_lit22:
> +	case DW_OP_lit23:
> +	case DW_OP_lit24:
> +	case DW_OP_lit25:
> +	case DW_OP_lit26:
> +	case DW_OP_lit27:
> +	case DW_OP_lit28:
> +	case DW_OP_lit29:
> +	case DW_OP_lit30:
> +	case DW_OP_lit31:
> +	  ++stack_depth;
> +	  break;
> +
> +	case DW_OP_addr:
> +	  op_ptr += addr_size;
> +	  ++stack_depth;
> +	  break;
> +
> +	case DW_OP_const1u:
> +	case DW_OP_const1s:
> +	  op_ptr += 1;
> +	  ++stack_depth;
> +	  break;
> +	case DW_OP_const2u:
> +	case DW_OP_const2s:
> +	  op_ptr += 2;
> +	  ++stack_depth;
> +	  break;
> +	case DW_OP_const4u:
> +	case DW_OP_const4s:
> +	  op_ptr += 4;
> +	  ++stack_depth;
> +	  break;
> +	case DW_OP_const8u:
> +	case DW_OP_const8s:
> +	  op_ptr += 8;
> +	  ++stack_depth;
> +	  break;
> +	case DW_OP_constu:
> +	case DW_OP_consts:
> +	  op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
> +	  ++stack_depth;
> +	  break;
> +
> +	case DW_OP_reg0:
> +	case DW_OP_reg1:
> +	case DW_OP_reg2:
> +	case DW_OP_reg3:
> +	case DW_OP_reg4:
> +	case DW_OP_reg5:
> +	case DW_OP_reg6:
> +	case DW_OP_reg7:
> +	case DW_OP_reg8:
> +	case DW_OP_reg9:
> +	case DW_OP_reg10:
> +	case DW_OP_reg11:
> +	case DW_OP_reg12:
> +	case DW_OP_reg13:
> +	case DW_OP_reg14:
> +	case DW_OP_reg15:
> +	case DW_OP_reg16:
> +	case DW_OP_reg17:
> +	case DW_OP_reg18:
> +	case DW_OP_reg19:
> +	case DW_OP_reg20:
> +	case DW_OP_reg21:
> +	case DW_OP_reg22:
> +	case DW_OP_reg23:
> +	case DW_OP_reg24:
> +	case DW_OP_reg25:
> +	case DW_OP_reg26:
> +	case DW_OP_reg27:
> +	case DW_OP_reg28:
> +	case DW_OP_reg29:
> +	case DW_OP_reg30:
> +	case DW_OP_reg31:
> +	  ++stack_depth;
> +	  break;
> +
> +	case DW_OP_regx:
> +	  op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
> +	  ++stack_depth;
> +	  break;
> +
> +	case DW_OP_breg0:
> +	case DW_OP_breg1:
> +	case DW_OP_breg2:
> +	case DW_OP_breg3:
> +	case DW_OP_breg4:
> +	case DW_OP_breg5:
> +	case DW_OP_breg6:
> +	case DW_OP_breg7:
> +	case DW_OP_breg8:
> +	case DW_OP_breg9:
> +	case DW_OP_breg10:
> +	case DW_OP_breg11:
> +	case DW_OP_breg12:
> +	case DW_OP_breg13:
> +	case DW_OP_breg14:
> +	case DW_OP_breg15:
> +	case DW_OP_breg16:
> +	case DW_OP_breg17:
> +	case DW_OP_breg18:
> +	case DW_OP_breg19:
> +	case DW_OP_breg20:
> +	case DW_OP_breg21:
> +	case DW_OP_breg22:
> +	case DW_OP_breg23:
> +	case DW_OP_breg24:
> +	case DW_OP_breg25:
> +	case DW_OP_breg26:
> +	case DW_OP_breg27:
> +	case DW_OP_breg28:
> +	case DW_OP_breg29:
> +	case DW_OP_breg30:
> +	case DW_OP_breg31:
> +	  op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
> +	  ++stack_depth;
> +	  break;
> +	case DW_OP_bregx:
> +	  {
> +	    op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
> +	    op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
> +	    ++stack_depth;
> +	  }
> +	  break;
> +	case DW_OP_fbreg:
> +	  op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
> +	  ++stack_depth;
> +	  break;
> +
> +	case DW_OP_dup:
> +	  ++stack_depth;
> +	  break;
> +
> +	case DW_OP_drop:
> +	  --stack_depth;
> +	  break;
> +
> +	case DW_OP_pick:
> +	  ++op_ptr;
> +	  ++stack_depth;
> +	  break;
> +
> +	case DW_OP_rot:
> +	case DW_OP_swap:
> +	  *need_tempvar = 1;
> +	  break;
> +
> +	case DW_OP_over:
> +	  ++stack_depth;
> +	  break;
> +
> +	case DW_OP_abs:
> +	case DW_OP_neg:
> +	case DW_OP_not:
> +	case DW_OP_deref:
> +	  break;
> +
> +	case DW_OP_deref_size:
> +	  ++op_ptr;
> +	  break;
> +
> +	case DW_OP_plus_uconst:
> +	  op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
> +	  break;
> +
> +	case DW_OP_div:
> +	case DW_OP_shra:
> +	case DW_OP_and:
> +	case DW_OP_minus:
> +	case DW_OP_mod:
> +	case DW_OP_mul:
> +	case DW_OP_or:
> +	case DW_OP_plus:
> +	case DW_OP_shl:
> +	case DW_OP_shr:
> +	case DW_OP_xor:
> +	case DW_OP_le:
> +	case DW_OP_ge:
> +	case DW_OP_eq:
> +	case DW_OP_lt:
> +	case DW_OP_gt:
> +	case DW_OP_ne:
> +	  --stack_depth;
> +	  break;
> +
> +	case DW_OP_call_frame_cfa:
> +	  ++stack_depth;
> +	  break;
> +
> +	case DW_OP_GNU_push_tls_address:
> +	  info[ndx].is_tls = 1;
> +	  break;
> +
> +	case DW_OP_skip:
> +	  offset = extract_signed_integer (op_ptr, 2, byte_order);
> +	  op_ptr += 2;
> +	  offset = op_ptr + offset - base;
> +	  /* If the destination has not been seen yet, add it to the
> +	     to-do list.  */
> +	  if (!info[offset].visited)
> +	    VEC_safe_push (int, *to_do, offset);
> +	  SET_CHECK_DEPTH (offset);
> +	  info[offset].label = 1;
> +	  /* We're done with this line of code.  */
> +	  return;
> +
> +	case DW_OP_bra:
> +	  offset = extract_signed_integer (op_ptr, 2, byte_order);
> +	  op_ptr += 2;
> +	  offset = op_ptr + offset - base;
> +	  --stack_depth;
> +	  /* If the destination has not been seen yet, add it to the
> +	     to-do list.  */
> +	  if (!info[offset].visited)
> +	    VEC_safe_push (int, *to_do, offset);
> +	  SET_CHECK_DEPTH (offset);
> +	  info[offset].label = 1;
> +	  break;
> +
> +	case DW_OP_nop:
> +	  break;
> +
> +	default:
> +	  error (_("unhandled DWARF op: %s"), get_DW_OP_name (op));
> +	}
> +    }
> +
> +  gdb_assert (op_ptr == op_end);
> +
> +#undef SET_CHECK_DEPTH
> +}
> +
> +/* Compute the maximum needed stack depth of a DWARF expression, and
> +   some other information as well.
> +
> +   BYTE_ORDER and ADDR_SIZE describe this bytecode in the obvious way.
> +   NEED_TEMPVAR is an out parameter which is set if this expression
> +   needs a special temporary variable to be emitted (see the code
> +   generator).
> +   IS_TLS is an out parameter which is set if this expression refers
> +   to a TLS variable.
> +   OP_PTR and OP_END are the bounds of the DWARF expression.
> +   INITIAL_DEPTH is the initial depth of the DWARF expression stack.
> +   INFO is an array of insn_info objects, indexed by offset from the
> +   start of the DWARF expression.
> +
> +   This returns the maximum stack depth.  */
> +
> +static int
> +compute_stack_depth (enum bfd_endian byte_order, unsigned int addr_size,
> +		     int *need_tempvar, int *is_tls,
> +		     const gdb_byte *op_ptr, const gdb_byte *op_end,
> +		     int initial_depth,
> +		     struct insn_info **info)
> +{
> +  unsigned char *set;
> +  struct cleanup *outer_cleanup, *cleanup;
> +  VEC (int) *to_do = NULL;
> +  int stack_depth, i;
> +
> +  *info = XCNEWVEC (struct insn_info, op_end - op_ptr);
> +  outer_cleanup = make_cleanup (xfree, *info);
> +
> +  cleanup = make_cleanup (VEC_cleanup (int), &to_do);
> +
> +  VEC_safe_push (int, to_do, 0);
> +  (*info)[0].depth = initial_depth;
> +  (*info)[0].visited = 1;
> +
> +  while (!VEC_empty (int, to_do))
> +    {
> +      int ndx = VEC_pop (int, to_do);
> +
> +      compute_stack_depth_worker (ndx, need_tempvar, *info, &to_do,
> +				  byte_order, addr_size,
> +				  op_ptr, op_end);
> +    }
> +
> +  stack_depth = 0;
> +  *is_tls = 0;
> +  for (i = 0; i < op_end - op_ptr; ++i)
> +    {
> +      if ((*info)[i].depth > stack_depth)
> +	stack_depth = (*info)[i].depth;
> +      if ((*info)[i].is_tls)
> +	*is_tls = 1;
> +    }
> +
> +  do_cleanups (cleanup);
> +  discard_cleanups (outer_cleanup);
> +  return stack_depth + 1;
> +}
> +
> +
> +
> +#define GCC_UINTPTR "__gdb_uintptr"
> +#define GCC_INTPTR "__gdb_intptr"
> +
> +/* Emit code to push a constant.  */
> +
> +static void
> +push (int indent, struct ui_file *stream, ULONGEST l)
> +{
> +  fprintfi_filtered (indent, stream, "__gdb_stack[++__gdb_tos] = %s;\n",
> +		     hex_string (l));
> +}
> +
> +/* Emit code to push an arbitrary expression.  This works like
> +   printf.  */
> +
> +static void
> +pushf (int indent, struct ui_file *stream, const char *format, ...)
> +{
> +  va_list args;
> +
> +  fprintfi_filtered (indent, stream, "__gdb_stack[__gdb_tos + 1] = ");
> +  va_start (args, format);
> +  vfprintf_filtered (stream, format, args);
> +  va_end (args);
> +  fprintf_filtered (stream, ";\n");
> +
> +  fprintfi_filtered (indent, stream, "++__gdb_tos;\n");
> +}
> +
> +/* Emit code for a unary expression -- one which operates in-place on
> +   the top-of-stack.  This works like printf.  */
> +
> +static void
> +unary (int indent, struct ui_file *stream, const char *format, ...)
> +{
> +  va_list args;
> +
> +  fprintfi_filtered (indent, stream, "__gdb_stack[__gdb_tos] = ");
> +  va_start (args, format);
> +  vfprintf_filtered (stream, format, args);
> +  va_end (args);
> +  fprintf_filtered (stream, ";\n");
> +}
> +
> +/* Emit code for a unary expression -- one which uses the top two
> +   stack items, popping the topmost one.  This works like printf.  */
> +
> +static void
> +binary (int indent, struct ui_file *stream, const char *format, ...)
> +{
> +  va_list args;
> +
> +  fprintfi_filtered (indent, stream, "__gdb_stack[__gdb_tos - 1] = ");
> +  va_start (args, format);
> +  vfprintf_filtered (stream, format, args);
> +  va_end (args);
> +  fprintf_filtered (stream, ";\n");
> +  fprintfi_filtered (indent, stream, "--__gdb_tos;\n");
> +}
> +
> +/* Print the name of a label given its "SCOPE", an arbitrary integer
> +   used for uniqueness, and its TARGET, the bytecode offset
> +   corresponding to the label's point of definition.  */
> +
> +static void
> +print_label (struct ui_file *stream, unsigned int scope, int target)
> +{
> +  fprintf_filtered (stream, "__label_%u_%s",
> +		    scope, pulongest (target));
> +}
> +
> +/* Emit code that pushes a register's address on the stack.
> +   REGISTERS_USED is an out parameter which is updated to note which
> +   register was needed by this expression.  */
> +
> +static void
> +pushf_register_address (int indent, struct ui_file *stream,
> +			unsigned char *registers_used,
> +			struct gdbarch *gdbarch, int regnum)
> +{
> +  char *regname = compile_register_name_mangled (gdbarch, regnum);
> +  struct cleanup *cleanups = make_cleanup (xfree, regname);
> +
> +  registers_used[regnum] = 1;
> +  pushf (indent, stream, "&" COMPILE_I_SIMPLE_REGISTER_ARG_NAME	 "->%s",
> +	 regname);
> +
> +  do_cleanups (cleanups);
> +}
> +
> +/* Emit code that pushes a register's value on the stack.
> +   REGISTERS_USED is an out parameter which is updated to note which
> +   register was needed by this expression.  OFFSET is added to the
> +   register's value before it is pushed.  */
> +
> +static void
> +pushf_register (int indent, struct ui_file *stream,
> +		unsigned char *registers_used,
> +		struct gdbarch *gdbarch, int regnum, uint64_t offset)
> +{
> +  char *regname = compile_register_name_mangled (gdbarch, regnum);
> +  struct cleanup *cleanups = make_cleanup (xfree, regname);
> +
> +  registers_used[regnum] = 1;
> +  if (offset == 0)
> +    pushf (indent, stream, COMPILE_I_SIMPLE_REGISTER_ARG_NAME "->%s",
> +	   regname);
> +  else
> +    pushf (indent, stream, COMPILE_I_SIMPLE_REGISTER_ARG_NAME "->%s + %s",
> +	   regname, hex_string (offset));
> +
> +  do_cleanups (cleanups);
> +}
> +
> +/* Compile a DWARF expression to C code.
> +
> +   INDENT is the indentation level to use.
> +   STREAM is the stream where the code should be written.
> +
> +   TYPE_NAME names the type of the result of the DWARF expression.
> +   For locations this is "void *" but for array bounds it will be an
> +   integer type.
> +
> +   RESULT_NAME is the name of a variable in the resulting C code.  The
> +   result of the expression will be assigned to this variable.
> +
> +   SYM is the symbol corresponding to this expression.
> +   PC is the location at which the expression is being evaluated.
> +   ARCH is the architecture to use.
> +
> +   REGISTERS_USED is an out parameter which is updated to note which
> +   registers were needed by this expression.
> +
> +   ADDR_SIZE is the DWARF address size to use.
> +
> +   OPT_PTR and OP_END are the bounds of the DWARF expression.
> +
> +   If non-NULL, INITIAL points to an initial value to write to the
> +   stack.  If NULL, no initial value is written.
> +
> +   PER_CU is the per-CU object used for looking up various other
> +   things.  */
> +
> +static void
> +do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
> +			    const char *type_name,
> +			    const char *result_name,
> +			    struct symbol *sym, CORE_ADDR pc,
> +			    struct gdbarch *arch,
> +			    unsigned char *registers_used,
> +			    unsigned int addr_size,
> +			    const gdb_byte *op_ptr, const gdb_byte *op_end,
> +			    CORE_ADDR *initial,
> +			    struct dwarf2_per_cu_data *per_cu)
> +{
> +  /* We keep a counter so that labels and other objects we create have
> +     unique names.  */
> +  static unsigned int scope;
> +
> +  enum bfd_endian byte_order = gdbarch_byte_order (arch);
> +  const gdb_byte * const base = op_ptr;
> +  int need_tempvar = 0;
> +  int is_tls = 0;
> +  struct cleanup *cleanup;
> +  struct insn_info *info;
> +  int stack_depth;
> +
> +  ++scope;
> +
> +  fprintfi_filtered (indent, stream, "%s%s;\n", type_name, result_name);
> +  fprintfi_filtered (indent, stream, "{\n");
> +  indent += 2;
> +
> +  stack_depth = compute_stack_depth (byte_order, addr_size,
> +				     &need_tempvar, &is_tls,
> +				     op_ptr, op_end, initial != NULL,
> +				     &info);
> +  cleanup = make_cleanup (xfree, info);
> +
> +  /* This is a hack until we can add a feature to glibc to let us
> +     properly generate code for TLS.  You might think we could emit
> +     the address in the ordinary course of translating
> +     DW_OP_GNU_push_tls_address, but since the operand appears on the
> +     stack, it is relatively hard to find, and the idea of calling
> +     target_translate_tls_address with OFFSET==0 and then adding the
> +     offset by hand seemed too hackish.  */
> +  if (is_tls)
> +    {
> +      struct frame_info *frame = get_selected_frame (NULL);
> +      struct value *val;
> +
> +      if (frame == NULL)
> +	error (_("Symbol \"%s\" cannot be used because "
> +		 "there is no selected frame"),
> +	       SYMBOL_PRINT_NAME (sym));
> +
> +      val = read_var_value (sym, frame);
> +      if (VALUE_LVAL (val) != lval_memory)
> +	error (_("Symbol \"%s\" cannot be used for compilation evaluation "
> +		 "as its address has not been found."),
> +	       SYMBOL_PRINT_NAME (sym));
> +
> +      warning (_("Symbol \"%s\" is thread-local and currently can only "
> +		 "be referenced from the current thread in "
> +		 "compiled code."),
> +	       SYMBOL_PRINT_NAME (sym));
> +
> +      fprintfi_filtered (indent, stream, "%s = %s;\n",
> +			 result_name,
> +			 core_addr_to_string (value_address (val)));
> +      fprintfi_filtered (indent - 2, stream, "}\n");
> +      do_cleanups (cleanup);
> +      return;
> +    }
> +
> +  fprintfi_filtered (indent, stream, GCC_UINTPTR " __gdb_stack[%d];\n",
> +		     stack_depth);
> +
> +  if (need_tempvar)
> +    fprintfi_filtered (indent, stream, GCC_UINTPTR " __gdb_tmp;\n");
> +  fprintfi_filtered (indent, stream, "int __gdb_tos = -1;\n");
> +
> +  if (initial != NULL)
> +    pushf (indent, stream, core_addr_to_string (*initial));
> +
> +  while (op_ptr < op_end)
> +    {
> +      enum dwarf_location_atom op = *op_ptr;
> +      uint64_t uoffset, reg;
> +      int64_t offset;
> +
> +      print_spaces (indent - 2, stream);
> +      if (info[op_ptr - base].label)
> +	{
> +	  print_label (stream, scope, op_ptr - base);
> +	  fprintf_filtered (stream, ":;");
> +	}
> +      fprintf_filtered (stream, "/* %s */\n", get_DW_OP_name (op));
> +
> +      /* This is handy for debugging the generated code:
> +      fprintf_filtered (stream, "if (__gdb_tos != %d) abort ();\n",
> +			(int) info[op_ptr - base].depth - 1);
> +      */
> +
> +      ++op_ptr;
> +
> +      switch (op)
> +	{
> +	case DW_OP_lit0:
> +	case DW_OP_lit1:
> +	case DW_OP_lit2:
> +	case DW_OP_lit3:
> +	case DW_OP_lit4:
> +	case DW_OP_lit5:
> +	case DW_OP_lit6:
> +	case DW_OP_lit7:
> +	case DW_OP_lit8:
> +	case DW_OP_lit9:
> +	case DW_OP_lit10:
> +	case DW_OP_lit11:
> +	case DW_OP_lit12:
> +	case DW_OP_lit13:
> +	case DW_OP_lit14:
> +	case DW_OP_lit15:
> +	case DW_OP_lit16:
> +	case DW_OP_lit17:
> +	case DW_OP_lit18:
> +	case DW_OP_lit19:
> +	case DW_OP_lit20:
> +	case DW_OP_lit21:
> +	case DW_OP_lit22:
> +	case DW_OP_lit23:
> +	case DW_OP_lit24:
> +	case DW_OP_lit25:
> +	case DW_OP_lit26:
> +	case DW_OP_lit27:
> +	case DW_OP_lit28:
> +	case DW_OP_lit29:
> +	case DW_OP_lit30:
> +	case DW_OP_lit31:
> +	  push (indent, stream, op - DW_OP_lit0);
> +	  break;
> +
> +	case DW_OP_addr:
> +	  op_ptr += addr_size;
> +	  /* Some versions of GCC emit DW_OP_addr before
> +	     DW_OP_GNU_push_tls_address.  In this case the value is an
> +	     index, not an address.  We don't support things like
> +	     branching between the address and the TLS op.  */
> +	  if (op_ptr >= op_end || *op_ptr != DW_OP_GNU_push_tls_address)
> +	    uoffset += dwarf2_per_cu_text_offset (per_cu);
> +	  push (indent, stream, uoffset);
> +	  break;
> +
> +	case DW_OP_const1u:
> +	  push (indent, stream,
> +		extract_unsigned_integer (op_ptr, 1, byte_order));
> +	  op_ptr += 1;
> +	  break;
> +	case DW_OP_const1s:
> +	  push (indent, stream,
> +		extract_signed_integer (op_ptr, 1, byte_order));
> +	  op_ptr += 1;
> +	  break;
> +	case DW_OP_const2u:
> +	  push (indent, stream,
> +		extract_unsigned_integer (op_ptr, 2, byte_order));
> +	  op_ptr += 2;
> +	  break;
> +	case DW_OP_const2s:
> +	  push (indent, stream,
> +		extract_signed_integer (op_ptr, 2, byte_order));
> +	  op_ptr += 2;
> +	  break;
> +	case DW_OP_const4u:
> +	  push (indent, stream,
> +		extract_unsigned_integer (op_ptr, 4, byte_order));
> +	  op_ptr += 4;
> +	  break;
> +	case DW_OP_const4s:
> +	  push (indent, stream,
> +		extract_signed_integer (op_ptr, 4, byte_order));
> +	  op_ptr += 4;
> +	  break;
> +	case DW_OP_const8u:
> +	  push (indent, stream,
> +		extract_unsigned_integer (op_ptr, 8, byte_order));
> +	  op_ptr += 8;
> +	  break;
> +	case DW_OP_const8s:
> +	  push (indent, stream,
> +		extract_signed_integer (op_ptr, 8, byte_order));
> +	  op_ptr += 8;
> +	  break;
> +	case DW_OP_constu:
> +	  op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
> +	  push (indent, stream, uoffset);
> +	  break;
> +	case DW_OP_consts:
> +	  op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
> +	  push (indent, stream, offset);
> +	  break;
> +
> +	case DW_OP_reg0:
> +	case DW_OP_reg1:
> +	case DW_OP_reg2:
> +	case DW_OP_reg3:
> +	case DW_OP_reg4:
> +	case DW_OP_reg5:
> +	case DW_OP_reg6:
> +	case DW_OP_reg7:
> +	case DW_OP_reg8:
> +	case DW_OP_reg9:
> +	case DW_OP_reg10:
> +	case DW_OP_reg11:
> +	case DW_OP_reg12:
> +	case DW_OP_reg13:
> +	case DW_OP_reg14:
> +	case DW_OP_reg15:
> +	case DW_OP_reg16:
> +	case DW_OP_reg17:
> +	case DW_OP_reg18:
> +	case DW_OP_reg19:
> +	case DW_OP_reg20:
> +	case DW_OP_reg21:
> +	case DW_OP_reg22:
> +	case DW_OP_reg23:
> +	case DW_OP_reg24:
> +	case DW_OP_reg25:
> +	case DW_OP_reg26:
> +	case DW_OP_reg27:
> +	case DW_OP_reg28:
> +	case DW_OP_reg29:
> +	case DW_OP_reg30:
> +	case DW_OP_reg31:
> +	  dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_regx");
> +	  pushf_register_address (indent, stream, registers_used, arch,
> +				  dwarf2_reg_to_regnum_or_error (arch,
> +							      op - DW_OP_reg0));
> +	  break;
> +
> +	case DW_OP_regx:
> +	  op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
> +	  dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_regx");
> +	  pushf_register_address (indent, stream, registers_used, arch,
> +				  dwarf2_reg_to_regnum_or_error (arch, reg));
> +	  break;
> +
> +	case DW_OP_breg0:
> +	case DW_OP_breg1:
> +	case DW_OP_breg2:
> +	case DW_OP_breg3:
> +	case DW_OP_breg4:
> +	case DW_OP_breg5:
> +	case DW_OP_breg6:
> +	case DW_OP_breg7:
> +	case DW_OP_breg8:
> +	case DW_OP_breg9:
> +	case DW_OP_breg10:
> +	case DW_OP_breg11:
> +	case DW_OP_breg12:
> +	case DW_OP_breg13:
> +	case DW_OP_breg14:
> +	case DW_OP_breg15:
> +	case DW_OP_breg16:
> +	case DW_OP_breg17:
> +	case DW_OP_breg18:
> +	case DW_OP_breg19:
> +	case DW_OP_breg20:
> +	case DW_OP_breg21:
> +	case DW_OP_breg22:
> +	case DW_OP_breg23:
> +	case DW_OP_breg24:
> +	case DW_OP_breg25:
> +	case DW_OP_breg26:
> +	case DW_OP_breg27:
> +	case DW_OP_breg28:
> +	case DW_OP_breg29:
> +	case DW_OP_breg30:
> +	case DW_OP_breg31:
> +	  op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
> +	  pushf_register (indent, stream, registers_used, arch,
> +			  dwarf2_reg_to_regnum_or_error (arch,
> +							 op - DW_OP_breg0),
> +			  offset);
> +	  break;
> +	case DW_OP_bregx:
> +	  {
> +	    op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
> +	    op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
> +	    pushf_register (indent, stream, registers_used, arch,
> +			    dwarf2_reg_to_regnum_or_error (arch, reg), offset);
> +	  }
> +	  break;
> +	case DW_OP_fbreg:
> +	  {
> +	    const gdb_byte *datastart;
> +	    size_t datalen;
> +	    struct block *b;
> +	    struct symbol *framefunc;
> +	    char fb_name[50];
> +
> +	    b = block_for_pc (pc);
> +
> +	    if (!b)
> +	      error (_("No block found for address"));
> +
> +	    framefunc = block_linkage_function (b);
> +
> +	    if (!framefunc)
> +	      error (_("No function found for block"));
> +
> +	    dwarf_expr_frame_base_1 (framefunc, pc, &datastart, &datalen);
> +
> +	    op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
> +
> +	    /* Generate a unique-enough name, in case the frame base
> +	       is computed multiple times in this expression.  */
> +	    xsnprintf (fb_name, sizeof (fb_name), "__frame_base_%ld",
> +		       (long) (op_ptr - base));
> +
> +	    do_compile_dwarf_expr_to_c (indent, stream,
> +					"void *", fb_name,
> +					sym, pc,
> +					arch, registers_used, addr_size,
> +					datastart, datastart + datalen,
> +					NULL, per_cu);
> +
> +	    pushf (indent, stream, "%s + %s", fb_name, hex_string (offset));
> +	  }
> +	  break;
> +
> +	case DW_OP_dup:
> +	  pushf (indent, stream, "__gdb_stack[__gdb_tos]");
> +	  break;
> +
> +	case DW_OP_drop:
> +	  fprintfi_filtered (indent, stream, "--__gdb_tos;\n");
> +	  break;
> +
> +	case DW_OP_pick:
> +	  offset = *op_ptr++;
> +	  pushf (indent, stream, "__gdb_stack[__gdb_tos - %d]", offset);
> +	  break;
> +
> +	case DW_OP_swap:
> +	  fprintfi_filtered (indent, stream,
> +			     "__gdb_tmp = __gdb_stack[__gdb_tos - 1];\n");
> +	  fprintfi_filtered (indent, stream,
> +			     "__gdb_stack[__gdb_tos - 1] = "
> +			     "__gdb_stack[__gdb_tos];\n");
> +	  fprintfi_filtered (indent, stream, ("__gdb_stack[__gdb_tos] = "
> +					      "__gdb_tmp;\n"));
> +	  break;
> +
> +	case DW_OP_over:
> +	  pushf (indent, stream, "__gdb_stack[__gdb_tos - 1]");
> +	  break;
> +
> +	case DW_OP_rot:
> +	  fprintfi_filtered (indent, stream, ("__gdb_tmp = "
> +					      "__gdb_stack[__gdb_tos];\n"));
> +	  fprintfi_filtered (indent, stream,
> +			     "__gdb_stack[__gdb_tos] = "
> +			     "__gdb_stack[__gdb_tos - 1];\n");
> +	  fprintfi_filtered (indent, stream,
> +			     "__gdb_stack[__gdb_tos - 1] = "
> +			     "__gdb_stack[__gdb_tos -2];\n");
> +	  fprintfi_filtered (indent, stream, "__gdb_stack[__gdb_tos - 2] = "
> +			     "__gdb_tmp;\n");
> +	  break;
> +
> +	case DW_OP_deref:
> +	case DW_OP_deref_size:
> +	  {
> +	    int size;
> +	    const char *mode;
> +
> +	    if (op == DW_OP_deref_size)
> +	      size = *op_ptr++;
> +	    else
> +	      size = addr_size;
> +
> +	    mode = c_get_mode_for_size (size);
> +	    if (mode == NULL)
> +	      error (_("Unsupported size %d in %s"),
> +		     size, get_DW_OP_name (op));
> +
> +	    /* Cast to a pointer of the desired type, then
> +	       dereference.  */
> +	    fprintfi_filtered (indent, stream,
> +			       "__gdb_stack[__gdb_tos] = "
> +			       "*((__gdb_int_%s *) "
> +			       "__gdb_stack[__gdb_tos]);\n",
> +			       mode);
> +	  }
> +	  break;
> +
> +	case DW_OP_abs:
> +	  unary (indent, stream,
> +		 "((" GCC_INTPTR ") __gdb_stack[__gdb_tos]) < 0 ? "
> +		 "-__gdb_stack[__gdb_tos] : __gdb_stack[__gdb_tos]");
> +	  break;
> +
> +	case DW_OP_neg:
> +	  unary (indent, stream, "-__gdb_stack[__gdb_tos]");
> +	  break;
> +
> +	case DW_OP_not:
> +	  unary (indent, stream, "~__gdb_stack[__gdb_tos]");
> +	  break;
> +
> +	case DW_OP_plus_uconst:
> +	  op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
> +	  unary (indent, stream, "__gdb_stack[__gdb_tos] + %s",
> +		 hex_string (reg));
> +	  break;
> +
> +	case DW_OP_div:
> +	  binary (indent, stream, ("((" GCC_INTPTR
> +				   ") __gdb_stack[__gdb_tos-1]) / (("
> +				   GCC_INTPTR ") __gdb_stack[__gdb_tos])"));
> +	  break;
> +
> +	case DW_OP_shra:
> +	  binary (indent, stream,
> +		  "((" GCC_INTPTR ") __gdb_stack[__gdb_tos-1]) >> "
> +		  "__gdb_stack[__gdb_tos]");
> +	  break;
> +
> +#define BINARY(OP)							\
> +	  binary (indent, stream, ("__gdb_stack[__gdb_tos-1] " #OP	\
> +				   " __gdb_stack[__gdb_tos]"));	\
> +	  break
> +
> +	case DW_OP_and:
> +	  BINARY (&);
> +	case DW_OP_minus:
> +	  BINARY (-);
> +	case DW_OP_mod:
> +	  BINARY (%);
> +	case DW_OP_mul:
> +	  BINARY (*);
> +	case DW_OP_or:
> +	  BINARY (|);
> +	case DW_OP_plus:
> +	  BINARY (+);
> +	case DW_OP_shl:
> +	  BINARY (<<);
> +	case DW_OP_shr:
> +	  BINARY (>>);
> +	case DW_OP_xor:
> +	  BINARY (^);
> +#undef BINARY
> +
> +#define COMPARE(OP)							\
> +	  binary (indent, stream,					\
> +		  "(((" GCC_INTPTR ") __gdb_stack[__gdb_tos-1]) " #OP	\
> +		  " ((" GCC_INTPTR					\
> +		  ") __gdb_stack[__gdb_tos]))");			\
> +	  break
> +
> +	case DW_OP_le:
> +	  COMPARE (<=);
> +	case DW_OP_ge:
> +	  COMPARE (>=);
> +	case DW_OP_eq:
> +	  COMPARE (==);
> +	case DW_OP_lt:
> +	  COMPARE (<);
> +	case DW_OP_gt:
> +	  COMPARE (>);
> +	case DW_OP_ne:
> +	  COMPARE (!=);
> +#undef COMPARE
> +
> +	case DW_OP_call_frame_cfa:
> +	  {
> +	    int regnum;
> +	    CORE_ADDR text_offset;
> +	    LONGEST off;
> +	    const gdb_byte *cfa_start, *cfa_end;
> +
> +	    if (dwarf2_fetch_cfa_info (arch, pc, per_cu,
> +				       &regnum, &off,
> +				       &text_offset, &cfa_start, &cfa_end))
> +	      {
> +		/* Register.  */
> +		pushf_register (indent, stream, registers_used, arch, regnum,
> +				off);
> +	      }
> +	    else
> +	      {
> +		/* Another expression.  */
> +		char cfa_name[50];
> +
> +		/* Generate a unique-enough name, in case the CFA is
> +		   computed multiple times in this expression.  */
> +		xsnprintf (cfa_name, sizeof (cfa_name),
> +			   "__cfa_%ld", (long) (op_ptr - base));
> +
> +		do_compile_dwarf_expr_to_c (indent, stream,
> +					    "void *", cfa_name,
> +					    sym, pc, arch, registers_used,
> +					    addr_size,
> +					    cfa_start, cfa_end,
> +					    &text_offset, per_cu);
> +		pushf (indent, stream, cfa_name);
> +	      }
> +	  }
> +
> +	  break;
> +
> +	case DW_OP_skip:
> +	  offset = extract_signed_integer (op_ptr, 2, byte_order);
> +	  op_ptr += 2;
> +	  fprintfi_filtered (indent, stream, "goto ");
> +	  print_label (stream, scope, op_ptr + offset - base);
> +	  fprintf_filtered (stream, ";\n");
> +	  break;
> +
> +	case DW_OP_bra:
> +	  offset = extract_signed_integer (op_ptr, 2, byte_order);
> +	  op_ptr += 2;
> +	  fprintfi_filtered (indent, stream,
> +			     "if ((( " GCC_INTPTR
> +			     ") __gdb_stack[__gdb_tos--]) != 0) goto ");
> +	  print_label (stream, scope, op_ptr + offset - base);
> +	  fprintf_filtered (stream, ";\n");
> +	  break;
> +
> +	case DW_OP_nop:
> +	  break;
> +
> +	default:
> +	  error (_("unhandled DWARF op: %s"), get_DW_OP_name (op));
> +	}
> +    }
> +
> +  fprintfi_filtered (indent, stream, "%s = (%s) __gdb_stack[__gdb_tos];\n",
> +		     result_name, type_name);
> +  fprintfi_filtered (indent - 2, stream, "}\n");
> +
> +  do_cleanups (cleanup);
> +}
> +
> +/* See compile.h.  */
> +
> +void
> +compile_dwarf_expr_to_c (struct ui_file *stream, const char *result_name,
> +			 struct symbol *sym, CORE_ADDR pc,
> +			 struct gdbarch *arch, unsigned char *registers_used,
> +			 unsigned int addr_size,
> +			 const gdb_byte *op_ptr, const gdb_byte *op_end,
> +			 struct dwarf2_per_cu_data *per_cu)
> +{
> +  do_compile_dwarf_expr_to_c (2, stream, "void *", result_name, sym, pc,
> +			      arch, registers_used, addr_size, op_ptr, op_end,
> +			      NULL, per_cu);
> +}
> +
> +/* See compile.h.  */
> +
> +void
> +compile_dwarf_bounds_to_c (struct ui_file *stream,
> +			   const char *result_name,
> +			   const struct dynamic_prop *prop,
> +			   struct symbol *sym, CORE_ADDR pc,
> +			   struct gdbarch *arch, unsigned char *registers_used,
> +			   unsigned int addr_size,
> +			   const gdb_byte *op_ptr, const gdb_byte *op_end,
> +			   struct dwarf2_per_cu_data *per_cu)
> +{
> +  do_compile_dwarf_expr_to_c (2, stream, "unsigned long ", result_name,
> +			      sym, pc, arch, registers_used,
> +			      addr_size, op_ptr, op_end, NULL, per_cu);
> +}
> diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c
> new file mode 100644
> index 0000000..abf5b43
> --- /dev/null
> +++ b/gdb/compile/compile-object-load.c
> @@ -0,0 +1,570 @@
> +/* Load module for 'compile' command.
> +
> +   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/>.  */
> +
> +#include "defs.h"
> +#include "compile-object-load.h"
> +#include "compile-internal.h"
> +#include "command.h"
> +#include "objfiles.h"
> +#include "gdbcore.h"
> +#include "readline/tilde.h"
> +#include "bfdlink.h"
> +#include "gdbcmd.h"
> +#include "regcache.h"
> +#include "inferior.h"
> +#include "compile.h"
> +
> +/* Helper data for setup_sections.  */
> +
> +struct setup_sections_data
> +{
> +  /* Size of all recent sections with matching LAST_PROT.  */
> +  CORE_ADDR last_size;
> +
> +  /* First section matching LAST_PROT.  */
> +  asection *last_section_first;
> +
> +  /* Memory protection like the prot parameter of gdbarch_infcall_mmap. */
> +  unsigned last_prot;
> +
> +  /* Maximum of alignments of all sections matching LAST_PROT.
> +     This value is always at least 1.  This value is always a power of 2.  */
> +  CORE_ADDR last_max_alignment;
> +};
> +
> +/* Place all ABFD sections next to each other obeying all constraints.  */
> +
> +static void
> +setup_sections (bfd *abfd, asection *sect, void *data_voidp)
> +{
> +  struct setup_sections_data *data = data_voidp;
> +  CORE_ADDR alignment;
> +  unsigned prot;
> +
> +  if (sect != NULL)
> +    {
> +      /* It is required by later bfd_get_relocated_section_contents.  */
> +      if (sect->output_section == NULL)
> +	sect->output_section = sect;
> +
> +      if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
> +	return;
> +
> +      // Make the memory always readable.
> +      prot = 4;
> +      if ((bfd_get_section_flags (abfd, sect) & SEC_READONLY) == 0)
> +	prot |= 2;
> +      if ((bfd_get_section_flags (abfd, sect) & SEC_CODE) != 0)
> +	prot |= 1;
> +
> +      if (compile_debug)
> +	fprintf_unfiltered (gdb_stdout,
> +			    "module \"%s\" section \"%s\" size %s prot %u\n",
> +			    bfd_get_filename (abfd),
> +			    bfd_get_section_name (abfd, sect),
> +			    paddress (target_gdbarch (),
> +				      bfd_get_section_size (sect)),
> +			    prot);
> +    }
> +  else
> +    prot = -1;
> +
> +  if (sect == NULL
> +      || (data->last_prot != prot && bfd_get_section_size (sect) != 0))
> +    {
> +      CORE_ADDR addr;
> +      asection *sect_iter;
> +
> +      if (data->last_size != 0)
> +	{
> +	  addr = gdbarch_infcall_mmap (target_gdbarch (), data->last_size,
> +				       data->last_prot);
> +	  if (compile_debug)
> +	    fprintf_unfiltered (gdb_stdout,
> +				"allocated %s bytes at %s prot %u\n",
> +				paddress (target_gdbarch (), data->last_size),
> +				paddress (target_gdbarch (), addr),
> +				data->last_prot);
> +	}
> +      else
> +	addr = 0;
> +
> +      if ((addr & (data->last_max_alignment - 1)) != 0)
> +	error (_("Inferior compiled module address %s "
> +		 "is not aligned to BFD required %s."),
> +	       paddress (target_gdbarch (), addr),
> +	       paddress (target_gdbarch (), data->last_max_alignment));
> +
> +      for (sect_iter = data->last_section_first; sect_iter != sect;
> +	   sect_iter = sect_iter->next)
> +	if ((bfd_get_section_flags (abfd, sect_iter) & SEC_ALLOC) != 0)
> +	  bfd_set_section_vma (abfd, sect_iter,
> +			       addr + bfd_get_section_vma (abfd, sect_iter));
> +
> +      data->last_size = 0;
> +      data->last_section_first = sect;
> +      data->last_prot = prot;
> +      data->last_max_alignment = 1;
> +    }
> +
> +  if (sect == NULL)
> +    return;
> +
> +  alignment = ((CORE_ADDR) 1) << bfd_get_section_alignment (abfd, sect);
> +  data->last_max_alignment = max (data->last_max_alignment, alignment);
> +
> +  data->last_size = (data->last_size + alignment - 1) & -alignment;
> +
> +  bfd_set_section_vma (abfd, sect, data->last_size);
> +
> +  data->last_size += bfd_get_section_size (sect);
> +  data->last_size = (data->last_size + alignment - 1) & -alignment;
> +}
> +
> +/* Helper for link_callbacks callbacks vector.  */
> +
> +static bfd_boolean
> +link_callbacks_multiple_definition (struct bfd_link_info *link_info,
> +				    struct bfd_link_hash_entry *h, bfd *nbfd,
> +				    asection *nsec, bfd_vma nval)
> +{
> +  bfd *abfd = link_info->input_bfds;
> +
> +  if (link_info->allow_multiple_definition)
> +    return TRUE;
> +  warning (_("Compiled module \"%s\": multiple symbol definitions: %s\n"),
> +	   bfd_get_filename (abfd), h->root.string);
> +  return FALSE;
> +}
> +
> +/* Helper for link_callbacks callbacks vector.  */
> +
> +static bfd_boolean
> +link_callbacks_warning (struct bfd_link_info *link_info, const char *xwarning,
> +                        const char *symbol, bfd *abfd, asection *section,
> +			bfd_vma address)
> +{
> +  warning (_("Compiled module \"%s\" section \"%s\": warning: %s\n"),
> +	   bfd_get_filename (abfd), bfd_get_section_name (abfd, section),
> +	   xwarning);
> +  /* Maybe permit running as a module?  */
> +  return FALSE;
> +}
> +
> +/* Helper for link_callbacks callbacks vector.  */
> +
> +static bfd_boolean
> +link_callbacks_undefined_symbol (struct bfd_link_info *link_info,
> +				 const char *name, bfd *abfd, asection *section,
> +				 bfd_vma address, bfd_boolean is_fatal)
> +{
> +  warning (_("Cannot resolve relocation to \"%s\" "
> +	     "from compiled module \"%s\" section \"%s\"."),
> +	   name, bfd_get_filename (abfd), bfd_get_section_name (abfd, section));
> +  return FALSE;
> +}
> +
> +/* Helper for link_callbacks callbacks vector.  */
> +
> +static bfd_boolean
> +link_callbacks_reloc_overflow (struct bfd_link_info *link_info,
> +			       struct bfd_link_hash_entry *entry,
> +			       const char *name, const char *reloc_name,
> +			       bfd_vma addend, bfd *abfd, asection *section,
> +			       bfd_vma address)
> +{
> +  /* TRUE is required for intra-module relocations.  */
> +  return TRUE;
> +}
> +
> +/* Helper for link_callbacks callbacks vector.  */
> +
> +static bfd_boolean
> +link_callbacks_reloc_dangerous (struct bfd_link_info *link_info,
> +				const char *message, bfd *abfd,
> +				asection *section, bfd_vma address)
> +{
> +  warning (_("Compiled module \"%s\" section \"%s\": dangerous "
> +	     "relocation: %s\n"),
> +	   bfd_get_filename (abfd), bfd_get_section_name (abfd, section),
> +	   message);
> +  return FALSE;
> +}
> +
> +/* Helper for link_callbacks callbacks vector.  */
> +
> +static bfd_boolean
> +link_callbacks_unattached_reloc (struct bfd_link_info *link_info,
> +				 const char *name, bfd *abfd, asection *section,
> +				 bfd_vma address)
> +{
> +  warning (_("Compiled module \"%s\" section \"%s\": unattached "
> +	     "relocation: %s\n"),
> +	   bfd_get_filename (abfd), bfd_get_section_name (abfd, section),
> +	   name);
> +  return FALSE;
> +}
> +
> +/* Helper for link_callbacks callbacks vector.  */
> +
> +static void
> +link_callbacks_einfo (const char *fmt, ...)
> +{
> +  struct cleanup *cleanups;
> +  va_list ap;
> +  char *str;
> +
> +  va_start (ap, fmt);
> +  str = xstrvprintf (fmt, ap);
> +  va_end (ap);
> +  cleanups = make_cleanup (xfree, str);
> +
> +  warning (_("Compile module: warning: %s\n"), str);
> +
> +  do_cleanups (cleanups);
> +}
> +
> +/* Helper for bfd_get_relocated_section_contents.
> +   Only these symbols are set by bfd_simple_get_relocated_section_contents
> +   but bfd/ seems to use even the NULL ones without checking them first.  */
> +
> +static const struct bfd_link_callbacks link_callbacks =
> +{
> +  NULL, /* add_archive_element */
> +  link_callbacks_multiple_definition, /* multiple_definition */
> +  NULL, /* multiple_common */
> +  NULL, /* add_to_set */
> +  NULL, /* constructor */
> +  link_callbacks_warning, /* warning */
> +  link_callbacks_undefined_symbol, /* undefined_symbol */
> +  link_callbacks_reloc_overflow, /* reloc_overflow */
> +  link_callbacks_reloc_dangerous, /* reloc_dangerous */
> +  link_callbacks_unattached_reloc, /* unattached_reloc */
> +  NULL, /* notice */
> +  link_callbacks_einfo, /* einfo */
> +  NULL, /* info */
> +  NULL, /* minfo */
> +  NULL, /* override_segment_assignment */
> +};
> +
> +/* Cleanup callback for struct bfd_link_info.  */
> +
> +static void
> +link_hash_table_free (void *data)
> +{
> +  struct bfd_link_info *link_info = data;
> +  bfd *abfd = link_info->input_bfds;
> +
> +  bfd_link_hash_table_free (abfd, link_info->hash);
> +}
> +
> +/* Relocate and store into inferior memory each section SECT of ABFD.  */
> +
> +static void
> +copy_sections (bfd *abfd, asection *sect, void *data)
> +{
> +  asymbol **symbol_table = data;
> +  bfd_byte *sect_data, *sect_data_got;
> +  struct cleanup *cleanups;
> +  struct bfd_link_info link_info;
> +  struct bfd_link_order link_order;
> +  CORE_ADDR inferior_addr;
> +
> +  if ((bfd_get_section_flags (abfd, sect) & (SEC_ALLOC | SEC_LOAD))
> +      != (SEC_ALLOC | SEC_LOAD))
> +    return;
> +
> +  if (bfd_get_section_size (sect) == 0)
> +    return;
> +
> +  /* Mostly a copy of bfd_simple_get_relocated_section_contents which GDB
> +     cannot use as it does not report relocations to undefined symbols.  */
> +  memset (&link_info, 0, sizeof (link_info));
> +  link_info.output_bfd = abfd;
> +  link_info.input_bfds = abfd;
> +  link_info.input_bfds_tail = &abfd->link_next;
> +  link_info.hash = bfd_link_hash_table_create (abfd);
> +  cleanups = make_cleanup (link_hash_table_free, &link_info);
> +  link_info.callbacks = &link_callbacks;
> +  memset (&link_order, 0, sizeof (link_order));
> +  link_order.next = NULL;
> +  link_order.type = bfd_indirect_link_order;
> +  link_order.offset = 0;
> +  link_order.size = bfd_get_section_size (sect);
> +  link_order.u.indirect.section = sect;
> +
> +  sect_data = xmalloc (bfd_get_section_size (sect));
> +  make_cleanup (xfree, sect_data);
> +
> +  sect_data_got = bfd_get_relocated_section_contents (abfd, &link_info,
> +						      &link_order, sect_data,
> +						      FALSE, symbol_table);
> +  if (sect_data_got == NULL)
> +    error (_("Cannot map compiled module \"%s\" section \"%s\": %s"),
> +	   bfd_get_filename (abfd), bfd_get_section_name (abfd, sect),
> +	   bfd_errmsg (bfd_get_error ()));
> +  gdb_assert (sect_data_got == sect_data);
> +
> +  inferior_addr = bfd_get_section_vma (abfd, sect);
> +  if (0 != target_write_memory (inferior_addr, sect_data,
> +				bfd_get_section_size (sect)))
> +    error (_("Cannot write compiled module \"%s\" section \"%s\" "
> +	     "to inferior memory range %s-%s."),
> +	   bfd_get_filename (abfd), bfd_get_section_name (abfd, sect),
> +	   paddress (target_gdbarch (), inferior_addr),
> +	   paddress (target_gdbarch (),
> +		     inferior_addr + bfd_get_section_size (sect)));
> +
> +  do_cleanups (cleanups);
> +}
> +
> +/* Fetch the type of first parameter of GCC_FE_WRAPPER_FUNCTION.
> +   Return NULL if GCC_FE_WRAPPER_FUNCTION has no parameters.
> +   Throw an error otherwise.  */
> +
> +static struct type *
> +get_regs_type (struct objfile *objfile)
> +{
> +  struct symbol *func_sym;
> +  struct type *func_type, *regsp_type, *regs_type;
> +
> +  func_sym = lookup_global_symbol_from_objfile (objfile,
> +						GCC_FE_WRAPPER_FUNCTION,
> +						VAR_DOMAIN);
> +  if (func_sym == NULL)
> +    error (_("Cannot find function \"%s\" in compiled module \"%s\"."),
> +	   GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile));
> +
> +  func_type = SYMBOL_TYPE (func_sym);
> +  if (TYPE_CODE (func_type) != TYPE_CODE_FUNC)
> +    error (_("Invalid type code %d of function \"%s\" in compiled "
> +	     "module \"%s\"."),
> +	   TYPE_CODE (func_type), GCC_FE_WRAPPER_FUNCTION,
> +	   objfile_name (objfile));
> +
> +  /* No register parameter present.  */
> +  if (TYPE_NFIELDS (func_type) == 0)
> +    return NULL;
> +
> +  if (TYPE_NFIELDS (func_type) != 1)
> +    error (_("Invalid %d parameters of function \"%s\" in compiled "
> +	     "module \"%s\"."),
> +	   TYPE_NFIELDS (func_type), GCC_FE_WRAPPER_FUNCTION,
> +	   objfile_name (objfile));
> +
> +  regsp_type = check_typedef (TYPE_FIELD_TYPE (func_type, 0));
> +  if (TYPE_CODE (regsp_type) != TYPE_CODE_PTR)
> +    error (_("Invalid type code %d of first parameter of function \"%s\" "
> +	     "in compiled module \"%s\"."),
> +	   TYPE_CODE (regsp_type), GCC_FE_WRAPPER_FUNCTION,
> +	   objfile_name (objfile));
> +
> +  regs_type = check_typedef (TYPE_TARGET_TYPE (regsp_type));
> +  if (TYPE_CODE (regs_type) != TYPE_CODE_STRUCT)
> +    error (_("Invalid type code %d of dereferenced first parameter "
> +	     "of function \"%s\" in compiled module \"%s\"."),
> +	   TYPE_CODE (regs_type), GCC_FE_WRAPPER_FUNCTION,
> +	   objfile_name (objfile));
> +
> +  return regs_type;
> +}
> +
> +/* Store all inferior registers required by REGS_TYPE to inferior memory
> +   starting at inferior address REGS_BASE.  */
> +
> +static void
> +store_regs (struct type *regs_type, CORE_ADDR regs_base)
> +{
> +  struct gdbarch *gdbarch = target_gdbarch ();
> +  struct regcache *regcache = get_thread_regcache (inferior_ptid);
> +  int fieldno;
> +
> +  for (fieldno = 0; fieldno < TYPE_NFIELDS (regs_type); fieldno++)
> +    {
> +      const char *reg_name = TYPE_FIELD_NAME (regs_type, fieldno);
> +      ULONGEST reg_bitpos = TYPE_FIELD_BITPOS (regs_type, fieldno);
> +      ULONGEST reg_bitsize = TYPE_FIELD_BITSIZE (regs_type, fieldno);
> +      ULONGEST reg_offset;
> +      struct type *reg_type = check_typedef (TYPE_FIELD_TYPE (regs_type,
> +							      fieldno));
> +      ULONGEST reg_size = TYPE_LENGTH (reg_type);
> +      int regnum;
> +      struct value *regval;
> +      CORE_ADDR inferior_addr;
> +
> +      if (strcmp (reg_name, COMPILE_I_SIMPLE_REGISTER_DUMMY) == 0)
> +	continue;
> +
> +      if ((reg_bitpos % 8) != 0 || reg_bitsize != 0)
> +	error (_("Invalid register \"%s\" position %s bits or size %s bits"),
> +	       reg_name, pulongest (reg_bitpos), pulongest (reg_bitsize));
> +      reg_offset = reg_bitpos / 8;
> +
> +      if (TYPE_CODE (reg_type) != TYPE_CODE_INT
> +	  && TYPE_CODE (reg_type) != TYPE_CODE_PTR)
> +	error (_("Invalid register \"%s\" type code %d"), reg_name,
> +	       TYPE_CODE (reg_type));
> +
> +      regnum = compile_register_name_demangle (gdbarch, reg_name);
> +
> +      regval = value_from_register (reg_type, regnum, get_current_frame ());
> +      if (value_optimized_out (regval))
> +	error (_("Register \"%s\" is optimized out."), reg_name);
> +      if (!value_entirely_available (regval))
> +	error (_("Register \"%s\" is not available."), reg_name);
> +
> +      inferior_addr = regs_base + reg_offset;
> +      if (0 != target_write_memory (inferior_addr, value_contents (regval),
> +				    reg_size))
> +	error (_("Cannot write register \"%s\" to inferior memory at %s."),
> +	       reg_name, paddress (gdbarch, inferior_addr));
> +    }
> +}
> +
> +/* Load OBJECT_FILE into inferior memory.  Throw an error otherwise.
> +   Caller must fully dispose the return value by calling compile_object_run.
> +   SOURCE_FILE's copy is stored into the returned object.
> +   Caller should free both OBJECT_FILE and SOURCE_FILE immediatelly after this
> +   function returns.  */
> +
> +struct compile_module *
> +compile_object_load (const char *object_file, const char *source_file)
> +{
> +  struct cleanup *cleanups, *cleanups_free_objfile;
> +  bfd *abfd;
> +  struct setup_sections_data setup_sections_data;
> +  CORE_ADDR addr, func_addr, regs_addr;
> +  struct bound_minimal_symbol bmsym;
> +  long storage_needed;
> +  asymbol **symbol_table, **symp;
> +  long number_of_symbols, missing_symbols;
> +  struct type *dptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
> +  unsigned dptr_type_len = TYPE_LENGTH (dptr_type);
> +  struct compile_module *retval;
> +  struct type *regs_type;
> +  char *filename, **matching;
> +  struct objfile *objfile;
> +
> +  filename = tilde_expand (object_file);
> +  cleanups = make_cleanup (xfree, filename);
> +
> +  abfd = gdb_bfd_open (filename, gnutarget, -1);
> +  if (abfd == NULL)
> +    error (_("\"%s\": could not open as compiled module: %s"),
> +          filename, bfd_errmsg (bfd_get_error ()));
> +  make_cleanup_bfd_unref (abfd);
> +
> +  if (!bfd_check_format_matches (abfd, bfd_object, &matching))
> +    error (_("\"%s\": not in loadable format: %s"),
> +          filename, gdb_bfd_errmsg (bfd_get_error (), matching));
> +
> +  if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) != 0)
> +    error (_("\"%s\": not in object format."), filename);
> +
> +  setup_sections_data.last_size = 0;
> +  setup_sections_data.last_section_first = abfd->sections;
> +  setup_sections_data.last_prot = -1;
> +  setup_sections_data.last_max_alignment = 1;
> +  bfd_map_over_sections (abfd, setup_sections, &setup_sections_data);
> +  setup_sections (abfd, NULL, &setup_sections_data);
> +
> +  storage_needed = bfd_get_symtab_upper_bound (abfd);
> +  if (storage_needed < 0)
> +    error (_("Cannot read symbols of compiled module \"%s\": %s"),
> +          filename, bfd_errmsg (bfd_get_error ()));
> +
> +  /* SYMFILE_VERBOSE is not passed even if FROM_TTY, user is not interested in
> +     "Reading symbols from ..." message for automatically generated file.  */
> +  objfile = symbol_file_add_from_bfd (abfd, filename, 0, NULL, 0, NULL);
> +  cleanups_free_objfile = make_cleanup_free_objfile (objfile);
> +
> +  bmsym = lookup_minimal_symbol_text (GCC_FE_WRAPPER_FUNCTION, objfile);
> +  if (bmsym.minsym == NULL || MSYMBOL_TYPE (bmsym.minsym) == mst_file_text)
> +    error (_("Could not find symbol \"%s\" of compiled module \"%s\"."),
> +	   GCC_FE_WRAPPER_FUNCTION, filename);
> +  func_addr = BMSYMBOL_VALUE_ADDRESS (bmsym);
> +
> +  /* The memory may be later needed
> +     by bfd_generic_get_relocated_section_contents
> +     called from default_symfile_relocate.  */
> +  symbol_table = obstack_alloc (&objfile->objfile_obstack, storage_needed);
> +  number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
> +  if (number_of_symbols < 0)
> +    error (_("Cannot parse symbols of compiled module \"%s\": %s"),
> +          filename, bfd_errmsg (bfd_get_error ()));
> +
> +  missing_symbols = 0;
> +  for (symp = symbol_table; symp < symbol_table + number_of_symbols; symp++)
> +    {
> +      asymbol *sym = *symp;
> +
> +      if (sym->flags != 0)
> +	continue;
> +      if (compile_debug)
> +	fprintf_unfiltered (gdb_stdout,
> +			    "lookup undefined ELF symbol \"%s\"\n",
> +			    sym->name);
> +      sym->flags = BSF_GLOBAL;
> +      sym->section = bfd_abs_section_ptr;
> +      if (strcmp (sym->name, "_GLOBAL_OFFSET_TABLE_") == 0)
> +	{
> +	  sym->value = 0;
> +	  continue;
> +	}
> +      bmsym = lookup_minimal_symbol (sym->name, NULL, NULL);
> +      switch (bmsym.minsym == NULL
> +	      ? mst_unknown : MSYMBOL_TYPE (bmsym.minsym))
> +	{
> +	case mst_text:
> +	  sym->value = BMSYMBOL_VALUE_ADDRESS (bmsym);
> +	  break;
> +	default:
> +	  warning (_("Could not find symbol \"%s\" "
> +		     "for compiled module \"%s\"."),
> +		   sym->name, filename);
> +	  missing_symbols++;
> +	}
> +    }
> +  if (missing_symbols)
> +    error (_("%ld symbols were missing, cannot continue."), missing_symbols);
> +
> +  bfd_map_over_sections (abfd, copy_sections, symbol_table);
> +
> +  regs_type = get_regs_type (objfile);
> +  if (regs_type == NULL)
> +    regs_addr = 0;
> +  else
> +    {
> +      /* Use read-only non-executable memory protection.  */
> +      regs_addr = gdbarch_infcall_mmap (target_gdbarch (),
> +					TYPE_LENGTH (regs_type), 4);
> +      gdb_assert (regs_addr != 0);
> +      store_regs (regs_type, regs_addr);
> +    }
> +
> +  discard_cleanups (cleanups_free_objfile);
> +  do_cleanups (cleanups);
> +
> +  retval = xmalloc (sizeof (*retval));
> +  retval->objfile = objfile;
> +  retval->source_file = xstrdup (source_file);
> +  retval->func_addr = func_addr;
> +  retval->regs_addr = regs_addr;
> +  return retval;
> +}
> diff --git a/gdb/compile/compile-object-load.h b/gdb/compile/compile-object-load.h
> new file mode 100644
> index 0000000..850111e
> --- /dev/null
> +++ b/gdb/compile/compile-object-load.h
> @@ -0,0 +1,39 @@
> +/* Header file to load module for 'compile' command.
> +   Copyright (C) 2014 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_OBJECT_LOAD_H
> +#define GDB_COMPILE_OBJECT_LOAD_H
> +
> +struct compile_module
> +{
> +  /* objfile for the compiled module.  */
> +  struct objfile *objfile;
> +
> +  /* .c file OBJFILE was built from.  It needs to be xfree-d.  */
> +  char *source_file;
> +
> +  /* Inferior function address.  */
> +  CORE_ADDR func_addr;
> +
> +  /* Inferior registers address or NULL if the inferior function does not
> +     require any.  */
> +  CORE_ADDR regs_addr;
> +};
> +
> +extern struct compile_module *compile_object_load (const char *object_file,
> +						   const char *source_file);
> +
> +#endif /* GDB_COMPILE_OBJECT_LOAD_H */
> diff --git a/gdb/compile/compile-object-run.c b/gdb/compile/compile-object-run.c
> new file mode 100644
> index 0000000..b7c4c4d
> --- /dev/null
> +++ b/gdb/compile/compile-object-run.c
> @@ -0,0 +1,138 @@
> +/* Call module for 'compile' command.
> +
> +   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/>.  */
> +
> +#include "defs.h"
> +#include "compile-object-run.h"
> +#include "value.h"
> +#include "infcall.h"
> +#include "objfiles.h"
> +#include "compile-internal.h"
> +#include "dummy-frame.h"
> +
> +/* Helper for do_module_cleanup.  */
> +
> +struct do_module_cleanup
> +{
> +  /* Boolean to set true upon a call of do_module_cleanup.
> +     The pointer may be NULL.  */
> +  int *executedp;
> +
> +  /* .c file OBJFILE was built from.  It needs to be xfree-d.  */
> +  char *source_file;
> +
> +  /* objfile_name of our objfile.  */
> +  char objfile_name_string[1];
> +};
> +
> +/* Cleanup everything after the inferior function dummy frame gets
> +   discarded.  */
> +
> +static dummy_frame_dtor_ftype do_module_cleanup;
> +static void
> +do_module_cleanup (void *arg)
> +{
> +  struct do_module_cleanup *data = arg;
> +  struct objfile *objfile;
> +
> +  if (data->executedp != NULL)
> +    *data->executedp = 1;
> +
> +  ALL_OBJFILES (objfile)
> +    if ((objfile->flags & OBJF_USERLOADED) == 0
> +        && (strcmp (objfile_name (objfile), data->objfile_name_string) == 0))
> +      {
> +	free_objfile (objfile);
> +
> +	/* It may be a bit too pervasive in this dummy_frame dtor callback.  */
> +	clear_symtab_users (0);
> +
> +	break;
> +      }
> +
> +  /* Delete the .c file.  */
> +  unlink (data->source_file);
> +  xfree (data->source_file);
> +
> +  /* Delete the .o file.  */
> +  unlink (data->objfile_name_string);
> +  xfree (data);
> +}
> +
> +/* Perform inferior call of MODULE.  This function may throw an error.
> +   This function may leave files referenced by MODULE on disk until
> +   the inferior call dummy frame is discarded.  This function may throw errors.
> +   Thrown errors and left MODULE files are unrelated events.  Caller must no
> +   longer touch MODULE's memory after this function has been called.  */
> +
> +void
> +compile_object_run (struct compile_module *module)
> +{
> +  struct value *func_val;
> +  struct frame_id dummy_id;
> +  struct cleanup *cleanups;
> +  struct do_module_cleanup *data;
> +  volatile struct gdb_exception ex;
> +  const char *objfile_name_s = objfile_name (module->objfile);
> +  int dtor_found, executed = 0;
> +  CORE_ADDR func_addr = module->func_addr;
> +  CORE_ADDR regs_addr = module->regs_addr;
> +
> +  data = xmalloc (sizeof (*data) + strlen (objfile_name_s));
> +  data->executedp = &executed;
> +  data->source_file = xstrdup (module->source_file);
> +  strcpy (data->objfile_name_string, objfile_name_s);
> +
> +  xfree (module->source_file);
> +  xfree (module);
> +
> +  TRY_CATCH (ex, RETURN_MASK_ERROR)
> +    {
> +      func_val = value_from_pointer
> +		 (builtin_type (target_gdbarch ())->builtin_func_ptr,
> +		  func_addr);
> +
> +      if (regs_addr == 0)
> +	call_function_by_hand_dummy (func_val, 0, NULL,
> +				     do_module_cleanup, data);
> +      else
> +	{
> +	  struct value *arg_val;
> +
> +	  arg_val = value_from_pointer
> +		    (builtin_type (target_gdbarch ())->builtin_func_ptr,
> +		     regs_addr);
> +	  call_function_by_hand_dummy (func_val, 1, &arg_val,
> +				       do_module_cleanup, data);
> +	}
> +    }
> +  dtor_found = find_dummy_frame_dtor (do_module_cleanup, data);
> +  if (!executed)
> +    data->executedp = NULL;
> +  if (ex.reason >= 0)
> +    gdb_assert (!dtor_found && executed);
> +  else
> +    {
> +      /* In the case od DTOR_FOUND or in the case of EXECUTED nothing
> +	 needs to be done.  */
> +      gdb_assert (!(dtor_found && executed));
> +      if (!dtor_found && !executed)
> +	do_module_cleanup (data);
> +      throw_exception (ex);
> +    }
> +}
> diff --git a/gdb/compile/compile-object-run.h b/gdb/compile/compile-object-run.h
> new file mode 100644
> index 0000000..71ba077
> --- /dev/null
> +++ b/gdb/compile/compile-object-run.h
> @@ -0,0 +1,24 @@
> +/* Header file to call module for 'compile' command.
> +   Copyright (C) 2014 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_OBJECT_RUN_H
> +#define GDB_COMPILE_OBJECT_RUN_H
> +
> +#include "compile-object-load.h"
> +
> +extern void compile_object_run (struct compile_module *module);
> +
> +#endif /* GDB_COMPILE_OBJECT_RUN_H */
> diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
> new file mode 100644
> index 0000000..86571e8
> --- /dev/null
> +++ b/gdb/compile/compile.c
> @@ -0,0 +1,623 @@
> +/* General Compile and inject code
> +
> +   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/>.  */
> +
> +#include "defs.h"
> +#include "interps.h"
> +#include "ui-out.h"
> +#include "command.h"
> +#include "cli/cli-script.h"
> +#include "cli/cli-utils.h"
> +#include "completer.h"
> +#include "gdbcmd.h"
> +#include "compile.h"
> +#include "compile-internal.h"
> +#include "compile-object-load.h"
> +#include "compile-object-run.h"
> +#include "language.h"
> +#include "frame.h"
> +#include "source.h"
> +#include "block.h"
> +#include "arch-utils.h"
> +#include "filestuff.h"
> +#include "target.h"
> +
> +
> +
> +/* Hold "compile" commands.  */
> +
> +static struct cmd_list_element *compile_command_list;
> +
> +/* Debug flag for "compile" commands.  */
> +
> +int compile_debug;
> +
> +/* Implement "show debug compile".  */
> +
> +static void
> +show_compile_debug (struct ui_file *file, int from_tty,
> +		    struct cmd_list_element *c, const char *value)
> +{
> +  fprintf_filtered (file, _("Compile debugging is %s.\n"), value);
> +}
> +
> +
> +
> +/* Check *ARG for a "-raw" or "-r" argument.  Return 0 if not seen.
> +   Return 1 if seen and update *ARG.  */
> +
> +static int
> +check_raw_argument (char **arg)
> +{
> +  *arg = skip_spaces (*arg);
> +
> +  if (arg != NULL
> +      && (check_for_argument (arg, "-raw", sizeof ("-raw") - 1)
> +	  || check_for_argument (arg, "-r", sizeof ("-r") - 1)))
> +      return 1;
> +  return 0;
> +}
> +
> +/* Handle the input from the 'compile file' command.  The "compile
> +   file" command is used to evaluate an expression contained in a file
> +   that may contain calls to the GCC compiler.  */
> +
> +static void
> +compile_file_command (char *arg, int from_tty)
> +{
> +  enum compile_i_scope_types scope = COMPILE_I_SIMPLE_SCOPE;
> +  char *buffer;
> +  struct cleanup *cleanup;
> +
> +  cleanup = make_cleanup_restore_integer (&interpreter_async);
> +  interpreter_async = 0;
> +
> +  /* Check the user did not just <enter> after command.  */
> +  if (arg == NULL)
> +    error (_("You must provide a filename for this command."));
> +
> +  /* Check if a raw (-r|-raw) argument is provided.  */
> +  if (arg != NULL && check_raw_argument (&arg))
> +    {
> +      scope = COMPILE_I_RAW_SCOPE;
> +      arg = skip_spaces (arg);
> +    }
> +
> +  /* After processing arguments, check there is a filename at the end
> +     of the command.  */
> +  if (arg[0] == '\0')
> +    error (_("You must provide a filename with the raw option set."));
> +
> +  if (arg[0] == '-')
> +    error (_("Unknown argument specified."));
> +
> +  arg = skip_spaces (arg);
> +  arg = gdb_abspath (arg);
> +  make_cleanup (xfree, arg);
> +  buffer = xstrprintf ("#include \"%s\"\n", arg);
> +  make_cleanup (xfree, buffer);
> +  eval_compile_command (NULL, buffer, scope);
> +  do_cleanups (cleanup);
> +}
> +
> +/* Handle the input from the 'compile code' command.  The
> +   "compile code" command is used to evaluate an expression that may
> +   contain calls to the GCC compiler.  The language expected in this
> +   compile command is the language currently set in GDB.  */
> +
> +static void
> +compile_code_command (char *arg, int from_tty)
> +{
> +  struct cleanup *cleanup;
> +  enum compile_i_scope_types scope = COMPILE_I_SIMPLE_SCOPE;
> +
> +  cleanup = make_cleanup_restore_integer (&interpreter_async);
> +  interpreter_async = 0;
> +
> +  if (arg != NULL && check_raw_argument (&arg))
> +    {
> +      scope = COMPILE_I_RAW_SCOPE;
> +      arg = skip_spaces (arg);
> +    }
> +
> +  arg = skip_spaces (arg);
> +
> +  if (arg != NULL && !check_for_argument (&arg, "--", sizeof ("--") - 1))
> +    {
> +      if (arg[0] == '-')
> +	error (_("Unknown argument specified."));
> +    }
> +
> +  if (arg && *arg)
> +      eval_compile_command (NULL, arg, scope);
> +  else
> +    {
> +      struct command_line *l = get_command_line (compile_control, "");
> +
> +      make_cleanup_free_command_lines (&l);
> +      l->control_u.compile.scope = scope;
> +      execute_control_command_untraced (l);
> +    }
> +
> +  do_cleanups (cleanup);
> +}
> +
> +/* A cleanup function to remove a directory and all its contents.  */
> +
> +static void
> +do_rmdir (void *arg)
> +{
> +  char *zap = concat ("rm -rf ", arg, (char *) NULL);
> +
> +  system (zap);
> +}
> +
> +/* Return the name of the temporary directory to use for .o files, and
> +   arrange for the directory to be removed at shutdown.  */
> +
> +static const char *
> +get_compile_file_tempdir (void)
> +{
> +  static char *tempdir_name;
> +
> +#define TEMPLATE "/tmp/gdbobj-XXXXXX"
> +  char tname[sizeof (TEMPLATE)];
> +
> +  if (tempdir_name != NULL)
> +    return tempdir_name;
> +
> +  strcpy (tname, TEMPLATE);
> +#undef TEMPLATE
> +  tempdir_name = mkdtemp (tname);
> +  if (tempdir_name == NULL)
> +    perror_with_name (_("Could not make temporary directory"));
> +
> +  tempdir_name = xstrdup (tempdir_name);
> +  make_final_cleanup (do_rmdir, tempdir_name);
> +  return tempdir_name;
> +}
> +
> +/* Compute the names of source and object files to use.  The names are
> +   allocated by malloc and should be freed by the caller.  */
> +
> +static void
> +get_new_file_names (char **source_file, char **object_file)
> +{
> +  static int seq;
> +  const char *dir = get_compile_file_tempdir ();
> +
> +  ++seq;
> +  *source_file = xstrprintf ("%s%sout%d.c", dir, SLASH_STRING, seq);
> +  *object_file = xstrprintf ("%s%sout%d.o", dir, SLASH_STRING, seq);
> +}
> +
> +/* Get the block and PC at which to evaluate an expression.  */
> +
> +static const struct block *
> +get_expr_block_and_pc (CORE_ADDR *pc)
> +{
> +  const struct block *block = get_selected_block (pc);
> +
> +  if (block == NULL)
> +    {
> +      struct symtab_and_line cursal = get_current_source_symtab_and_line ();
> +
> +      if (cursal.symtab)
> +	block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (cursal.symtab), STATIC_BLOCK);
> +      if (block != NULL)
> +	*pc = BLOCK_START (block);
> +    }
> +  else
> +    *pc = BLOCK_START (block);
> +
> +  return block;
> +}
> +
> +/* Call gdb_buildargv, set its result for S into *ARGVP but calculate also the
> +   number of parsed arguments into *ARGCP.  If gdb_buildargv has returned NULL
> +   then *ARGCP is set to zero.  */
> +
> +static void
> +build_argc_argv (const char *s, int *argcp, char ***argvp)
> +{
> +  *argvp = gdb_buildargv (s);
> +  *argcp = countargv (*argvp);
> +}
> +
> +/* String for 'set compile-args' and 'show compile-args'.  */
> +static char *compile_args;
> +
> +/* Parsed form of COMPILE_ARGS.  COMPILE_ARGS_ARGV is NULL terminated.  */
> +static int compile_args_argc;
> +static char **compile_args_argv;
> +
> +/* Implement 'set compile-args'.  */
> +
> +static void
> +set_compile_args (char *args, int from_tty, struct cmd_list_element *c)
> +{
> +  freeargv (compile_args_argv);
> +  build_argc_argv (compile_args, &compile_args_argc, &compile_args_argv);
> +}
> +
> +/* Implement 'show compile-args'.  */
> +
> +static void
> +show_compile_args (struct ui_file *file, int from_tty,
> +		   struct cmd_list_element *c, const char *value)
> +{
> +  fprintf_filtered (file, _("Compile command command-line arguments "
> +			    "are \"%s\".\n"),
> +		    value);
> +}
> +
> +/* Append ARGC and ARGV (as parsed by build_argc_argv) to *ARGCP and *ARGVP.
> +   ARGCP+ARGVP can be zero+NULL and also ARGC+ARGV can be zero+NULL.  */
> +
> +static void
> +append_args (int *argcp, char ***argvp, int argc, char **argv)
> +{
> +  int argi;
> +
> +  *argvp = xrealloc (*argvp, (*argcp + argc + 1) * sizeof (**argvp));
> +
> +  for (argi = 0; argi < argc; argi++)
> +    (*argvp)[(*argcp)++] = xstrdup (argv[argi]);
> +  (*argvp)[(*argcp)] = NULL;
> +}
> +
> +/* Return DW_AT_producer parsed for get_selected_frame () (if any).
> +   Return NULL otherwise.
> +
> +   GCC already filters its command-line arguments only for the suitable ones to
> +   put into DW_AT_producer - see GCC function gen_producer_string.  */
> +
> +static const char *
> +get_selected_pc_producer_options (void)
> +{
> +  CORE_ADDR pc = get_frame_pc (get_selected_frame (NULL));
> +  struct symtab *symtab = find_pc_symtab (pc);
> +  const char *cs;
> +
> +  if (symtab == NULL || symtab->producer == NULL
> +      || strncmp (symtab->producer, "GNU ", strlen ("GNU ")) != 0)
> +    return NULL;
> +
> +  cs = symtab->producer;
> +  while (*cs != 0 && *cs != '-')
> +    cs = skip_spaces_const (skip_to_space_const (cs));
> +  if (*cs != '-')
> +    return NULL;
> +  return cs;
> +}
> +
> +/* Produce final vector of GCC compilation options.  First element is target
> +   size ("-m64", "-m32" etc.), optionally followed by DW_AT_producer options
> +   and then compile-args string GDB variable.  */
> +
> +static void
> +get_args (const struct compile_instance *compiler, int *argcp, char ***argvp)
> +{
> +  const char *cs_producer_options;
> +  int argc_compiler;
> +  char **argv_compiler;
> +
> +  build_argc_argv (gdbarch_gcc_target_options (target_gdbarch ()),
> +		   argcp, argvp);
> +
> +  cs_producer_options = get_selected_pc_producer_options ();
> +  if (cs_producer_options != NULL)
> +    {
> +      int argc_producer;
> +      char **argv_producer;
> +
> +      build_argc_argv (cs_producer_options, &argc_producer, &argv_producer);
> +      append_args (argcp, argvp, argc_producer, argv_producer);
> +      freeargv (argv_producer);
> +    }
> +
> +  build_argc_argv (compiler->gcc_target_options,
> +		   &argc_compiler, &argv_compiler);
> +  append_args (argcp, argvp, argc_compiler, argv_compiler);
> +  freeargv (argv_compiler);
> +
> +  append_args (argcp, argvp, compile_args_argc, compile_args_argv);
> +}
> +
> +/* A cleanup function to destroy a gdb_gcc_instance.  */
> +
> +static void
> +cleanup_compile_instance (void *arg)
> +{
> +  struct compile_instance *inst = arg;
> +
> +  inst->destroy (inst);
> +}
> +
> +/* A cleanup function to unlink a file.  */
> +
> +static void
> +cleanup_unlink_file (void *arg)
> +{
> +  const char *filename = arg;
> +
> +  unlink (filename);
> +}
> +
> +/* A helper function suitable for use as the "print_callback" in the
> +   compiler object.  */
> +
> +static void
> +print_callback (void *ignore, const char *message)
> +{
> +  fputs_filtered (message, gdb_stderr);
> +}
> +
> +/* Process the compilation request.  On success it returns the object
> +   file name and *SOURCE_FILEP is set to source file name.  On an
> +   error condition, error () is called.  The caller is responsible for
> +   freeing both strings.  */
> +
> +static char *
> +compile_to_object (struct command_line *cmd, char *cmd_string,
> +		   enum compile_i_scope_types scope,
> +		   char **source_filep)
> +{
> +  char *code;
> +  char *source_file, *object_file;
> +  struct 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;
> +  FILE *src;
> +
> +  if (!target_has_execution)
> +    error (_("The program must be running for the compile command to "\
> +	     "work."));
> +
> +  expr_block = get_expr_block_and_pc (&trash_pc);
> +  expr_pc = get_frame_address_in_block (get_selected_frame (NULL));
> +
> +  /* Set up instance and context for the compiler.  */
> +  if (current_language->la_get_compile_instance == NULL)
> +    error (_("No compiler support for this language."));
> +  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;
> +
> +  /* From the provided expression, build a scope to pass to the
> +     compiler.  */
> +  if (cmd != NULL)
> +    {
> +      struct ui_file *stream = mem_fileopen ();
> +      struct command_line *iter;
> +
> +      make_cleanup_ui_file_delete (stream);
> +      for (iter = cmd->body_list[0]; iter; iter = iter->next)
> +	{
> +	  fputs_unfiltered (iter->line, stream);
> +	  fputs_unfiltered ("\n", stream);
> +	}
> +
> +      code = ui_file_xstrdup (stream, NULL);
> +      make_cleanup (xfree, code);
> +    }
> +  else if (cmd_string != NULL)
> +    code = cmd_string;
> +  else
> +    error (_("Neither a simple expression, or a multi-line specified."));
> +
> +  code = current_language->la_compute_program (compiler, code,
> +					       get_current_arch (),
> +					       expr_block, expr_pc);
> +  make_cleanup (xfree, code);
> +  if (compile_debug)
> +    fprintf_unfiltered (gdb_stdout, "debug output:\n\n%s", code);
> +
> +  /* Set compiler command-line arguments.  */
> +  get_args (compiler, &argc, &argv);
> +  compiler->fe->ops->set_arguments (compiler->fe, argc, argv);
> +  if (compile_debug)
> +    {
> +      int argi;
> +
> +      fprintf_unfiltered (gdb_stdout, "Passing %d compiler options:\n", argc);
> +      for (argi = 0; argi < argc; argi++)
> +	fprintf_unfiltered (gdb_stdout, "Compiler option %d: <%s>\n",
> +			    argi, argv[argi]);
> +    }
> +  freeargv (argv);
> +
> +  get_new_file_names (&source_file, &object_file);
> +  inner_cleanup = make_cleanup (xfree, source_file);
> +  make_cleanup (xfree, object_file);
> +
> +  src = gdb_fopen_cloexec (source_file, "w");
> +  if (src == NULL)
> +    perror_with_name (_("Could not open source file for writing"));
> +  make_cleanup (cleanup_unlink_file, source_file);
> +  if (fputs (code, src) == EOF)
> +    perror_with_name (_("Could not write to source file"));
> +  fclose (src);
> +
> +  if (compile_debug)
> +    fprintf_unfiltered (gdb_stdout, "source file produced: %s\n\n",
> +			source_file);
> +
> +  /* Call the compiler and start the compilation process.  */
> +  compiler->fe->ops->set_source_file (compiler->fe, source_file);
> +
> +  if (!compiler->fe->ops->compile (compiler->fe, object_file,
> +				   compile_debug))
> +    error (_("Compilation failed."));
> +
> +  if (compile_debug)
> +    fprintf_unfiltered (gdb_stdout, "object file produced: %s\n\n",
> +			object_file);
> +
> +  discard_cleanups (inner_cleanup);
> +  do_cleanups (cleanup);
> +  *source_filep = source_file;
> +  return object_file;
> +}
> +
> +/* The "compile" prefix command.  */
> +
> +static void
> +compile_command (char *args, int from_tty)
> +{
> +  /* If a sub-command is not specified to the compile prefix command,
> +     assume it is a direct code compilation.  */
> +  compile_code_command (args, from_tty);
> +}
> +
> +/* See compile.h.  */
> +
> +void
> +eval_compile_command (struct command_line *cmd, char *cmd_string,
> +		      enum compile_i_scope_types scope)
> +{
> +  char *object_file, *source_file;
> +
> +  object_file = compile_to_object (cmd, cmd_string, scope, &source_file);
> +  if (object_file != NULL)
> +    {
> +      struct cleanup *cleanup_xfree, *cleanup_unlink;
> +      struct compile_module *compile_module;
> +
> +      cleanup_xfree = make_cleanup (xfree, object_file);
> +      make_cleanup (xfree, source_file);
> +      cleanup_unlink = make_cleanup (cleanup_unlink_file, object_file);
> +      make_cleanup (cleanup_unlink_file, source_file);
> +      compile_module = compile_object_load (object_file, source_file);
> +      discard_cleanups (cleanup_unlink);
> +      do_cleanups (cleanup_xfree);
> +      compile_object_run (compile_module);
> +    }
> +}
> +
> +/* See compile/compile-internal.h.  */
> +
> +char *
> +compile_register_name_mangled (struct gdbarch *gdbarch, int regnum)
> +{
> +  const char *regname = gdbarch_register_name (gdbarch, regnum);
> +
> +  return xstrprintf ("__%s", regname);
> +}
> +
> +/* See compile/compile-internal.h.  */
> +
> +int
> +compile_register_name_demangle (struct gdbarch *gdbarch,
> +				 const char *regname)
> +{
> +  int regnum;
> +
> +  if (regname[0] != '_' || regname[1] != '_')
> +    error (_("Invalid register name \"%s\"."), regname);
> +  regname += 2;
> +
> +  for (regnum = 0; regnum < gdbarch_num_regs (gdbarch); regnum++)
> +    if (strcmp (regname, gdbarch_register_name (gdbarch, regnum)) == 0)
> +      return regnum;
> +
> +  error (_("Cannot find gdbarch register \"%s\"."), regname);
> +}
> +
> +extern initialize_file_ftype _initialize_compile;
> +
> +void
> +_initialize_compile (void)
> +{
> +  struct cmd_list_element *c = NULL;
> +
> +  add_prefix_cmd ("compile", class_obscure, compile_command,
> +		  _("\
> +Command to compile source code and inject it into the inferior."),
> +		  &compile_command_list, "compile ", 1, &cmdlist);
> +  add_com_alias ("expression", "compile", class_obscure, 0);
> +
> +  add_cmd ("code", class_obscure, compile_code_command,
> +	   _("\
> +Evaluate a block of source code.\n\
> +\n\
> +Usage: code [-r|-raw] [--] [CODE]\n\
> +-r|-raw: Suppress automatic 'void _gdb_expr () { CODE }' wrapping.\n\
> +--: Do not parse any options beyond this delimiter.  All text to the\n\
> +    right will be treated as source code.\n\
> +\n\
> +The source code may be specified as a simple one line expression, e.g:\n\
> +\n\
> +    compile code printf(\"Hello world\\n\");\n\
> +\n\
> +Alternatively, you can type the source code interactively.\n\
> +You can invoke this mode when no argument is given to the command\n\
> +(i.e.,\"compile code\" is typed with nothing after it).  An\n\
> +interactive prompt will be shown allowing you to enter multiple\n\
> +lines of source code.  Type a line containing \"end\" to indicate\n\
> +the end of the source code."),
> +	   &compile_command_list);
> +
> +  c = add_cmd ("file", class_obscure, compile_file_command,
> +	       _("\
> +Evaluate a file containing source code.\n\
> +\n\
> +Usage: file [-r|-raw] [filename]\n\
> +-r|-raw: Suppress automatic 'void _gdb_expr () { CODE }' wrapping."),
> +	       &compile_command_list);
> +  set_cmd_completer (c, filename_completer);
> +
> +  add_setshow_boolean_cmd ("compile", class_maintenance, &compile_debug, _("\
> +Set compile command debugging."), _("\
> +Show compile command debugging."), _("\
> +When on, compile command debugging is enabled."),
> +			   NULL, show_compile_debug,
> +			   &setdebuglist, &showdebuglist);
> +
> +  add_setshow_string_cmd ("compile-args", class_support,
> +			  &compile_args,
> +			  _("Set compile command GCC command-line arguments"),
> +			  _("Show compile command GCC command-line arguments"),
> +			  _("\
> +Use options like -I (include file directory) or ABI settings.\n\
> +String quoting is parsed like in shell, for example:\n\
> +  -mno-align-double \"-I/dir with a space/include\""),
> +			  set_compile_args, show_compile_args, &setlist, &showlist);
> +
> +  /* Override flags possibly coming from DW_AT_producer.  */
> +  compile_args = xstrdup ("-O0 -gdwarf-4"
> +  /* We use -fPIC to ensure that we can reference properly.  Otherwise
> +     on x86-64 a string constant's address might be truncated when gdb
> +     loads the object; another approach would be -mcmodel=large, but
> +     -fPIC seems more portable across back ends.  */
> +			 " -fPIC"
> +  /* We don't want warnings.  */
> +			 " -w"
> +  /* Override CU's possible -fstack-protector-strong.  */
> +			 " -fno-stack-protector"
> +  );
> +  set_compile_args (compile_args, 0, NULL);
> +}
> diff --git a/gdb/compile/compile.h b/gdb/compile/compile.h
> new file mode 100644
> index 0000000..486361f
> --- /dev/null
> +++ b/gdb/compile/compile.h
> @@ -0,0 +1,102 @@
> +/* Header file for Compile and inject module.
> +
> +   Copyright (C) 2014 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_H
> +#define GDB_COMPILE_H
> +
> +struct ui_file;
> +struct gdbarch;
> +struct dwarf2_per_cu_data;
> +struct symbol;
> +struct dynamic_prop;
> +
> +/* Public function that is called from compile_control case in the
> +   expression command.  GDB returns either a CMD, or a CMD_STRING, but
> +   never both.  */
> +
> +extern void eval_compile_command (struct command_line *cmd, char *cmd_string,
> +				  enum compile_i_scope_types scope);
> +
> +/* Compile a DWARF location expression to C, suitable for use by the
> +   compiler.
> +
> +   STREAM is the stream where the code should be written.
> +
> +   RESULT_NAME is the name of a variable in the resulting C code.  The
> +   result of the expression will be assigned to this variable.
> +
> +   SYM is the symbol corresponding to this expression.
> +   PC is the location at which the expression is being evaluated.
> +   ARCH is the architecture to use.
> +
> +   REGISTERS_USED is an out parameter which is updated to note which
> +   registers were needed by this expression.
> +
> +   ADDR_SIZE is the DWARF address size to use.
> +
> +   OPT_PTR and OP_END are the bounds of the DWARF expression.
> +
> +   PER_CU is the per-CU object used for looking up various other
> +   things.  */
> +
> +extern void compile_dwarf_expr_to_c (struct ui_file *stream,
> +				     const char *result_name,
> +				     struct symbol *sym,
> +				     CORE_ADDR pc,
> +				     struct gdbarch *arch,
> +				     unsigned char *registers_used,
> +				     unsigned int addr_size,
> +				     const gdb_byte *op_ptr,
> +				     const gdb_byte *op_end,
> +				     struct dwarf2_per_cu_data *per_cu);
> +
> +/* Compile a DWARF bounds expression to C, suitable for use by the
> +   compiler.
> +
> +   STREAM is the stream where the code should be written.
> +
> +   RESULT_NAME is the name of a variable in the resulting C code.  The
> +   result of the expression will be assigned to this variable.
> +
> +   PROP is the dynamic property for which we're compiling.
> +
> +   SYM is the symbol corresponding to this expression.
> +   PC is the location at which the expression is being evaluated.
> +   ARCH is the architecture to use.
> +
> +   REGISTERS_USED is an out parameter which is updated to note which
> +   registers were needed by this expression.
> +
> +   ADDR_SIZE is the DWARF address size to use.
> +
> +   OPT_PTR and OP_END are the bounds of the DWARF expression.
> +
> +   PER_CU is the per-CU object used for looking up various other
> +   things.  */
> +
> +extern void compile_dwarf_bounds_to_c (struct ui_file *stream,
> +				       const char *result_name,
> +				       const struct dynamic_prop *prop,
> +				       struct symbol *sym, CORE_ADDR pc,
> +				       struct gdbarch *arch,
> +				       unsigned char *registers_used,
> +				       unsigned int addr_size,
> +				       const gdb_byte *op_ptr,
> +				       const gdb_byte *op_end,
> +				       struct dwarf2_per_cu_data *per_cu);
> +
> +#endif /* GDB_COMPILE_H */
> diff --git a/gdb/d-lang.c b/gdb/d-lang.c
> index 434f30a..597f7d0 100644
> --- a/gdb/d-lang.c
> +++ b/gdb/d-lang.c
> @@ -259,6 +259,8 @@ static const struct language_defn d_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &default_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> diff --git a/gdb/defs.h b/gdb/defs.h
> index 47da43a..70fcf71 100644
> --- a/gdb/defs.h
> +++ b/gdb/defs.h
> @@ -73,6 +73,24 @@
>  
>  #include "host-defs.h"
>  
> +/* Scope types enumerator.  List the types of scopes the compiler will
> +   accept.  */
> +
> +enum compile_i_scope_types
> +  {
> +    COMPILE_I_INVALID_SCOPE,
> +
> +    /* A simple scope.  Wrap an expression into a simple scope that
> +       takes no arguments, returns no value, and uses the generic
> +       function name "_gdb_expr". */
> +
> +    COMPILE_I_SIMPLE_SCOPE,
> +
> +    /* Do not wrap the expression,
> +       it has to provide function "_gdb_expr" on its own.  */
> +    COMPILE_I_RAW_SCOPE,
> +  };
> +
>  /* Just in case they're not defined in stdio.h.  */
>  
>  #ifndef SEEK_SET
> @@ -414,6 +432,7 @@ enum command_control_type
>      if_control,
>      commands_control,
>      python_control,
> +    compile_control,
>      guile_control,
>      while_stepping_control,
>      invalid_control
> @@ -427,6 +446,15 @@ struct command_line
>      struct command_line *next;
>      char *line;
>      enum command_control_type control_type;
> +    union
> +      {
> +	struct
> +	  {
> +	    enum compile_i_scope_types scope;
> +	  }
> +	compile;
> +      }
> +    control_u;
>      /* * The number of elements in body_list.  */
>      int body_count;
>      /* * For composite commands, the nested lists of commands.  For
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 2aff5e5..d6d5a42 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -16311,6 +16311,7 @@ address, or even return prematurely from a function.
>  * Returning::                   Returning from a function
>  * Calling::                     Calling your program's functions
>  * Patching::                    Patching your program
> +* Compiling and Injecting Code:: Compiling and injecting code in GDB
>  @end menu
>  
>  @node Assignment
> @@ -16700,6 +16701,247 @@ Display whether executable files and core files are opened for writing
>  as well as reading.
>  @end table
>  
> +@node Compiling and Injecting Code
> +@section Compiling and injecting code in GDB
> +@cindex injecting code
> +@cindex writing into executables
> +@cindex compiling code
> +
> +@value{GDBN} supports on-demand compilation and code injection into
> +programs running under GDB.  A suitable compiler must be installed for
> +this functionality to be enabled.  This functionality is implemented
> +with the following commands.
> +
> +@table @code
> +@kindex compile code
> +@item compile code @var{source}
> +@itemx compile code -@var{raw} @var{--} @var{source}
> +Compile @var{source} using the language set in @value{GDBN}
> +(@pxref{Languages}), as the compilation language type.  If compilation
> +and injection is not supported with the current language specified in
> +@value{GDBN}, or the compiler does not support this feature, an error
> +message will be printed and the command will exit.  If @var{source}
> +compiles and links successfully, @value{GDBN} will load the object-code
> +emitted, and execute it within the context of the currently selected
> +inferior.
> +
> +The command allows you to specify source code in two ways.  The simplest
> +method is to provide a single line of code to the command.  E.g.:
> +
> +@smallexample
> +compile code printf ("hello world\n");
> +@end smallexample
> +
> +If you specify options on the command line as well as source code, they
> +may conflict.  The @samp{@var{--}} delimiter can be used to separate options
> +from actual source code.  E.g.:
> +
> +@smallexample
> +compile code -r -- printf ("hello world\n");
> +@end smallexample
> +
> +Alternatively you can enter source code as multiple lines of text.  To
> +enter this mode, invoke the @samp{compile code} command without any text
> +following the command.  This will start the multiple-line editor and
> +allow you to type as many lines of source code as required.  When you
> +have completed typing, enter @samp{end} on its own line to exit the
> +editor.
> +
> +@smallexample
> +compile code
> +>printf ("hello\n");
> +>printf ("world\n");
> +>end
> +@end smallexample
> +
> +Specifying @samp{-@var{raw}}, prohibits @value{GDBN} from wrapping the
> +provided @var{source} in a callable scope.  In this case, you must
> +specify the entry point of the code by defining a function named
> +@code{_gdb_expr_}.  @samp{-@var{raw}} code does not automatically access
> +variables of the inferior, for their import you must use
> +the @samp{#pragma} line first:
> +
> +@smallexample
> +#pragma GCC user_expression
> +@end smallexample
> +
> +@samp{#include} lines are better to be placed before the @samp{#pragma}
> +line.  The use of @var{raw} is considered to be expert usage, and care
> +should be taken when using it.
> +
> +@kindex compile file
> +@item compile file @var{filename}
> +@itemx compile file -@var{raw} @var{filename}
> +Load source code from the file specified by @var{filename}, and compile
> +it using the language set in @value{GDBN} (@pxref{Languages}), as the
> +compilation language type.  If compilation and injection is not
> +supported with the current language specified in @value{GDBN}, or the
> +compiler does not support this feature, an error message will be printed
> +and the command will exit.  If the source-code contained within
> +@var{filename} compiles and links successfully, @value{GDBN} will load
> +the object-code emitted, and execute it within the context of the
> +currently selected inferior.
> +
> +@smallexample
> +compile file /home/user/example.c
> +@end smallexample
> +
> +Specifying @samp{-@var{raw}}, prohibits @value{GDBN} from wrapping the
> +provided @var{source} in a callable scope.  In this case, you must
> +specify the entry point of the code by defining a function named
> +@code{_gdb_expr_}.  @samp{-@var{raw}} code does not automatically access
> +variables of the inferior, for their import you must use
> +the @samp{#pragma} line first:
> +
> +@smallexample
> +#pragma GCC user_expression
> +@end smallexample
> +
> +@samp{#include} lines are better to be placed before the @samp{#pragma}
> +line.  The use of @var{raw} is considered to be expert usage, and care
> +should be taken when using it.
> +@end table
> +
> +There are a few caveats to keep in mind when using the compile command.
> +As the caveats are different per language, the table below highlights
> +specific issues on a per language basis.
> +
> +@table @code
> +@item C code examples and caveats
> +When the language in @value{GDBN} is set to @samp{C}, the compiler will
> +attempt to compile the source code with a @samp{C} compiler.  The source
> +code provided to the @samp{compile} command will have much the same
> +access to variables and types as it normally would if it were part of
> +the program currently being debugged in @value{GDBN}.
> +
> +Below is a sample program that forms the basis of the examples that
> +follow.  This program has been compiled and loaded into @value{GDBN},
> +much like any other normal debugging session.
> +
> +@smallexample
> +void function1 (void)
> +@{
> +   int i = 42;
> +   printf ("function 1\n");
> +@}
> +
> +void function2 (void)
> +@{
> +   int j = 12;
> +   function1 ();
> +@}
> +
> +int main(void)
> +@{
> +   int k = 6;
> +   int *p;
> +   function2 ();
> +   return 0;
> +@}
> +@end smallexample
> +
> +For the purposes of the examples in this section, the program above has
> +been compiled, loaded into @value{GDBN}, stopped at the function
> +@samp{main}, and @value{GDBN} is awaiting input from the user.
> +
> +To access variables and types for any program in @value{GDBN}, the
> +program must be compiled and packaged with debug information.  The
> +@samp{compile} command is not an exception to this rule.  Without debug
> +information, you can still use the @samp{compile} command, but you will
> +be very limited in what variables and types you can access.
> +
> +So with that in mind, the example above has been compiled with debug
> +information enabled.  The @samp{compile} command will have access to all
> +variables and types (except those that may have been optimized out).
> +Currently, as @value{GDBN} has stopped the program in the @samp{main}
> +function, the @samp{compile} command would have access to the variable
> +@var{k}.  You could invoke the @samp{compile} command and type some
> +source code to set the value of @var{k}.  You can also read it, or do
> +anything with that variable you would normally do in @samp{C}.  Be aware
> +that changes to variables you make in the @samp{compile} command are
> +persistent, so in the following example:
> +
> +@smallexample
> +compile code k = 3;
> +@end smallexample
> +
> +The variable @var{k} is now 3.  It will remain that value until
> +something else in the example program changes it, or another
> +@samp{compile} command changes it.
> +
> +Normal scope and access rules apply to source code compiled and injected
> +by the @samp{compile} command.  In the example, the variables @var{j}
> +and @var{k} are not accessible; subsequent execution will bring these
> +variables into scope, and later, code written and compiled with the
> +@samp{compile} command will be able to access them.  At this point the
> +program is stopped in the @samp{main} function so the following example:
> +
> +@smallexample
> +compile code j = 3;
> +@end smallexample
> +
> +would result in a compilation error, and @value{GDBN} would print that
> +error to the console.
> +
> +You can create variables and types with the @samp{compile} command as
> +part of your source code.  Variables and types that are created as part
> +of the @samp{compile} command are not persistent, and only exist as
> +long as the injected object code exists.  This example is valid:
> +
> +@smallexample
> +compile code int ff = 5; printf ("ff is %d\n", ff);
> +@end smallexample
> +
> +However, if you were to type the following into @value{GDBN} after that
> +command has completed:
> +
> +@smallexample
> +compile code printf ("ff is %d\n'', ff);
> +@end smallexample
> +
> +A compiler error would be raised as the variable @var{ff} no longer
> +exists.  Object code generated and injected by the @samp{compile}
> +command is removed on completion of the command.  Caution is advised
> +when assigning variables belonging to the program with variables created
> +in the @samp{compile} command.  This example is valid:
> +
> +@smallexample
> +compile code int ff = 5; k = ff;
> +@end smallexample
> +
> +The @var{k} variable is assigned to the value of @var{ff}.  The variable
> +@var{k} does not require the existence of @var{ff} to maintain the value
> +it has been assigned.  Pointers and other types of references require
> +particular care in assignment.  If the source code compiled with the
> +@samp{compile} command changed the address of a pointer in the example
> +program, perhaps to a variable created in the @samp{compile} command,
> +that pointer would point to an invalid location when the command exits.
> +The following example would likely cause issues with your debugged
> +program:
> +
> +@smallexample
> +compile code int ff = 5; p = &ff;
> +@end smallexample
> +
> +In this example, @var{p} would point to @var{ff} when the @samp{compile}
> +command is executing the source code provided to it.  However, as
> +variables in the (example) program persist with their assigned values, the
> +variable @samp{p} would point to an invalid location when the command
> +exists.  A general rule should be followed in that you should either
> +assign NULL to any assigned pointers, or restore a valid location to the
> +pointer before the command exits.
> +
> +Similar caution must be exercised with any types defined in
> +@samp{compile} command.  Types defined in the @samp{compile} are also
> +deleted when the command exits.  Therefore, if you cast a variable to a
> +type defined in the @samp{compile} command, care must be taken to ensure
> +that any future need to resolve the type can be achieved.
> +
> +Variables that have been optimized away by the compiler are not
> +accessible to the @samp{compile} command.  Access to those variables
> +will generate a compiler error which @value{GDBN} will print to the console.
> +@end table
> +
>  @node GDB Files
>  @chapter @value{GDBN} Files
>  
> diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
> index 7bb4c48..dc3b9cc 100644
> --- a/gdb/dwarf2loc.c
> +++ b/gdb/dwarf2loc.c
> @@ -41,6 +41,7 @@
>  
>  #include <string.h>
>  #include "gdb_assert.h"
> +#include "compile/compile.h"
>  
>  extern int dwarf2_always_disassemble;
>  
> @@ -2545,6 +2546,42 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop, CORE_ADDR *value)
>    return 0;
>  }
>  
> +/* See dwarf2loc.h.  */
> +
> +void
> +dwarf2_compile_property_to_c (struct ui_file *stream,
> +			      const char *result_name,
> +			      struct gdbarch *gdbarch,
> +			      unsigned char *registers_used,
> +			      const struct dynamic_prop *prop,
> +			      CORE_ADDR pc,
> +			      struct symbol *sym)
> +{
> +  struct dwarf2_property_baton *baton = prop->data.baton;
> +  const gdb_byte *data;
> +  size_t size;
> +  struct dwarf2_per_cu_data *per_cu;
> +
> +  if (prop->kind == PROP_LOCEXPR)
> +    {
> +      data = baton->locexpr.data;
> +      size = baton->locexpr.size;
> +      per_cu = baton->locexpr.per_cu;
> +    }
> +  else
> +    {
> +      gdb_assert (prop->kind == PROP_LOCLIST);
> +
> +      data = dwarf2_find_location_expression (&baton->loclist, &size, pc);
> +      per_cu = baton->loclist.per_cu;
> +    }
> +
> +  compile_dwarf_bounds_to_c (stream, result_name, prop, sym, pc,
> +			     gdbarch, registers_used,
> +			     dwarf2_per_cu_addr_size (per_cu),
> +			     data, data + size, per_cu);
> +}
> +
>  
>  /* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */
>  
> @@ -4198,6 +4235,26 @@ locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
>  			       dlbaton->per_cu);
>  }
>  
> +/* symbol_computed_ops 'generate_c_location' method.  */
> +
> +static void
> +locexpr_generate_c_location (struct symbol *sym, struct ui_file *stream,
> +			     struct gdbarch *gdbarch,
> +			     unsigned char *registers_used,
> +			     CORE_ADDR pc, const char *result_name)
> +{
> +  struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (sym);
> +  unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
> +
> +  if (dlbaton->size == 0)
> +    error (_("symbol \"%s\" is optimized out"), SYMBOL_NATURAL_NAME (sym));
> +
> +  compile_dwarf_expr_to_c (stream, result_name,
> +			   sym, pc, gdbarch, registers_used, addr_size,
> +			   dlbaton->data, dlbaton->data + dlbaton->size,
> +			   dlbaton->per_cu);
> +}
> +
>  /* The set of location functions used with the DWARF-2 expression
>     evaluator.  */
>  const struct symbol_computed_ops dwarf2_locexpr_funcs = {
> @@ -4206,7 +4263,8 @@ const struct symbol_computed_ops dwarf2_locexpr_funcs = {
>    locexpr_read_needs_frame,
>    locexpr_describe_location,
>    0,	/* location_has_loclist */
> -  locexpr_tracepoint_var_ref
> +  locexpr_tracepoint_var_ref,
> +  locexpr_generate_c_location
>  };
>  
>  
> @@ -4377,6 +4435,29 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
>  			       dlbaton->per_cu);
>  }
>  
> +/* symbol_computed_ops 'generate_c_location' method.  */
> +
> +static void
> +loclist_generate_c_location (struct symbol *sym, struct ui_file *stream,
> +			     struct gdbarch *gdbarch,
> +			     unsigned char *registers_used,
> +			     CORE_ADDR pc, const char *result_name)
> +{
> +  struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (sym);
> +  unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
> +  const gdb_byte *data;
> +  size_t size;
> +
> +  data = dwarf2_find_location_expression (dlbaton, &size, pc);
> +  if (size == 0)
> +    error (_("symbol \"%s\" is optimized out"), SYMBOL_NATURAL_NAME (sym));
> +
> +  compile_dwarf_expr_to_c (stream, result_name,
> +			   sym, pc, gdbarch, registers_used, addr_size,
> +			   data, data + size,
> +			   dlbaton->per_cu);
> +}
> +
>  /* The set of location functions used with the DWARF-2 expression
>     evaluator and location lists.  */
>  const struct symbol_computed_ops dwarf2_loclist_funcs = {
> @@ -4385,7 +4466,8 @@ const struct symbol_computed_ops dwarf2_loclist_funcs = {
>    loclist_read_needs_frame,
>    loclist_describe_location,
>    1,	/* location_has_loclist */
> -  loclist_tracepoint_var_ref
> +  loclist_tracepoint_var_ref,
> +  loclist_generate_c_location
>  };
>  
>  /* Provide a prototype to silence -Wmissing-prototypes.  */
> diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
> index bc7dfb7..36f5a59 100644
> --- a/gdb/dwarf2loc.h
> +++ b/gdb/dwarf2loc.h
> @@ -108,6 +108,27 @@ struct value *dwarf2_evaluate_loc_desc (struct type *type,
>  int dwarf2_evaluate_property (const struct dynamic_prop *prop,
>  			      CORE_ADDR *value);
>  
> +/* A helper for the compiler interface that compiles a single dynamic
> +   property to C code.
> +
> +   STREAM is where the C code is to be written.
> +   RESULT_NAME is the name of the generated variable.
> +   GDBARCH is the architecture to use.
> +   REGISTERS_USED is a bit-vector that is filled to note which
> +   registers are required by the generated expression.
> +   PROP is the property for which code is generated.
> +   ADDRESS is the address at which the property is considered to be
> +   evaluated.
> +   SYM the originating symbol, used for error reporting.  */
> +
> +void dwarf2_compile_property_to_c (struct ui_file *stream,
> +				   const char *result_name,
> +				   struct gdbarch *gdbarch,
> +				   unsigned char *registers_used,
> +				   const struct dynamic_prop *prop,
> +				   CORE_ADDR address,
> +				   struct symbol *sym);
> +
>  CORE_ADDR dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
>  				  unsigned int addr_index);
>  
> diff --git a/gdb/f-lang.c b/gdb/f-lang.c
> index bbfd89c..5243d35 100644
> --- a/gdb/f-lang.c
> +++ b/gdb/f-lang.c
> @@ -276,6 +276,8 @@ const struct language_defn f_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &default_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> diff --git a/gdb/go-lang.c b/gdb/go-lang.c
> index 42535df..429bc4d 100644
> --- a/gdb/go-lang.c
> +++ b/gdb/go-lang.c
> @@ -599,6 +599,8 @@ static const struct language_defn go_language_defn =
>    NULL,
>    iterate_over_symbols,
>    &default_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
> index 243a45a..fc28bd3 100644
> --- a/gdb/jv-lang.c
> +++ b/gdb/jv-lang.c
> @@ -1197,6 +1197,8 @@ const struct language_defn java_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &java_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> diff --git a/gdb/language.c b/gdb/language.c
> index d5502f2..20d0c9b 100644
> --- a/gdb/language.c
> +++ b/gdb/language.c
> @@ -829,6 +829,8 @@ const struct language_defn unknown_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &default_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> @@ -874,6 +876,8 @@ const struct language_defn auto_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &default_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> @@ -917,6 +921,8 @@ const struct language_defn local_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &default_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> diff --git a/gdb/language.h b/gdb/language.h
> index 73619ca..9ed7e22 100644
> --- a/gdb/language.h
> +++ b/gdb/language.h
> @@ -35,6 +35,7 @@ struct value_print_options;
>  struct type_print_options;
>  struct lang_varobj_ops;
>  struct parser_state;
> +struct compile_instance;
>  
>  #define MAX_FORTRAN_DIMS  7	/* Maximum number of F77 array dims.  */
>  
> @@ -355,6 +356,36 @@ struct language_defn
>      /* Various operations on varobj.  */
>      const struct lang_varobj_ops *la_varobj_ops;
>  
> +    /* If this language allows compilation from the gdb command line,
> +       this method should be non-NULL.  When called it should return
> +       an instance of struct gcc_context appropriate to the language.
> +       When defined this method must never return NULL; instead it
> +       should throw an exception on failure.  The returned compiler
> +       instance is owned by its caller and must be deallocated by
> +       calling its 'destroy' method.  */
> +
> +    struct 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
> +       ignored.
> +
> +       This takes the user-supplied text and returns a newly malloc'd
> +       bit of code to compile.  The caller owns the result.
> +
> +       INST is the compiler instance being used.
> +       INPUT is the user's input text.
> +       GDBARCH is the architecture to use.
> +       EXPR_BLOCK is the block in which the expression is being
> +       parsed.
> +       EXPR_PC is the PC at which the expression is being parsed.  */
> +
> +    char *(*la_compute_program) (struct compile_instance *inst,
> +				 const char *input,
> +				 struct gdbarch *gdbarch,
> +				 const struct block *expr_block,
> +				 CORE_ADDR expr_pc);
> +
>      /* Add fields above this point, so the magic number is always last.  */
>      /* Magic number for compat checking.  */
>  
> diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
> index 940cbcf..6a68520 100644
> --- a/gdb/m2-lang.c
> +++ b/gdb/m2-lang.c
> @@ -394,6 +394,8 @@ const struct language_defn m2_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &default_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
> index 68f0d10..1b83614 100644
> --- a/gdb/objc-lang.c
> +++ b/gdb/objc-lang.c
> @@ -392,6 +392,8 @@ const struct language_defn objc_language_defn = {
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &default_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
> index 2dd76fa..3770a22 100644
> --- a/gdb/opencl-lang.c
> +++ b/gdb/opencl-lang.c
> @@ -1139,6 +1139,8 @@ const struct language_defn opencl_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &default_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> diff --git a/gdb/p-lang.c b/gdb/p-lang.c
> index 856beb3..a5a367b 100644
> --- a/gdb/p-lang.c
> +++ b/gdb/p-lang.c
> @@ -452,6 +452,8 @@ const struct language_defn pascal_language_defn =
>    NULL,				/* la_get_symbol_name_cmp */
>    iterate_over_symbols,
>    &default_varobj_ops,
> +  NULL,
> +  NULL,
>    LANG_MAGIC
>  };
>  
> diff --git a/gdb/symtab.h b/gdb/symtab.h
> index efc3643..ce430a5 100644
> --- a/gdb/symtab.h
> +++ b/gdb/symtab.h
> @@ -641,6 +641,21 @@ struct symbol_computed_ops
>  
>    void (*tracepoint_var_ref) (struct symbol *symbol, struct gdbarch *gdbarch,
>  			      struct agent_expr *ax, struct axs_value *value);
> +
> +  /* Generate C code to compute the location of SYMBOL.  The C code is
> +     emitted to STREAM.  GDBARCH is the current architecture and PC is
> +     the PC at which SYMBOL's location should be evaluated.
> +     REGISTERS_USED is a vector indexed by register number; the
> +     generator function should set an element in this vector if the
> +     corresponding register is needed by the location computation.
> +     The generated C code must assign the location to a local
> +     variable; this variable's name is RESULT_NAME.  */
> +
> +  void (*generate_c_location) (struct symbol *symbol, struct ui_file *stream,
> +			       struct gdbarch *gdbarch,
> +			       unsigned char *registers_used,
> +			       CORE_ADDR pc, const char *result_name);
> +
>  };
>  
>  /* The methods needed to implement LOC_BLOCK for inferior functions.
> diff --git a/gdb/testsuite/gdb.base/compile-constvar.S b/gdb/testsuite/gdb.base/compile-constvar.S
> new file mode 100644
> index 0000000..55d81bc
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/compile-constvar.S
> @@ -0,0 +1,95 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2014 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/>.  */
> +
> +// gcc -o gdb.base/compile-constvar.S -dA -S -g gdb.base/compile-constvar.c
> +
> +	.file	"compile-constvar.c"
> +	.file 1 "gdb.base/compile-constvar.c"
> +	.section	.debug_info,"",@progbits
> +.Ldebug_info0:
> +	.long	.Lend-.Lstart	# Length of Compilation Unit Info
> +.Lstart:
> +	.value	0x4	# DWARF version number
> +	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
> +	.byte	0x8	# Pointer Size (in bytes)
> +	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
> +	.long	.LASF0	# DW_AT_producer: "GNU C 4.8.2 20131212 (Red Hat 4.8.2-7) -mtune=generic -march=x86-64 -g"
> +	.byte	0x1	# DW_AT_language
> +	.long	.LASF1	# DW_AT_name: "gdb.base/compile-constvar.c"
> +	.long	.LASF2	# DW_AT_comp_dir: "/home/jkratoch/redhat/gdb-gdbjit/gdb/testsuite"
> +	.uleb128 0x2	# (DIE (0x1d) DW_TAG_variable)
> +	.long	.LASF3	# DW_AT_name: "constvar"
> +	.long	.Linttype-.Ldebug_info0	# DW_AT_type
> +			# DW_AT_external
> +	.byte	0x3	# DW_AT_const_value
> +.Linttype:
> +	.uleb128 0x3	# (DIE (0x32) DW_TAG_base_type)
> +	.byte	0x4	# DW_AT_byte_size
> +	.byte	0x5	# DW_AT_encoding
> +	.ascii "int\0"	# DW_AT_name
> +	.byte	0	# end of children of DIE 0xb
> +.Lend:
> +	.section	.debug_abbrev,"",@progbits
> +.Ldebug_abbrev0:
> +	.uleb128 0x1	# (abbrev code)
> +	.uleb128 0x11	# (TAG: DW_TAG_compile_unit)
> +	.byte	0x1	# DW_children_yes
> +	.uleb128 0x25	# (DW_AT_producer)
> +	.uleb128 0xe	# (DW_FORM_strp)
> +	.uleb128 0x13	# (DW_AT_language)
> +	.uleb128 0xb	# (DW_FORM_data1)
> +	.uleb128 0x3	# (DW_AT_name)
> +	.uleb128 0xe	# (DW_FORM_strp)
> +	.uleb128 0x1b	# (DW_AT_comp_dir)
> +	.uleb128 0xe	# (DW_FORM_strp)
> +	.byte	0
> +	.byte	0
> +	.uleb128 0x2	# (abbrev code)
> +	.uleb128 0x34	# (TAG: DW_TAG_variable)
> +	.byte	0	# DW_children_no
> +	.uleb128 0x3	# (DW_AT_name)
> +	.uleb128 0xe	# (DW_FORM_strp)
> +	.uleb128 0x49	# (DW_AT_type)
> +	.uleb128 0x13	# (DW_FORM_ref4)
> +	.uleb128 0x3f	# (DW_AT_external)
> +	.uleb128 0x19	# (DW_FORM_flag_present)
> +	.uleb128 0x1c	# (DW_AT_const_value)
> +	.uleb128 0xb	# (DW_FORM_data1)
> +	.byte	0
> +	.byte	0
> +	.uleb128 0x3	# (abbrev code)
> +	.uleb128 0x24	# (TAG: DW_TAG_base_type)
> +	.byte	0	# DW_children_no
> +	.uleb128 0xb	# (DW_AT_byte_size)
> +	.uleb128 0xb	# (DW_FORM_data1)
> +	.uleb128 0x3e	# (DW_AT_encoding)
> +	.uleb128 0xb	# (DW_FORM_data1)
> +	.uleb128 0x3	# (DW_AT_name)
> +	.uleb128 0x8	# (DW_FORM_string)
> +	.byte	0
> +	.byte	0
> +	.byte	0
> +	.section	.debug_str,"MS",@progbits,1
> +.LASF1:
> +	.string	"gdb.base/compile-constvar.c"
> +.LASF3:
> +	.string	"constvar"
> +.LASF2:
> +	.string	""
> +.LASF0:
> +	.string	"GNU C 4.8.2 20131212 (Red Hat 4.8.2-7) -mtune=generic -march=x86-64 -g"
> +	.ident	"GCC: (GNU) 4.8.2 20131212 (Red Hat 4.8.2-7)"
> diff --git a/gdb/testsuite/gdb.base/compile-constvar.c b/gdb/testsuite/gdb.base/compile-constvar.c
> new file mode 100644
> index 0000000..3820b43
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/compile-constvar.c
> @@ -0,0 +1,18 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2014 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/>.  */
> +
> +int constvar = 5;
> diff --git a/gdb/testsuite/gdb.base/compile-mod.c b/gdb/testsuite/gdb.base/compile-mod.c
> new file mode 100644
> index 0000000..a6dbc32
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/compile-mod.c
> @@ -0,0 +1,26 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2014 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/>.  */
> +
> +// Make 'globalvar' lookup working.
> +#pragma GCC user_expression
> +
> +void
> +_gdb_expr (void)
> +{
> +  globalvar = 3;
> +  globalvar += 4;
> +}
> diff --git a/gdb/testsuite/gdb.base/compile-nodebug.c b/gdb/testsuite/gdb.base/compile-nodebug.c
> new file mode 100644
> index 0000000..4cc8bb3
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/compile-nodebug.c
> @@ -0,0 +1,24 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2014 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/>.  */
> +
> +int
> +func_nodebug (int neg)
> +{
> +  return -neg;
> +}
> +
> +int unresolved = 20;
> diff --git a/gdb/testsuite/gdb.base/compile-setjmp-mod.c b/gdb/testsuite/gdb.base/compile-setjmp-mod.c
> new file mode 100644
> index 0000000..8a1c413
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/compile-setjmp-mod.c
> @@ -0,0 +1,46 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2014 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/>.  */
> +
> +#include <setjmp.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +// Make 'done' lookup working.
> +#pragma GCC user_expression
> +
> +static void
> +foo ()
> +{
> +  jmp_buf env;
> +
> +  switch (setjmp (env))
> +    {
> +    case 2:
> +      done = 1;
> +      return;
> +    case 0:
> +      longjmp (env, 2);
> +      break;
> +    }
> +  abort ();
> +}
> +
> +void
> +_gdb_expr (void)
> +{
> +  foo ();
> +}
> diff --git a/gdb/testsuite/gdb.base/compile-setjmp.c b/gdb/testsuite/gdb.base/compile-setjmp.c
> new file mode 100644
> index 0000000..c462f48
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/compile-setjmp.c
> @@ -0,0 +1,24 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2014 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/>.  */
> +
> +static int done;
> +
> +int
> +main (void)
> +{
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.base/compile-setjmp.exp b/gdb/testsuite/gdb.base/compile-setjmp.exp
> new file mode 100644
> index 0000000..557c1f0
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/compile-setjmp.exp
> @@ -0,0 +1,34 @@
> +# Copyright 2014 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/>.
> +
> +standard_testfile .c compile-setjmp-mod.c
> +
> +if { [prepare_for_testing ${testfile}.exp $testfile] } {
> +    return -1
> +}
> +
> +if ![runto_main] {
> +    return -1
> +}
> +
> +if {[skip_compile_feature_tests]} {
> +    untested "could not find libcc1 shared library"
> +    return -1
> +}
> +
> +gdb_test_no_output "compile file -r ${srcdir}/${subdir}/$srcfile2" \
> +    "compile file -r"
> +
> +gdb_test "p done" " = 1"
> diff --git a/gdb/testsuite/gdb.base/compile-shlib.c b/gdb/testsuite/gdb.base/compile-shlib.c
> new file mode 100644
> index 0000000..6181af2
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/compile-shlib.c
> @@ -0,0 +1,26 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2014 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/>.  */
> +
> +extern int globalvar;
> +
> +int shlibvar = 10;
> +
> +void
> +shlib_func (void)
> +{
> +  globalvar = 1;
> +}
> diff --git a/gdb/testsuite/gdb.base/compile.c b/gdb/testsuite/gdb.base/compile.c
> new file mode 100644
> index 0000000..b48acab
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/compile.c
> @@ -0,0 +1,130 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2014 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/>.  */
> +
> +#define SOME_MACRO 23
> +#define ARG_MACRO(X, Y) ((X) + (Y) - 1)
> +
> +
> +enum enum_type {
> +  ONE = 1,
> +  TWO = 2
> +};
> +
> +typedef int v4 __attribute__ ((vector_size (16)));
> +
> +union union_type;
> +
> +struct struct_type {
> +  char charfield;
> +  unsigned char ucharfield;
> +  short shortfield;
> +  unsigned short ushortfield;
> +  int intfield;
> +  unsigned int uintfield;
> +  unsigned int bitfield : 3;
> +  long longfield;
> +  unsigned long ulongfield;
> +  enum enum_type enumfield;
> +  float floatfield;
> +  double doublefield;
> +  const union union_type *ptrfield;
> +  struct struct_type *selffield;
> +  int arrayfield[5];
> +  _Complex double complexfield;
> +  _Bool boolfield;
> +  v4 vectorfield;
> +};
> +
> +typedef int inttypedef;
> +
> +union union_type {
> +  int intfield;
> +  inttypedef typedeffield;
> +};
> +
> +/* volatile provides some coverage of the conversion code.  */
> +volatile struct struct_type struct_object;
> +
> +union union_type union_object;
> +
> +
> +enum ulonger_enum_type {
> +  REALLY_MINUS_1 = -1UL,
> +};
> +
> +enum ulonger_enum_type ulonger;
> +
> +enum longer_enum_type {
> +  MINUS_1 = -1,
> +  FORCE_TO_LONG = 1L << ((8 * sizeof (long)) - 2)
> +};
> +
> +enum longer_enum_type longer;
> +
> +int globalvar = 10;
> +
> +static void
> +func_static (int addend)
> +{
> +  globalvar += addend;
> +}
> +
> +void
> +func_global (int subtrahend)
> +{
> +  globalvar -= subtrahend;
> +}
> +
> +void
> +no_args_or_locals (void)
> +{
> +  /* no_args_or_locals breakpoint */
> +}
> +
> +int *intptr;
> +int globalshadow = 10;
> +static int staticshadow = 20;
> +int externed = 7;
> +
> +int
> +main (void)
> +{
> +  int localvar = 50;
> +  int shadowed = 51;
> +  int bound = 3;
> +  int unresolved = 10;
> +  int globalshadow = 100;
> +  int staticshadow = 200;
> +  int externed = 9;
> +  int f = 0;
> +
> +  static int static_local = 77000;
> +
> +  {
> +    int another_local = 7;
> +    int shadowed = 52;
> +    extern int unresolved;
> +    extern int externed;
> +
> +    int vla[bound];
> +
> +    func_static (0); /* break-here */
> +    no_args_or_locals ();
> +  }
> +
> + return 0;
> +}
> diff --git a/gdb/testsuite/gdb.base/compile.exp b/gdb/testsuite/gdb.base/compile.exp
> new file mode 100644
> index 0000000..d0dd791
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/compile.exp
> @@ -0,0 +1,357 @@
> +# Copyright 2014 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/>.
> +
> +standard_testfile .c compile-shlib.c compile-constvar.S compile-nodebug.c
> +
> +get_compiler_info
> +set options {}
> +if [test_compiler_info gcc*] {
> +    lappend options additional_flags=-g3
> +}
> +
> +if { ![istarget x86_64-*-* ] || ![is_lp64_target] } {
> +    verbose "Skipping x86_64 LOC_CONST test."
> +    set srcfile3 ""
> +}
> +
> +set srcfilesoptions [list ${srcfile} ${options}]
> +if { $srcfile3 != "" } {
> +    lappend srcfilesoptions $srcfile3 ${options}
> +}
> +lappend srcfilesoptions $srcfile4 "nodebug"
> +if { [eval build_executable_from_specs ${testfile}.exp $testfile {$options} ${srcfilesoptions}] } {
> +    return -1
> +}
> +
> +clean_restart ${testfile}
> +
> +#
> +# Test command without an running inferior.
> +#
> +gdb_test "compile code int i=2;" \
> +    "The program must be running for the compile command to work.*" \
> +    "Test compile code command without running inferior"
> +
> +gdb_test "compile int i=2;" \
> +    "The program must be running for the compile command to work.*" \
> +    "Test compile command without running inferior"
> +
> +gdb_test "compile file -r ${srcdir}/${subdir}/${testfile}-mod.c" \
> +    "The program must be running for the compile command to work.*" \
> +    "Test compile file command without running inferior"
> +
> +if ![runto_main] {
> +    return -1
> +}
> +
> +if {[skip_compile_feature_tests]} {
> +    untested "could not find libcc1 shared library"
> +    return -1
> +}
> +
> +#
> +# Test delimiter for code, and arguments.
> +#
> +
> +gdb_test_no_output "compile -- f = 10" \
> +    "Test abbreviations and code delimiter"
> +
> +gdb_test "compile f = 10;" ".*= 10;: No such file.*" \
> +    "Test abbreviations and code collision"
> +
> +gdb_test_no_output "compile -r -- _gdb_expr(){int i = 5;}" \
> +    "Test delimiter with -r"
> +
> +gdb_test_no_output "compile -raw -- _gdb_expr(){int i = 5;}" \
> +    "Test delimiter with -raw"
> +
> +gdb_test "compile -- -r  _gdb_expr(){int i = 5;}" \
> +    ".* error: 'r' undeclared \\(first use in this function\\).*" \
> +    "Test delimiter with -r after it"
> +
> +gdb_test "p globalvar" " = 10" "expect 10"
> +
> +gdb_test_no_output "compile code globalvar = 11" \
> +    "set variable without trailing semicolon"
> +gdb_test "p globalvar" " = 11" "check variable without trailing semicolon"
> +
> +gdb_test_no_output "compile code globalvar = SOME_MACRO;" \
> +    "set variable from macro"
> +gdb_test "p globalvar" " = 23" "expect 23"
> +
> +gdb_test_no_output "compile code globalvar = ARG_MACRO(0, 0);" \
> +    "set variable from function-like macro"
> +gdb_test "p globalvar" " = -1" "expect -1"
> +
> +gdb_test_no_output "compile code globalvar = 42;" "set variable"
> +gdb_test "p globalvar" " = 42" "expect 42"
> +
> +gdb_test_no_output "compile code globalvar *= 2;" "modify variable"
> +gdb_test "p globalvar" " = 84" "expect 84"
> +
> +gdb_test_multiple "compile code" "compile code multiline 1" { -re "\r\n>$" {} }
> +gdb_test_multiple "globalvar = 10;" "compile code multiline 2" { -re "\r\n>$" {} }
> +gdb_test_multiple "globalvar *= 2;" "compile code multiline 3" { -re "\r\n>$" {} }
> +gdb_test_no_output "end" "compile code multiline 4"
> +gdb_test "p globalvar" " = 20" "expect 20"
> +
> +gdb_test_no_output "compile file -r ${srcdir}/${subdir}/${testfile}-mod.c" \
> +    "use external source file"
> +gdb_test "p globalvar" " = 7" "expect 7"
> +
> +gdb_test_no_output "compile code func_static (2);" "call static function"
> +gdb_test "p globalvar" " = 9" "expect 9"
> +gdb_test_no_output "compile code func_global (1);" "call global function"
> +gdb_test "p globalvar" " = 8" "expect 8"
> +
> +gdb_test_no_output \
> +    "compile code globalvar = (sizeof (ulonger) == sizeof (long))" \
> +    "compute size of ulonger"
> +gdb_test "p globalvar" " = 1" "check size of ulonger"
> +gdb_test_no_output \
> +    "compile code globalvar = (sizeof (longer) == sizeof (long))" \
> +    "compute size of longer"
> +gdb_test "p globalvar" " = 1" "check size of longer"
> +gdb_test_no_output "compile code globalvar = MINUS_1"
> +gdb_test "p globalvar" " = -1" "check MINUS_1"
> +
> +gdb_test_no_output "compile code globalvar = static_local"
> +gdb_test "p globalvar" " = 77000" "check static_local"
> +
> +gdb_test_no_output "compile code static int staticvar = 5; intptr = &staticvar" \
> +    "keep jit in memory"
> +gdb_test "p *intptr" " = 5" "expect 5"
> +
> +gdb_test "compile code func_doesnotexist ();" "warning: Could not find symbol \"func_doesnotexist\" for .*"
> +
> +gdb_test "compile code *(volatile int *) 0 = 0;" \
> +    "The program being debugged was signaled while in a function called from GDB\\.\r\nGDB remains in the frame where the signal was received\\.\r\n.*" \
> +    "compile code segfault first"
> +gdb_test "bt" \
> +    "\r\n#0  \[^\r\n\]* in _gdb_expr \[^\r\n\]*\r\n#1  <function called from gdb>\r\n.*"
> +
> +set test "p/x \$pc"
> +set infcall_pc 0
> +gdb_test_multiple $test $test {
> +    -re " = (0x\[0-9a-f\]+)\r\n$gdb_prompt $" {
> +	set infcall_pc $expect_out(1,string)
> +	pass $test
> +    }
> +}
> +
> +gdb_test "info sym $infcall_pc" "\r\n_gdb_expr .*" "info sym found"
> +gdb_test "return" "\r\n#0  main .*" "return" \
> +	 "Make _gdb_expr return now\\? \\(y or n\\) " "y"
> +gdb_test "info sym $infcall_pc" "\r\nNo symbol matches .*" "info sym not found"
> +
> +gdb_test_no_output "set unwindonsignal on"
> +gdb_test "compile code *(volatile int *) 0 = 0;" \
> +    "The program being debugged was signaled while in a function called from GDB\\.\r\nGDB has restored the context to what it was before the call\\.\r\n.*" \
> +    "compile code segfault second"
> +
> +gdb_breakpoint [gdb_get_line_number "break-here"]
> +gdb_continue_to_breakpoint "break-here" ".* break-here .*"
> +
> +gdb_test "p localvar" " = 50" "expect localvar 50"
> +
> +gdb_test_no_output "compile code localvar = 12;" "set localvar"
> +gdb_test "p localvar" " = 12" "expect 12"
> +
> +gdb_test_no_output "compile code localvar *= 2;" "modify localvar"
> +gdb_test "p localvar" " = 24" "expect 24"
> +
> +gdb_test_no_output "compile code localvar = shadowed" \
> +    "test shadowing"
> +gdb_test "p localvar" " = 52" "expect 52"
> +
> +gdb_test_no_output "compile code localvar = externed"
> +gdb_test "p localvar" " = 7" "test extern in inner scope"
> +
> +gdb_test_no_output "compile code vla\[2\] = 7"
> +gdb_test "p vla\[2\]" " = 7"
> +gdb_test_no_output \
> +    "compile code localvar = (sizeof (vla) == bound * sizeof (vla\[0\]))"
> +gdb_test "p localvar" " = 1"
> +
> +#
> +# Test setting fields and also many different types.
> +#
> +
> +gdb_test_no_output "compile code struct_object.selffield = &struct_object"
> +gdb_test "print struct_object.selffield == &struct_object" " = 1"
> +
> +gdb_test_no_output "compile code struct_object.charfield = 1"
> +gdb_test "print struct_object.charfield" " = 1 '\\\\001'"
> +gdb_test_no_output "compile code struct_object.ucharfield = 1"
> +gdb_test "print struct_object.ucharfield" " = 1 '\\\\001'"
> +
> +foreach {field value} {
> +    shortfield -5
> +    ushortfield 5
> +    intfield -7
> +    uintfield 7
> +    bitfield 2
> +    longfield -9
> +    ulongfield 9
> +    enumfield ONE
> +    floatfield 1
> +    doublefield 2
> +} {
> +    gdb_test_no_output "compile code struct_object.$field = $value"
> +    gdb_test "print struct_object.$field" " = $value"
> +}
> +
> +gdb_test_no_output "compile code struct_object.arrayfield\[2\] = 7"
> +gdb_test "print struct_object.arrayfield" \
> +    " = \\{0, 0, 7, 0, 0\\}"
> +
> +gdb_test_no_output "compile code struct_object.complexfield = 7 + 5i"
> +gdb_test "print struct_object.complexfield" " = 7 \\+ 5 \\* I"
> +
> +gdb_test_no_output "compile code struct_object.boolfield = 1"
> +gdb_test "print struct_object.boolfield" " = true"
> +
> +gdb_test_no_output "compile code struct_object.vectorfield\[2\] = 7"
> +gdb_test "print struct_object.vectorfield" \
> +    " = \\{0, 0, 7, 0\\}"
> +
> +gdb_test_no_output "compile code union_object.typedeffield = 7"
> +gdb_test "print union_object.typedeffield" " = 7"
> +gdb_test "print union_object.intfield" " = 7"
> +
> +
> +# LOC_UNRESOLVED tests.
> +
> +gdb_test "print unresolved" " = 20"
> +gdb_test "compile code globalvar = unresolved;"
> +gdb_test "print globalvar" " = 20" "print unresolved value"
> +
> +# Test shadowing with global and static variables.
> +
> +gdb_test_no_output "compile code globalshadow += 1;"
> +gdb_test "print globalshadow" " = 101"
> +gdb_test_no_output "compile code extern int globalshadow; globalshadow += 5;"
> +gdb_test "print 'compile.c'::globalshadow" " = 15"
> +gdb_test "print globalshadow" " = 101" "print globalshadow second time"
> +gdb_test_no_output "compile code staticshadow += 2;"
> +gdb_test "print staticshadow" " = 202"
> +# "extern int staticshadow;" cannot access static variable.
> +
> +# Raw code cannot refer to locals.
> +# As it references global variable we need the #pragma.
> +# For #pragma we need multiline input.
> +gdb_test_multiple "compile code -r" "compile code -r multiline 1" { -re "\r\n>$" {} }
> +gdb_test_multiple "#pragma GCC user_expression" "compile code -r multiline 2" { -re "\r\n>$" {} }
> +gdb_test_multiple "void _gdb_expr(void) { globalshadow = 77000; }" "compile code -r multiline 3" { -re "\r\n>$" {} }
> +gdb_test_no_output "end" "compile code -r multiline 4"
> +gdb_test "print 'compile.c'::globalshadow" " = 77000" \
> +    "check globalshadow with -r"
> +
> +#
> +# Test the case where the registers structure would not normally have
> +# any fields.
> +#
> +
> +gdb_breakpoint [gdb_get_line_number "no_args_or_locals breakpoint"]
> +gdb_continue_to_breakpoint "no_args_or_locals"
> +
> +gdb_test_no_output "compile code globalvar = 77;" "set variable to 77"
> +gdb_test "p globalvar" " = 77" "expect 77"
> +
> +
> +# Test reference to minimal_symbol, not (full) symbol.
> +
> +gdb_test_no_output "compile code globalvar = func_nodebug (75);" \
> +    "call func_nodebug"
> +gdb_test "p globalvar" " = -75" "expect -75"
> +gdb_test_no_output \
> +  "compile code int (*funcp) (int) = func_nodebug; globalvar = funcp (76);" \
> +  "call func_nodebug indirectly"
> +gdb_test "p globalvar" " = -76" "expect -76"
> +
> +
> +# Test compiled module memory protection.
> +
> +gdb_test_no_output "set debug compile on"
> +gdb_test "compile code static const int readonly = 1; *(int *) &readonly = 2;" \
> +    "The program being debugged was signaled while in a function called from GDB\\.\r\nGDB has restored the context to what it was before the call\\.\r\n.*"
> +gdb_test_no_output "set debug compile off"
> +
> +
> +#
> +# Some simple coverage tests.
> +#
> +
> +gdb_test "show debug compile" "Compile debugging is .*"
> +gdb_test "show compile-args" \
> +    "Compile command command-line arguments are .*"
> +gdb_test "compile code -z" "Unknown argument.*"
> +
> +gdb_test "set lang java" \
> +    "Warning: the current language does not match this frame."
> +gdb_test "compile code globalvar" "No compiler support for this language\."
> +gdb_test_no_output "set lang auto"
> +
> +gdb_test_no_output "compile code union union_type newdecl_u"
> +gdb_test_no_output "compile code struct struct_type newdecl_s"
> +gdb_test_no_output "compile code inttypedef newdecl_i"
> +
> +gdb_test "compile file" \
> +    "You must provide a filename for this command.*" \
> +    "Test compile file without a filename"
> +gdb_test "compile file -r" \
> +    "You must provide a filename with the raw option set.*" \
> +    "Test compile file and raw option without a filename"
> +gdb_test "compile file -z" \
> +    "Unknown argument.*" \
> +    "Test compile file with unknown argument"
> +
> +
> +# LOC_CONST tests.
> +
> +if { $srcfile3 != "" } {
> +    gdb_test "p constvar" " = 3"
> +    gdb_test "info addr constvar" {Symbol "constvar" is constant\.}
> +
> +    gdb_test "compile code globalvar = constvar;"
> +    gdb_test "print globalvar" " = 3" "print constvar value"
> +} else {
> +    untested "print constvar value"
> +}
> +
> +# Shared library tests.
> +
> +if {[skip_shlib_tests]} {
> +    untested "skipping shlib tests"
> +    return;
> +}
> +
> +set libbin [standard_output_file ${testfile}-shlib.so]
> +if { [gdb_compile_shlib ${srcdir}/${subdir}/${srcfile2} $libbin {debug}] != ""
> +     || [build_executable $testfile ${testfile}-shlib $srcfile \
> +	     [list debug ldflags=$libbin]] == -1 } {
> +    return -1
> +}
> +
> +clean_restart ${testfile}-shlib
> +if ![runto_main] {
> +    return -1
> +}
> +
> +gdb_test_no_output "compile code shlib_func ();" "call shared library function"
> +gdb_test "p globalvar" " = 1" "expect 1"
> +
> +gdb_test_no_output "compile code shlibvar += 5;" "modify shared library variable"
> +gdb_test "p shlibvar" " = 15" "expect 15"
> diff --git a/gdb/testsuite/gdb.dwarf2/compile-ops.exp b/gdb/testsuite/gdb.dwarf2/compile-ops.exp
> new file mode 100644
> index 0000000..dd28083
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/compile-ops.exp
> @@ -0,0 +1,424 @@
> +# Copyright 2014 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/>.
> +
> +# Some coverage testing of DWARF operators for the compiler
> +# integration.
> +
> +load_lib dwarf.exp
> +
> +# This test can only be run on targets which support DWARF-2 and use gas.
> +if {![dwarf2_support]} {
> +    return 0
> +}
> +
> +standard_testfile dw2-ifort-parameter.c gdbjit-ops.S
> +
> +#
> +# A port of the pr10770.c test code to the DWARF assembler format.
> +#
> +
> +set assert_tos_non0 {
> +    bra 3
> +    skip -3
> +}
> +
> +set assert_tos_0 [subst {
> +    lit0
> +    eq
> +    $assert_tos_non0
> +}]
> +
> +set program [subst {
> +    lit0
> +    nop
> +    $assert_tos_0
> +    lit1
> +    const1u 1
> +    eq
> +    $assert_tos_non0
> +    lit16
> +    const2u 16
> +    eq
> +    $assert_tos_non0
> +    lit31
> +    const4u 31
> +    ne
> +    $assert_tos_0
> +    lit1
> +    neg
> +    const1s -1
> +    eq
> +    $assert_tos_non0
> +    lit16
> +    neg
> +    const2s -16
> +    ne
> +    $assert_tos_0
> +    lit31
> +    const4s -31
> +    neg
> +    ne
> +    $assert_tos_0
> +    lit7
> +    dup
> +    plus_uconst 2
> +    lit9
> +    eq
> +    $assert_tos_non0
> +    lit7
> +    eq
> +    $assert_tos_non0
> +    lit20
> +    lit1
> +    drop
> +    lit20
> +    eq
> +    $assert_tos_non0
> +    lit17
> +    lit19
> +    over
> +    lit17
> +    eq
> +    $assert_tos_non0
> +    lit19
> +    eq
> +    $assert_tos_non0
> +    lit17
> +    eq
> +    $assert_tos_non0
> +    lit1
> +    lit2
> +    lit3
> +    lit4
> +    pick 2
> +    lit2
> +    eq
> +    $assert_tos_non0
> +    lit4
> +    eq
> +    $assert_tos_non0
> +    lit3
> +    eq
> +    $assert_tos_non0
> +    pick 0
> +    lit2
> +    eq
> +    $assert_tos_non0
> +    lit2
> +    eq
> +    $assert_tos_non0
> +    lit1
> +    eq
> +    $assert_tos_non0
> +    lit6
> +    lit12
> +    swap
> +    lit6
> +    eq
> +    $assert_tos_non0
> +    lit12
> +    eq
> +    $assert_tos_non0
> +    lit7
> +    lit8
> +    lit9
> +    rot
> +    lit8
> +    eq
> +    $assert_tos_non0
> +    lit7
> +    eq
> +    $assert_tos_non0
> +    lit9
> +    eq
> +    $assert_tos_non0
> +    lit7
> +    abs
> +    lit7
> +    eq
> +    $assert_tos_non0
> +    const1s -123
> +    abs
> +    const1u 123
> +    eq
> +    $assert_tos_non0
> +    lit3
> +    lit6
> +    and
> +    lit2
> +    eq
> +    $assert_tos_non0
> +    lit3
> +    lit6
> +    or
> +    lit7
> +    eq
> +    $assert_tos_non0
> +    lit17
> +    lit2
> +    minus
> +    lit15
> +    eq
> +    $assert_tos_non0
> +    # Divide is signed truncating toward zero.
> +    const1s -6
> +    const1s -2
> +    div
> +    lit3
> +    eq
> +    $assert_tos_non0
> +    const1s -7
> +    const1s 3
> +    div
> +    const1s -2
> +    eq
> +    $assert_tos_non0
> +    # Modulo is unsigned.
> +    const1s -6
> +    const1s -4
> +    mod
> +    const1s -6
> +    eq
> +    $assert_tos_non0
> +    const1s -6
> +    lit4
> +    mod
> +    lit2
> +    eq
> +    $assert_tos_non0
> +    lit6
> +    const1s -4
> +    mod
> +    lit6
> +    eq
> +    $assert_tos_non0
> +    # Signed modulo can be implemented using 'over over div mul minus'.
> +    const1s -6
> +    const1s -4
> +    over
> +    over
> +    div
> +    mul
> +    minus
> +    const1s -2
> +    eq
> +    $assert_tos_non0
> +    const1s -7
> +    lit3
> +    over
> +    over
> +    div
> +    mul
> +    minus
> +    const1s -1
> +    eq
> +    $assert_tos_non0
> +    lit7
> +    const1s -3
> +    over
> +    over
> +    div
> +    mul
> +    minus
> +    lit1
> +    eq
> +    $assert_tos_non0
> +    lit16
> +    lit31
> +    plus_uconst 1
> +    mul
> +    const2u 512
> +    eq
> +    $assert_tos_non0
> +    lit5
> +    not
> +    lit31
> +    and
> +    lit26
> +    eq
> +    $assert_tos_non0
> +    lit12
> +    lit31
> +    plus
> +    const1u 43
> +    eq
> +    $assert_tos_non0
> +    const1s -6
> +    lit2
> +    plus
> +    const1s -4
> +    eq
> +    $assert_tos_non0
> +    const1s -6
> +    plus_uconst 3
> +    const1s -3
> +    eq
> +    $assert_tos_non0
> +    lit16
> +    lit4
> +    shl
> +    const2u 256
> +    eq
> +    $assert_tos_non0
> +    lit16
> +    lit3
> +    shr
> +    lit2
> +    eq
> +    $assert_tos_non0
> +    const1s -16
> +    lit3
> +    shra
> +    const1s -2
> +    eq
> +    $assert_tos_non0
> +    lit3
> +    lit6
> +    xor
> +    lit5
> +    eq
> +    $assert_tos_non0
> +    lit3
> +    lit6
> +    le
> +    $assert_tos_non0
> +    lit3
> +    lit3
> +    le
> +    $assert_tos_non0
> +    lit6
> +    lit3
> +    le
> +    $assert_tos_0
> +    lit3
> +    lit6
> +    lt
> +    $assert_tos_non0
> +    lit3
> +    lit3
> +    lt
> +    $assert_tos_0
> +    lit6
> +    lit3
> +    lt
> +    $assert_tos_0
> +    lit3
> +    lit6
> +    ge
> +    $assert_tos_0
> +    lit3
> +    lit3
> +    ge
> +    $assert_tos_non0
> +    lit6
> +    lit3
> +    ge
> +    $assert_tos_non0
> +    lit3
> +    lit6
> +    gt
> +    $assert_tos_0
> +    lit3
> +    lit3
> +    gt
> +    $assert_tos_0
> +    lit6
> +    lit3
> +    gt
> +    $assert_tos_non0
> +    const1s -6
> +    lit1
> +    shr
> +    lit0
> +    gt
> +    $assert_tos_non0
> +    const1s -6
> +    lit1
> +    shra
> +    lit0
> +    lt
> +    $assert_tos_non0
> +    # Finally some result.
> +    addr ptr
> +}]
> +
> +# Make some DWARF for the test.
> +set asm_file [standard_output_file $srcfile2]
> +Dwarf::assemble $asm_file {
> +    # Creating a CU with 4-byte addresses lets this test link on both
> +    # 32- and 64-bit machines.
> +    cu { addr_size 4 } {
> +
> +	declare_labels int_label
> +	extern func_start func_end ptr
> +
> +	compile_unit {
> +	    {name file1.txt}
> +	    {language @DW_LANG_C}
> +	    {low_pc func_start addr}
> +	    {high_pc func_end addr}
> +	} {
> +	    global program
> +
> +	    int_label: base_type {
> +		{name int}
> +		{byte_size 4 sdata}
> +		{encoding @DW_ATE_signed}
> +	    }
> +
> +	    subprogram {
> +		{external 1 flag}
> +		{name func}
> +		{low_pc func_start addr}
> +		{high_pc func_end addr}
> +	    } {
> +		formal_parameter {
> +		    {name param}
> +		    {variable_parameter 1 flag}
> +		    {type :$int_label}
> +		    {location $program SPECIAL_expr}
> +		}
> +
> +		formal_parameter {
> +		    {name optimized_out}
> +		    {variable_parameter 1 flag}
> +		    {type :$int_label}
> +		}
> +	    }
> +	}
> +    }
> +}
> +
> +if { [prepare_for_testing ${testfile}.exp ${testfile} \
> +	  [list $srcfile $asm_file] {nodebug}] } {
> +    return -1
> +}
> +
> +if ![runto func] {
> +    return -1
> +}
> +
> +if {[skip_compile_feature_tests]} {
> +    untested "could not find libcc1 shared library"
> +    return -1
> +}
> +
> +# If we have a bug, this will hang.
> +gdb_test_no_output "compile code param"
> +
> +# We can't access optimized-out variables, but their presence should
> +# not affect compilations that don't refer to them.
> +gdb_test "compile code optimized_out" \
> +    ".*optimized out.*Compilation failed."
> diff --git a/gdb/testsuite/gdb.threads/compile-tls.c b/gdb/testsuite/gdb.threads/compile-tls.c
> new file mode 100644
> index 0000000..6e08a30
> --- /dev/null
> +++ b/gdb/testsuite/gdb.threads/compile-tls.c
> @@ -0,0 +1,40 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2014 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/>.  */
> +
> +#include <pthread.h>
> +
> +__thread int global_scope;
> +
> +static __thread int static_scope;
> +
> +int foo ()
> +{
> +  /* Ensure we link against pthreads even with --as-needed.  */
> +  pthread_testcancel();
> +  return 27;
> +}
> +
> +int
> +main (void)
> +{
> +  static __thread int local_scope;
> +
> +  /* break-here */
> +  foo ();
> +
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.threads/compile-tls.exp b/gdb/testsuite/gdb.threads/compile-tls.exp
> new file mode 100644
> index 0000000..e9613f5
> --- /dev/null
> +++ b/gdb/testsuite/gdb.threads/compile-tls.exp
> @@ -0,0 +1,42 @@
> +# Copyright 2014 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/>.  */
> +
> +standard_testfile .c
> +
> +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
> +	 executable {debug}] != "" } {
> +    return -1
> +}
> +
> +clean_restart ${binfile}
> +if ![runto_main] then {
> +   fail "Can't run to main"
> +   return 0
> +}
> +
> +if {[skip_compile_feature_tests]} {
> +    untested "could not find libcc1 shared library"
> +    return -1
> +}
> +
> +gdb_test "compile code local_scope = 1" \
> +    "warning: .* compiled code."
> +gdb_test "print local_scope" " = 1"
> +gdb_test "compile code static_scope = 2" \
> +    "warning: .* compiled code."
> +gdb_test "print static_scope" " = 2"
> +gdb_test "compile code global_scope = 3" \
> +    "warning: .* compiled code."
> +gdb_test "print global_scope" " = 3"
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index 3125e7a..0fa6ded 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -2454,6 +2454,23 @@ proc skip_libstdcxx_probe_tests {} {
>      return $ok
>  }
>  
> +# Return 1 if we should skip tests of the "compile" feature.
> +# This must be invoked after the inferior has been started.
> +
> +proc skip_compile_feature_tests {} {
> +    global gdb_prompt
> +
> +    set result 0
> +    gdb_test_multiple "compile code -- ;" "check for working compile command" {
> +	"Could not load libcc1.*\r\n$gdb_prompt $" {
> +	    set result 1
> +	}
> +	-re "\r\n$gdb_prompt $" {
> +	}
> +    }
> +    return $result
> +}
> +
>  # Check whether we're testing with the remote or extended-remote
>  # targets.
>  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]