+2015-05-16 Jan Kratochvil <jan.kratochvil@redhat.com>
+ Phil Muldoon <pmuldoon@redhat.com>
+
+ * NEWS (Changes since GDB 7.9): Add compile print.
+ * compile/compile-c-support.c (add_code_header, add_code_footer)
+ (c_compute_program): Add COMPILE_I_PRINT_ADDRESS_SCOPE and
+ COMPILE_I_PRINT_VALUE_SCOPE.
+ * compile/compile-internal.h (COMPILE_I_PRINT_OUT_ARG_TYPE)
+ (COMPILE_I_PRINT_OUT_ARG, COMPILE_I_EXPR_VAL, COMPILE_I_EXPR_PTR_TYPE):
+ New.
+ * compile/compile-object-load.c: Include block.h.
+ (get_out_value_type): New function.
+ (compile_object_load): Handle COMPILE_I_PRINT_ADDRESS_SCOPE and
+ COMPILE_I_PRINT_VALUE_SCOPE. Set compile_module's OUT_VALUE_ADDR and
+ OUT_VALUE_TYPE.
+ * compile/compile-object-load.h (struct compile_module): Add fields
+ out_value_addr and out_value_type.
+ * compile/compile-object-run.c: Include valprint.h and compile.h.
+ (struct do_module_cleanup): Add fields out_value_addr and
+ out_value_type.
+ (do_module_cleanup): Handle COMPILE_I_PRINT_ADDRESS_SCOPE and
+ COMPILE_I_PRINT_VALUE_SCOPE.
+ (compile_object_run): Propagate out_value_addr and out_value_type.
+ Pass OUT_VALUE_ADDR.
+ * compile/compile.c: Include valprint.h.
+ (compile_print_value, compile_print_command): New functions.
+ (eval_compile_command): Handle failed COMPILE_I_PRINT_ADDRESS_SCOPE.
+ (_initialize_compile): Update compile code help text. Install
+ compile_print_command.
+ * compile/compile.h (compile_print_value): New prototype.
+ * defs.h (enum compile_i_scope_types): Add
+ COMPILE_I_PRINT_ADDRESS_SCOPE and COMPILE_I_PRINT_VALUE_SCOPE.
+
2015-05-16 Jan Kratochvil <jan.kratochvil@redhat.com>
* compile/compile-object-load.c (get_regs_type): Add parameter func_sym.
record bts
Start branch trace recording using Branch Trace Store (BTS) format.
+compile print
+ Evaluate expression by using the compiler and print result.
+
* New options
set max-completions
") {\n",
buf);
break;
+ case COMPILE_I_PRINT_ADDRESS_SCOPE:
+ case COMPILE_I_PRINT_VALUE_SCOPE:
+ /* <string.h> is needed for a memcpy call below. */
+ fputs_unfiltered ("#include <string.h>\n"
+ "void "
+ GCC_FE_WRAPPER_FUNCTION
+ " (struct "
+ COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
+ " *"
+ COMPILE_I_SIMPLE_REGISTER_ARG_NAME
+ ", "
+ COMPILE_I_PRINT_OUT_ARG_TYPE
+ " "
+ COMPILE_I_PRINT_OUT_ARG
+ ") {\n",
+ buf);
+ break;
+
case COMPILE_I_RAW_SCOPE:
break;
default:
switch (type)
{
case COMPILE_I_SIMPLE_SCOPE:
+ case COMPILE_I_PRINT_ADDRESS_SCOPE:
+ case COMPILE_I_PRINT_VALUE_SCOPE:
fputs_unfiltered ("}\n", buf);
break;
case COMPILE_I_RAW_SCOPE:
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_ADDRESS_SCOPE
+ || inst->scope == COMPILE_I_PRINT_VALUE_SCOPE)
{
ui_file_put (var_stream, ui_file_write_for_put, buf);
fputs_unfiltered ("#pragma GCC user_expression\n", buf);
fputs_unfiltered ("{\n", buf);
fputs_unfiltered ("#line 1 \"gdb command line\"\n", buf);
- fputs_unfiltered (input, buf);
+
+ switch (inst->scope)
+ {
+ case COMPILE_I_PRINT_ADDRESS_SCOPE:
+ case COMPILE_I_PRINT_VALUE_SCOPE:
+ fprintf_unfiltered (buf,
+"__auto_type " COMPILE_I_EXPR_VAL " = %s;\n"
+"typeof (%s) *" COMPILE_I_EXPR_PTR_TYPE ";\n"
+"memcpy (" COMPILE_I_PRINT_OUT_ARG ", %s" COMPILE_I_EXPR_VAL ",\n"
+ "sizeof (*" COMPILE_I_EXPR_PTR_TYPE "));\n"
+ , input, input,
+ (inst->scope == COMPILE_I_PRINT_ADDRESS_SCOPE
+ ? "&" : ""));
+ break;
+ default:
+ fputs_unfiltered (input, buf);
+ break;
+ }
+
fputs_unfiltered ("\n", buf);
/* For larger user expressions the automatic semicolons may be
#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_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
#include "regcache.h"
#include "inferior.h"
#include "compile.h"
+#include "block.h"
#include "arch-utils.h"
/* Helper data for setup_sections. */
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.
+ GDB first tries to compile the code with COMPILE_I_PRINT_ADDRESS_SCOPE.
+ If it finds user tries to print an array type this function returns
+ NULL. Caller will then regenerate the code with
+ COMPILE_I_PRINT_VALUE_SCOPE, recompiles it again and finally runs it.
+ This is because __auto_type array-to-pointer type conversion of
+ COMPILE_I_EXPR_VAL which gets detected by COMPILE_I_EXPR_PTR_TYPE
+ preserving the array type. */
+
+static struct type *
+get_out_value_type (struct symbol *func_sym, struct objfile *objfile,
+ enum compile_i_scope_types scope)
+{
+ struct symbol *gdb_ptr_type_sym, *gdb_val_sym;
+ struct type *gdb_ptr_type, *gdb_type_from_ptr, *gdb_type;
+ const struct block *block;
+ const struct blockvector *bv;
+ int nblocks = 0;
+ int block_loop = 0;
+
+ 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_val_sym = block_lookup_symbol (block, COMPILE_I_EXPR_VAL, VAR_DOMAIN);
+ if (gdb_val_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_type = SYMBOL_TYPE (gdb_val_sym);
+ CHECK_TYPEDEF (gdb_type);
+
+ gdb_ptr_type_sym = block_lookup_symbol (block, COMPILE_I_EXPR_PTR_TYPE,
+ VAR_DOMAIN);
+ if (gdb_ptr_type_sym == NULL)
+ 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);
+
+ if (types_deeply_equal (gdb_type, gdb_type_from_ptr))
+ {
+ if (scope != COMPILE_I_PRINT_ADDRESS_SCOPE)
+ error (_("Expected address scope in compiled module \"%s\"."),
+ objfile_name (objfile));
+ 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:
+ gdb_type_from_ptr = TYPE_TARGET_TYPE (gdb_type_from_ptr);
+ break;
+ case TYPE_CODE_FUNC:
+ 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));
+ if (scope == COMPILE_I_PRINT_ADDRESS_SCOPE)
+ return NULL;
+ return gdb_type_from_ptr;
+}
+
/* Fetch the type of first parameter of FUNC_SYM.
Return NULL if FUNC_SYM has no parameters. 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. */
+ function returns.
+ Function returns NULL only for COMPILE_I_PRINT_ADDRESS_SCOPE when
+ COMPILE_I_PRINT_VALUE_SCOPE should have been used instead. */
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, regs_addr;
+ CORE_ADDR addr, regs_addr, out_value_addr = 0;
struct symbol *func_sym;
struct type *func_type;
struct bound_minimal_symbol bmsym;
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;
char *filename, **matching;
struct objfile *objfile;
int expect_parameters;
expect_parameters = 0;
expect_return_type = builtin_type (target_gdbarch ())->builtin_void;
break;
+ case COMPILE_I_PRINT_ADDRESS_SCOPE:
+ case COMPILE_I_PRINT_VALUE_SCOPE:
+ expect_parameters = 2;
+ expect_return_type = builtin_type (target_gdbarch ())->builtin_void;
+ break;
default:
internal_error (__FILE__, __LINE__, _("invalid scope %d"), scope);
}
store_regs (regs_type, regs_addr);
}
+ if (scope == COMPILE_I_PRINT_ADDRESS_SCOPE
+ || scope == COMPILE_I_PRINT_VALUE_SCOPE)
+ {
+ out_value_type = get_out_value_type (func_sym, objfile, scope);
+ if (out_value_type == NULL)
+ {
+ do_cleanups (cleanups);
+ return NULL;
+ }
+ check_typedef (out_value_type);
+ out_value_addr = gdbarch_infcall_mmap (target_gdbarch (),
+ TYPE_LENGTH (out_value_type),
+ (GDB_MMAP_PROT_READ
+ | GDB_MMAP_PROT_WRITE));
+ gdb_assert (out_value_addr != 0);
+ if (compile_debug)
+ fprintf_unfiltered (gdb_stdout,
+ "allocated %s bytes at %s for printed value\n",
+ paddress (target_gdbarch (),
+ TYPE_LENGTH (out_value_type)),
+ paddress (target_gdbarch (), out_value_addr));
+ }
+
discard_cleanups (cleanups_free_objfile);
do_cleanups (cleanups);
retval->regs_addr = regs_addr;
retval->scope = scope;
retval->scope_data = scope_data;
+ retval->out_value_type = out_value_type;
+ retval->out_value_addr = out_value_addr;
return retval;
}
/* User data for SCOPE in use. */
void *scope_data;
+
+ /* Inferior parameter out value type or NULL if the inferior function does not
+ have one. */
+ struct type *out_value_type;
+
+ /* If the inferior function has an out value, this is its address.
+ Otherwise it is zero. */
+ CORE_ADDR out_value_addr;
};
extern struct compile_module *compile_object_load
#include "compile-internal.h"
#include "dummy-frame.h"
#include "block.h"
+#include "valprint.h"
+#include "compile.h"
/* Helper for do_module_cleanup. */
enum compile_i_scope_types scope;
void *scope_data;
+ /* Copy from struct compile_module. */
+ struct type *out_value_type;
+ CORE_ADDR out_value_addr;
+
/* objfile_name of our objfile. */
char objfile_name_string[1];
};
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->scope == COMPILE_I_PRINT_ADDRESS_SCOPE
+ || data->scope == COMPILE_I_PRINT_VALUE_SCOPE)
+ {
+ 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);
+
+ /* SCOPE_DATA would be stale unlesse EXECUTEDP != NULL. */
+ compile_print_value (value_ind (addr_value), data->scope_data);
+ }
+ }
ALL_OBJFILES (objfile)
if ((objfile->flags & OBJF_USERLOADED) == 0
strcpy (data->objfile_name_string, objfile_name_s);
data->scope = module->scope;
data->scope_data = module->scope_data;
+ data->out_value_type = module->out_value_type;
+ data->out_value_addr = module->out_value_addr;
xfree (module->source_file);
xfree (module);
(TYPE_FIELD_TYPE (func_type, current_arg), regs_addr);
++current_arg;
}
+ if (TYPE_NFIELDS (func_type) >= 2)
+ {
+ gdb_assert (data->out_value_addr != 0);
+ vargs[current_arg] = value_from_pointer
+ (TYPE_FIELD_TYPE (func_type, current_arg), data->out_value_addr);
+ ++current_arg;
+ }
gdb_assert (current_arg == TYPE_NFIELDS (func_type));
call_function_by_hand_dummy (func_val, TYPE_NFIELDS (func_type), vargs,
do_module_cleanup, data);
#include "target.h"
#include "osabi.h"
#include "gdb_wait.h"
+#include "valprint.h"
\f
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_ADDRESS_SCOPE;
+ struct format_data fmt;
+
+ cleanup = make_cleanup_restore_integer (&interpreter_async);
+ interpreter_async = 0;
+
+ /* Passing &FMT as SCOPE_DATA is safe as do_module_cleanup will not
+ touch the stale pointer if compile_object_run has already quit. */
+ print_command_parse_format (&arg, "compile print", &fmt);
+
+ if (arg && *arg)
+ eval_compile_command (NULL, arg, scope, &fmt);
+ 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 = &fmt;
+ execute_control_command_untraced (l);
+ }
+
+ do_cleanups (cleanup);
+}
+
/* A cleanup function to remove a directory and all its contents. */
static void
make_cleanup (cleanup_unlink_file, source_file);
compile_module = compile_object_load (object_file, source_file,
scope, scope_data);
+ if (compile_module == NULL)
+ {
+ gdb_assert (scope == COMPILE_I_PRINT_ADDRESS_SCOPE);
+ do_cleanups (cleanup_xfree);
+ eval_compile_command (cmd, cmd_string,
+ COMPILE_I_PRINT_VALUE_SCOPE, scope_data);
+ return;
+ }
discard_cleanups (cleanup_unlink);
do_cleanups (cleanup_xfree);
compile_object_run (compile_module);
\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."),
+Alternatively, you can type a multiline expression by invoking\n\
+this command with no argument. GDB will then prompt for the\n\
+expression interactively; type a line containing \"end\" to\n\
+indicate the end of the expression."),
&compile_command_list);
c = add_cmd ("file", class_obscure, compile_file_command,
&compile_command_list);
set_cmd_completer (c, filename_completer);
+ add_cmd ("print", class_obscure, compile_print_command,
+ _("\
+Evaluate EXPR by using the compiler and print result.\n\
+\n\
+Usage: compile print[/FMT] [EXPR]\n\
+\n\
+The expression may be specified on the same line as the command, e.g.:\n\
+\n\
+ compile print i\n\
+\n\
+Alternatively, you can type a multiline expression by invoking\n\
+this command with no argument. GDB will then prompt for the\n\
+expression interactively; type a line containing \"end\" to\n\
+indicate the end of the expression.\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."), _("\
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 */
/* 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_ADDRESS_SCOPE variant
+ is the usual one, taking address of the object.
+ COMPILE_I_PRINT_VALUE_SCOPE is needed for arrays where the array
+ name already specifies its address. See get_out_value_type. */
+ COMPILE_I_PRINT_ADDRESS_SCOPE,
+ COMPILE_I_PRINT_VALUE_SCOPE,
};
/* Just in case they're not defined in stdio.h. */
+2015-05-16 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ * gdb.texinfo (Compiling and Injecting Code): Add compile print.
+
2015-05-12 Don Breazeal <donb@codesourcery.com>
* gdb.texinfo (Forks): Note that fork debugging is
@end smallexample
@end table
+@table @code
+@item compile print @var{expr}
+@itemx compile print /@var{f} @var{expr}
+Compile and execute @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
+
@noindent
The process of compiling and injecting the code can be inspected using:
+2015-05-16 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ * gdb.compile/compile-print.c: New file.
+ * gdb.compile/compile-print.exp: New file.
+
2015-05-16 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.compile/compile-ops.exp: Cast param to void.
--- /dev/null
+/* 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;
+struct object
+{
+ int field;
+} varobject = { 1 };
+
+int
+main (void)
+{
+ return 0;
+}
--- /dev/null
+# 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"
+
+gdb_test "compile print varobject" { = {field = 1}}