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)