This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
How to implement '@' GDB-like operator for libcc1
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: gcc at gcc dot gnu dot org
- Cc: Phil Muldoon <pmuldoon at redhat dot com>
- Date: Sun, 15 Mar 2015 20:29:04 +0100
- Subject: How to implement '@' GDB-like operator for libcc1
- Authentication-results: sourceware.org; auth=none
Hi,
based on the GCC libcc1 plugin GDB will implement GDB command 'compile print'
equivalent to default 'print' but evaluating the expression by GCC:
https://github.com/tromey/gdb/tree/pmuldoon/compile/print
It is currently done by compiling a .c->.o file and checking its DWARF for the
type and size of the resulting object to print.
But GDB features a useful custom expression operator '@':
https://sourceware.org/gdb/onlinedocs/gdb/Arrays.html
I have problems implementing '@' into GCC, could you suggest at which place
should I call build_array_type_nelts()? Or is it the right way at all?
Testing it on a sample code - it should return 2:
int a[]={1,2,3};int main(void){ return (*a@3)[1]; }
Proper overloading of '@' to keep it working for ObjC and/or enabling '@' only
for libcc1 I find currently off-topic.
With both c_fully_fold_internal() and gimplify_modify_expr_rhs() hooks #if 0-ed
(as they are in the attached patch) GCC crashes on infinite loop:
<-gimplify_expr<-gimplify_modify_expr<-gimplify_expr<-gimplify_stmt<-
<-gimplify_and_add<-internal_get_tmp_var<-get_formal_tmp_var<-
Thanks,
Jan
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 8c23e09..69fa054 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -1289,6 +1289,25 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
ret = fold (ret);
goto out;
+#if 0 // it would crash at array_ref_low_bound()'s first line
+ case ATSIGN_EXPR:
+ orig_op0 = op0 = TREE_OPERAND (expr, 0);
+ orig_op1 = op1 = TREE_OPERAND (expr, 1);
+#if 0 // not needed
+ op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
+ maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
+ op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
+ maybe_const_itself);
+ STRIP_TYPE_NOPS (op1);
+#endif
+ ret = build_array_type_nelts (TREE_TYPE (op0), tree_to_uhwi (op1));
+#if 0 // not needed
+ ret = fold (ret);
+#endif
+ goto out;
+#endif
+
case COMPOUND_EXPR:
case MODIFY_EXPR:
case PREDECREMENT_EXPR:
@@ -4078,6 +4097,8 @@ binary_op_error (location_t location, enum tree_code code,
opname = "||"; break;
case BIT_XOR_EXPR:
opname = "^"; break;
+ case ATSIGN_EXPR:
+ opname = "@"; break;
default:
gcc_unreachable ();
}
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index bb55be8..ad8b82f 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -468,6 +468,8 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
break;
case CPP_ATSIGN:
+ *value = NULL_TREE;
+ break;
/* An @ may give the next token special significance in Objective-C. */
if (c_dialect_objc ())
{
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index ceb9e1a..5d5a0a8 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1173,6 +1173,7 @@ enum c_parser_prec {
PREC_EQ,
PREC_REL,
PREC_SHIFT,
+ PREC_ATSIGN,
PREC_ADD,
PREC_MULT,
NUM_PRECS
@@ -6283,6 +6284,10 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
oprec = PREC_ADD;
ocode = MINUS_EXPR;
break;
+ case CPP_ATSIGN:
+ oprec = PREC_ATSIGN;
+ ocode = ATSIGN_EXPR;
+ break;
case CPP_LSHIFT:
oprec = PREC_SHIFT;
ocode = LSHIFT_EXPR;
@@ -7082,6 +7087,10 @@ c_parser_postfix_expression (c_parser *parser)
expr.original_type = NULL;
switch (c_parser_peek_token (parser)->type)
{
+ case CPP_ATSIGN:
+ error_at (loc, "gdbjit hit");
+ expr.value = error_mark_node;
+ break;
case CPP_NUMBER:
expr.value = c_parser_peek_token (parser)->value;
loc = c_parser_peek_token (parser)->location;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index a3a9c77..0c2f1f9 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -10949,6 +10949,14 @@ build_binary_op (location_t location, enum tree_code code,
maybe_warn_bool_compare (location, code, orig_op0, orig_op1);
break;
+ case ATSIGN_EXPR:
+ if (TREE_CODE (orig_op1) == INTEGER_CST)
+ {
+ result_type = build_array_type_nelts (type0, tree_to_uhwi (orig_op1));
+ converted = 1;
+ }
+ break;
+
default:
gcc_unreachable ();
}
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index d822913..b4027dc 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4418,6 +4418,12 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
return GS_OK;
}
}
+ break;
+
+#if 0 // it would get hit
+ case ATSIGN_EXPR:
+ gcc_unreachable ();
+#endif
default:
break;
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index d7c049f..cf00457 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -2037,6 +2037,7 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, int flags,
case LTGT_EXPR:
case ORDERED_EXPR:
case UNORDERED_EXPR:
+ case ATSIGN_EXPR:
{
const char *op = op_symbol (node);
op0 = TREE_OPERAND (node, 0);
@@ -3432,6 +3433,9 @@ op_symbol_code (enum tree_code code)
case MIN_EXPR:
return "min";
+ case ATSIGN_EXPR:
+ return "@";
+
default:
return "<<< ??? >>>";
}
diff --git a/gcc/tree.def b/gcc/tree.def
index b4b4164..a2d28ce 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -669,6 +669,9 @@ DEFTREECODE (PLUS_EXPR, "plus_expr", tcc_binary, 2)
DEFTREECODE (MINUS_EXPR, "minus_expr", tcc_binary, 2)
DEFTREECODE (MULT_EXPR, "mult_expr", tcc_binary, 2)
+/* GDB '@' operator. */
+DEFTREECODE (ATSIGN_EXPR, "atsign_expr", tcc_binary, 2)
+
/* Pointer addition. The first operand is always a pointer and the
second operand is an integer of type sizetype. */
DEFTREECODE (POINTER_PLUS_EXPR, "pointer_plus_expr", tcc_binary, 2)