Change extension language pretty-printers to use value API

This changes the extension language pretty-printers to use the value
API.

Note that new functions were needed, for both Guile and Python.
Currently both languages always wrap values by removing the values
from the value chain.  This makes sense to avoid strange behavior with
watchpoints, and to avoid excessive memory use.  However, when
printing, it's important to leave the passed-in value untouched, in
case pretty-printing does nothing -- that way the caller can still
access it.

gdb/ChangeLog
2020-03-13  Tom Tromey  <tom@tromey.com>

	* valprint.c (do_val_print): Update.
	* python/python-internal.h (gdbpy_apply_val_pretty_printer): Take
	a struct value.
	(value_to_value_object_no_release): Declare.
	* python/py-value.c (value_to_value_object_no_release): New
	function.
	* python/py-prettyprint.c (gdbpy_apply_val_pretty_printer): Take a
	struct value.
	* guile/scm-value.c (vlscm_scm_from_value_no_release): New
	function.
	* guile/scm-pretty-print.c (gdbscm_apply_val_pretty_printer): Take
	a struct value.
	* guile/guile-internal.h (vlscm_scm_from_value_no_release):
	Declare.
	(gdbscm_apply_val_pretty_printer): Take a struct value.
	* extension.h (apply_ext_lang_val_pretty_printer): Take a struct
	value.
	* extension.c (apply_ext_lang_val_pretty_printer): Take a struct
	value.
	* extension-priv.h (struct extension_language_ops)
	<apply_val_pretty_printer>: Take a struct value.
	* cp-valprint.c (cp_print_value): Create a struct value.
	(cp_print_value): Update.
This commit is contained in:
Tom Tromey 2020-03-13 17:39:52 -06:00
parent 3a916a9757
commit 42331a1ea2
12 changed files with 119 additions and 76 deletions

View File

@ -1,3 +1,29 @@
2020-03-13 Tom Tromey <tom@tromey.com>
* valprint.c (do_val_print): Update.
* python/python-internal.h (gdbpy_apply_val_pretty_printer): Take
a struct value.
(value_to_value_object_no_release): Declare.
* python/py-value.c (value_to_value_object_no_release): New
function.
* python/py-prettyprint.c (gdbpy_apply_val_pretty_printer): Take a
struct value.
* guile/scm-value.c (vlscm_scm_from_value_no_release): New
function.
* guile/scm-pretty-print.c (gdbscm_apply_val_pretty_printer): Take
a struct value.
* guile/guile-internal.h (vlscm_scm_from_value_no_release):
Declare.
(gdbscm_apply_val_pretty_printer): Take a struct value.
* extension.h (apply_ext_lang_val_pretty_printer): Take a struct
value.
* extension.c (apply_ext_lang_val_pretty_printer): Take a struct
value.
* extension-priv.h (struct extension_language_ops)
<apply_val_pretty_printer>: Take a struct value.
* cp-valprint.c (cp_print_value): Create a struct value.
(cp_print_value): Update.
2020-03-13 Tom Tromey <tom@tromey.com> 2020-03-13 Tom Tromey <tom@tromey.com>
* ada-valprint.c (print_field_values): Call common_val_print. * ada-valprint.c (print_field_values): Call common_val_print.

View File

@ -848,13 +848,15 @@ cp_print_value (struct type *type, struct type *real_type,
/* Attempt to run an extension language pretty-printer on the /* Attempt to run an extension language pretty-printer on the
baseclass if possible. */ baseclass if possible. */
if (!options->raw) if (!options->raw)
result {
= apply_ext_lang_val_pretty_printer (baseclass, struct value *v
thisoffset + boffset, = value_from_component (base_val, baseclass,
value_address (base_val), thisoffset + boffset);
stream, recurse, result
base_val, options, = apply_ext_lang_val_pretty_printer (v, stream, recurse,
current_language); options,
current_language);
}
if (!result) if (!result)
cp_print_value_fields (baseclass, thistype, cp_print_value_fields (baseclass, thistype,
@ -1006,19 +1008,19 @@ cp_print_value (struct value *val, struct ui_file *stream,
} }
else else
{ {
struct value *baseclass_val = value_primitive_field (val, 0,
i, type);
/* Attempt to run an extension language pretty-printer on the /* Attempt to run an extension language pretty-printer on the
baseclass if possible. */ baseclass if possible. */
if (!options->raw) if (!options->raw)
result result
= apply_ext_lang_val_pretty_printer (baseclass, boffset, = apply_ext_lang_val_pretty_printer (baseclass_val, stream,
value_address (base_val), recurse, options,
stream, recurse,
base_val, options,
current_language); current_language);
if (!result) if (!result)
cp_print_value_fields (value_primitive_field (val, 0, i, type), cp_print_value_fields (baseclass_val, stream, recurse, options,
stream, recurse, options,
((struct type **) ((struct type **)
obstack_base (&dont_print_vb_obstack)), obstack_base (&dont_print_vb_obstack)),
0); 0);

View File

@ -152,19 +152,14 @@ struct extension_language_ops
void (*free_type_printers) (const struct extension_language_defn *, void (*free_type_printers) (const struct extension_language_defn *,
struct ext_lang_type_printers *); struct ext_lang_type_printers *);
/* Try to pretty-print a value of type TYPE located at VAL's contents /* Try to pretty-print a value, onto stdio stream STREAM according
buffer + EMBEDDED_OFFSET, which came from the inferior at address to OPTIONS. VAL is the object to print. Returns EXT_LANG_RC_OK
ADDRESS + EMBEDDED_OFFSET, onto stdio stream STREAM according to upon success, EXT_LANG_RC_NOP if the value is not recognized, and
OPTIONS. EXT_LANG_RC_ERROR if an error was encountered. */
VAL is the whole object that came from ADDRESS.
Returns EXT_LANG_RC_OK upon success, EXT_LANG_RC_NOP if the value
is not recognized, and EXT_LANG_RC_ERROR if an error was encountered. */
enum ext_lang_rc (*apply_val_pretty_printer) enum ext_lang_rc (*apply_val_pretty_printer)
(const struct extension_language_defn *, (const struct extension_language_defn *,
struct type *type, struct value *val, struct ui_file *stream, int recurse,
LONGEST embedded_offset, CORE_ADDR address, const struct value_print_options *options,
struct ui_file *stream, int recurse,
struct value *val, const struct value_print_options *options,
const struct language_defn *language); const struct language_defn *language);
/* GDB access to the "frame filter" feature. /* GDB access to the "frame filter" feature.

View File

@ -470,12 +470,9 @@ ext_lang_type_printers::~ext_lang_type_printers ()
} }
} }
/* Try to pretty-print a value of type TYPE located at VAL's contents /* Try to pretty-print a value onto stdio stream STREAM according to
buffer + EMBEDDED_OFFSET, which came from the inferior at address OPTIONS. VAL is the object to print. Returns non-zero if the
ADDRESS + EMBEDDED_OFFSET, onto stdio stream STREAM according to value was successfully pretty-printed.
OPTIONS.
VAL is the whole object that came from ADDRESS.
Returns non-zero if the value was successfully pretty-printed.
Extension languages are tried in the order specified by Extension languages are tried in the order specified by
extension_languages. The first one to provide a pretty-printed extension_languages. The first one to provide a pretty-printed
@ -488,10 +485,8 @@ ext_lang_type_printers::~ext_lang_type_printers ()
errors that trigger an exception in the extension language. */ errors that trigger an exception in the extension language. */
int int
apply_ext_lang_val_pretty_printer (struct type *type, apply_ext_lang_val_pretty_printer (struct value *val,
LONGEST embedded_offset, CORE_ADDR address,
struct ui_file *stream, int recurse, struct ui_file *stream, int recurse,
struct value *val,
const struct value_print_options *options, const struct value_print_options *options,
const struct language_defn *language) const struct language_defn *language)
{ {
@ -504,10 +499,8 @@ apply_ext_lang_val_pretty_printer (struct type *type,
if (extlang->ops->apply_val_pretty_printer == NULL) if (extlang->ops->apply_val_pretty_printer == NULL)
continue; continue;
rc = extlang->ops->apply_val_pretty_printer (extlang, type, rc = extlang->ops->apply_val_pretty_printer (extlang, val, stream,
embedded_offset, address, recurse, options, language);
stream, recurse, val,
options, language);
switch (rc) switch (rc)
{ {
case EXT_LANG_RC_OK: case EXT_LANG_RC_OK:

View File

@ -283,10 +283,8 @@ extern char *apply_ext_lang_type_printers (struct ext_lang_type_printers *,
struct type *); struct type *);
extern int apply_ext_lang_val_pretty_printer extern int apply_ext_lang_val_pretty_printer
(struct type *type, (struct value *value, struct ui_file *stream, int recurse,
LONGEST embedded_offset, CORE_ADDR address, const struct value_print_options *options,
struct ui_file *stream, int recurse,
struct value *val, const struct value_print_options *options,
const struct language_defn *language); const struct language_defn *language);
extern enum ext_lang_bt_status apply_ext_lang_frame_filter extern enum ext_lang_bt_status apply_ext_lang_frame_filter

View File

@ -579,6 +579,7 @@ extern struct value *vlscm_scm_to_value (SCM scm);
extern int vlscm_is_value (SCM scm); extern int vlscm_is_value (SCM scm);
extern SCM vlscm_scm_from_value (struct value *value); extern SCM vlscm_scm_from_value (struct value *value);
extern SCM vlscm_scm_from_value_no_release (struct value *value);
extern struct value *vlscm_convert_typed_value_from_scheme extern struct value *vlscm_convert_typed_value_from_scheme
(const char *func_name, int obj_arg_pos, SCM obj, (const char *func_name, int obj_arg_pos, SCM obj,
@ -602,10 +603,8 @@ extern void gdbscm_preserve_values
extern enum ext_lang_rc gdbscm_apply_val_pretty_printer extern enum ext_lang_rc gdbscm_apply_val_pretty_printer
(const struct extension_language_defn *, (const struct extension_language_defn *,
struct type *type,
LONGEST embedded_offset, CORE_ADDR address,
struct ui_file *stream, int recurse,
struct value *val, struct value *val,
struct ui_file *stream, int recurse,
const struct value_print_options *options, const struct value_print_options *options,
const struct language_defn *language); const struct language_defn *language);

View File

@ -943,36 +943,32 @@ ppscm_print_children (SCM printer, enum display_hint hint,
enum ext_lang_rc enum ext_lang_rc
gdbscm_apply_val_pretty_printer (const struct extension_language_defn *extlang, gdbscm_apply_val_pretty_printer (const struct extension_language_defn *extlang,
struct type *type, struct value *value,
LONGEST embedded_offset, CORE_ADDR address,
struct ui_file *stream, int recurse, struct ui_file *stream, int recurse,
struct value *val,
const struct value_print_options *options, const struct value_print_options *options,
const struct language_defn *language) const struct language_defn *language)
{ {
struct type *type = value_type (value);
struct gdbarch *gdbarch = get_type_arch (type); struct gdbarch *gdbarch = get_type_arch (type);
SCM exception = SCM_BOOL_F; SCM exception = SCM_BOOL_F;
SCM printer = SCM_BOOL_F; SCM printer = SCM_BOOL_F;
SCM val_obj = SCM_BOOL_F; SCM val_obj = SCM_BOOL_F;
struct value *value;
enum display_hint hint; enum display_hint hint;
enum ext_lang_rc result = EXT_LANG_RC_NOP; enum ext_lang_rc result = EXT_LANG_RC_NOP;
enum string_repr_result print_result; enum string_repr_result print_result;
if (value_lazy (val)) if (value_lazy (value))
value_fetch_lazy (val); value_fetch_lazy (value);
/* No pretty-printer support for unavailable values. */ /* No pretty-printer support for unavailable values. */
if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type))) if (!value_bytes_available (value, 0, TYPE_LENGTH (type)))
return EXT_LANG_RC_NOP; return EXT_LANG_RC_NOP;
if (!gdb_scheme_initialized) if (!gdb_scheme_initialized)
return EXT_LANG_RC_NOP; return EXT_LANG_RC_NOP;
/* Instantiate the printer. */ /* Instantiate the printer. */
value = value_from_component (val, type, embedded_offset); val_obj = vlscm_scm_from_value_no_release (value);
val_obj = vlscm_scm_from_value (value);
if (gdbscm_is_exception (val_obj)) if (gdbscm_is_exception (val_obj))
{ {
exception = val_obj; exception = val_obj;

View File

@ -261,6 +261,24 @@ vlscm_scm_from_value (struct value *value)
return v_scm; return v_scm;
} }
/* Create a new <gdb:value> object that encapsulates VALUE.
The value is not released from the all_values chain. */
SCM
vlscm_scm_from_value_no_release (struct value *value)
{
/* N.B. It's important to not cause any side-effects until we know the
conversion worked. */
SCM v_scm = vlscm_make_value_smob ();
value_smob *v_smob = (value_smob *) SCM_SMOB_DATA (v_scm);
value_incref (value);
v_smob->value = value;
vlscm_remember_scheme_value (v_smob);
return v_scm;
}
/* Returns the <gdb:value> object in SELF. /* Returns the <gdb:value> object in SELF.
Throws an exception if SELF is not a <gdb:value> object. */ Throws an exception if SELF is not a <gdb:value> object. */

View File

@ -558,22 +558,20 @@ print_children (PyObject *printer, const char *hint,
enum ext_lang_rc enum ext_lang_rc
gdbpy_apply_val_pretty_printer (const struct extension_language_defn *extlang, gdbpy_apply_val_pretty_printer (const struct extension_language_defn *extlang,
struct type *type, struct value *value,
LONGEST embedded_offset, CORE_ADDR address,
struct ui_file *stream, int recurse, struct ui_file *stream, int recurse,
struct value *val,
const struct value_print_options *options, const struct value_print_options *options,
const struct language_defn *language) const struct language_defn *language)
{ {
struct type *type = value_type (value);
struct gdbarch *gdbarch = get_type_arch (type); struct gdbarch *gdbarch = get_type_arch (type);
struct value *value;
enum string_repr_result print_result; enum string_repr_result print_result;
if (value_lazy (val)) if (value_lazy (value))
value_fetch_lazy (val); value_fetch_lazy (value);
/* No pretty-printer support for unavailable values. */ /* No pretty-printer support for unavailable values. */
if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type))) if (!value_bytes_available (value, 0, TYPE_LENGTH (type)))
return EXT_LANG_RC_NOP; return EXT_LANG_RC_NOP;
if (!gdb_python_initialized) if (!gdb_python_initialized)
@ -581,10 +579,7 @@ gdbpy_apply_val_pretty_printer (const struct extension_language_defn *extlang,
gdbpy_enter enter_py (gdbarch, language); gdbpy_enter enter_py (gdbarch, language);
/* Instantiate the printer. */ gdbpy_ref<> val_obj (value_to_value_object_no_release (value));
value = value_from_component (val, type, embedded_offset);
gdbpy_ref<> val_obj (value_to_value_object (value));
if (val_obj == NULL) if (val_obj == NULL)
{ {
print_stack_unless_memory_error (stream); print_stack_unless_memory_error (stream);

View File

@ -1788,6 +1788,27 @@ value_to_value_object (struct value *val)
return (PyObject *) val_obj; return (PyObject *) val_obj;
} }
/* Returns an object for a value, but without releasing it from the
all_values chain. */
PyObject *
value_to_value_object_no_release (struct value *val)
{
value_object *val_obj;
val_obj = PyObject_New (value_object, &value_object_type);
if (val_obj != NULL)
{
value_incref (val);
val_obj->value = val;
val_obj->address = NULL;
val_obj->type = NULL;
val_obj->dynamic_type = NULL;
note_value (val_obj);
}
return (PyObject *) val_obj;
}
/* Returns a borrowed reference to the struct value corresponding to /* Returns a borrowed reference to the struct value corresponding to
the given value object. */ the given value object. */
struct value * struct value *

View File

@ -391,10 +391,8 @@ extern int gdbpy_auto_load_enabled (const struct extension_language_defn *);
extern enum ext_lang_rc gdbpy_apply_val_pretty_printer extern enum ext_lang_rc gdbpy_apply_val_pretty_printer
(const struct extension_language_defn *, (const struct extension_language_defn *,
struct type *type, struct value *value,
LONGEST embedded_offset, CORE_ADDR address,
struct ui_file *stream, int recurse, struct ui_file *stream, int recurse,
struct value *val,
const struct value_print_options *options, const struct value_print_options *options,
const struct language_defn *language); const struct language_defn *language);
extern enum ext_lang_bt_status gdbpy_apply_frame_filter extern enum ext_lang_bt_status gdbpy_apply_frame_filter
@ -456,6 +454,7 @@ PyObject *symbol_to_symbol_object (struct symbol *sym);
PyObject *block_to_block_object (const struct block *block, PyObject *block_to_block_object (const struct block *block,
struct objfile *objfile); struct objfile *objfile);
PyObject *value_to_value_object (struct value *v); PyObject *value_to_value_object (struct value *v);
PyObject *value_to_value_object_no_release (struct value *v);
PyObject *type_to_type_object (struct type *); PyObject *type_to_type_object (struct type *);
PyObject *frame_info_to_frame_object (struct frame_info *frame); PyObject *frame_info_to_frame_object (struct frame_info *frame);
PyObject *symtab_to_linetable_object (PyObject *symtab); PyObject *symtab_to_linetable_object (PyObject *symtab);

View File

@ -1279,9 +1279,13 @@ do_val_print (struct value *full_value,
if (!options->raw) if (!options->raw)
{ {
ret = apply_ext_lang_val_pretty_printer (type, embedded_offset, struct value *v = full_value;
address, stream, recurse,
val, options, language); if (v == nullptr)
v = value_from_component (val, type, embedded_offset);
ret = apply_ext_lang_val_pretty_printer (v, stream, recurse, options,
language);
if (ret) if (ret)
return; return;
} }
@ -1477,11 +1481,8 @@ value_print (struct value *val, struct ui_file *stream,
if (!options->raw) if (!options->raw)
{ {
int r int r
= apply_ext_lang_val_pretty_printer (value_type (val), = apply_ext_lang_val_pretty_printer (val, stream, 0, options,
value_embedded_offset (val), current_language);
value_address (val),
stream, 0,
val, options, current_language);
if (r) if (r)
return; return;