diff options
author | Tom Tromey <tom@tromey.com> | 2021-03-08 07:27:57 -0700 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2021-03-08 07:28:13 -0700 |
commit | e2803273a078950d0895de245cdc5375f362a8c5 (patch) | |
tree | 5831732b28dc39d8afa6d009089f501fe6b0c57c /gdb/expression.h | |
parent | e18c58f290609dcfe8d7df450bb88b1adf44337a (diff) | |
download | binutils-e2803273a078950d0895de245cdc5375f362a8c5.zip binutils-e2803273a078950d0895de245cdc5375f362a8c5.tar.gz binutils-e2803273a078950d0895de245cdc5375f362a8c5.tar.bz2 |
Introduce class operation
This patch introduces class operation, the new base class for all
expression operations.
In the new approach, an operation is simply a class that presents a
certain interface. Operations own their operands, and management is
done via unique_ptr.
The operation interface is largely ad hoc, based on the evolution of
expression handling in GDB. Parts (for example,
evaluate_with_coercion) are probably redundant; however I took this
approach to try to avoid mixing different kinds of refactorings.
In some specific situations, rather than add a generic method across
the entire operation class hierarchy, I chose instead to use
dynamic_cast and specialized methods on certain concrete subclasses.
This will appear in some subsequent patches.
One goal of this work is to avoid the kinds of easy-to-make errors
that affected the old implementation. To this end, some helper
subclasses are also added here. These helpers automate the
implementation of the 'dump', 'uses_objfile', and 'constant_p'
methods. Nearly every concrete operation that is subsequently added
will use these facilities. (Note that the 'dump' implementation is
only outlined here, the body appears in the next patch.)
gdb/ChangeLog
2021-03-08 Tom Tromey <tom@tromey.com>
* expression.h (expr::operation): New class.
(expr::make_operation): New function.
(expr::operation_up): New typedef.
* expop.h: New file.
* eval.c (operation::evaluate_for_cast)
(operation::evaluate_for_address, operation::evaluate_for_sizeof):
New methods.
* ax-gdb.c (operation::generate_ax): New method.
Diffstat (limited to 'gdb/expression.h')
-rw-r--r-- | gdb/expression.h | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/gdb/expression.h b/gdb/expression.h index 397a0af..24a0eb3 100644 --- a/gdb/expression.h +++ b/gdb/expression.h @@ -89,6 +89,105 @@ enum noside does in many situations. */ }; +struct expression; +struct agent_expr; +struct axs_value; +struct type; +struct ui_file; + +namespace expr +{ + +class operation; +typedef std::unique_ptr<operation> operation_up; + +/* Base class for an operation. An operation is a single component of + an expression. */ + +class operation +{ +protected: + + operation () = default; + DISABLE_COPY_AND_ASSIGN (operation); + +public: + + virtual ~operation () = default; + + /* Evaluate this operation. */ + virtual value *evaluate (struct type *expect_type, + struct expression *exp, + enum noside noside) = 0; + + /* Evaluate this operation in a context where C-like coercion is + needed. */ + virtual value *evaluate_with_coercion (struct expression *exp, + enum noside noside) + { + return evaluate (nullptr, exp, noside); + } + + /* Evaluate this expression in the context of a cast to + EXPECT_TYPE. */ + virtual value *evaluate_for_cast (struct type *expect_type, + struct expression *exp, + enum noside noside); + + /* Evaluate this expression in the context of a sizeof + operation. */ + virtual value *evaluate_for_sizeof (struct expression *exp, + enum noside noside); + + /* Evaluate this expression in the context of an address-of + operation. Must return the address. */ + virtual value *evaluate_for_address (struct expression *exp, + enum noside noside); + + /* True if this is a constant expression. */ + virtual bool constant_p () const + { return false; } + + /* Return true if this operation uses OBJFILE (and will become + dangling when OBJFILE is unloaded), otherwise return false. + OBJFILE must not be a separate debug info file. */ + virtual bool uses_objfile (struct objfile *objfile) const + { return false; } + + /* Generate agent expression bytecodes for this operation. */ + void generate_ax (struct expression *exp, struct agent_expr *ax, + struct axs_value *value, + struct type *cast_type = nullptr); + + /* Return the opcode that is implemented by this operation. */ + virtual enum exp_opcode opcode () const = 0; + + /* Print this operation to STREAM. */ + virtual void dump (struct ui_file *stream, int depth) const = 0; + +protected: + + /* Called by generate_ax to do the work for this particular + operation. */ + virtual void do_generate_ax (struct expression *exp, + struct agent_expr *ax, + struct axs_value *value, + struct type *cast_type) + { + error (_("Cannot translate to agent expression")); + } +}; + +/* A helper function for creating an operation_up, given a type. */ +template<typename T, typename... Arg> +operation_up +make_operation (Arg... args) +{ + return operation_up (new T (std::forward<Arg> (args)...)); +} + +} + union exp_element { enum exp_opcode opcode; |