Add xmethod interface to the extension language API.
* defs.h (enum lval_type): New enumerator "lval_xcallable". * extension-priv.h (struct extension_language_ops): Add the xmethod interface. * extension.c (new_xmethod_worker, clone_xmethod_worker, get_matching_xmethod_workers, get_xmethod_argtypes, invoke_xmethod, free_xmethod_worker, free_xmethod_worker_vec): New functions. * extension.h: #include "common/vec.h". New function declarations. (struct xmethod_worker): New struct. (VEC (xmethod_worker_ptr)): New vector type. (xmethod_worker_ptr): New typedef. (xmethod_worker_vec): Likewise. * gdbtypes.c (gdbtypes_post_init): Initialize "xmethod" field of builtin_type. * gdbtypes.h (enum type_code): New enumerator TYPE_CODE_XMETHOD. (struct builtin_type): New field "xmethod". * valarith.c (value_ptradd): Assert that the value argument is not lval_xcallable. * valops.c (value_must_coerce_to_target): Return 0 for lval_xcallable values. * value.c (struct value): New field XM_WORKER in the field LOCATION. (value_address, value_raw_address): Return 0 for lval_xcallable values. (set_value_address): Assert that the value is not an lval_xcallable. (value_free): Free the associated xmethod worker when freeing lval_xcallable values. (set_value_component_location): Assert that the WHOLE value is not lval_xcallable. (value_of_xmethod, call_xmethod): New functions. * value.h: Declare "struct xmethod_worker". Declare new functions value_of_xmethod, call_xmethod.
This commit is contained in:
parent
ef370185fc
commit
e81e7f5e38
10 changed files with 341 additions and 5 deletions
|
@ -1,3 +1,40 @@
|
||||||
|
2014-06-03 Siva Chandra Reddy <sivachandra@google.com>
|
||||||
|
|
||||||
|
* defs.h (enum lval_type): New enumerator "lval_xcallable".
|
||||||
|
* extension-priv.h (struct extension_language_ops): Add the
|
||||||
|
xmethod interface.
|
||||||
|
* extension.c (new_xmethod_worker, clone_xmethod_worker,
|
||||||
|
get_matching_xmethod_workers, get_xmethod_argtypes,
|
||||||
|
invoke_xmethod, free_xmethod_worker,
|
||||||
|
free_xmethod_worker_vec): New functions.
|
||||||
|
* extension.h: #include "common/vec.h".
|
||||||
|
New function declarations.
|
||||||
|
(struct xmethod_worker): New struct.
|
||||||
|
(VEC (xmethod_worker_ptr)): New vector type.
|
||||||
|
(xmethod_worker_ptr): New typedef.
|
||||||
|
(xmethod_worker_vec): Likewise.
|
||||||
|
* gdbtypes.c (gdbtypes_post_init): Initialize "xmethod" field of
|
||||||
|
builtin_type.
|
||||||
|
* gdbtypes.h (enum type_code): New enumerator TYPE_CODE_XMETHOD.
|
||||||
|
(struct builtin_type): New field "xmethod".
|
||||||
|
* valarith.c (value_ptradd): Assert that the value argument is not
|
||||||
|
lval_xcallable.
|
||||||
|
* valops.c (value_must_coerce_to_target): Return 0 for
|
||||||
|
lval_xcallable values.
|
||||||
|
* value.c (struct value): New field XM_WORKER in the field
|
||||||
|
LOCATION.
|
||||||
|
(value_address, value_raw_address): Return 0 for lval_xcallable
|
||||||
|
values.
|
||||||
|
(set_value_address): Assert that the value is not an
|
||||||
|
lval_xcallable.
|
||||||
|
(value_free): Free the associated xmethod worker when freeing
|
||||||
|
lval_xcallable values.
|
||||||
|
(set_value_component_location): Assert that the WHOLE value is not
|
||||||
|
lval_xcallable.
|
||||||
|
(value_of_xmethod, call_xmethod): New functions.
|
||||||
|
* value.h: Declare "struct xmethod_worker".
|
||||||
|
Declare new functions value_of_xmethod, call_xmethod.
|
||||||
|
|
||||||
2014-06-03 Joel Brobecker <brobecker@adacore.com>
|
2014-06-03 Joel Brobecker <brobecker@adacore.com>
|
||||||
Pedro Alves <palves@redhat.com>
|
Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
|
|
|
@ -388,6 +388,8 @@ enum lval_type
|
||||||
lval_register,
|
lval_register,
|
||||||
/* * In a gdb internal variable. */
|
/* * In a gdb internal variable. */
|
||||||
lval_internalvar,
|
lval_internalvar,
|
||||||
|
/* * Value encapsulates a callable defined in an extension language. */
|
||||||
|
lval_xcallable,
|
||||||
/* * Part of a gdb internal variable (structure field). */
|
/* * Part of a gdb internal variable (structure field). */
|
||||||
lval_internalvar_component,
|
lval_internalvar_component,
|
||||||
/* * Value's bits are fetched and stored using functions provided
|
/* * Value's bits are fetched and stored using functions provided
|
||||||
|
|
|
@ -256,6 +256,52 @@ struct extension_language_ops
|
||||||
changed or an error occurs no further languages are called. */
|
changed or an error occurs no further languages are called. */
|
||||||
enum ext_lang_rc (*before_prompt) (const struct extension_language_defn *,
|
enum ext_lang_rc (*before_prompt) (const struct extension_language_defn *,
|
||||||
const char *current_gdb_prompt);
|
const char *current_gdb_prompt);
|
||||||
|
|
||||||
|
/* xmethod support:
|
||||||
|
clone_xmethod_worker_data, free_xmethod_worker_data,
|
||||||
|
get_matching_xmethod_workers, get_xmethod_arg_types,
|
||||||
|
invoke_xmethod.
|
||||||
|
These methods are optional and may be NULL, but if one of them is
|
||||||
|
implemented then they all must be. */
|
||||||
|
|
||||||
|
/* Clone DATA and return a new but identical xmethod worker data
|
||||||
|
object for this extension language. */
|
||||||
|
void * (*clone_xmethod_worker_data)
|
||||||
|
(const struct extension_language_defn *extlang, void *data);
|
||||||
|
|
||||||
|
/* Free the DATA object of this extension language. */
|
||||||
|
void (*free_xmethod_worker_data)
|
||||||
|
(const struct extension_language_defn *extlang, void *data);
|
||||||
|
|
||||||
|
/* Return a vector of matching xmethod workers defined in this
|
||||||
|
extension language. The workers service methods with name
|
||||||
|
METHOD_NAME on objects of type OBJ_TYPE. The vector is returned
|
||||||
|
in DM_VEC. */
|
||||||
|
enum ext_lang_rc (*get_matching_xmethod_workers)
|
||||||
|
(const struct extension_language_defn *extlang,
|
||||||
|
struct type *obj_type,
|
||||||
|
const char *method_name,
|
||||||
|
xmethod_worker_vec **dm_vec);
|
||||||
|
|
||||||
|
/* Given a WORKER servicing a particular method, return the types
|
||||||
|
of the arguments the method takes. The number of arguments is
|
||||||
|
returned in NARGS, and their types are returned in the array
|
||||||
|
ARGTYPES. */
|
||||||
|
enum ext_lang_rc (*get_xmethod_arg_types)
|
||||||
|
(const struct extension_language_defn *extlang,
|
||||||
|
struct xmethod_worker *worker,
|
||||||
|
int *nargs,
|
||||||
|
struct type ***arg_types);
|
||||||
|
|
||||||
|
/* Invoke the xmethod serviced by WORKER. The xmethod is invoked
|
||||||
|
on OBJECT with arguments in the array ARGS. NARGS is the length of
|
||||||
|
this array. Returns the value returned by the xmethod. */
|
||||||
|
struct value * (*invoke_xmethod)
|
||||||
|
(const struct extension_language_defn *extlang,
|
||||||
|
struct xmethod_worker *worker,
|
||||||
|
struct value *object,
|
||||||
|
struct value **args,
|
||||||
|
int nargs);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* State necessary to restore a signal handler to its previous value. */
|
/* State necessary to restore a signal handler to its previous value. */
|
||||||
|
|
154
gdb/extension.c
154
gdb/extension.c
|
@ -834,6 +834,160 @@ check_quit_flag (void)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* xmethod support. */
|
||||||
|
|
||||||
|
/* The xmethod API routines do not have "ext_lang" in the name because
|
||||||
|
the name "xmethod" implies that this routine deals with extension
|
||||||
|
languages. Plus some of the methods take a xmethod_foo * "self/this"
|
||||||
|
arg, not an extension_language_defn * arg. */
|
||||||
|
|
||||||
|
/* Returns a new xmethod_worker with EXTLANG and DATA. Space for the
|
||||||
|
result must be freed with free_xmethod_worker. */
|
||||||
|
|
||||||
|
struct xmethod_worker *
|
||||||
|
new_xmethod_worker (const struct extension_language_defn *extlang, void *data)
|
||||||
|
{
|
||||||
|
struct xmethod_worker *worker = XCNEW (struct xmethod_worker);
|
||||||
|
|
||||||
|
worker->extlang = extlang;
|
||||||
|
worker->data = data;
|
||||||
|
worker->value = NULL;
|
||||||
|
|
||||||
|
return worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clones WORKER and returns a new but identical worker.
|
||||||
|
The function get_matching_xmethod_workers (see below), returns a
|
||||||
|
vector of matching workers. If a particular worker is selected by GDB
|
||||||
|
to invoke a method, then this function can help in cloning the
|
||||||
|
selected worker and freeing up the vector via a cleanup.
|
||||||
|
|
||||||
|
Space for the result must be freed with free_xmethod_worker. */
|
||||||
|
|
||||||
|
struct xmethod_worker *
|
||||||
|
clone_xmethod_worker (struct xmethod_worker *worker)
|
||||||
|
{
|
||||||
|
struct xmethod_worker *new_worker;
|
||||||
|
const struct extension_language_defn *extlang = worker->extlang;
|
||||||
|
|
||||||
|
gdb_assert (extlang->ops->clone_xmethod_worker_data != NULL);
|
||||||
|
|
||||||
|
new_worker = new_xmethod_worker
|
||||||
|
(extlang,
|
||||||
|
extlang->ops->clone_xmethod_worker_data (extlang, worker->data));
|
||||||
|
|
||||||
|
return new_worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If a method with name METHOD_NAME is to be invoked on an object of type
|
||||||
|
TYPE, then all entension languages are searched for implementations of
|
||||||
|
methods with name METHOD. All matches found are returned as a vector
|
||||||
|
of 'xmethod_worker_ptr' objects. If no matching methods are
|
||||||
|
found, NULL is returned. */
|
||||||
|
|
||||||
|
VEC (xmethod_worker_ptr) *
|
||||||
|
get_matching_xmethod_workers (struct type *type, const char *method_name)
|
||||||
|
{
|
||||||
|
VEC (xmethod_worker_ptr) *workers = NULL;
|
||||||
|
int i;
|
||||||
|
const struct extension_language_defn *extlang;
|
||||||
|
|
||||||
|
ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
|
||||||
|
{
|
||||||
|
VEC (xmethod_worker_ptr) *lang_workers, *new_vec;
|
||||||
|
enum ext_lang_rc rc;
|
||||||
|
|
||||||
|
/* If an extension language does not support xmethods, ignore
|
||||||
|
it. */
|
||||||
|
if (extlang->ops->get_matching_xmethod_workers == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rc = extlang->ops->get_matching_xmethod_workers (extlang,
|
||||||
|
type, method_name,
|
||||||
|
&lang_workers);
|
||||||
|
if (rc == EXT_LANG_RC_ERROR)
|
||||||
|
{
|
||||||
|
free_xmethod_worker_vec (workers);
|
||||||
|
error (_("Error while looking for matching xmethod workers "
|
||||||
|
"defined in %s."), extlang->capitalized_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_vec = VEC_merge (xmethod_worker_ptr, workers, lang_workers);
|
||||||
|
/* Free only the vectors and not the elements as NEW_VEC still
|
||||||
|
contains them. */
|
||||||
|
VEC_free (xmethod_worker_ptr, workers);
|
||||||
|
VEC_free (xmethod_worker_ptr, lang_workers);
|
||||||
|
workers = new_vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
return workers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the arg types of the xmethod encapsulated in WORKER.
|
||||||
|
An array of arg types is returned. The length of the array is returned in
|
||||||
|
NARGS. The type of the 'this' object is returned as the first element of
|
||||||
|
array. */
|
||||||
|
|
||||||
|
struct type **
|
||||||
|
get_xmethod_arg_types (struct xmethod_worker *worker, int *nargs)
|
||||||
|
{
|
||||||
|
enum ext_lang_rc rc;
|
||||||
|
struct type **type_array = NULL;
|
||||||
|
const struct extension_language_defn *extlang = worker->extlang;
|
||||||
|
|
||||||
|
gdb_assert (extlang->ops->get_xmethod_arg_types != NULL);
|
||||||
|
|
||||||
|
rc = extlang->ops->get_xmethod_arg_types (extlang, worker, nargs,
|
||||||
|
&type_array);
|
||||||
|
if (rc == EXT_LANG_RC_ERROR)
|
||||||
|
{
|
||||||
|
error (_("Error while looking for arg types of a xmethod worker "
|
||||||
|
"defined in %s."), extlang->capitalized_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return type_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invokes the xmethod encapsulated in WORKER and returns the result.
|
||||||
|
The method is invoked on OBJ with arguments in the ARGS array. NARGS is
|
||||||
|
the length of the this array. */
|
||||||
|
|
||||||
|
struct value *
|
||||||
|
invoke_xmethod (struct xmethod_worker *worker, struct value *obj,
|
||||||
|
struct value **args, int nargs)
|
||||||
|
{
|
||||||
|
gdb_assert (worker->extlang->ops->invoke_xmethod != NULL);
|
||||||
|
|
||||||
|
return worker->extlang->ops->invoke_xmethod (worker->extlang, worker,
|
||||||
|
obj, args, nargs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Frees the xmethod worker WORKER. */
|
||||||
|
|
||||||
|
void
|
||||||
|
free_xmethod_worker (struct xmethod_worker *worker)
|
||||||
|
{
|
||||||
|
gdb_assert (worker->extlang->ops->free_xmethod_worker_data != NULL);
|
||||||
|
worker->extlang->ops->free_xmethod_worker_data (worker->extlang,
|
||||||
|
worker->data);
|
||||||
|
xfree (worker);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Frees a vector of xmethod_workers VEC. */
|
||||||
|
|
||||||
|
void
|
||||||
|
free_xmethod_worker_vec (void *vec)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct xmethod_worker *worker;
|
||||||
|
VEC (xmethod_worker_ptr) *v = (VEC (xmethod_worker_ptr) *) vec;
|
||||||
|
|
||||||
|
for (i = 0; VEC_iterate (xmethod_worker_ptr, v, i, worker); i++)
|
||||||
|
free_xmethod_worker (worker);
|
||||||
|
|
||||||
|
VEC_free (xmethod_worker_ptr, v);
|
||||||
|
}
|
||||||
|
|
||||||
/* Called via an observer before gdb prints its prompt.
|
/* Called via an observer before gdb prints its prompt.
|
||||||
Iterate over the extension languages giving them a chance to
|
Iterate over the extension languages giving them a chance to
|
||||||
change the prompt. The first one to change the prompt wins,
|
change the prompt. The first one to change the prompt wins,
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define EXTENSION_H
|
#define EXTENSION_H
|
||||||
|
|
||||||
#include "mi/mi-cmds.h" /* For PRINT_NO_VALUES, etc. */
|
#include "mi/mi-cmds.h" /* For PRINT_NO_VALUES, etc. */
|
||||||
|
#include "common/vec.h"
|
||||||
|
|
||||||
struct breakpoint;
|
struct breakpoint;
|
||||||
struct command_line;
|
struct command_line;
|
||||||
|
@ -138,6 +139,26 @@ struct ext_lang_type_printers
|
||||||
/* Type-printers from Python. */
|
/* Type-printers from Python. */
|
||||||
void *py_type_printers;
|
void *py_type_printers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* A type which holds its extension language specific xmethod worker data. */
|
||||||
|
|
||||||
|
struct xmethod_worker
|
||||||
|
{
|
||||||
|
/* The language the xmethod worker is implemented in. */
|
||||||
|
const struct extension_language_defn *extlang;
|
||||||
|
|
||||||
|
/* The extension language specific data for this xmethod worker. */
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
/* The TYPE_CODE_XMETHOD value corresponding to this worker.
|
||||||
|
Always use value_of_xmethod to access it. */
|
||||||
|
struct value *value;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct xmethod_worker *xmethod_worker_ptr;
|
||||||
|
DEF_VEC_P (xmethod_worker_ptr);
|
||||||
|
typedef VEC (xmethod_worker_ptr) xmethod_worker_vec;
|
||||||
|
|
||||||
|
|
||||||
/* The interface for gdb's own extension(/scripting) language. */
|
/* The interface for gdb's own extension(/scripting) language. */
|
||||||
extern const struct extension_language_defn extension_language_gdb;
|
extern const struct extension_language_defn extension_language_gdb;
|
||||||
|
@ -212,4 +233,22 @@ extern const struct extension_language_defn *get_breakpoint_cond_ext_lang
|
||||||
|
|
||||||
extern int breakpoint_ext_lang_cond_says_stop (struct breakpoint *);
|
extern int breakpoint_ext_lang_cond_says_stop (struct breakpoint *);
|
||||||
|
|
||||||
|
extern struct value *invoke_xmethod (struct xmethod_worker *,
|
||||||
|
struct value *,
|
||||||
|
struct value **, int nargs);
|
||||||
|
|
||||||
|
extern struct xmethod_worker *clone_xmethod_worker (struct xmethod_worker *);
|
||||||
|
|
||||||
|
extern struct xmethod_worker *new_xmethod_worker
|
||||||
|
(const struct extension_language_defn *extlang, void *data);
|
||||||
|
|
||||||
|
extern void free_xmethod_worker (struct xmethod_worker *);
|
||||||
|
|
||||||
|
extern void free_xmethod_worker_vec (void *vec);
|
||||||
|
|
||||||
|
extern xmethod_worker_vec *get_matching_xmethod_workers
|
||||||
|
(struct type *, const char *);
|
||||||
|
|
||||||
|
extern struct type **get_xmethod_arg_types (struct xmethod_worker *, int *);
|
||||||
|
|
||||||
#endif /* EXTENSION_H */
|
#endif /* EXTENSION_H */
|
||||||
|
|
|
@ -4387,6 +4387,10 @@ gdbtypes_post_init (struct gdbarch *gdbarch)
|
||||||
= arch_type (gdbarch, TYPE_CODE_INTERNAL_FUNCTION, 0,
|
= arch_type (gdbarch, TYPE_CODE_INTERNAL_FUNCTION, 0,
|
||||||
"<internal function>");
|
"<internal function>");
|
||||||
|
|
||||||
|
/* This type represents an xmethod. */
|
||||||
|
builtin_type->xmethod
|
||||||
|
= arch_type (gdbarch, TYPE_CODE_XMETHOD, 0, "<xmethod>");
|
||||||
|
|
||||||
return builtin_type;
|
return builtin_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,10 @@ enum type_code
|
||||||
TYPE_CODE_MODULE, /**< Fortran module. */
|
TYPE_CODE_MODULE, /**< Fortran module. */
|
||||||
|
|
||||||
/* * Internal function type. */
|
/* * Internal function type. */
|
||||||
TYPE_CODE_INTERNAL_FUNCTION
|
TYPE_CODE_INTERNAL_FUNCTION,
|
||||||
|
|
||||||
|
/* * Methods implemented in extension languages. */
|
||||||
|
TYPE_CODE_XMETHOD
|
||||||
};
|
};
|
||||||
|
|
||||||
/* * For now allow source to use TYPE_CODE_CLASS for C++ classes, as
|
/* * For now allow source to use TYPE_CODE_CLASS for C++ classes, as
|
||||||
|
@ -1468,6 +1471,9 @@ struct builtin_type
|
||||||
/* * This type is used to represent a GDB internal function. */
|
/* * This type is used to represent a GDB internal function. */
|
||||||
|
|
||||||
struct type *internal_fn;
|
struct type *internal_fn;
|
||||||
|
|
||||||
|
/* * This type is used to represent an xmethod. */
|
||||||
|
struct type *xmethod;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* * Return the type table for the specified architecture. */
|
/* * Return the type table for the specified architecture. */
|
||||||
|
|
|
@ -1372,7 +1372,8 @@ value_must_coerce_to_target (struct value *val)
|
||||||
|
|
||||||
/* The only lval kinds which do not live in target memory. */
|
/* The only lval kinds which do not live in target memory. */
|
||||||
if (VALUE_LVAL (val) != not_lval
|
if (VALUE_LVAL (val) != not_lval
|
||||||
&& VALUE_LVAL (val) != lval_internalvar)
|
&& VALUE_LVAL (val) != lval_internalvar
|
||||||
|
&& VALUE_LVAL (val) != lval_xcallable)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
valtype = check_typedef (value_type (val));
|
valtype = check_typedef (value_type (val));
|
||||||
|
|
47
gdb/value.c
47
gdb/value.c
|
@ -230,6 +230,9 @@ struct value
|
||||||
/* Pointer to internal variable. */
|
/* Pointer to internal variable. */
|
||||||
struct internalvar *internalvar;
|
struct internalvar *internalvar;
|
||||||
|
|
||||||
|
/* Pointer to xmethod worker. */
|
||||||
|
struct xmethod_worker *xm_worker;
|
||||||
|
|
||||||
/* If lval == lval_computed, this is a set of function pointers
|
/* If lval == lval_computed, this is a set of function pointers
|
||||||
to use to access and describe the value, and a closure pointer
|
to use to access and describe the value, and a closure pointer
|
||||||
for them to use. */
|
for them to use. */
|
||||||
|
@ -1340,7 +1343,8 @@ CORE_ADDR
|
||||||
value_address (const struct value *value)
|
value_address (const struct value *value)
|
||||||
{
|
{
|
||||||
if (value->lval == lval_internalvar
|
if (value->lval == lval_internalvar
|
||||||
|| value->lval == lval_internalvar_component)
|
|| value->lval == lval_internalvar_component
|
||||||
|
|| value->lval == lval_xcallable)
|
||||||
return 0;
|
return 0;
|
||||||
if (value->parent != NULL)
|
if (value->parent != NULL)
|
||||||
return value_address (value->parent) + value->offset;
|
return value_address (value->parent) + value->offset;
|
||||||
|
@ -1352,7 +1356,8 @@ CORE_ADDR
|
||||||
value_raw_address (struct value *value)
|
value_raw_address (struct value *value)
|
||||||
{
|
{
|
||||||
if (value->lval == lval_internalvar
|
if (value->lval == lval_internalvar
|
||||||
|| value->lval == lval_internalvar_component)
|
|| value->lval == lval_internalvar_component
|
||||||
|
|| value->lval == lval_xcallable)
|
||||||
return 0;
|
return 0;
|
||||||
return value->location.address;
|
return value->location.address;
|
||||||
}
|
}
|
||||||
|
@ -1361,7 +1366,8 @@ void
|
||||||
set_value_address (struct value *value, CORE_ADDR addr)
|
set_value_address (struct value *value, CORE_ADDR addr)
|
||||||
{
|
{
|
||||||
gdb_assert (value->lval != lval_internalvar
|
gdb_assert (value->lval != lval_internalvar
|
||||||
&& value->lval != lval_internalvar_component);
|
&& value->lval != lval_internalvar_component
|
||||||
|
&& value->lval != lval_xcallable);
|
||||||
value->location.address = addr;
|
value->location.address = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1433,6 +1439,8 @@ value_free (struct value *val)
|
||||||
if (funcs->free_closure)
|
if (funcs->free_closure)
|
||||||
funcs->free_closure (val);
|
funcs->free_closure (val);
|
||||||
}
|
}
|
||||||
|
else if (VALUE_LVAL (val) == lval_xcallable)
|
||||||
|
free_xmethod_worker (val->location.xm_worker);
|
||||||
|
|
||||||
xfree (val->contents);
|
xfree (val->contents);
|
||||||
VEC_free (range_s, val->unavailable);
|
VEC_free (range_s, val->unavailable);
|
||||||
|
@ -1623,6 +1631,8 @@ void
|
||||||
set_value_component_location (struct value *component,
|
set_value_component_location (struct value *component,
|
||||||
const struct value *whole)
|
const struct value *whole)
|
||||||
{
|
{
|
||||||
|
gdb_assert (whole->lval != lval_xcallable);
|
||||||
|
|
||||||
if (whole->lval == lval_internalvar)
|
if (whole->lval == lval_internalvar)
|
||||||
VALUE_LVAL (component) = lval_internalvar_component;
|
VALUE_LVAL (component) = lval_internalvar_component;
|
||||||
else
|
else
|
||||||
|
@ -2456,6 +2466,37 @@ show_convenience (char *ignore, int from_tty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the TYPE_CODE_XMETHOD value corresponding to WORKER. */
|
||||||
|
|
||||||
|
struct value *
|
||||||
|
value_of_xmethod (struct xmethod_worker *worker)
|
||||||
|
{
|
||||||
|
if (worker->value == NULL)
|
||||||
|
{
|
||||||
|
struct value *v;
|
||||||
|
|
||||||
|
v = allocate_value (builtin_type (target_gdbarch ())->xmethod);
|
||||||
|
v->lval = lval_xcallable;
|
||||||
|
v->location.xm_worker = worker;
|
||||||
|
v->modifiable = 0;
|
||||||
|
worker->value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return worker->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call the xmethod corresponding to the TYPE_CODE_XMETHOD value METHOD. */
|
||||||
|
|
||||||
|
struct value *
|
||||||
|
call_xmethod (struct value *method, int argc, struct value **argv)
|
||||||
|
{
|
||||||
|
gdb_assert (TYPE_CODE (value_type (method)) == TYPE_CODE_XMETHOD
|
||||||
|
&& method->lval == lval_xcallable && argc > 0);
|
||||||
|
|
||||||
|
return invoke_xmethod (method->location.xm_worker,
|
||||||
|
argv[0], argv + 1, argc - 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Extract a value as a C number (either long or double).
|
/* Extract a value as a C number (either long or double).
|
||||||
Knows how to convert fixed values to double, or
|
Knows how to convert fixed values to double, or
|
||||||
floating values to long.
|
floating values to long.
|
||||||
|
|
|
@ -31,6 +31,7 @@ struct type;
|
||||||
struct ui_file;
|
struct ui_file;
|
||||||
struct language_defn;
|
struct language_defn;
|
||||||
struct value_print_options;
|
struct value_print_options;
|
||||||
|
struct xmethod_worker;
|
||||||
|
|
||||||
/* The structure which defines the type of a value. It should never
|
/* The structure which defines the type of a value. It should never
|
||||||
be possible for a program lval value to survive over a call to the
|
be possible for a program lval value to survive over a call to the
|
||||||
|
@ -1011,4 +1012,9 @@ struct value *call_internal_function (struct gdbarch *gdbarch,
|
||||||
|
|
||||||
char *value_internal_function_name (struct value *);
|
char *value_internal_function_name (struct value *);
|
||||||
|
|
||||||
|
extern struct value *value_of_xmethod (struct xmethod_worker *);
|
||||||
|
|
||||||
|
struct value *call_xmethod (struct value *function,
|
||||||
|
int argc, struct value **argv);
|
||||||
|
|
||||||
#endif /* !defined (VALUE_H) */
|
#endif /* !defined (VALUE_H) */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue