diff --git a/gdb/NEWS b/gdb/NEWS
index 3fa33c9..0aa6365 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -32,6 +32,9 @@ record btrace bts
 record bts
   Start branch trace recording using Branch Trace Store (BTS) format.
 
+compile print
+  Evaluate expression with the compiler and print result.
+
 * New options
 
 set max-completions
diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
index 1711cda..027b678 100644
--- a/gdb/compile/compile-c-support.c
+++ b/gdb/compile/compile-c-support.c
@@ -188,6 +188,25 @@ add_code_header (enum compile_i_scope_types type, struct ui_file *buf)
 			") {\n",
 			buf);
       break;
+    case COMPILE_I_PRINT_SCOPE:
+      fputs_unfiltered ("void "
+			GCC_FE_WRAPPER_FUNCTION
+			" (struct "
+			COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
+			" *"
+			COMPILE_I_SIMPLE_REGISTER_ARG_NAME
+			", "
+			COMPILE_I_PRINT_OUT_ARG_TYPE
+			" "
+			COMPILE_I_PRINT_OUT_ARG
+			", "
+			COMPILE_I_PRINT_EXPR_TAKE_ADDRESS_TYPE
+			" "
+			COMPILE_I_PRINT_EXPR_TAKE_ADDRESS
+			") {\n",
+			buf);
+      break;
+
     case COMPILE_I_RAW_SCOPE:
       break;
     default:
@@ -205,6 +224,7 @@ add_code_footer (enum compile_i_scope_types type, struct ui_file *buf)
   switch (type)
     {
     case COMPILE_I_SIMPLE_SCOPE:
+    case COMPILE_I_PRINT_SCOPE:
       fputs_unfiltered ("}\n", buf);
       break;
     case COMPILE_I_RAW_SCOPE:
@@ -367,7 +387,8 @@ c_compute_program (struct compile_instance *inst,
 
   add_code_header (inst->scope, buf);
 
-  if (inst->scope == COMPILE_I_SIMPLE_SCOPE)
+  if (inst->scope == COMPILE_I_SIMPLE_SCOPE
+      || inst->scope == COMPILE_I_PRINT_SCOPE)
     {
       ui_file_put (var_stream, ui_file_write_for_put, buf);
       fputs_unfiltered ("#pragma GCC user_expression\n", buf);
@@ -381,7 +402,23 @@ c_compute_program (struct compile_instance *inst,
     fputs_unfiltered ("{\n", buf);
 
   fputs_unfiltered ("#line 1 \"gdb command line\"\n", buf);
-  fputs_unfiltered (input, buf);
+
+  if (inst->scope == COMPILE_I_PRINT_SCOPE)
+    {
+      fprintf_unfiltered (buf,
+"__auto_type " COMPILE_I_EXPR_VAL " = %s;\n"
+"typeof (%s) *" COMPILE_I_EXPR_PTR_TYPE ";\n"
+"if (" COMPILE_I_PRINT_EXPR_TAKE_ADDRESS ")\n"
+"\tmemcpy (" COMPILE_I_PRINT_OUT_ARG ", &" COMPILE_I_EXPR_VAL ",\n"
+	   "sizeof (*" COMPILE_I_EXPR_PTR_TYPE "));\n"
+"else\n"
+"\tmemcpy (" COMPILE_I_PRINT_OUT_ARG ", "  COMPILE_I_EXPR_VAL ",\n"
+	   "sizeof (*" COMPILE_I_EXPR_PTR_TYPE "));\n"
+			  , input, input);
+    }
+  else
+    fputs_unfiltered (input, buf);
+
   fputs_unfiltered ("\n", buf);
 
   /* For larger user expressions the automatic semicolons may be
diff --git a/gdb/compile/compile-internal.h b/gdb/compile/compile-internal.h
index c369d46..a5893b2 100644
--- a/gdb/compile/compile-internal.h
+++ b/gdb/compile/compile-internal.h
@@ -84,6 +84,12 @@ struct compile_c_instance
 #define COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG "__gdb_regs"
 #define COMPILE_I_SIMPLE_REGISTER_ARG_NAME "__regs"
 #define COMPILE_I_SIMPLE_REGISTER_DUMMY "_dummy"
+#define COMPILE_I_PRINT_OUT_ARG_TYPE "void *"
+#define COMPILE_I_PRINT_OUT_ARG "__gdb_out_param"
+#define COMPILE_I_PRINT_EXPR_TAKE_ADDRESS_TYPE "int"
+#define COMPILE_I_PRINT_EXPR_TAKE_ADDRESS "__gdb_expr_take_address"
+#define COMPILE_I_EXPR_VAL "__gdb_expr_val"
+#define COMPILE_I_EXPR_PTR_TYPE "__gdb_expr_ptr_type"
 
 /* Call gdbarch_register_name (GDBARCH, REGNUM) and convert its result
    to a form suitable for the compiler source.  The register names
diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c
index 8a7f232..f57b34e 100644
--- a/gdb/compile/compile-object-load.c
+++ b/gdb/compile/compile-object-load.c
@@ -29,6 +29,7 @@
 #include "regcache.h"
 #include "inferior.h"
 #include "compile.h"
+#include "block.h"
 #include "arch-utils.h"
 
 /* Helper data for setup_sections.  */
@@ -354,6 +355,114 @@ copy_sections (bfd *abfd, asection *sect, void *data)
   do_cleanups (cleanups);
 }
 
+/* Fetch the type of COMPILE_I_EXPR_PTR_TYPE and COMPILE_I_EXPR_VAL
+   symbols in OBJFILE so we can calculate how much memory to allocate
+   for the out parameter.  This avoids needing a malloc in the generated
+   code.  Throw an error if anything fails.
+   Set *OUT_VALUE_TAKE_ADDRESSP depending whether inferior code should
+   copy COMPILE_I_EXPR_VAL or its address - this depends on __auto_type
+   array-to-pointer type conversion of COMPILE_I_EXPR_VAL, as detected
+   by COMPILE_I_EXPR_PTR_TYPE preserving the array type.  */
+
+static struct type *
+get_out_value_type (struct objfile *objfile, int *out_value_take_addressp)
+{
+  struct symbol *func_sym, *gdb_ptr_type_sym, *gdb_val_sym;
+  struct type *gdb_ptr_type, *gdb_type_from_ptr, *gdb_type, *retval;
+  const struct block *block;
+  const struct blockvector *bv;
+  int nblocks = 0;
+  int block_loop = 0;
+
+  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));
+
+  bv = SYMTAB_BLOCKVECTOR (func_sym->owner.symtab);
+  nblocks = BLOCKVECTOR_NBLOCKS (bv);
+
+  gdb_ptr_type_sym = NULL;
+  for (block_loop = 0; block_loop < nblocks; block_loop++)
+    {
+      struct symbol *function;
+      const struct block *function_block;
+
+      block = BLOCKVECTOR_BLOCK (bv, block_loop);
+      if (BLOCK_FUNCTION (block) != NULL)
+	continue;
+      gdb_ptr_type_sym = block_lookup_symbol (block, COMPILE_I_EXPR_PTR_TYPE,
+					      VAR_DOMAIN);
+      if (gdb_ptr_type_sym == NULL)
+	continue;
+
+      function_block = block;
+      while (function_block != BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)
+	     && function_block != BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK))
+	{
+	  function_block = BLOCK_SUPERBLOCK (function_block);
+	  function = BLOCK_FUNCTION (function_block);
+	  if (function != NULL)
+	    break;
+	}
+      if (function != NULL
+	  && (BLOCK_SUPERBLOCK (function_block)
+	      == BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK))
+	  && (strcmp (SYMBOL_LINKAGE_NAME (function), GCC_FE_WRAPPER_FUNCTION)
+	      == 0))
+	break;
+    }
+  if (block_loop == nblocks)
+    error (_("No \"%s\" symbol found"), COMPILE_I_EXPR_PTR_TYPE);
+
+  gdb_ptr_type = SYMBOL_TYPE (gdb_ptr_type_sym);
+  CHECK_TYPEDEF (gdb_ptr_type);
+  if (TYPE_CODE (gdb_ptr_type) != TYPE_CODE_PTR)
+    error (_("Type of \"%s\" is not a pointer"), COMPILE_I_EXPR_PTR_TYPE);
+  gdb_type_from_ptr = TYPE_TARGET_TYPE (gdb_ptr_type);
+
+  gdb_val_sym = block_lookup_symbol (block, COMPILE_I_EXPR_VAL, VAR_DOMAIN);
+  if (gdb_val_sym == NULL)
+    error (_("No \"%s\" symbol found"), COMPILE_I_EXPR_VAL);
+  gdb_type = SYMBOL_TYPE (gdb_val_sym);
+  CHECK_TYPEDEF (gdb_type);
+
+  *out_value_take_addressp = types_deeply_equal (gdb_type, gdb_type_from_ptr);
+  if (*out_value_take_addressp)
+    return gdb_type;
+
+  if (TYPE_CODE (gdb_type) != TYPE_CODE_PTR)
+    error (_("Invalid type code %d of symbol \"%s\" "
+	     "in compiled module \"%s\"."),
+	   TYPE_CODE (gdb_type_from_ptr), COMPILE_I_EXPR_VAL,
+	   objfile_name (objfile));
+  
+  switch (TYPE_CODE (gdb_type_from_ptr))
+    {
+    case TYPE_CODE_ARRAY:
+      retval = gdb_type_from_ptr;
+      gdb_type_from_ptr = TYPE_TARGET_TYPE (gdb_type_from_ptr);
+      break;
+    case TYPE_CODE_FUNC:
+      retval = gdb_type_from_ptr;
+      break;
+    default:
+      error (_("Invalid type code %d of symbol \"%s\" "
+	       "in compiled module \"%s\"."),
+	     TYPE_CODE (gdb_type_from_ptr), COMPILE_I_EXPR_PTR_TYPE,
+	     objfile_name (objfile));
+    }
+  if (!types_deeply_equal (gdb_type_from_ptr,
+			   TYPE_TARGET_TYPE (gdb_type)))
+    error (_("Referenced types do not match for symbols \"%s\" and \"%s\" "
+	     "in compiled module \"%s\"."),
+	   COMPILE_I_EXPR_PTR_TYPE, COMPILE_I_EXPR_VAL,
+	   objfile_name (objfile));
+  return retval;
+}
+
 /* 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.  */
@@ -362,7 +471,7 @@ static struct type *
 get_regs_type (struct objfile *objfile)
 {
   struct symbol *func_sym;
-  struct type *func_type, *regsp_type, *regs_type;
+  struct type *func_type, *regsp_type, *regs_type, *take_address_type;
 
   func_sym = lookup_global_symbol_from_objfile (objfile,
 						GCC_FE_WRAPPER_FUNCTION,
@@ -382,7 +491,7 @@ get_regs_type (struct objfile *objfile)
   if (TYPE_NFIELDS (func_type) == 0)
     return NULL;
 
-  if (TYPE_NFIELDS (func_type) != 1)
+  if (TYPE_NFIELDS (func_type) != 1 && TYPE_NFIELDS (func_type) != 3)
     error (_("Invalid %d parameters of function \"%s\" in compiled "
 	     "module \"%s\"."),
 	   TYPE_NFIELDS (func_type), GCC_FE_WRAPPER_FUNCTION,
@@ -402,6 +511,16 @@ get_regs_type (struct objfile *objfile)
 	   TYPE_CODE (regs_type), GCC_FE_WRAPPER_FUNCTION,
 	   objfile_name (objfile));
 
+  if (TYPE_NFIELDS (func_type) == 3)
+    {
+      take_address_type = check_typedef (TYPE_FIELD_TYPE (func_type, 2));
+      if (TYPE_CODE (take_address_type) != TYPE_CODE_INT)
+	error (_("Invalid type code %d of third parameter of function \"%s\" "
+		 "in compiled module \"%s\"."),
+	       TYPE_CODE (take_address_type), GCC_FE_WRAPPER_FUNCTION,
+	       objfile_name (objfile));
+    }
+
   return regs_type;
 }
 
@@ -464,12 +583,13 @@ store_regs (struct type *regs_type, CORE_ADDR regs_base)
    function returns.  */
 
 struct compile_module *
-compile_object_load (const char *object_file, const char *source_file)
+compile_object_load (const char *object_file, const char *source_file,
+		     const int has_out_arg)
 {
   struct cleanup *cleanups, *cleanups_free_objfile;
   bfd *abfd;
   struct setup_sections_data setup_sections_data;
-  CORE_ADDR addr, func_addr, regs_addr;
+  CORE_ADDR addr, func_addr, regs_addr, out_value_addr = 0;
   struct bound_minimal_symbol bmsym;
   long storage_needed;
   asymbol **symbol_table, **symp;
@@ -477,7 +597,8 @@ compile_object_load (const char *object_file, const char *source_file)
   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;
+  struct type *regs_type, *out_value_type = NULL;
+  int out_value_take_address;
   char *filename, **matching;
   struct objfile *objfile;
 
@@ -579,6 +700,15 @@ compile_object_load (const char *object_file, const char *source_file)
       store_regs (regs_type, regs_addr);
     }
 
+  if (has_out_arg)
+    {
+      out_value_type = get_out_value_type (objfile, &out_value_take_address);
+      check_typedef (out_value_type);
+      out_value_addr = gdbarch_infcall_mmap (target_gdbarch (),
+					     TYPE_LENGTH (out_value_type), 6);
+      gdb_assert (out_value_addr != 0);
+    }
+
   discard_cleanups (cleanups_free_objfile);
   do_cleanups (cleanups);
 
@@ -587,5 +717,8 @@ compile_object_load (const char *object_file, const char *source_file)
   retval->source_file = xstrdup (source_file);
   retval->func_addr = func_addr;
   retval->regs_addr = regs_addr;
+  retval->out_value_addr = out_value_addr;
+  retval->out_value_type = out_value_type;
+  retval->out_value_take_address = out_value_take_address;
   return retval;
 }
diff --git a/gdb/compile/compile-object-load.h b/gdb/compile/compile-object-load.h
index ed3ac3a..be9cc65 100644
--- a/gdb/compile/compile-object-load.h
+++ b/gdb/compile/compile-object-load.h
@@ -32,11 +32,24 @@ struct compile_module
      require any.  */
   CORE_ADDR regs_addr;
 
+  /* Inferior parameter out value address or NULL if the inferior function does not
+     have one.  */
+  CORE_ADDR out_value_addr;
+
+  /* Should we memcpy address of the value or the value itself
+     (for coerced arrays)?  */
+  int out_value_take_address;
+
+  /* Inferior parameter out value type or NULL if the inferior function does not
+     have one.  */
+  struct type *out_value_type;
+
   /* User data for enum compile_i_scope_types in use.  */
   void *scope_data;
 };
 
 extern struct compile_module *compile_object_load (const char *object_file,
-						   const char *source_file);
+						   const char *source_file,
+						   const int has_out_arg);
 
 #endif /* GDB_COMPILE_OBJECT_LOAD_H */
diff --git a/gdb/compile/compile-object-run.c b/gdb/compile/compile-object-run.c
index 0864712..d2b176c 100644
--- a/gdb/compile/compile-object-run.c
+++ b/gdb/compile/compile-object-run.c
@@ -24,6 +24,8 @@
 #include "objfiles.h"
 #include "compile-internal.h"
 #include "dummy-frame.h"
+#include "valprint.h"
+#include "compile.h"
 
 /* Helper for do_module_cleanup.  */
 
@@ -36,6 +38,10 @@ struct do_module_cleanup
   /* .c file OBJFILE was built from.  It needs to be xfree-d.  */
   char *source_file;
 
+  /* Copy from struct compile_module.  */
+  CORE_ADDR out_value_addr;
+  struct type *out_value_type;
+
   /* User data for enum compile_i_scope_types in use.  */
   void *scope_data;
 
@@ -54,7 +60,20 @@ do_module_cleanup (void *arg)
   struct objfile *objfile;
 
   if (data->executedp != NULL)
-    *data->executedp = 1;
+    {
+      *data->executedp = 1;
+
+      /* This code cannot be in compile_object_run as OUT_VALUE_TYPE
+	 no longer exists there.  */
+      if (data->out_value_addr != 0)
+	{
+	  struct value *addr_value;
+	  struct type *ptr_type = lookup_pointer_type (data->out_value_type);
+
+	  addr_value = value_from_pointer (ptr_type, data->out_value_addr);
+	  compile_print_value (value_ind (addr_value), data->scope_data);
+	}
+    }
 
   ALL_OBJFILES (objfile)
     if ((objfile->flags & OBJF_USERLOADED) == 0
@@ -91,36 +110,67 @@ compile_object_run (struct compile_module *module)
   struct cleanup *cleanups;
   struct do_module_cleanup *data;
   const char *objfile_name_s = objfile_name (module->objfile);
-  int dtor_found, executed = 0;
+  int dtor_found, executed = 0, args_count = 0;
   CORE_ADDR func_addr = module->func_addr;
   CORE_ADDR regs_addr = module->regs_addr;
+  CORE_ADDR out_value_addr = module->out_value_addr;
+  int out_value_take_address = module->out_value_take_address;
+  struct type *out_value_type = module->out_value_type;
 
   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);
+  data->out_value_addr = module->out_value_addr;
+  data->out_value_type = module->out_value_type;
   data->scope_data = module->scope_data;
 
   xfree (module->source_file);
   xfree (module);
 
+  if (regs_addr != 0)
+    args_count++;
+
+  if (out_value_addr != 0)
+    args_count += 2;
+
   TRY
     {
       func_val = value_from_pointer
 		 (builtin_type (target_gdbarch ())->builtin_func_ptr,
 		  func_addr);
 
-      if (regs_addr == 0)
+      if (args_count == 0)
 	call_function_by_hand_dummy (func_val, 0, NULL,
 				     do_module_cleanup, data);
       else
 	{
 	  struct value *arg_val;
+	  int current_arg = 0;
+	  struct value **vargs = NULL;
+
+	  vargs = alloca (sizeof (struct value *) * args_count);
 
-	  arg_val = value_from_pointer
+	  if (regs_addr != 0)
+	    {
+	      vargs[current_arg] = value_from_pointer
 		    (builtin_type (target_gdbarch ())->builtin_func_ptr,
 		     regs_addr);
-	  call_function_by_hand_dummy (func_val, 1, &arg_val,
+	      current_arg++;
+	    }
+	  if (out_value_addr != 0)
+	    {
+	      vargs[current_arg] = value_from_pointer
+		(builtin_type (target_gdbarch ())->builtin_func_ptr,
+		 out_value_addr);
+	      current_arg++;
+	      vargs[current_arg] = value_from_longest
+		(builtin_type (target_gdbarch ())->builtin_int,
+		 out_value_take_address);
+	      current_arg++;
+	    }
+
+	  call_function_by_hand_dummy (func_val, args_count, vargs,
 				       do_module_cleanup, data);
 	}
     }
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index 7589f2a..8c01b54 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -38,6 +38,7 @@
 #include "target.h"
 #include "osabi.h"
 #include "gdb_wait.h"
+#include "valprint.h"
 
 
 
@@ -163,6 +164,49 @@ compile_code_command (char *arg, int from_tty)
   do_cleanups (cleanup);
 }
 
+/* Callback for compile_print_command.  */
+
+void
+compile_print_value (struct value *val, void *data_voidp)
+{
+  const struct format_data *fmtp = data_voidp;
+
+  print_value (val, fmtp);
+}
+
+/* Handle the input from the 'compile print' command.  The "compile
+   print" command is used to evaluate and print 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_print_command (char *arg_param, int from_tty)
+{
+  const char *arg = arg_param;
+  struct cleanup *cleanup;
+  enum compile_i_scope_types scope = COMPILE_I_PRINT_SCOPE;
+  struct format_data *fmtp;
+
+  cleanup = make_cleanup_restore_integer (&interpreter_async);
+  interpreter_async = 0;
+
+  fmtp = print_command_parse_format (&arg, "compile print");
+
+  if (arg && *arg)
+    eval_compile_command (NULL, arg, scope, fmtp);
+  else
+    {
+      struct command_line *l = get_command_line (compile_control, "");
+
+      make_cleanup_free_command_lines (&l);
+      l->control_u.compile.scope = scope;
+      l->control_u.compile.scope_data = fmtp;
+      execute_control_command_untraced (l);
+    }
+
+  do_cleanups (cleanup);
+}
+
 /* A cleanup function to remove a directory and all its contents.  */
 
 static void
@@ -561,6 +605,10 @@ eval_compile_command (struct command_line *cmd, const char *cmd_string,
 		      enum compile_i_scope_types scope, void *scope_data)
 {
   char *object_file, *source_file;
+  int has_out_arg = 0;
+
+  if (scope == COMPILE_I_PRINT_SCOPE)
+    has_out_arg = 1;
 
   object_file = compile_to_object (cmd, cmd_string, scope, &source_file);
   if (object_file != NULL)
@@ -572,7 +620,7 @@ eval_compile_command (struct command_line *cmd, const char *cmd_string,
       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);
+      compile_module = compile_object_load (object_file, source_file, has_out_arg);
       discard_cleanups (cleanup_unlink);
       do_cleanups (cleanup_xfree);
       compile_module->scope_data = scope_data;
@@ -652,6 +700,27 @@ Usage: compile file [-r|-raw] [filename]\n\
 	       &compile_command_list);
   set_cmd_completer (c, filename_completer);
 
+  add_cmd ("print", class_obscure, compile_print_command,
+	   _("\
+Evaluate a EXPR with the compiler and print result.\n\
+\n\
+Usage: compile print[/FMT] [EXPR]\n\
+\n\
+The expression may be specified in one line, e.g.:\n\
+\n\
+    compile print i\n\
+\n\
+Alternatively, you can type the expression interactively.\n\
+You can invoke this mode when no argument is given to the command\n\
+(i.e.,\"compile print\" 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.\n\
+\n\
+EXPR may be preceded with /FMT, where FMT is a format letter\n\
+but no count or size letter (see \"x\" command)."),
+	   &compile_command_list);
+
   add_setshow_boolean_cmd ("compile", class_maintenance, &compile_debug, _("\
 Set compile command debugging."), _("\
 Show compile command debugging."), _("\
diff --git a/gdb/compile/compile.h b/gdb/compile/compile.h
index a973167..6e108c7 100644
--- a/gdb/compile/compile.h
+++ b/gdb/compile/compile.h
@@ -101,4 +101,6 @@ extern void compile_dwarf_bounds_to_c (struct ui_file *stream,
 				       const gdb_byte *op_end,
 				       struct dwarf2_per_cu_data *per_cu);
 
+extern void compile_print_value (struct value *val, void *data_voidp);
+
 #endif /* GDB_COMPILE_H */
diff --git a/gdb/defs.h b/gdb/defs.h
index 6476f80..849adf2 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -70,6 +70,11 @@ enum compile_i_scope_types
     /* Do not wrap the expression,
        it has to provide function "_gdb_expr" on its own.  */
     COMPILE_I_RAW_SCOPE,
+
+    /* A printable expression scope.  Wrap an expression into a scope
+       suitable for the "compile print" command.  It uses the generic
+       function name "_gdb_expr". */
+    COMPILE_I_PRINT_SCOPE,
   };
 
 /* Just in case they're not defined in stdio.h.  */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c03ecb0..b866117 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -17182,6 +17182,25 @@ compile file /home/user/example.c
 @end smallexample
 @end table
 
+@table @code
+@item compile print @var{expr}
+@itemx compile print /@var{f} @var{expr}
+Compile @var{expr} with the compiler language found as the current
+language in @value{GDBN} (@pxref{Languages}).  By default the
+value of @var{expr} is printed in a format appropriate to its data type;
+you can choose a different format by specifying @samp{/@var{f}}, where
+@var{f} is a letter specifying the format; see @ref{Output Formats,,Output
+Formats}.
+
+@item compile print
+@itemx compile print /@var{f}
+@cindex reprint the last value
+Alternatively you can enter the expression (source code producing it) as
+multiple lines of text.  To enter this mode, invoke the @samp{compile print}
+command without any text following the command.  This will start the
+multiple-line editor.
+@end table
+
 @subsection Caveats when using the @code{compile} command
 
 There are a few caveats to keep in mind when using the @code{compile}
diff --git a/gdb/testsuite/gdb.compile/compile-print.c b/gdb/testsuite/gdb.compile/compile-print.c
new file mode 100644
index 0000000..773871c
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/compile-print.c
@@ -0,0 +1,28 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 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 <stdlib.h>
+
+int varint = 10;
+int vararray[] = { 1, 2, 3, 4, 5 };
+int *vararrayp = vararray;
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.compile/compile-print.exp b/gdb/testsuite/gdb.compile/compile-print.exp
new file mode 100644
index 0000000..0e7c8fe
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/compile-print.exp
@@ -0,0 +1,56 @@
+# Copyright 2015 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
+
+if { [prepare_for_testing ${testfile}.exp "$testfile"] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+if {[skip_compile_feature_tests]} {
+    untested "compile command not supported (could not find libcc1 shared library?)"
+    return -1
+}
+
+gdb_test "compile print varint" " = 10"
+gdb_test "compile print vararray" " = \\{1, 2, 3, 4, 5\\}"
+gdb_test "compile print main" " = \\{int \\(void\\)\\} 0x\[0-9a-f\]+"
+
+set test "compile print *vararray@3"
+gdb_test_multiple $test $test {
+    -re " = \\{1, 2, 3\\}\r\n$gdb_prompt $" {
+	pass $test
+    }
+    -re ": error: stray '@' in program\r\n.*\r\n$gdb_prompt $" {
+	xfail "$test (gcc does not support '@')"
+    }
+}
+
+set test "compile print *vararrayp@3"
+gdb_test_multiple $test $test {
+    -re " = \\{1, 2, 3\\}\r\n$gdb_prompt $" {
+	pass $test
+    }
+    -re ": error: stray '@' in program\r\n.*\r\n$gdb_prompt $" {
+	xfail "$test (gcc does not support '@')"
+    }
+}
+
+gdb_test "compile print/x 256" " = 0x100"
+gdb_test {print $} " = 256"
