|
|
Created:
13 years, 7 months ago by Lawrence Crowl Modified:
12 years, 10 months ago CC:
gcc-patches_gcc.gnu.org Base URL:
svn+ssh://gcc.gnu.org/svn/gcc/trunk/ Visibility:
Public. |
Patch Set 1 #
MessagesTotal messages: 29
The gcc source uses several constructs that GDB does not understand. This patch corrects some of them. It affects only compilers built with ENABLE_TREE_CHECKING, and hence release compilers are unaffected. In particular, I change the implementation of CHECK macros using __extension__ into macros calling inline functions. I do not change the accessor macros themselves. The effect is that it now possible to get useful responses to gdb command like (gdb) print DECL_FUNCTION_CODE (decl) To make the feature work, you must define two macros within gdb. (gdb) macro define __FILE__ "gdb" (gdb) macro define __LINE__ 1 The reason for these definitions is that gdb does not expand the magic preprocessor macros, and then cannot find what it thinks is a regular symbol. (There is now a gdb issue for this problem.) I added these definitions to gdbinit.in. There a non-transparent change in behavior that may affect some users. The inline functions will introduce additional lines in a sequence of gdb 'step' commands. Use 'next' instead. There is one change that appears to be completely transparent, but I mention it here for completeness. The static type of the result of the macros is 'tree' rather than a more specific sub-type of tree. The reason for this change is that gdb does not parse typeof expressions. (There is now a gdb issue for this problem.) Three run average bootstrap times with all default languages enabled are 10234.1 second base and 10272.7 seconds with patch for a 0.377% slow down. Tested on x86-64. Index: gcc/ChangeLog 2011-09-22 Lawrence Crowl <crowl@google.com> * tree.h (tree_check): New. (TREE_CHECK): Use inline function above instead of __extension__. (tree_not_check): New. (TREE_NOT_CHECK): Use inline function above instead of __extension__. (tree_check2): New. (TREE_CHECK2): Use inline function above instead of __extension__. (tree_not_check2): New. (TREE_NOT_CHECK2): Use inline function above instead of __extension__. (tree_check3): New. (TREE_CHECK3): Use inline function above instead of __extension__. (tree_not_check3): New. (TREE_NOT_CHECK3): Use inline function above instead of __extension__. (tree_check4): New. (TREE_CHECK4): Use inline function above instead of __extension__. (tree_not_check4): New. (TREE_NOT_CHECK4): Use inline function above instead of __extension__. (tree_check5): New. (TREE_CHECK5): Use inline function above instead of __extension__. (tree_not_check5): New. (TREE_NOT_CHECK5): Use inline function above instead of __extension__. (contains_struct_check): New. (CONTAINS_STRUCT_CHECK): Use inline function above instead of __extension__. (tree_class_check): New. (TREE_CLASS_CHECK): Use inline function above instead of __extension__. (tree_range_check): New. (TREE_RANGE_CHECK): Use inline function above instead of __extension__. (omp_clause_subcode_check): New. (OMP_CLAUSE_SUBCODE_CHECK): Use inline function above instead of __extension__. (omp_clause_range_check): New. (OMP_CLAUSE_RANGE_CHECK): Use inline function above instead of __extension__. (expr_check): New. (EXPR_CHECK): Use inline function above instead of __extension__. (non_type_check): New. (NON_TYPE_CHECK): Use inline function above instead of __extension__. (tree_vec_elt_check): New. (TREE_VEC_ELT_CHECK): Use inline function above instead of __extension__. (omp_clause_elt_check): New. (OMP_CLAUSE_ELT_CHECK): Use inline function above instead of __extension__. (tree_operand_check): New. (TREE_OPERAND_CHECK): Use inline function above instead of __extension__. (tree_operand_check_code): New. (TREE_OPERAND_CHECK_CODE): Use inline function above instead of __extension__. (TREE_CHAIN): Simplify implementation. (TREE_TYPE): Simplify implementation. (tree_operand_length): Move for compilation dependences. Index: gcc/tree.h =================================================================== --- gcc/tree.h (revision 179074) +++ gcc/tree.h (working copy) @@ -737,195 +737,122 @@ enum tree_node_structure_enum { is accessed incorrectly. The macros die with a fatal error. */ #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) -#define TREE_CHECK(T, CODE) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) != (CODE)) \ - tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - (CODE), 0); \ - __t; }) +#define TREE_CHECK(T, CODE) \ +(tree_check ((T), __FILE__, __LINE__, __FUNCTION__, (CODE))) +/* ((typeof (T)) tree_check ((T), __FILE__, __LINE__, __FUNCTION__, (CODE))) */ -#define TREE_NOT_CHECK(T, CODE) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) == (CODE)) \ - tree_not_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - (CODE), 0); \ - __t; }) +#define TREE_NOT_CHECK(T, CODE) \ +(tree_not_check ((T), __FILE__, __LINE__, __FUNCTION__, (CODE))) +/* ((typeof (T)) tree_not_check ((T), __FILE__, __LINE__, __FUNCTION__, (CODE))) */ -#define TREE_CHECK2(T, CODE1, CODE2) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) != (CODE1) \ - && TREE_CODE (__t) != (CODE2)) \ - tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - (CODE1), (CODE2), 0); \ - __t; }) +#define TREE_CHECK2(T, CODE1, CODE2) \ +(tree_check2 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2))) +/* ((typeof (T)) tree_check2 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2))) */ -#define TREE_NOT_CHECK2(T, CODE1, CODE2) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) == (CODE1) \ - || TREE_CODE (__t) == (CODE2)) \ - tree_not_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - (CODE1), (CODE2), 0); \ - __t; }) +#define TREE_NOT_CHECK2(T, CODE1, CODE2) \ +( tree_not_check2 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2))) +/* ((typeof (T)) tree_not_check2 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2))) */ -#define TREE_CHECK3(T, CODE1, CODE2, CODE3) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) != (CODE1) \ - && TREE_CODE (__t) != (CODE2) \ - && TREE_CODE (__t) != (CODE3)) \ - tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - (CODE1), (CODE2), (CODE3), 0); \ - __t; }) +#define TREE_CHECK3(T, CODE1, CODE2, CODE3) \ +(tree_check3 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2), (CODE3))) +/* ((typeof (T)) tree_check3 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2), (CODE3))) */ -#define TREE_NOT_CHECK3(T, CODE1, CODE2, CODE3) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) == (CODE1) \ - || TREE_CODE (__t) == (CODE2) \ - || TREE_CODE (__t) == (CODE3)) \ - tree_not_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - (CODE1), (CODE2), (CODE3), 0); \ - __t; }) +#define TREE_NOT_CHECK3(T, CODE1, CODE2, CODE3) \ +(tree_not_check3 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2), (CODE3))) +/* ((typeof (T)) tree_not_check3 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2), (CODE3))) */ -#define TREE_CHECK4(T, CODE1, CODE2, CODE3, CODE4) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) != (CODE1) \ - && TREE_CODE (__t) != (CODE2) \ - && TREE_CODE (__t) != (CODE3) \ - && TREE_CODE (__t) != (CODE4)) \ - tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - (CODE1), (CODE2), (CODE3), (CODE4), 0); \ - __t; }) +#define TREE_CHECK4(T, CODE1, CODE2, CODE3, CODE4) \ +(tree_check4 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2), (CODE3), (CODE4))) +/* ((typeof (T)) tree_check4 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2), (CODE3), (CODE4))) */ -#define TREE_NOT_CHECK4(T, CODE1, CODE2, CODE3, CODE4) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) == (CODE1) \ - || TREE_CODE (__t) == (CODE2) \ - || TREE_CODE (__t) == (CODE3) \ - || TREE_CODE (__t) == (CODE4)) \ - tree_not_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - (CODE1), (CODE2), (CODE3), (CODE4), 0); \ - __t; }) +#define TREE_NOT_CHECK4(T, CODE1, CODE2, CODE3, CODE4) \ +(tree_not_check4 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2), (CODE3), (CODE4))) +/* ((typeof (T)) tree_not_check4 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2), (CODE3), (CODE4))) */ -#define TREE_CHECK5(T, CODE1, CODE2, CODE3, CODE4, CODE5) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) != (CODE1) \ - && TREE_CODE (__t) != (CODE2) \ - && TREE_CODE (__t) != (CODE3) \ - && TREE_CODE (__t) != (CODE4) \ - && TREE_CODE (__t) != (CODE5)) \ - tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - (CODE1), (CODE2), (CODE3), (CODE4), (CODE5), 0);\ - __t; }) +#define TREE_CHECK5(T, CODE1, CODE2, CODE3, CODE4, CODE5) \ +(tree_check5 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2), (CODE3), (CODE4), (CODE5))) +/* ((typeof (T)) tree_check5 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2), (CODE3), (CODE4), (CODE5))) */ -#define TREE_NOT_CHECK5(T, CODE1, CODE2, CODE3, CODE4, CODE5) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) == (CODE1) \ - || TREE_CODE (__t) == (CODE2) \ - || TREE_CODE (__t) == (CODE3) \ - || TREE_CODE (__t) == (CODE4) \ - || TREE_CODE (__t) == (CODE5)) \ - tree_not_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - (CODE1), (CODE2), (CODE3), (CODE4), (CODE5), 0);\ - __t; }) +#define TREE_NOT_CHECK5(T, CODE1, CODE2, CODE3, CODE4, CODE5) \ +(tree_not_check5 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2), (CODE3), (CODE4), (CODE5))) +/* ((typeof (T)) tree_not_check5 ((T), __FILE__, __LINE__, __FUNCTION__, \ + (CODE1), (CODE2), (CODE3), (CODE4), (CODE5))) */ -#define CONTAINS_STRUCT_CHECK(T, STRUCT) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (tree_contains_struct[TREE_CODE(__t)][(STRUCT)] != 1) \ - tree_contains_struct_check_failed (__t, (STRUCT), __FILE__, __LINE__, \ - __FUNCTION__); \ - __t; }) +#define CONTAINS_STRUCT_CHECK(T, STRUCT) \ +(contains_struct_check ((T), (STRUCT), \ + __FILE__, __LINE__, __FUNCTION__)) +/* ((typeof (T)) contains_struct_check ((T), (STRUCT), \ + __FILE__, __LINE__, __FUNCTION__)) */ -#define TREE_CLASS_CHECK(T, CLASS) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE_CLASS (TREE_CODE(__t)) != (CLASS)) \ - tree_class_check_failed (__t, (CLASS), __FILE__, __LINE__, \ - __FUNCTION__); \ - __t; }) +#define TREE_CLASS_CHECK(T, CLASS) \ +(tree_class_check ((T), (CLASS), \ + __FILE__, __LINE__, __FUNCTION__)) +/* ((typeof (T)) tree_class_check ((T), (CLASS), \ + __FILE__, __LINE__, __FUNCTION__)) */ -#define TREE_RANGE_CHECK(T, CODE1, CODE2) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) < (CODE1) || TREE_CODE (__t) > (CODE2)) \ - tree_range_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - (CODE1), (CODE2)); \ - __t; }) +#define TREE_RANGE_CHECK(T, CODE1, CODE2) \ +(tree_range_check ((T), (CODE1), (CODE2), \ + __FILE__, __LINE__, __FUNCTION__)) +/* ((typeof (T)) tree_range_check ((T), (CODE1), (CODE2), \ + __FILE__, __LINE__, __FUNCTION__)) */ -#define OMP_CLAUSE_SUBCODE_CHECK(T, CODE) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) != OMP_CLAUSE) \ - tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - OMP_CLAUSE, 0); \ - if (__t->omp_clause.code != (CODE)) \ - omp_clause_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - (CODE)); \ - __t; }) +#define OMP_CLAUSE_SUBCODE_CHECK(T, CODE) \ +(omp_clause_subcode_check ((T), (CODE), \ + __FILE__, __LINE__, __FUNCTION__)) +/* ((typeof (T)) omp_clause_subcode_check ((T), (CODE), \ + __FILE__, __LINE__, __FUNCTION__)) */ -#define OMP_CLAUSE_RANGE_CHECK(T, CODE1, CODE2) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TREE_CODE (__t) != OMP_CLAUSE) \ - tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - OMP_CLAUSE, 0); \ - if ((int) __t->omp_clause.code < (int) (CODE1) \ - || (int) __t->omp_clause.code > (int) (CODE2)) \ - omp_clause_range_check_failed (__t, __FILE__, __LINE__, \ - __FUNCTION__, (CODE1), (CODE2)); \ - __t; }) +#define OMP_CLAUSE_RANGE_CHECK(T, CODE1, CODE2) \ +(omp_clause_range_check ((T), (CODE1), (CODE2), \ + __FILE__, __LINE__, __FUNCTION__)) +/* ((typeof (T)) omp_clause_range_check ((T), (CODE1), (CODE2), \ + __FILE__, __LINE__, __FUNCTION__)) */ /* These checks have to be special cased. */ -#define EXPR_CHECK(T) __extension__ \ -({ __typeof (T) const __t = (T); \ - char const __c = TREE_CODE_CLASS (TREE_CODE (__t)); \ - if (!IS_EXPR_CODE_CLASS (__c)) \ - tree_class_check_failed (__t, tcc_expression, __FILE__, __LINE__, \ - __FUNCTION__); \ - __t; }) +#define EXPR_CHECK(T) \ +(expr_check ((T), __FILE__, __LINE__, __FUNCTION__)) +/* ((typeof (T)) expr_check ((T), __FILE__, __LINE__, __FUNCTION__)) */ /* These checks have to be special cased. */ -#define NON_TYPE_CHECK(T) __extension__ \ -({ __typeof (T) const __t = (T); \ - if (TYPE_P (__t)) \ - tree_not_class_check_failed (__t, tcc_type, __FILE__, __LINE__, \ - __FUNCTION__); \ - __t; }) +#define NON_TYPE_CHECK(T) \ +(non_type_check ((T), __FILE__, __LINE__, __FUNCTION__)) +/* ((typeof (T)) non_type_check ((T), __FILE__, __LINE__, __FUNCTION__)) */ -#define TREE_VEC_ELT_CHECK(T, I) __extension__ \ -(*({__typeof (T) const __t = (T); \ - const int __i = (I); \ - if (TREE_CODE (__t) != TREE_VEC) \ - tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - TREE_VEC, 0); \ - if (__i < 0 || __i >= __t->vec.length) \ - tree_vec_elt_check_failed (__i, __t->vec.length, \ - __FILE__, __LINE__, __FUNCTION__); \ - &__t->vec.a[__i]; })) +#define TREE_VEC_ELT_CHECK(T, I) \ +(*(CONST_CAST2 (tree *, typeof (T)*, \ + tree_vec_elt_check ((T), (I), __FILE__, __LINE__, __FUNCTION__)))) -#define OMP_CLAUSE_ELT_CHECK(T, I) __extension__ \ -(*({__typeof (T) const __t = (T); \ - const int __i = (I); \ - if (TREE_CODE (__t) != OMP_CLAUSE) \ - tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, \ - OMP_CLAUSE, 0); \ - if (__i < 0 || __i >= omp_clause_num_ops [__t->omp_clause.code]) \ - omp_clause_operand_check_failed (__i, __t, __FILE__, __LINE__, \ - __FUNCTION__); \ - &__t->omp_clause.ops[__i]; })) +#define OMP_CLAUSE_ELT_CHECK(T, I) \ +(*(omp_clause_elt_check ((T), (I), \ + __FILE__, __LINE__, __FUNCTION__))) +/* (*((typeof (T)*) omp_clause_elt_check ((T), (I), \ + __FILE__, __LINE__, __FUNCTION__))) */ /* Special checks for TREE_OPERANDs. */ -#define TREE_OPERAND_CHECK(T, I) __extension__ \ -(*({__typeof (T) const __t = EXPR_CHECK (T); \ - const int __i = (I); \ - if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t)) \ - tree_operand_check_failed (__i, __t, \ - __FILE__, __LINE__, __FUNCTION__); \ - &__t->exp.operands[__i]; })) +#define TREE_OPERAND_CHECK(T, I) \ +(*(CONST_CAST2 (tree*, typeof (T)*, \ + tree_operand_check ((T), (I), __FILE__, __LINE__, __FUNCTION__)))) -#define TREE_OPERAND_CHECK_CODE(T, CODE, I) __extension__ \ -(*({__typeof (T) const __t = (T); \ - const int __i = (I); \ - if (TREE_CODE (__t) != CODE) \ - tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, (CODE), 0);\ - if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t)) \ - tree_operand_check_failed (__i, __t, \ - __FILE__, __LINE__, __FUNCTION__); \ - &__t->exp.operands[__i]; })) +#define TREE_OPERAND_CHECK_CODE(T, CODE, I) \ +(*(tree_operand_check_code ((T), (CODE), (I), \ + __FILE__, __LINE__, __FUNCTION__))) +/* (*((typeof (T)*) tree_operand_check_code ((T), (CODE), (I), \ + __FILE__, __LINE__, __FUNCTION__))) */ /* Nodes are chained together for many purposes. Types are chained together to record them for being output to the debugger @@ -936,17 +863,15 @@ enum tree_node_structure_enum { Often lists of things are represented by TREE_LIST nodes that are chained together. */ -#define TREE_CHAIN(NODE) __extension__ \ -(*({__typeof (NODE) const __t = CONTAINS_STRUCT_CHECK (NODE, TS_COMMON);\ - &__t->common.chain; })) +#define TREE_CHAIN(NODE) \ +(CONTAINS_STRUCT_CHECK (NODE, TS_COMMON)->common.chain) /* In all nodes that are expressions, this is the data type of the expression. In POINTER_TYPE nodes, this is the type that the pointer points to. In ARRAY_TYPE nodes, this is the type of the elements. In VECTOR_TYPE nodes, this is the type of the elements. */ -#define TREE_TYPE(NODE) __extension__ \ -(*({__typeof (NODE) const __t = CONTAINS_STRUCT_CHECK (NODE, TS_TYPED); \ - &__t->typed.type; })) +#define TREE_TYPE(NODE) \ +(CONTAINS_STRUCT_CHECK (NODE, TS_TYPED)->typed.type) extern void tree_contains_struct_check_failed (const_tree, const enum tree_node_structure_enum, @@ -3671,6 +3596,253 @@ union GTY ((ptr_alias (union lang_tree_n struct tree_optimization_option GTY ((tag ("TS_OPTIMIZATION"))) optimization; struct tree_target_option GTY ((tag ("TS_TARGET_OPTION"))) target_option; }; + + +#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) + +static inline tree +tree_check (const_tree __t, const char *__f, int __l, const char *__g, + enum tree_code __c) +{ + if (TREE_CODE (__t) != __c) + tree_check_failed (__t, __f, __l, __g, __c, 0); + return CONST_CAST_TREE (__t); +} + +static inline tree +tree_not_check (const_tree __t, const char *__f, int __l, const char *__g, + enum tree_code __c) +{ + if (TREE_CODE (__t) == __c) + tree_not_check_failed (__t, __f, __l, __g, __c, 0); + return CONST_CAST_TREE (__t); +} + +static inline tree +tree_check2 (const_tree __t, const char *__f, int __l, const char *__g, + enum tree_code __c1, enum tree_code __c2) +{ + if (TREE_CODE (__t) != __c1 + && TREE_CODE (__t) != __c2) + tree_check_failed (__t, __f, __l, __g, __c1, __c2, 0); + return CONST_CAST_TREE (__t); +} + +static inline tree +tree_not_check2 (const_tree __t, const char *__f, int __l, const char *__g, + enum tree_code __c1, enum tree_code __c2) +{ + if (TREE_CODE (__t) == __c1 + || TREE_CODE (__t) == __c2) + tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, 0); + return CONST_CAST_TREE (__t); +} + +static inline tree +tree_check3 (const_tree __t, const char *__f, int __l, const char *__g, + enum tree_code __c1, enum tree_code __c2, enum tree_code __c3) +{ + if (TREE_CODE (__t) != __c1 + && TREE_CODE (__t) != __c2 + && TREE_CODE (__t) != __c3) + tree_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, 0); + return CONST_CAST_TREE (__t); +} + +static inline tree +tree_not_check3 (const_tree __t, const char *__f, int __l, const char *__g, + enum tree_code __c1, enum tree_code __c2, enum tree_code __c3) +{ + if (TREE_CODE (__t) == __c1 + || TREE_CODE (__t) == __c2 + || TREE_CODE (__t) == __c3) + tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, 0); + return CONST_CAST_TREE (__t); +} + +static inline tree +tree_check4 (const_tree __t, const char *__f, int __l, const char *__g, + enum tree_code __c1, enum tree_code __c2, enum tree_code __c3, + enum tree_code __c4) +{ + if (TREE_CODE (__t) != __c1 + && TREE_CODE (__t) != __c2 + && TREE_CODE (__t) != __c3 + && TREE_CODE (__t) != __c4) + tree_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, 0); + return CONST_CAST_TREE (__t); +} + +static inline tree +tree_not_check4 (const_tree __t, const char *__f, int __l, const char *__g, + enum tree_code __c1, enum tree_code __c2, enum tree_code __c3, + enum tree_code __c4) +{ + if (TREE_CODE (__t) == __c1 + || TREE_CODE (__t) == __c2 + || TREE_CODE (__t) == __c3 + || TREE_CODE (__t) == __c4) + tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, 0); + return CONST_CAST_TREE (__t); +} + +static inline tree +tree_check5 (const_tree __t, const char *__f, int __l, const char *__g, + enum tree_code __c1, enum tree_code __c2, enum tree_code __c3, + enum tree_code __c4, enum tree_code __c5) +{ + if (TREE_CODE (__t) != __c1 + && TREE_CODE (__t) != __c2 + && TREE_CODE (__t) != __c3 + && TREE_CODE (__t) != __c4 + && TREE_CODE (__t) != __c5) + tree_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, __c5, 0); + return CONST_CAST_TREE (__t); +} + +static inline tree +tree_not_check5 (const_tree __t, const char *__f, int __l, const char *__g, + enum tree_code __c1, enum tree_code __c2, enum tree_code __c3, + enum tree_code __c4, enum tree_code __c5) +{ + if (TREE_CODE (__t) == __c1 + || TREE_CODE (__t) == __c2 + || TREE_CODE (__t) == __c3 + || TREE_CODE (__t) == __c4 + || TREE_CODE (__t) == __c5) + tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, __c5, 0); + return CONST_CAST_TREE (__t); +} + +static inline tree +contains_struct_check (const_tree __t, const enum tree_node_structure_enum __s, + const char *__f, int __l, const char *__g) +{ + if (tree_contains_struct[TREE_CODE(__t)][__s] != 1) + tree_contains_struct_check_failed (__t, __s, __f, __l, __g); + return CONST_CAST_TREE (__t); +} + +static inline tree +tree_class_check (const_tree __t, const enum tree_code_class __class, + const char *__f, int __l, const char *__g) +{ + if (TREE_CODE_CLASS (TREE_CODE(__t)) != __class) + tree_class_check_failed (__t, __class, __f, __l, __g); + return CONST_CAST_TREE (__t); +} + +static inline tree +tree_range_check (const_tree __t, + enum tree_code __code1, enum tree_code __code2, + const char *__f, int __l, const char *__g) +{ + if (TREE_CODE (__t) < __code1 || TREE_CODE (__t) > __code2) + tree_range_check_failed (__t, __f, __l, __g, __code1, __code2); + return CONST_CAST_TREE (__t); +} + +static inline tree +omp_clause_subcode_check (const_tree __t, enum omp_clause_code __code, + const char *__f, int __l, const char *__g) +{ + if (TREE_CODE (__t) != OMP_CLAUSE) + tree_check_failed (__t, __f, __l, __g, OMP_CLAUSE, 0); + if (__t->omp_clause.code != __code) + omp_clause_check_failed (__t, __f, __l, __g, __code); + return CONST_CAST_TREE (__t); +} + +static inline tree +omp_clause_range_check (const_tree __t, + enum omp_clause_code __code1, + enum omp_clause_code __code2, + const char *__f, int __l, const char *__g) +{ + if (TREE_CODE (__t) != OMP_CLAUSE) + tree_check_failed (__t, __f, __l, __g, OMP_CLAUSE, 0); + if ((int) __t->omp_clause.code < (int) __code1 + || (int) __t->omp_clause.code > (int) __code2) + omp_clause_range_check_failed (__t, __f, __l, __g, __code1, __code2); + return CONST_CAST_TREE (__t); +} + +/* These checks have to be special cased. */ +static inline tree +expr_check (const_tree __t, const char *__f, int __l, const char *__g) +{ + char const __c = TREE_CODE_CLASS (TREE_CODE (__t)); + if (!IS_EXPR_CODE_CLASS (__c)) + tree_class_check_failed (__t, tcc_expression, __f, __l, __g); + return CONST_CAST_TREE (__t); +} + +/* These checks have to be special cased. */ +static inline tree +non_type_check (const_tree __t, const char *__f, int __l, const char *__g) +{ + if (TYPE_P (__t)) + tree_not_class_check_failed (__t, tcc_type, __f, __l, __g); + return CONST_CAST_TREE (__t); +} + +static inline tree * +tree_vec_elt_check (const_tree __t, int __i, + const char *__f, int __l, const char *__g) +{ + if (TREE_CODE (__t) != TREE_VEC) + tree_check_failed (__t, __f, __l, __g, TREE_VEC, 0); + if (__i < 0 || __i >= __t->vec.length) + tree_vec_elt_check_failed (__i, __t->vec.length, __f, __l, __g); + return &CONST_CAST_TREE (__t)->vec.a[__i]; +} + +static inline tree * +omp_clause_elt_check (const_tree __t, int __i, + const char *__f, int __l, const char *__g) +{ + if (TREE_CODE (__t) != OMP_CLAUSE) + tree_check_failed (__t, __f, __l, __g, OMP_CLAUSE, 0); + if (__i < 0 || __i >= omp_clause_num_ops [__t->omp_clause.code]) + omp_clause_operand_check_failed (__i, __t, __f, __l, __g); + return &CONST_CAST_TREE (__t)->omp_clause.ops[__i]; +} + +/* Compute the number of operands in an expression node NODE. For + tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself, + otherwise it is looked up from the node's code. */ +static inline int +tree_operand_length (const_tree node) +{ + if (VL_EXP_CLASS_P (node)) + return VL_EXP_OPERAND_LENGTH (node); + else + return TREE_CODE_LENGTH (TREE_CODE (node)); +} + +/* Special checks for TREE_OPERANDs. */ +static inline tree * +tree_operand_check (const_tree __t, int __i, + const char *__f, int __l, const char *__g) +{ + const_tree __u = EXPR_CHECK (__t); + if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__u)) + tree_operand_check_failed (__i, __u, __f, __l, __g); + return &CONST_CAST_TREE (__u)->exp.operands[__i]; +} + +static inline tree * +tree_operand_check_code (const_tree __t, enum tree_code __code, int __i, + const char *__f, int __l, const char *__g) +{ + if (TREE_CODE (__t) != __code) + tree_check_failed (__t, __f, __l, __g, __code, 0); + if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t)) + tree_operand_check_failed (__i, __t, __f, __l, __g); + return &CONST_CAST_TREE (__t)->exp.operands[__i]; +} + +#endif /* Standard named or nameless data types of the C compiler. */ @@ -5791,18 +5963,6 @@ extern tree build_personality_function ( void init_inline_once (void); -/* Compute the number of operands in an expression node NODE. For - tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself, - otherwise it is looked up from the node's code. */ -static inline int -tree_operand_length (const_tree node) -{ - if (VL_EXP_CLASS_P (node)) - return VL_EXP_OPERAND_LENGTH (node); - else - return TREE_CODE_LENGTH (TREE_CODE (node)); -} - /* Abstract iterators for CALL_EXPRs. These static inline definitions have to go towards the end of tree.h so that union tree_node is fully defined by this point. */ -- This patch is available for review at http://codereview.appspot.com/5132047
Sign in to reply to this message.
On 09/27/2011 12:05 AM, crowl@google.com wrote: > The gcc source uses several constructs that GDB does not understand. > This patch corrects some of them. It affects only compilers built > with ENABLE_TREE_CHECKING, and hence release compilers are unaffected. This is "funny". I have been using for years and years the attached .gdbinit, assuming it was part of life ;) (I don't know much about gdb, it's clear) Paolo.
Sign in to reply to this message.
On Mon, Sep 26, 2011 at 03:05:00PM -0700, Lawrence Crowl wrote: > There a non-transparent change in behavior that may affect some users. > The inline functions will introduce additional lines in a sequence of > gdb 'step' commands. Use 'next' instead. That is IMHO a serious obstackle. If anything, the inlines should use always_inline, artificial attributes, but don't know if GDB treats them already specially and doesn't step into them with step. Also, I'm afraid it will significantly grow cc1plus/cc1 debug info. The .gdbinit macro redefinition Paolo posted sounds to be a better approach. Jakub
Sign in to reply to this message.
On Tue, Sep 27, 2011 at 9:14 AM, Jakub Jelinek <jakub@redhat.com> wrote: > On Mon, Sep 26, 2011 at 03:05:00PM -0700, Lawrence Crowl wrote: >> There a non-transparent change in behavior that may affect some users. >> The inline functions will introduce additional lines in a sequence of >> gdb 'step' commands. Use 'next' instead. > > That is IMHO a serious obstackle. If anything, the inlines should > use always_inline, artificial attributes, but don't know if GDB treats them > already specially and doesn't step into them with step. > Also, I'm afraid it will significantly grow cc1plus/cc1 debug info. > > The .gdbinit macro redefinition Paolo posted sounds to be a better approach. Yeah, I already see me typing s<return>finish<return> gazillion of times when trying to step into a function call that produces a function argument ... there is already the very very very annoying tree_code_length function that you get for each TREE_OPERAND (...) macro on function arguments. I'd be very opposed to any change that makes this situation worse. Richard. > Jakub >
Sign in to reply to this message.
On Tue, Sep 27, 2011 at 9:35 AM, Richard Guenther <richard.guenther@gmail.com> wrote: > On Tue, Sep 27, 2011 at 9:14 AM, Jakub Jelinek <jakub@redhat.com> wrote: >> On Mon, Sep 26, 2011 at 03:05:00PM -0700, Lawrence Crowl wrote: >>> There a non-transparent change in behavior that may affect some users. >>> The inline functions will introduce additional lines in a sequence of >>> gdb 'step' commands. Use 'next' instead. >> >> That is IMHO a serious obstackle. If anything, the inlines should >> use always_inline, artificial attributes, but don't know if GDB treats them >> already specially and doesn't step into them with step. >> Also, I'm afraid it will significantly grow cc1plus/cc1 debug info. >> >> The .gdbinit macro redefinition Paolo posted sounds to be a better approach. > > Yeah, I already see me typing s<return>finish<return> gazillion of times when > trying to step into a function call that produces a function argument > ... there is > already the very very very annoying tree_code_length function that you get for > each TREE_OPERAND (...) macro on function arguments. I'd be very opposed > to any change that makes this situation worse. tree_operand_length actually. Please produce a patch that makes this function transparent to gdb, then I might be convinced converting the other macros to such function might be worthwhile. Thanks, Richard. > Richard. > >> Jakub >> >
Sign in to reply to this message.
On 11-09-27 03:37 , Richard Guenther wrote: > On Tue, Sep 27, 2011 at 9:35 AM, Richard Guenther > <richard.guenther@gmail.com> wrote: >> On Tue, Sep 27, 2011 at 9:14 AM, Jakub Jelinek<jakub@redhat.com> wrote: >>> On Mon, Sep 26, 2011 at 03:05:00PM -0700, Lawrence Crowl wrote: >>>> There a non-transparent change in behavior that may affect some users. >>>> The inline functions will introduce additional lines in a sequence of >>>> gdb 'step' commands. Use 'next' instead. >>> >>> That is IMHO a serious obstackle. If anything, the inlines should >>> use always_inline, artificial attributes, but don't know if GDB treats them >>> already specially and doesn't step into them with step. >>> Also, I'm afraid it will significantly grow cc1plus/cc1 debug info. >>> >>> The .gdbinit macro redefinition Paolo posted sounds to be a better approach. >> >> Yeah, I already see me typing s<return>finish<return> gazillion of times when >> trying to step into a function call that produces a function argument >> ... there is >> already the very very very annoying tree_code_length function that you get for >> each TREE_OPERAND (...) macro on function arguments. I'd be very opposed >> to any change that makes this situation worse. > > tree_operand_length actually. Please produce a patch that makes this function > transparent to gdb, then I might be convinced converting the other macros to > such function might be worthwhile. > > Thanks, > Richard. I think we need to find a solution for this situation. The suggestions I see in this thread are nothing but workarounds to cope with current debugging limitations. We have learned to live with them and hack around them, but debugging GCC is already a daunting task, and I think we can improve it. Richard, yes, stepping into one-liner inline functions can be aggravating (particularly with some of the 2-3 embedded function calls we have in some places). However, the ability to easily inspect state of data structures using the standard accessors is fundamental. Particularly, for developers that may not have the extensive knowledge of internals that you do. Jakub, is size of a debuggable cc1/cc1plus really all that important? Yes, more debug info makes for bigger binaries. But when debugging, that hardly matters. Unless we were talking about a multi-Gb binary, which we aren't. I would like to solve this problem for all inline functions that we may not care to step into. There is a whole bunch of one-liners that generally annoy me: tree_operand_length, gimple_op, ... in fact, all the gimple accessors, etc. How about one of these two ideas? 1- Add -g to the list of supported settings in #pragma GCC optimize (or create a new #pragma GCC no_debug). This way, we can brace all these one liners with: #pragma push_options #pragma GCC optimize ("-g0") [ ... inline functions ... ] #pragma pop_options 2- Similar to #1, but with __attribute__ in each function declaration. I think I prefer #1 since it's simpler for the user to specify. This would also let us generate smaller debug binaries, since the bracketed functions would not get any debug info at all. Any reason why that scheme couldn't work? It works well for separate TUs. Thanks. Diego.
Sign in to reply to this message.
On Wed, Oct 5, 2011 at 3:18 PM, Diego Novillo <dnovillo@google.com> wrote: > On 11-09-27 03:37 , Richard Guenther wrote: >> >> On Tue, Sep 27, 2011 at 9:35 AM, Richard Guenther >> <richard.guenther@gmail.com> wrote: >>> >>> On Tue, Sep 27, 2011 at 9:14 AM, Jakub Jelinek<jakub@redhat.com> wrote: >>>> >>>> On Mon, Sep 26, 2011 at 03:05:00PM -0700, Lawrence Crowl wrote: >>>>> >>>>> There a non-transparent change in behavior that may affect some users. >>>>> The inline functions will introduce additional lines in a sequence of >>>>> gdb 'step' commands. Use 'next' instead. >>>> >>>> That is IMHO a serious obstackle. If anything, the inlines should >>>> use always_inline, artificial attributes, but don't know if GDB treats >>>> them >>>> already specially and doesn't step into them with step. >>>> Also, I'm afraid it will significantly grow cc1plus/cc1 debug info. >>>> >>>> The .gdbinit macro redefinition Paolo posted sounds to be a better >>>> approach. >>> >>> Yeah, I already see me typing s<return>finish<return> gazillion of times >>> when >>> trying to step into a function call that produces a function argument >>> ... there is >>> already the very very very annoying tree_code_length function that you >>> get for >>> each TREE_OPERAND (...) macro on function arguments. I'd be very opposed >>> to any change that makes this situation worse. >> >> tree_operand_length actually. Please produce a patch that makes this >> function >> transparent to gdb, then I might be convinced converting the other macros >> to >> such function might be worthwhile. >> >> Thanks, >> Richard. > > I think we need to find a solution for this situation. The suggestions I > see in this thread are nothing but workarounds to cope with current > debugging limitations. We have learned to live with them and hack around > them, but debugging GCC is already a daunting task, and I think we can > improve it. > > Richard, yes, stepping into one-liner inline functions can be aggravating > (particularly with some of the 2-3 embedded function calls we have in some > places). However, the ability to easily inspect state of data structures > using the standard accessors is fundamental. Particularly, for developers > that may not have the extensive knowledge of internals that you do. It is much more important to optimize my debugging time as experienced developer resources are more scarce than some random unexperienced guy that happens to dig into GCC. ;) or not really ;). > Jakub, is size of a debuggable cc1/cc1plus really all that important? Yes, > more debug info makes for bigger binaries. But when debugging, that hardly > matters. Unless we were talking about a multi-Gb binary, which we aren't. > > I would like to solve this problem for all inline functions that we may not > care to step into. There is a whole bunch of one-liners that generally > annoy me: tree_operand_length, gimple_op, ... in fact, all the gimple > accessors, etc. > > How about one of these two ideas? > > 1- Add -g to the list of supported settings in #pragma GCC optimize (or > create a new #pragma GCC no_debug). This way, we can brace all these one > liners with: > > #pragma push_options > #pragma GCC optimize ("-g0") > [ ... inline functions ... ] > #pragma pop_options > > > 2- Similar to #1, but with __attribute__ in each function declaration. I > think I prefer #1 since it's simpler for the user to specify. > > > This would also let us generate smaller debug binaries, since the bracketed > functions would not get any debug info at all. > > Any reason why that scheme couldn't work? It works well for separate TUs. If you crash inside those -g0 marked functions, what happens? Why not use the artificial attribute on them instead? At least what is documented is exactly what we want (well, at least it seems to me). Thus, produce a patch that improves tree_operand_length with either approach so we can test it. Richard. > > Thanks. Diego. >
Sign in to reply to this message.
On Wed, Oct 5, 2011 at 09:45, Richard Guenther <richard.guenther@gmail.com> wrote: > On Wed, Oct 5, 2011 at 3:18 PM, Diego Novillo <dnovillo@google.com> wrote: >> On 11-09-27 03:37 , Richard Guenther wrote: >>> >>> On Tue, Sep 27, 2011 at 9:35 AM, Richard Guenther >>> <richard.guenther@gmail.com> wrote: >>>> >>>> On Tue, Sep 27, 2011 at 9:14 AM, Jakub Jelinek<jakub@redhat.com> wrote: >>>>> >>>>> On Mon, Sep 26, 2011 at 03:05:00PM -0700, Lawrence Crowl wrote: >>>>>> >>>>>> There a non-transparent change in behavior that may affect some users. >>>>>> The inline functions will introduce additional lines in a sequence of >>>>>> gdb 'step' commands. Use 'next' instead. >>>>> >>>>> That is IMHO a serious obstackle. If anything, the inlines should >>>>> use always_inline, artificial attributes, but don't know if GDB treats >>>>> them >>>>> already specially and doesn't step into them with step. >>>>> Also, I'm afraid it will significantly grow cc1plus/cc1 debug info. >>>>> >>>>> The .gdbinit macro redefinition Paolo posted sounds to be a better >>>>> approach. >>>> >>>> Yeah, I already see me typing s<return>finish<return> gazillion of times >>>> when >>>> trying to step into a function call that produces a function argument >>>> ... there is >>>> already the very very very annoying tree_code_length function that you >>>> get for >>>> each TREE_OPERAND (...) macro on function arguments. I'd be very opposed >>>> to any change that makes this situation worse. >>> >>> tree_operand_length actually. Please produce a patch that makes this >>> function >>> transparent to gdb, then I might be convinced converting the other macros >>> to >>> such function might be worthwhile. >>> >>> Thanks, >>> Richard. >> >> I think we need to find a solution for this situation. The suggestions I >> see in this thread are nothing but workarounds to cope with current >> debugging limitations. We have learned to live with them and hack around >> them, but debugging GCC is already a daunting task, and I think we can >> improve it. >> >> Richard, yes, stepping into one-liner inline functions can be aggravating >> (particularly with some of the 2-3 embedded function calls we have in some >> places). However, the ability to easily inspect state of data structures >> using the standard accessors is fundamental. Particularly, for developers >> that may not have the extensive knowledge of internals that you do. > > It is much more important to optimize my debugging time as experienced > developer resources are more scarce than some random unexperienced > guy that happens to dig into GCC. > > ;) > > or not really ;). You are being facetious, I hope. Part of the reason that experienced developers are scarce is precisely because dealing with GCC's code base is so daunting. We should be trying to attract those random inexperienced developers, not scare them away. The experienced developers will retire, eventually. Who is going to replace them? >> Jakub, is size of a debuggable cc1/cc1plus really all that important? Yes, >> more debug info makes for bigger binaries. But when debugging, that hardly >> matters. Unless we were talking about a multi-Gb binary, which we aren't. >> >> I would like to solve this problem for all inline functions that we may not >> care to step into. There is a whole bunch of one-liners that generally >> annoy me: tree_operand_length, gimple_op, ... in fact, all the gimple >> accessors, etc. >> >> How about one of these two ideas? >> >> 1- Add -g to the list of supported settings in #pragma GCC optimize (or >> create a new #pragma GCC no_debug). This way, we can brace all these one >> liners with: >> >> #pragma push_options >> #pragma GCC optimize ("-g0") >> [ ... inline functions ... ] >> #pragma pop_options >> >> >> 2- Similar to #1, but with __attribute__ in each function declaration. I >> think I prefer #1 since it's simpler for the user to specify. >> >> >> This would also let us generate smaller debug binaries, since the bracketed >> functions would not get any debug info at all. >> >> Any reason why that scheme couldn't work? It works well for separate TUs. > > If you crash inside those -g0 marked functions, what happens? You don't see the body of the function, but you can go up into the exact call site. > Why > not use the artificial attribute on them instead? At least what is documented > is exactly what we want (well, at least it seems to me). Yes, I forgot to mention in my reply. I tried it, but you still step into the functions. If this is a bug with the attribute, then it could be fixed. > Thus, produce a patch that improves tree_operand_length with either > approach so we can test it. I have a slight preference for making these functions totally opaque to the debugger. But may be there is a setting we can use that will not affect step and still give us some debug info in the presence of crashes. Tom, Cary, Ian, any suggestions? We are trying to figure out a compromise for tiny inline functions that are generally a nuisance when debugging. The scenario is a call like this: big_function_foo (inlined_f (x), inlined_g (y)); We want to use 's' to step inside the call to big_function_foo(), but we don't want to step into either inlined_f() or inlined_g(). I tried __attribute__((artificial)), but that is either buggy on the gcc side or the gdb side, because I am still getting into the inlined function (with -g3). I proposed extending #pragma GCC options to bracket these functions with -g0. This would help reduce the impact of debug info size. Thoughts? Thanks. Diego.
Sign in to reply to this message.
Diego Novillo <dnovillo@google.com> writes: >> It is much more important to optimize my debugging time as experienced >> developer resources are more scarce than some random unexperienced >> guy that happens to dig into GCC. >> >> ;) >> >> or not really ;). > > You are being facetious, I hope. Part of the reason that experienced > developers are scarce is precisely because dealing with GCC's code > base is so daunting. We should be trying to attract those random > inexperienced developers, not scare them away. > > The experienced developers will retire, eventually. Who is going to > replace them? Yes. We experienced gcc developers can adapt to the tools, and we can modify the tools to work better. We should not hold up code improvements because of tool deficiencies. We should fix both problems, but we don't have to fix them in sequence. > Tom, Cary, Ian, any suggestions? We are trying to figure out a > compromise for tiny inline functions that are generally a nuisance > when debugging. The scenario is a call like this: big_function_foo > (inlined_f (x), inlined_g (y)); > We want to use 's' to step inside the call to big_function_foo(), but > we don't want to step into either inlined_f() or inlined_g(). This is a general problem when debugging C++ programs, so any solution to this gcc-specific issue will be of general use. However, I don't know of a way to make it work today without changing gdb. There is a lot I don't know about gdb, so it is possible that there is some approach that will work. Basically, gdb's relatively new support for debugging inline functions is sometimes nice, but sometimes it just gets in the way. I guess the most general solution is a way to mark the inline function in the source as uninteresting. I don't really understand the doc for the "artificial" function attribute, but it looks like it was intended to serve this purpose. So it seems to me that there is a bug in gdb: "step" should not step into a function with the "artificial" attribute. I agree that it does not currently work that way. Looking at the gdb sources, it seems to me that it currently ignores DW_AT_artificial on an ordinary function. Ian
Sign in to reply to this message.
On Wed, Oct 5, 2011 at 4:10 PM, Diego Novillo <dnovillo@google.com> wrote: > On Wed, Oct 5, 2011 at 09:45, Richard Guenther > <richard.guenther@gmail.com> wrote: >> On Wed, Oct 5, 2011 at 3:18 PM, Diego Novillo <dnovillo@google.com> wrote: >>> On 11-09-27 03:37 , Richard Guenther wrote: >>>> >>>> On Tue, Sep 27, 2011 at 9:35 AM, Richard Guenther >>>> <richard.guenther@gmail.com> wrote: >>>>> >>>>> On Tue, Sep 27, 2011 at 9:14 AM, Jakub Jelinek<jakub@redhat.com> wrote: >>>>>> >>>>>> On Mon, Sep 26, 2011 at 03:05:00PM -0700, Lawrence Crowl wrote: >>>>>>> >>>>>>> There a non-transparent change in behavior that may affect some users. >>>>>>> The inline functions will introduce additional lines in a sequence of >>>>>>> gdb 'step' commands. Use 'next' instead. >>>>>> >>>>>> That is IMHO a serious obstackle. If anything, the inlines should >>>>>> use always_inline, artificial attributes, but don't know if GDB treats >>>>>> them >>>>>> already specially and doesn't step into them with step. >>>>>> Also, I'm afraid it will significantly grow cc1plus/cc1 debug info. >>>>>> >>>>>> The .gdbinit macro redefinition Paolo posted sounds to be a better >>>>>> approach. >>>>> >>>>> Yeah, I already see me typing s<return>finish<return> gazillion of times >>>>> when >>>>> trying to step into a function call that produces a function argument >>>>> ... there is >>>>> already the very very very annoying tree_code_length function that you >>>>> get for >>>>> each TREE_OPERAND (...) macro on function arguments. I'd be very opposed >>>>> to any change that makes this situation worse. >>>> >>>> tree_operand_length actually. Please produce a patch that makes this >>>> function >>>> transparent to gdb, then I might be convinced converting the other macros >>>> to >>>> such function might be worthwhile. >>>> >>>> Thanks, >>>> Richard. >>> >>> I think we need to find a solution for this situation. The suggestions I >>> see in this thread are nothing but workarounds to cope with current >>> debugging limitations. We have learned to live with them and hack around >>> them, but debugging GCC is already a daunting task, and I think we can >>> improve it. >>> >>> Richard, yes, stepping into one-liner inline functions can be aggravating >>> (particularly with some of the 2-3 embedded function calls we have in some >>> places). However, the ability to easily inspect state of data structures >>> using the standard accessors is fundamental. Particularly, for developers >>> that may not have the extensive knowledge of internals that you do. >> >> It is much more important to optimize my debugging time as experienced >> developer resources are more scarce than some random unexperienced >> guy that happens to dig into GCC. >> >> ;) >> >> or not really ;). > > You are being facetious, I hope. Part of the reason that experienced > developers are scarce is precisely because dealing with GCC's code > base is so daunting. We should be trying to attract those random > inexperienced developers, not scare them away. > > The experienced developers will retire, eventually. Who is going to > replace them? > > >>> Jakub, is size of a debuggable cc1/cc1plus really all that important? Yes, >>> more debug info makes for bigger binaries. But when debugging, that hardly >>> matters. Unless we were talking about a multi-Gb binary, which we aren't. >>> >>> I would like to solve this problem for all inline functions that we may not >>> care to step into. There is a whole bunch of one-liners that generally >>> annoy me: tree_operand_length, gimple_op, ... in fact, all the gimple >>> accessors, etc. >>> >>> How about one of these two ideas? >>> >>> 1- Add -g to the list of supported settings in #pragma GCC optimize (or >>> create a new #pragma GCC no_debug). This way, we can brace all these one >>> liners with: >>> >>> #pragma push_options >>> #pragma GCC optimize ("-g0") >>> [ ... inline functions ... ] >>> #pragma pop_options >>> >>> >>> 2- Similar to #1, but with __attribute__ in each function declaration. I >>> think I prefer #1 since it's simpler for the user to specify. >>> >>> >>> This would also let us generate smaller debug binaries, since the bracketed >>> functions would not get any debug info at all. >>> >>> Any reason why that scheme couldn't work? It works well for separate TUs. >> >> If you crash inside those -g0 marked functions, what happens? > > You don't see the body of the function, but you can go up into the > exact call site. > >> Why >> not use the artificial attribute on them instead? At least what is documented >> is exactly what we want (well, at least it seems to me). > > Yes, I forgot to mention in my reply. I tried it, but you still step > into the functions. If this is a bug with the attribute, then it > could be fixed. Did you also mark the function with always_inline? That's a requirement as artificial only works for inlined function bodies. >> Thus, produce a patch that improves tree_operand_length with either >> approach so we can test it. > > I have a slight preference for making these functions totally opaque > to the debugger. But may be there is a setting we can use that will > not affect step and still give us some debug info in the presence of > crashes. > > Tom, Cary, Ian, any suggestions? We are trying to figure out a > compromise for tiny inline functions that are generally a nuisance > when debugging. The scenario is a call like this: big_function_foo > (inlined_f (x), inlined_g (y)); > We want to use 's' to step inside the call to big_function_foo(), but > we don't want to step into either inlined_f() or inlined_g(). > > I tried __attribute__((artificial)), but that is either buggy on the > gcc side or the gdb side, because I am still getting into the inlined > function (with -g3). > > I proposed extending #pragma GCC options to bracket these functions > with -g0. This would help reduce the impact of debug info size. > > Thoughts? > > > Thanks. Diego. >
Sign in to reply to this message.
>>>>> "Diego" == Diego Novillo <dnovillo@google.com> writes: Diego> Tom, Cary, Ian, any suggestions? We are trying to figure out a Diego> compromise for tiny inline functions that are generally a nuisance Diego> when debugging. The scenario is a call like this: big_function_foo Diego> (inlined_f (x), inlined_g (y)); Diego> We want to use 's' to step inside the call to big_function_foo(), but Diego> we don't want to step into either inlined_f() or inlined_g(). FWIW, I wrote the "macro define" stuff that Paolo posted back when I was actively hacking on gcc. I consider it to be mildly superior to the inline approach, because it circumvents the runtime type checking -- this is a plus because it means that if I type the wrong thing to gdb it doesn't cause cc1 to abort. At least, this is a plus for me, since I make mistakes like that with reasonable frequency. Diego> I proposed extending #pragma GCC options to bracket these functions Diego> with -g0. This would help reduce the impact of debug info size. I think this is fixing the wrong component: it means making a one-size-fits-all decision in the gcc build, instead of just making the debugger be more flexible. If you want to pursue the inline function approach, I suggest resurrecting this gdb patch: http://sourceware.org/bugzilla/show_bug.cgi?id=8287 http://sourceware.org/ml/gdb-patches/2010-06/msg00417.html Then you could add the appropriate blacklisting commands to gcc's .gdbinit by default. Tom
Sign in to reply to this message.
On Wed, Oct 5, 2011 at 10:51, Richard Guenther <richard.guenther@gmail.com> wrote: > Did you also mark the function with always_inline? That's a requirement > as artificial only works for inlined function bodies. Yeah. It doesn't quite work as I expect it to. It steps into the function at odd places. Diego.
Sign in to reply to this message.
On 10/05/2011 05:27 PM, Tom Tromey wrote: > FWIW, I wrote the "macro define" stuff that Paolo posted back when I > was actively hacking on gcc. Yes, thanks Tom! Actually, I suspected that, but couldn't remember where I actually got it from, maybe you posted it on a public discussion thread somewhere... Paolo.
Sign in to reply to this message.
On Wed, Oct 5, 2011 at 11:27, Tom Tromey <tromey@redhat.com> wrote: > Diego> I proposed extending #pragma GCC options to bracket these functions > Diego> with -g0. This would help reduce the impact of debug info size. > > I think this is fixing the wrong component: it means making a > one-size-fits-all decision in the gcc build, instead of just making the > debugger be more flexible. That's true. > If you want to pursue the inline function approach, I suggest > resurrecting this gdb patch: > > http://sourceware.org/bugzilla/show_bug.cgi?id=8287 > http://sourceware.org/ml/gdb-patches/2010-06/msg00417.html > > Then you could add the appropriate blacklisting commands to gcc's > .gdbinit by default. I think this could work. I'm not sure I like the idea of having to specify all these blacklist commands, but I appreciate how it can make debugging more flexible. Is this patch stalled? the last I see is Justin's reply to review feedback, but no indication of whether it will be accepted. Richi, Jakub, Lawrence, would you be OK with this approach? IIUC, this means we'd have to add a bunch of blacklist commands to gcc/gdbinit.in. This does ties us to gdb, but I don't think that's a problem. How does this work with C++? Do the functions need to be specified with their mangled names? Diego.
Sign in to reply to this message.
On Wed, Oct 05, 2011 at 11:42:51AM -0400, Diego Novillo wrote: > Richi, Jakub, Lawrence, would you be OK with this approach? IIUC, > this means we'd have to add a bunch of blacklist commands to > gcc/gdbinit.in. I don't mind if it goes into gdb, but IMHO the blacklisting should definitely default to blacklisting DW_AT_artificial inline functions (and allowing to unblacklist them), because the artificial attribute has been designed for that purpose already more than 4 years ago and many headers use it. Jakub
Sign in to reply to this message.
>>>>> "Diego" == Diego Novillo <dnovillo@google.com> writes: Tom> http://sourceware.org/bugzilla/show_bug.cgi?id=8287 Diego> I think this could work. I'm not sure I like the idea of having to Diego> specify all these blacklist commands, but I appreciate how it can make Diego> debugging more flexible. Yeah, that's a drawback, since you have to remember to update .gdbinit. Diego> Is this patch stalled? the last I see is Justin's reply to review Diego> feedback, but no indication of whether it will be accepted. The thread continues in the next month: http://sourceware.org/ml/gdb-patches/2010-07/threads.html#00318 The patch needed some updates. I don't know what happened. Diego> How does this work with C++? Do the functions need to be specified Diego> with their mangled names? I would hope not, but I don't remember any more. Tom
Sign in to reply to this message.
>>>>> "Jakub" == Jakub Jelinek <jakub@redhat.com> writes: Jakub> I don't mind if it goes into gdb, but IMHO the blacklisting should Jakub> definitely default to blacklisting DW_AT_artificial inline functions Jakub> (and allowing to unblacklist them), because the artificial attribute Jakub> has been designed for that purpose already more than 4 years ago Jakub> and many headers use it. Could you file a gdb bug report for this? In general I'd appreciate it if folks making debug changes to gcc filed bug reports against gdb. I do follow the gcc list looking for things like this, but I miss things sometimes, and this isn't really the best way. Tom
Sign in to reply to this message.
On Wed, Oct 5, 2011 at 11:28, Diego Novillo <dnovillo@google.com> wrote: > On Wed, Oct 5, 2011 at 10:51, Richard Guenther > <richard.guenther@gmail.com> wrote: > >> Did you also mark the function with always_inline? That's a requirement >> as artificial only works for inlined function bodies. > > Yeah. It doesn't quite work as I expect it to. It steps into the > function at odd places. So, I played with this some more with this, and there seems to be some inconsistency in how these attributes get handled. http://sourceware.org/bugzilla/show_bug.cgi?id=13263 static inline int foo (int) __attribute__((always_inline,artificial)); static inline int foo (int x) { int y = x - 3; return y; } int bar (int y) { return y == 0; } main () { foo (10); return bar (foo (3)); } With GCC 4.7, the stand alone call foo(10) is not ignored by 'step'. However, the embedded call bar(foo(3)) is ignored as I was expecting. Diego.
Sign in to reply to this message.
On Oct 5, 2011, at 6:18 AM, Diego Novillo wrote: > I think we need to find a solution for this situation. The solution Apple found and implemented is a __nodebug__ attribute, as can be seen in Apple's gcc. We use it like so: #define __always_inline__ __always_inline__, __nodebug__ #undef __always_inline__ in headers like mmintrn.h: __STATIC_INLINE void __attribute__((__always_inline__)) /* APPLE LOCAL end radar 5618945 */ _mm_empty (void) { __builtin_ia32_emms (); } to disappear the debug information for all the routines, so that the context is the context in which the routine is called (because the routine is always inlined). It is implemented and works great. Easy to use and understand. Since we use the #define, #undef around the functions, it is mostly equivalent to #pragma, though, it does attach a little closer to the function. You can strip #.* from the .i files, and not have it removed (which is nice).
Sign in to reply to this message.
On Wed, Oct 5, 2011 at 14:20, Mike Stump <mikestump@comcast.net> wrote: > On Oct 5, 2011, at 6:18 AM, Diego Novillo wrote: >> I think we need to find a solution for this situation. > > The solution Apple found and implemented is a __nodebug__ attribute, as can be seen in Apple's gcc. > > We use it like so: > > #define __always_inline__ __always_inline__, __nodebug__ > #undef __always_inline__ > > in headers like mmintrn.h: > > __STATIC_INLINE void __attribute__((__always_inline__)) > /* APPLE LOCAL end radar 5618945 */ > _mm_empty (void) > { > __builtin_ia32_emms (); > } Ah, nice. Though, one of the things I am liking more and more about the blacklist solution is that it (a) does not need any modifications to the source code, and (b) it works with no-inline functions as well. This gives total control to the developer. I would blacklist a bunch of functions I never care to go into, for instance. Others may choose to blacklist a different set. And you can change that from debug session to the next. I agree with Jakub that artificial functions should be blacklisted automatically, however. Richi, Jakub, if the blacklist solution was implemented in GCC would you agree with promoting these macros into inline functions? This is orthogonal to http://sourceware.org/bugzilla/show_bug.cgi?id=13263, of course. Thanks. Diego.
Sign in to reply to this message.
On Wed, Oct 5, 2011 at 6:53 PM, Diego Novillo <dnovillo@google.com> wrote: > On Wed, Oct 5, 2011 at 11:28, Diego Novillo <dnovillo@google.com> wrote: >> On Wed, Oct 5, 2011 at 10:51, Richard Guenther >> <richard.guenther@gmail.com> wrote: >> >>> Did you also mark the function with always_inline? That's a requirement >>> as artificial only works for inlined function bodies. >> >> Yeah. It doesn't quite work as I expect it to. It steps into the >> function at odd places. > > So, I played with this some more with this, and there seems to be some > inconsistency in how these attributes get handled. > http://sourceware.org/bugzilla/show_bug.cgi?id=13263 > > static inline int foo (int) __attribute__((always_inline,artificial)); > > static inline int foo (int x) > { > int y = x - 3; > return y; > } > > int bar (int y) > { > return y == 0; > } > > main () > { > foo (10); > return bar (foo (3)); > } > > With GCC 4.7, the stand alone call foo(10) is not ignored by 'step'. > However, the embedded call bar(foo(3)) is ignored as I was expecting. Hm, nothing is ignored for me with gcc 4.6. > > Diego. >
Sign in to reply to this message.
On Wed, Oct 5, 2011 at 8:51 PM, Diego Novillo <dnovillo@google.com> wrote: > On Wed, Oct 5, 2011 at 14:20, Mike Stump <mikestump@comcast.net> wrote: >> On Oct 5, 2011, at 6:18 AM, Diego Novillo wrote: >>> I think we need to find a solution for this situation. >> >> The solution Apple found and implemented is a __nodebug__ attribute, as can be seen in Apple's gcc. >> >> We use it like so: >> >> #define __always_inline__ __always_inline__, __nodebug__ >> #undef __always_inline__ >> >> in headers like mmintrn.h: >> >> __STATIC_INLINE void __attribute__((__always_inline__)) >> /* APPLE LOCAL end radar 5618945 */ >> _mm_empty (void) >> { >> __builtin_ia32_emms (); >> } > > Ah, nice. Though, one of the things I am liking more and more about > the blacklist solution is that it (a) does not need any modifications > to the source code, and (b) it works with no-inline functions as well. > > This gives total control to the developer. I would blacklist a bunch > of functions I never care to go into, for instance. Others may choose > to blacklist a different set. And you can change that from debug > session to the next. > > I agree with Jakub that artificial functions should be blacklisted > automatically, however. > > Richi, Jakub, if the blacklist solution was implemented in GCC would > you agree with promoting these macros into inline functions? This is > orthogonal to http://sourceware.org/bugzilla/show_bug.cgi?id=13263, of > course. I know you are on to that C++ thing and ending up returning a reference to make it an lvalue. Which I very much don't like (please, if you go that route add _set functions and lower the case of the macros). What's the other advantage of using inline functions? The gdb annoyance with the macros can be solved with the .gdbinit macro defines (which might be nice to commit to SVN btw). Richard. > > Thanks. Diego. >
Sign in to reply to this message.
On 11-10-06 04:58 , Richard Guenther wrote: > I know you are on to that C++ thing and ending up returning a reference > to make it an lvalue. Which I very much don't like (please, if you go > that route add _set functions and lower the case of the macros). Not necessarily. I'm after making the debugging experience easier (among other things). Only a handful of macros were converted into functions in this patch, not all of them. We may not *need* to convert all of them either. > What's the other advantage of using inline functions? The gdb > annoyance with the macros can be solved with the .gdbinit macro > defines (which might be nice to commit to SVN btw). Static type checking, of course. Ability to set breakpoints, and as time goes on, more inline functions will start showing up. We already have several. The blacklist feature would solve your annoyance with tree_operand_length, too. Additionally, blacklist can deal with non-inline functions, which can be useful. Diego.
Sign in to reply to this message.
On Oct 6, 2011, at 1:58 AM, Richard Guenther wrote: > On Wed, Oct 5, 2011 at 8:51 PM, Diego Novillo <dnovillo@google.com> wrote: > What's the other advantage of using inline functions? The gdb > annoyance with the macros can be solved with the .gdbinit macro > defines (which might be nice to commit to SVN btw). http://old.nabble.com/-incremental--Patch%3A-FYI%3A-add-accessor-macros-to-gd... And yet, this still isn't in gcc. :-( I wonder how much programmer productivity we've lost due to it.
Sign in to reply to this message.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 10/06/11 12:46, Mike Stump wrote: > On Oct 6, 2011, at 1:58 AM, Richard Guenther wrote: >> On Wed, Oct 5, 2011 at 8:51 PM, Diego Novillo >> <dnovillo@google.com> wrote: What's the other advantage of using >> inline functions? The gdb annoyance with the macros can be >> solved with the .gdbinit macro defines (which might be nice to >> commit to SVN btw). > > http://old.nabble.com/-incremental--Patch%3A-FYI%3A-add-accessor-macros-to-gd... > > And yet, this still isn't in gcc. :-( I wonder how much > programmer productivity we've lost due to it. Presumably it hasn't been included because not all gdb's understand those bits and we typically don't build with -g3. Personally, the accessors I use are muscle-memory... Which works great until someone buries everything a level deeper :( jeff -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJOjfkaAAoJEBRtltQi2kC7nz0H/iOeU6/iqNBfMDGUMaJbFe/R rbBFKJzAR6IOXWBJzlnA+d1qvpF5z1GsdfkqtaLImKrAFNsbv1LV58X3lc7l8yLQ TGgLVuZPc/cJ8q0fyAd1rDBGsxRrapm5cPgyMFhl9eY1pC9pejAcbqLnXxRmIs41 NyohojHLu09o+WRkjNg79TOyapFNnY8w0Hz6PuFOyYv/eYthZ5dw9+N1XyUKey/M 6GHAOqTD3iQKz9QsG5dc+SVfTPLkToOnAZ5y8TnupFay9aLRXUlXDpFHZbre9h5C ICK8FnWf74Xemw79ID94WWwomdND69myTf7bMlD4pFiHK3Wz6fPeR1GIdTixi7s= =BrUJ -----END PGP SIGNATURE-----
Sign in to reply to this message.
On Oct 6, 2011, at 11:53 AM, Jeff Law wrote: > Presumably it hasn't been included because not all gdb's understand > those bits and we typically don't build with -g3. > Personally, the accessors I use are muscle-memory... Which works > great until someone buries everything a level deeper :( Yeah, which works great for encouraging new comers that doing anything with gcc is hard. They, by definition, don't have the muscle memory, and the documentation that describes which memory their muscles should have is hard to find, or non-existant. I'd merely favor any approach to make their life easier, -g3, a gdb macro package, all inline functions, no macros...
Sign in to reply to this message.
>>>>> "Jeff" == Jeff Law <law@redhat.com> writes: Jeff> Presumably it hasn't been included because not all gdb's understand Jeff> those bits and we typically don't build with -g3. GCC is pretty much the perfect candidate for a -g3 build. All those macros... The needed gdb changes have been in since right around when I added that patch to the incremental branch. Anybody with a > 3 year old gdb should upgrade :-) Tom
Sign in to reply to this message.
On Fri, Oct 07, 2011 at 07:42:44AM -0600, Tom Tromey wrote: > >>>>> "Jeff" == Jeff Law <law@redhat.com> writes: > > Jeff> Presumably it hasn't been included because not all gdb's understand > Jeff> those bits and we typically don't build with -g3. > > GCC is pretty much the perfect candidate for a -g3 build. All those > macros... > > The needed gdb changes have been in since right around when I added that > patch to the incremental branch. Anybody with a > 3 year old gdb should > upgrade :-) A > 3 years old gdb is useless for debugging gcc anyway, it won't understand epilogue unwind info, discriminators, lots of .debug_info stuff added in the last few years and not even the .debug_macro format. Jakub
Sign in to reply to this message.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 10/07/11 07:42, Tom Tromey wrote: >>>>>> "Jeff" == Jeff Law <law@redhat.com> writes: > > Jeff> Presumably it hasn't been included because not all gdb's > understand Jeff> those bits and we typically don't build with -g3. > > GCC is pretty much the perfect candidate for a -g3 build. All > those macros... > > The needed gdb changes have been in since right around when I added > that patch to the incremental branch. Anybody with a > 3 year old > gdb should upgrade :-) Hard to argue with that :-) Gone are the days when I'd build a binary tool of some sort and use it for many years thereafter. I doubt there's any binary on my boxes older than a year... jeff -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJOjx63AAoJEBRtltQi2kC7fXoH/13uE6l2klTOFPrAKbTszo5s 0fxtmLD9NQWyeOFuGL4P9O9J6rChdulFvY9oNlWUrJIwF7WTOp4FjqNZnhvzoIT8 zEqoT8yVO7pNS7KMyRbxJxz5iEx8pX0YW2O2Rl/qZGy/hFKatqaOgz/RuBZy4lg2 NpiKWULKRsc66FxPKhCPMqtSd338XOhC0S67D2GuK1qD93SFDEyoQbaViieMlmoo qr5oFn1052byWd3J1cPbu5vv76YLnzPEmBybm0k/ZaoGFC/JidDghQvR9uHtBbbl LLsFIej62rzCLWZTfbgaiAfKZv79msjhZIrhv8T9iSAolUG4KDvLCvP8SbUg6XI= =KKKR -----END PGP SIGNATURE-----
Sign in to reply to this message.
|