📄 tree.c
字号:
tree name2 = TYPE_NAME (type2); if (TREE_CODE (name1) == TYPE_DECL) name1 = DECL_NAME (name1); if (TREE_CODE (name2) == TYPE_DECL) name2 = DECL_NAME (name2); (*pfn) (s, IDENTIFIER_POINTER (name1), IDENTIFIER_POINTER (name2));}#define PRINT_RING_SIZE 4char *lang_printable_name (decl) tree decl;{ static tree decl_ring[PRINT_RING_SIZE]; static char *print_ring[PRINT_RING_SIZE]; static int ring_counter; int i; /* Only cache functions. */ if (TREE_CODE (decl) != FUNCTION_DECL || DECL_LANG_SPECIFIC (decl) == 0) return decl_as_string (decl, 1); /* See if this print name is lying around. */ for (i = 0; i < PRINT_RING_SIZE; i++) if (decl_ring[i] == decl) /* yes, so return it. */ return print_ring[i]; if (++ring_counter == PRINT_RING_SIZE) ring_counter = 0; if (current_function_decl != NULL_TREE) { if (decl_ring[ring_counter] == current_function_decl) ring_counter += 1; if (ring_counter == PRINT_RING_SIZE) ring_counter = 0; if (decl_ring[ring_counter] == current_function_decl) my_friendly_abort (106); } if (print_ring[ring_counter]) free (print_ring[ring_counter]); { int print_ret_type_p = (!DECL_CONSTRUCTOR_P (decl) && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl))); char *name = (char *)decl_as_string (decl, print_ret_type_p); print_ring[ring_counter] = (char *)malloc (strlen (name) + 1); strcpy (print_ring[ring_counter], name); decl_ring[ring_counter] = decl; } return print_ring[ring_counter];}/* Comparison function for sorting identifiers in RAISES lists. Note that because IDENTIFIER_NODEs are unique, we can sort them by address, saving an indirection. */static intid_cmp (p1, p2) tree *p1, *p2;{ return (HOST_WIDE_INT)TREE_VALUE (*p1) - (HOST_WIDE_INT)TREE_VALUE (*p2);}/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions listed in RAISES. */treebuild_exception_variant (type, raises) tree type; tree raises;{ int i; tree v = TYPE_MAIN_VARIANT (type); tree t, t2, cname; tree *a = (tree *)alloca ((list_length (raises)+1) * sizeof (tree)); int constp = TYPE_READONLY (type); int volatilep = TYPE_VOLATILE (type); for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v)) { if (TYPE_READONLY (v) != constp || TYPE_VOLATILE (v) != volatilep) continue; /* @@ This should do set equality, not exact match. */ if (simple_cst_list_equal (TYPE_RAISES_EXCEPTIONS (v), raises)) /* List of exceptions raised matches previously found list. @@ Nice to free up storage used in consing up the @@ list of exceptions raised. */ return v; } /* Need to build a new variant. */ v = copy_node (type); TYPE_NEXT_VARIANT (v) = TYPE_NEXT_VARIANT (type); TYPE_NEXT_VARIANT (type) = v; if (raises && ! TREE_PERMANENT (raises)) { push_obstacks_nochange (); end_temporary_allocation (); raises = copy_list (raises); pop_obstacks (); } TYPE_RAISES_EXCEPTIONS (v) = raises; return v;}/* Subroutine of copy_to_permanent Assuming T is a node build bottom-up, make it all exist on permanent obstack, if it is not permanent already. */treemapcar (t, func) tree t; tree (*func)();{ enum tree_code code; tree tmp; if (t == NULL_TREE) return t; if (tmp = func (t), tmp != NULL_TREE) return tmp; switch (code = TREE_CODE (t)) { case ERROR_MARK: return error_mark_node; case VAR_DECL: case FUNCTION_DECL: case CONST_DECL: break; case PARM_DECL: { tree chain = TREE_CHAIN (t); t = copy_node (t); TREE_CHAIN (t) = mapcar (chain, func); TREE_TYPE (t) = mapcar (TREE_TYPE (t), func); DECL_INITIAL (t) = mapcar (DECL_INITIAL (t), func); DECL_SIZE (t) = mapcar (DECL_SIZE (t), func); return t; } case TREE_LIST: { tree chain = TREE_CHAIN (t); t = copy_node (t); TREE_PURPOSE (t) = mapcar (TREE_PURPOSE (t), func); TREE_VALUE (t) = mapcar (TREE_VALUE (t), func); TREE_CHAIN (t) = mapcar (chain, func); return t; } case TREE_VEC: { int len = TREE_VEC_LENGTH (t); t = copy_node (t); while (len--) TREE_VEC_ELT (t, len) = mapcar (TREE_VEC_ELT (t, len), func); return t; } case INTEGER_CST: case REAL_CST: case STRING_CST: return copy_node (t); case COND_EXPR: case TARGET_EXPR: case NEW_EXPR: t = copy_node (t); TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func); return t; case SAVE_EXPR: t = copy_node (t); TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); return t; case MODIFY_EXPR: case PLUS_EXPR: case MINUS_EXPR: case MULT_EXPR: case TRUNC_DIV_EXPR: case TRUNC_MOD_EXPR: case MIN_EXPR: case MAX_EXPR: case LSHIFT_EXPR: case RSHIFT_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: case BIT_AND_EXPR: case BIT_ANDTC_EXPR: case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: case LT_EXPR: case LE_EXPR: case GT_EXPR: case GE_EXPR: case EQ_EXPR: case NE_EXPR: case CEIL_DIV_EXPR: case FLOOR_DIV_EXPR: case ROUND_DIV_EXPR: case CEIL_MOD_EXPR: case FLOOR_MOD_EXPR: case ROUND_MOD_EXPR: case COMPOUND_EXPR: case PREDECREMENT_EXPR: case PREINCREMENT_EXPR: case POSTDECREMENT_EXPR: case POSTINCREMENT_EXPR: case CALL_EXPR: t = copy_node (t); TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); return t; case CONVERT_EXPR: case ADDR_EXPR: case INDIRECT_REF: case NEGATE_EXPR: case BIT_NOT_EXPR: case TRUTH_NOT_EXPR: case NOP_EXPR: case COMPONENT_REF: t = copy_node (t); TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); return t; case POINTER_TYPE: return build_pointer_type (mapcar (TREE_TYPE (t), func)); case REFERENCE_TYPE: return build_reference_type (mapcar (TREE_TYPE (t), func)); case FUNCTION_TYPE: return build_function_type (mapcar (TREE_TYPE (t), func), mapcar (TYPE_ARG_TYPES (t), func)); case ARRAY_TYPE: return build_array_type (mapcar (TREE_TYPE (t), func), mapcar (TYPE_DOMAIN (t), func)); case INTEGER_TYPE: return build_index_type (mapcar (TYPE_MAX_VALUE (t), func)); case OFFSET_TYPE: return build_offset_type (mapcar (TYPE_OFFSET_BASETYPE (t), func), mapcar (TREE_TYPE (t), func)); case METHOD_TYPE: return build_method_type (mapcar (TYPE_METHOD_BASETYPE (t), func), build_function_type (mapcar (TREE_TYPE (t), func), mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func))); case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (t)) return build_ptrmemfunc_type (mapcar (TYPE_PTRMEMFUNC_FN_TYPE (t), func)); /* else fall through */ /* This list is incomplete, but should suffice for now. It is very important that `sorry' does not call `report_error_function'. That could cause an infinite loop. */ default: sorry ("initializer contains unrecognized tree code"); return error_mark_node; } my_friendly_abort (107); /* NOTREACHED */ return NULL_TREE;}static treeperm_manip (t) tree t;{ if (TREE_PERMANENT (t)) return t; return NULL_TREE;}/* Assuming T is a node built bottom-up, make it all exist on permanent obstack, if it is not permanent already. */treecopy_to_permanent (t) tree t;{ register struct obstack *ambient_obstack = current_obstack; register struct obstack *ambient_saveable_obstack = saveable_obstack; int resume; if (t == NULL_TREE || TREE_PERMANENT (t)) return t; saveable_obstack = &permanent_obstack; current_obstack = saveable_obstack; resume = suspend_momentary (); t = mapcar (t, perm_manip); resume_momentary (resume); current_obstack = ambient_obstack; saveable_obstack = ambient_saveable_obstack; return t;}voidprint_lang_statistics (){ extern struct obstack maybepermanent_obstack; print_obstack_statistics ("class_obstack", &class_obstack); print_obstack_statistics ("permanent_obstack", &permanent_obstack); print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack); print_search_statistics (); print_class_statistics ();}/* This is used by the `assert' macro. It is provided in libgcc.a, which `cc' doesn't know how to link. Note that the C++ front-end no longer actually uses the `assert' macro (instead, it calls my_friendly_assert). But all of the back-end files still need this. */void__eprintf (string, expression, line, filename)#ifdef __STDC__ const char *string; const char *expression; unsigned line; const char *filename;#else char *string; char *expression; unsigned line; char *filename;#endif{ fprintf (stderr, string, expression, line, filename); fflush (stderr); abort ();}/* Return, as an INTEGER_CST node, the number of elements for TYPE (which is an ARRAY_TYPE). This counts only elements of the top array. */treearray_type_nelts_top (type) tree type;{ return fold (build (PLUS_EXPR, sizetype, array_type_nelts (type), integer_one_node));}/* Return, as an INTEGER_CST node, the number of elements for TYPE (which is an ARRAY_TYPE). This one is a recursive count of all ARRAY_TYPEs that are clumped together. */treearray_type_nelts_total (type) tree type;{ tree sz = array_type_nelts_top (type); type = TREE_TYPE (type); while (TREE_CODE (type) == ARRAY_TYPE) { tree n = array_type_nelts_top (type); sz = fold (build (MULT_EXPR, sizetype, sz, n)); type = TREE_TYPE (type); } return sz;}statictreebot_manip (t) tree t;{ if (TREE_CODE (t) != TREE_LIST && ! TREE_SIDE_EFFECTS (t)) return t; else if (TREE_CODE (t) == TARGET_EXPR) return build_cplus_new (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)), 0); return NULL_TREE;} /* Actually, we'll just clean out the target exprs for the moment. */treebreak_out_target_exprs (t) tree t;{ return mapcar (t, bot_manip);}treeunsave_expr (expr) tree expr;{ tree t; t = build1 (UNSAVE_EXPR, TREE_TYPE (expr), expr); TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr); return t;}/* Modify a tree in place so that all the evaluate only once things are cleared out. Return the EXPR given. */treeunsave_expr_now (expr) tree expr;{ enum tree_code code; register int i; if (expr == NULL_TREE) return expr; code = TREE_CODE (expr); switch (code) { case SAVE_EXPR: SAVE_EXPR_RTL (expr) = NULL_RTX; break; case TARGET_EXPR: sorry ("TARGET_EXPR reused inside UNSAVE_EXPR"); break; case RTL_EXPR: warning ("RTL_EXPR reused inside UNSAVE_EXPR"); RTL_EXPR_SEQUENCE (expr) = NULL_RTX; break; case CALL_EXPR: CALL_EXPR_RTL (expr) = NULL_RTX; if (TREE_OPERAND (expr, 1) && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST) { tree exp = TREE_OPERAND (expr, 1); while (exp) { unsave_expr_now (TREE_VALUE (exp)); exp = TREE_CHAIN (exp); } } break; case WITH_CLEANUP_EXPR: warning ("WITH_CLEANUP_EXPR reused inside UNSAVE_EXPR"); RTL_EXPR_RTL (expr) = NULL_RTX; break; } switch (TREE_CODE_CLASS (code)) { case 'c': /* a constant */ case 't': /* a type node */ case 'x': /* something random, like an identifier or an ERROR_MARK. */ case 'd': /* A decl node */ case 'b': /* A block node */ return expr; case 'e': /* an expression */ case 'r': /* a reference */ case 's': /* an expression with side effects */ case '<': /* a comparison expression */ case '2': /* a binary arithmetic expression */ case '1': /* a unary arithmetic expression */ for (i = tree_code_length[(int) code] - 1; i >= 0; i--) unsave_expr_now (TREE_OPERAND (expr, i)); return expr; default: my_friendly_abort (999); }}/* Since cleanup may have SAVE_EXPRs in it, we protect it with an UNSAVE_EXPR as the backend cannot yet handle SAVE_EXPRs in cleanups by itself. */intcp_expand_decl_cleanup (decl, cleanup) tree decl, cleanup;{ return expand_decl_cleanup (decl, unsave_expr (cleanup));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -