aboutsummaryrefslogtreecommitdiff
path: root/gdb/ax-gdb.c
diff options
context:
space:
mode:
authorStan Shebs <shebs@codesourcery.com>2009-12-28 23:39:10 +0000
committerStan Shebs <shebs@codesourcery.com>2009-12-28 23:39:10 +0000
commitf61e138d9a5c10da22c01ef377034e66e6978fe6 (patch)
tree399c49505e3d1aa2e3f71937bd6f1034cf5c6acc /gdb/ax-gdb.c
parentae77ee9a7fe8e4b4e05bd65b4f9f2b8ca63a129d (diff)
downloadfsf-binutils-gdb-f61e138d9a5c10da22c01ef377034e66e6978fe6.zip
fsf-binutils-gdb-f61e138d9a5c10da22c01ef377034e66e6978fe6.tar.gz
fsf-binutils-gdb-f61e138d9a5c10da22c01ef377034e66e6978fe6.tar.bz2
2009-12-28 Stan Shebs <stan@codesourcery.com>
Add trace state variables. * ax.h (enum agent_op): Add getv, setv, and tracev. (ax_tsv): Declare. * ax-gdb.c: Include tracepoint.h. (gen_expr): Handle BINOP_ASSIGN, BINOP_ASSIGN_MODIFY, and OP_INTERNALVAR. (gen_expr_binop_rest): New function, split from gen_expr. * ax-general.c (ax_tsv): New function. (aop_map): Add new bytecodes. * tracepoint.h (struct trace_state_variable): New struct. (tsv_s): New typedef. (find_trace_state_variable): Declare. * tracepoint.c (tvariables): New global. (next_tsv_number): New global. (create_trace_state_variable): New function. (find_trace_state_variable): New function. (delete_trace_state_variable): New function. (trace_variable_command): New function. (delete_trace_variable_command): New function. (tvariables_info): New function. (trace_start_command): Download tsvs with initial values. (_initialize_tracepoint): Add new commands. * NEWS: Mention the addition of trace state variables. ==> doc/ChangeLog <== 2009-12-28 Stan Shebs <stan@codesourcery.com> * gdb.texinfo (Trace State Variables): New section. (Tracepoint Packets): Describe trace state variable packets. * agentexpr.texi (Bytecode Descriptions): Describe trace state variable bytecodes. ==> testsuite/ChangeLog <== 2009-12-28 Stan Shebs <stan@codesourcery.com> * gdb.trace/tsv.exp: New file. * gdb.base/completion.exp: Update ambiguous info output.
Diffstat (limited to 'gdb/ax-gdb.c')
-rw-r--r--gdb/ax-gdb.c311
1 files changed, 202 insertions, 109 deletions
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index a64658d..ee1f515 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -36,6 +36,7 @@
#include "user-regs.h"
#include "language.h"
#include "dictionary.h"
+#include "tracepoint.h"
/* To make sense of this file, you should read doc/agentexpr.texi.
Then look at the types and enums in ax-gdb.h. For the code itself,
@@ -139,6 +140,12 @@ static void gen_sizeof (struct expression *exp, union exp_element **pc,
struct type *size_type);
static void gen_expr (struct expression *exp, union exp_element **pc,
struct agent_expr *ax, struct axs_value *value);
+static void gen_expr_binop_rest (struct expression *exp,
+ enum exp_opcode op, union exp_element **pc,
+ struct agent_expr *ax,
+ struct axs_value *value,
+ struct axs_value *value1,
+ struct axs_value *value2);
static void agent_command (char *exp, int from_tty);
@@ -1441,7 +1448,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
{
/* Used to hold the descriptions of operand expressions. */
struct axs_value value1, value2;
- enum exp_opcode op = (*pc)[0].opcode;
+ enum exp_opcode op = (*pc)[0].opcode, op2;
/* If we're looking at a constant expression, just push its value. */
{
@@ -1478,119 +1485,63 @@ gen_expr (struct expression *exp, union exp_element **pc,
(*pc)++;
gen_expr (exp, pc, ax, &value1);
gen_usual_unary (exp, ax, &value1);
- gen_expr (exp, pc, ax, &value2);
- gen_usual_unary (exp, ax, &value2);
- gen_usual_arithmetic (exp, ax, &value1, &value2);
- switch (op)
+ gen_expr_binop_rest (exp, op, pc, ax, value, &value1, &value2);
+ break;
+
+ case BINOP_ASSIGN:
+ (*pc)++;
+ if ((*pc)[0].opcode == OP_INTERNALVAR)
{
- case BINOP_ADD:
- if (TYPE_CODE (value1.type) == TYPE_CODE_INT
- && TYPE_CODE (value2.type) == TYPE_CODE_PTR)
+ char *name = internalvar_name ((*pc)[1].internalvar);
+ struct trace_state_variable *tsv;
+ (*pc) += 3;
+ gen_expr (exp, pc, ax, value);
+ tsv = find_trace_state_variable (name);
+ if (tsv)
{
- /* Swap the values and proceed normally. */
- ax_simple (ax, aop_swap);
- gen_ptradd (ax, value, &value2, &value1);
+ ax_tsv (ax, aop_setv, tsv->number);
+ if (trace_kludge)
+ ax_tsv (ax, aop_tracev, tsv->number);
}
- else if (TYPE_CODE (value1.type) == TYPE_CODE_PTR
- && TYPE_CODE (value2.type) == TYPE_CODE_INT)
- gen_ptradd (ax, value, &value1, &value2);
- else
- gen_binop (ax, value, &value1, &value2,
- aop_add, aop_add, 1, "addition");
- break;
- case BINOP_SUB:
- if (TYPE_CODE (value1.type) == TYPE_CODE_PTR
- && TYPE_CODE (value2.type) == TYPE_CODE_INT)
- gen_ptrsub (ax,value, &value1, &value2);
- else if (TYPE_CODE (value1.type) == TYPE_CODE_PTR
- && TYPE_CODE (value2.type) == TYPE_CODE_PTR)
- /* FIXME --- result type should be ptrdiff_t */
- gen_ptrdiff (ax, value, &value1, &value2,
- builtin_type (exp->gdbarch)->builtin_long);
else
- gen_binop (ax, value, &value1, &value2,
- aop_sub, aop_sub, 1, "subtraction");
- break;
- case BINOP_MUL:
- gen_binop (ax, value, &value1, &value2,
- aop_mul, aop_mul, 1, "multiplication");
- break;
- case BINOP_DIV:
- gen_binop (ax, value, &value1, &value2,
- aop_div_signed, aop_div_unsigned, 1, "division");
- break;
- case BINOP_REM:
- gen_binop (ax, value, &value1, &value2,
- aop_rem_signed, aop_rem_unsigned, 1, "remainder");
- break;
- case BINOP_SUBSCRIPT:
- gen_ptradd (ax, value, &value1, &value2);
- if (TYPE_CODE (value->type) != TYPE_CODE_PTR)
- error (_("Invalid combination of types in array subscripting."));
- gen_deref (ax, value);
- break;
- case BINOP_BITWISE_AND:
- gen_binop (ax, value, &value1, &value2,
- aop_bit_and, aop_bit_and, 0, "bitwise and");
- break;
-
- case BINOP_BITWISE_IOR:
- gen_binop (ax, value, &value1, &value2,
- aop_bit_or, aop_bit_or, 0, "bitwise or");
- break;
-
- case BINOP_BITWISE_XOR:
- gen_binop (ax, value, &value1, &value2,
- aop_bit_xor, aop_bit_xor, 0, "bitwise exclusive-or");
- break;
-
- case BINOP_EQUAL:
- gen_binop (ax, value, &value1, &value2,
- aop_equal, aop_equal, 0, "equal");
- break;
-
- case BINOP_NOTEQUAL:
- gen_binop (ax, value, &value1, &value2,
- aop_equal, aop_equal, 0, "equal");
- gen_logical_not (ax, value,
- language_bool_type (exp->language_defn,
- exp->gdbarch));
- break;
-
- case BINOP_LESS:
- gen_binop (ax, value, &value1, &value2,
- aop_less_signed, aop_less_unsigned, 0, "less than");
- break;
-
- case BINOP_GTR:
- ax_simple (ax, aop_swap);
- gen_binop (ax, value, &value1, &value2,
- aop_less_signed, aop_less_unsigned, 0, "less than");
- break;
-
- case BINOP_LEQ:
- ax_simple (ax, aop_swap);
- gen_binop (ax, value, &value1, &value2,
- aop_less_signed, aop_less_unsigned, 0, "less than");
- gen_logical_not (ax, value,
- language_bool_type (exp->language_defn,
- exp->gdbarch));
- break;
-
- case BINOP_GEQ:
- gen_binop (ax, value, &value1, &value2,
- aop_less_signed, aop_less_unsigned, 0, "less than");
- gen_logical_not (ax, value,
- language_bool_type (exp->language_defn,
- exp->gdbarch));
- break;
+ error (_("$%s is not a trace state variable, may not assign to it"), name);
+ }
+ else
+ error (_("May only assign to trace state variables"));
+ break;
- default:
- /* We should only list operators in the outer case statement
- that we actually handle in the inner case statement. */
- internal_error (__FILE__, __LINE__,
- _("gen_expr: op case sets don't match"));
+ case BINOP_ASSIGN_MODIFY:
+ (*pc)++;
+ op2 = (*pc)[0].opcode;
+ (*pc)++;
+ (*pc)++;
+ if ((*pc)[0].opcode == OP_INTERNALVAR)
+ {
+ char *name = internalvar_name ((*pc)[1].internalvar);
+ struct trace_state_variable *tsv;
+ (*pc) += 3;
+ tsv = find_trace_state_variable (name);
+ if (tsv)
+ {
+ /* The tsv will be the left half of the binary operation. */
+ ax_tsv (ax, aop_getv, tsv->number);
+ if (trace_kludge)
+ ax_tsv (ax, aop_tracev, tsv->number);
+ /* Trace state variables are always 64-bit integers. */
+ value1.kind = axs_rvalue;
+ value1.type = builtin_type (exp->gdbarch)->builtin_long_long;
+ /* Now do right half of expression. */
+ gen_expr_binop_rest (exp, op2, pc, ax, value, &value1, &value2);
+ /* We have a result of the binary op, set the tsv. */
+ ax_tsv (ax, aop_setv, tsv->number);
+ if (trace_kludge)
+ ax_tsv (ax, aop_tracev, tsv->number);
+ }
+ else
+ error (_("$%s is not a trace state variable, may not assign to it"), name);
}
+ else
+ error (_("May only assign to trace state variables"));
break;
/* Note that we need to be a little subtle about generating code
@@ -1644,7 +1595,24 @@ gen_expr (struct expression *exp, union exp_element **pc,
break;
case OP_INTERNALVAR:
- error (_("GDB agent expressions cannot use convenience variables."));
+ {
+ const char *name = internalvar_name ((*pc)[1].internalvar);
+ struct trace_state_variable *tsv;
+ (*pc) += 3;
+ tsv = find_trace_state_variable (name);
+ if (tsv)
+ {
+ ax_tsv (ax, aop_getv, tsv->number);
+ if (trace_kludge)
+ ax_tsv (ax, aop_tracev, tsv->number);
+ /* Trace state variables are always 64-bit integers. */
+ value->kind = axs_rvalue;
+ value->type = builtin_type (exp->gdbarch)->builtin_long_long;
+ }
+ else
+ error (_("$%s is not a trace state variable; GDB agent expressions cannot use convenience variables."), name);
+ }
+ break;
/* Weirdo operator: see comments for gen_repeat for details. */
case BINOP_REPEAT:
@@ -1788,6 +1756,131 @@ gen_expr (struct expression *exp, union exp_element **pc,
error (_("Unsupported operator in expression."));
}
}
+
+/* This handles the middle-to-right-side of code generation for binary
+ expressions, which is shared between regular binary operations and
+ assign-modify (+= and friends) expressions. */
+
+static void
+gen_expr_binop_rest (struct expression *exp,
+ enum exp_opcode op, union exp_element **pc,
+ struct agent_expr *ax, struct axs_value *value,
+ struct axs_value *value1, struct axs_value *value2)
+{
+ gen_expr (exp, pc, ax, value2);
+ gen_usual_unary (exp, ax, value2);
+ gen_usual_arithmetic (exp, ax, value1, value2);
+ switch (op)
+ {
+ case BINOP_ADD:
+ if (TYPE_CODE (value1->type) == TYPE_CODE_INT
+ && TYPE_CODE (value2->type) == TYPE_CODE_PTR)
+ {
+ /* Swap the values and proceed normally. */
+ ax_simple (ax, aop_swap);
+ gen_ptradd (ax, value, value2, value1);
+ }
+ else if (TYPE_CODE (value1->type) == TYPE_CODE_PTR
+ && TYPE_CODE (value2->type) == TYPE_CODE_INT)
+ gen_ptradd (ax, value, value1, value2);
+ else
+ gen_binop (ax, value, value1, value2,
+ aop_add, aop_add, 1, "addition");
+ break;
+ case BINOP_SUB:
+ if (TYPE_CODE (value1->type) == TYPE_CODE_PTR
+ && TYPE_CODE (value2->type) == TYPE_CODE_INT)
+ gen_ptrsub (ax,value, value1, value2);
+ else if (TYPE_CODE (value1->type) == TYPE_CODE_PTR
+ && TYPE_CODE (value2->type) == TYPE_CODE_PTR)
+ /* FIXME --- result type should be ptrdiff_t */
+ gen_ptrdiff (ax, value, value1, value2,
+ builtin_type (exp->gdbarch)->builtin_long);
+ else
+ gen_binop (ax, value, value1, value2,
+ aop_sub, aop_sub, 1, "subtraction");
+ break;
+ case BINOP_MUL:
+ gen_binop (ax, value, value1, value2,
+ aop_mul, aop_mul, 1, "multiplication");
+ break;
+ case BINOP_DIV:
+ gen_binop (ax, value, value1, value2,
+ aop_div_signed, aop_div_unsigned, 1, "division");
+ break;
+ case BINOP_REM:
+ gen_binop (ax, value, value1, value2,
+ aop_rem_signed, aop_rem_unsigned, 1, "remainder");
+ break;
+ case BINOP_SUBSCRIPT:
+ gen_ptradd (ax, value, value1, value2);
+ if (TYPE_CODE (value->type) != TYPE_CODE_PTR)
+ error (_("Invalid combination of types in array subscripting."));
+ gen_deref (ax, value);
+ break;
+ case BINOP_BITWISE_AND:
+ gen_binop (ax, value, value1, value2,
+ aop_bit_and, aop_bit_and, 0, "bitwise and");
+ break;
+
+ case BINOP_BITWISE_IOR:
+ gen_binop (ax, value, value1, value2,
+ aop_bit_or, aop_bit_or, 0, "bitwise or");
+ break;
+
+ case BINOP_BITWISE_XOR:
+ gen_binop (ax, value, value1, value2,
+ aop_bit_xor, aop_bit_xor, 0, "bitwise exclusive-or");
+ break;
+
+ case BINOP_EQUAL:
+ gen_binop (ax, value, value1, value2,
+ aop_equal, aop_equal, 0, "equal");
+ break;
+
+ case BINOP_NOTEQUAL:
+ gen_binop (ax, value, value1, value2,
+ aop_equal, aop_equal, 0, "equal");
+ gen_logical_not (ax, value,
+ language_bool_type (exp->language_defn,
+ exp->gdbarch));
+ break;
+
+ case BINOP_LESS:
+ gen_binop (ax, value, value1, value2,
+ aop_less_signed, aop_less_unsigned, 0, "less than");
+ break;
+
+ case BINOP_GTR:
+ ax_simple (ax, aop_swap);
+ gen_binop (ax, value, value1, value2,
+ aop_less_signed, aop_less_unsigned, 0, "less than");
+ break;
+
+ case BINOP_LEQ:
+ ax_simple (ax, aop_swap);
+ gen_binop (ax, value, value1, value2,
+ aop_less_signed, aop_less_unsigned, 0, "less than");
+ gen_logical_not (ax, value,
+ language_bool_type (exp->language_defn,
+ exp->gdbarch));
+ break;
+
+ case BINOP_GEQ:
+ gen_binop (ax, value, value1, value2,
+ aop_less_signed, aop_less_unsigned, 0, "less than");
+ gen_logical_not (ax, value,
+ language_bool_type (exp->language_defn,
+ exp->gdbarch));
+ break;
+
+ default:
+ /* We should only list operators in the outer case statement
+ that we actually handle in the inner case statement. */
+ internal_error (__FILE__, __LINE__,
+ _("gen_expr: op case sets don't match"));
+ }
+}
/* Given a single variable and a scope, generate bytecodes to trace