"binary",
"statement",
"vl_exp",
- "expression",
- "gimple_stmt"
+ "expression"
};
/* obstack.[ch] explicitly declined to prototype this. */
"temp_tree_lists",
"vecs",
"binfos",
- "phi_nodes",
"ssa names",
"constructors",
"random kinds",
"lang_decl kinds",
"lang_type kinds",
"omp clauses",
- "gimple statements"
};
#endif /* GATHER_STATISTICS */
tree_contains_struct[CONST_DECL][TS_CONST_DECL] = 1;
tree_contains_struct[TYPE_DECL][TS_TYPE_DECL] = 1;
tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL] = 1;
+ tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL] = 1;
+ tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON] = 1;
lang_hooks.init_ts ();
}
/* Compute the number of bytes occupied by a tree with code CODE.
This function cannot be used for nodes that have variable sizes,
- including TREE_VEC, PHI_NODE, STRING_CST, and CALL_EXPR. */
+ including TREE_VEC, STRING_CST, and CALL_EXPR. */
size_t
tree_code_size (enum tree_code code)
{
return (sizeof (struct tree_exp)
+ (TREE_CODE_LENGTH (code) - 1) * sizeof (tree));
- case tcc_gimple_stmt:
- return (sizeof (struct gimple_stmt)
- + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *));
-
case tcc_constant: /* a constant */
switch (code)
{
case PLACEHOLDER_EXPR: return sizeof (struct tree_common);
case TREE_VEC:
- case OMP_CLAUSE:
- case PHI_NODE: gcc_unreachable ();
+ case OMP_CLAUSE: gcc_unreachable ();
case SSA_NAME: return sizeof (struct tree_ssa_name);
const enum tree_code code = TREE_CODE (node);
switch (code)
{
- case PHI_NODE:
- return (sizeof (struct tree_phi_node)
- + (PHI_ARG_CAPACITY (node) - 1) * sizeof (struct phi_arg_d));
-
case TREE_BINFO:
return (offsetof (struct tree_binfo, base_binfos)
+ VEC_embedded_size (tree, BINFO_N_BASE_BINFOS (node)));
/* Return a newly allocated node of code CODE. For decl and type
nodes, some other fields are initialized. The rest of the node is
- initialized to zero. This function cannot be used for PHI_NODE,
- TREE_VEC or OMP_CLAUSE nodes, which is enforced by asserts in
- tree_code_size.
+ initialized to zero. This function cannot be used for TREE_VEC or
+ OMP_CLAUSE nodes, which is enforced by asserts in tree_code_size.
Achoo! I got a code in the node. */
kind = c_kind;
break;
- case tcc_gimple_stmt:
- kind = gimple_stmt_kind;
- break;
-
case tcc_exceptional: /* something random, like an identifier. */
switch (code)
{
kind = binfo_kind;
break;
- case PHI_NODE:
- kind = phi_kind;
- break;
-
case SSA_NAME:
kind = ssa_name_kind;
break;
}
break;
- case tcc_gimple_stmt:
- switch (code)
- {
- case GIMPLE_MODIFY_STMT:
- TREE_SIDE_EFFECTS (t) = 1;
- break;
-
- default:
- break;
- }
-
default:
/* Other classes need no special treatment. */
break;
t = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone);
memcpy (t, node, length);
- if (!GIMPLE_TUPLE_P (node))
- TREE_CHAIN (t) = 0;
+ TREE_CHAIN (t) = 0;
TREE_ASM_WRITTEN (t) = 0;
TREE_VISITED (t) = 0;
t->base.ann = 0;
align1 = TYPE_ALIGN (TREE_TYPE (t));
return MAX (align0, align1);
- case GIMPLE_MODIFY_STMT:
- /* We should never ask for the alignment of a gimple statement. */
- gcc_unreachable ();
-
case SAVE_EXPR: case COMPOUND_EXPR: case MODIFY_EXPR:
case INIT_EXPR: case TARGET_EXPR: case WITH_CLEANUP_EXPR:
case CLEANUP_POINT_EXPR:
return false;
}
+/* Return whether OP is a DECL whose address is interprocedural-invariant. */
+
+bool
+decl_address_ip_invariant_p (const_tree op)
+{
+ /* The conditions below are slightly less strict than the one in
+ staticp. */
+
+ switch (TREE_CODE (op))
+ {
+ case LABEL_DECL:
+ case FUNCTION_DECL:
+ case STRING_CST:
+ return true;
+
+ case VAR_DECL:
+ if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
+ && !DECL_DLLIMPORT_P (op))
+ || DECL_THREAD_LOCAL_P (op))
+ return true;
+ break;
+
+ case CONST_DECL:
+ if ((TREE_STATIC (op) || DECL_EXTERNAL (op)))
+ return true;
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
/* Return true if T is function-invariant (internal function, does
not handle arithmetic; that's handled in skip_simple_arithmetic and
case tcc_statement:
case tcc_vl_exp:
return TS_EXP;
- case tcc_gimple_stmt:
- return TS_GIMPLE_STATEMENT;
default: /* tcc_constant and tcc_exceptional */
break;
}
case VECTOR_CST: return TS_VECTOR;
case STRING_CST: return TS_STRING;
/* tcc_exceptional cases. */
- /* FIXME tuples: eventually this should be TS_BASE. For now, nothing
- returns TS_BASE. */
case ERROR_MARK: return TS_COMMON;
case IDENTIFIER_NODE: return TS_IDENTIFIER;
case TREE_LIST: return TS_LIST;
case TREE_VEC: return TS_VEC;
- case PHI_NODE: return TS_PHI_NODE;
case SSA_NAME: return TS_SSA_NAME;
case PLACEHOLDER_EXPR: return TS_COMMON;
case STATEMENT_LIST: return TS_STATEMENT_LIST;
|| CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1))
|| CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2)));
+ case SAVE_EXPR:
+ /* The save_expr function never wraps anything containing
+ a PLACEHOLDER_EXPR. */
+ return 0;
+
default:
break;
}
{
enum tree_code code = TREE_CODE (exp);
tree op0, op1, op2, op3;
- tree new, inner;
+ tree new_tree, inner;
/* We handle TREE_LIST and COMPONENT_REF separately. */
if (code == TREE_LIST)
if (op0 == TREE_OPERAND (exp, 0))
return exp;
- new = fold_build3 (COMPONENT_REF, TREE_TYPE (exp),
+ new_tree = fold_build3 (COMPONENT_REF, TREE_TYPE (exp),
op0, TREE_OPERAND (exp, 1), NULL_TREE);
}
else
if (op0 == TREE_OPERAND (exp, 0))
return exp;
- new = fold_build1 (code, TREE_TYPE (exp), op0);
+ new_tree = fold_build1 (code, TREE_TYPE (exp), op0);
break;
case 2:
if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
return exp;
- new = fold_build2 (code, TREE_TYPE (exp), op0, op1);
+ new_tree = fold_build2 (code, TREE_TYPE (exp), op0, op1);
break;
case 3:
&& op2 == TREE_OPERAND (exp, 2))
return exp;
- new = fold_build3 (code, TREE_TYPE (exp), op0, op1, op2);
+ new_tree = fold_build3 (code, TREE_TYPE (exp), op0, op1, op2);
break;
case 4:
&& op3 == TREE_OPERAND (exp, 3))
return exp;
- new = fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3));
+ new_tree = fold (build4 (code, TREE_TYPE (exp), op0, op1, op2, op3));
break;
default:
}
if (copy)
- new = fold (copy);
+ new_tree = fold (copy);
else
return exp;
}
gcc_unreachable ();
}
- TREE_READONLY (new) = TREE_READONLY (exp);
- return new;
+ TREE_READONLY (new_tree) = TREE_READONLY (exp);
+ return new_tree;
}
/* Similar, but look for a PLACEHOLDER_EXPR in EXP and find a replacement
gcc_assert (TREE_CODE_LENGTH (code) == 2);
-#if 1
- /* FIXME tuples: Statement's aren't expressions! */
- if (code == GIMPLE_MODIFY_STMT)
- return build_gimple_modify_stmt_stat (arg0, arg1 PASS_MEM_STAT);
-#else
- /* Must use build_gimple_modify_stmt to construct GIMPLE_MODIFY_STMTs. */
- gcc_assert (code != GIMPLE_MODIFY_STMT);
-#endif
-
if ((code == MINUS_EXPR || code == PLUS_EXPR || code == MULT_EXPR)
&& arg0 && arg1 && tt && POINTER_TYPE_P (tt))
gcc_assert (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST);
}
-/* Build a GIMPLE_MODIFY_STMT node. This tree code doesn't have a
- type, so we can't use build2 (a.k.a. build2_stat). */
-
-tree
-build_gimple_modify_stmt_stat (tree arg0, tree arg1 MEM_STAT_DECL)
-{
- tree t;
-
- t = make_node_stat (GIMPLE_MODIFY_STMT PASS_MEM_STAT);
- /* ?? We don't care about setting flags for tuples... */
- GIMPLE_STMT_OPERAND (t, 0) = arg0;
- GIMPLE_STMT_OPERAND (t, 1) = arg1;
- return t;
-}
-
tree
build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
tree arg2 MEM_STAT_DECL)
/* Source location accessor functions. */
-/* The source location of this expression. Non-tree_exp nodes such as
- decls and constants can be shared among multiple locations, so
- return nothing. */
-location_t
-expr_location (const_tree node)
-{
- if (GIMPLE_STMT_P (node))
- return GIMPLE_STMT_LOCUS (node);
- return EXPR_P (node) ? node->exp.locus : UNKNOWN_LOCATION;
-}
-
-void
-set_expr_location (tree node, location_t locus)
-{
- if (GIMPLE_STMT_P (node))
- GIMPLE_STMT_LOCUS (node) = locus;
- else
- EXPR_CHECK (node)->exp.locus = locus;
-}
-
-bool
-expr_has_location (const_tree node)
-{
- return expr_location (node) != UNKNOWN_LOCATION;
-}
-
-source_location *
-expr_locus (const_tree node)
-{
- if (GIMPLE_STMT_P (node))
- return CONST_CAST (source_location *, &GIMPLE_STMT_LOCUS (node));
- return (EXPR_P (node)
- ? CONST_CAST (source_location *, &node->exp.locus)
- : (source_location *) NULL);
-}
-
void
set_expr_locus (tree node, source_location *loc)
{
if (loc == NULL)
- {
- if (GIMPLE_STMT_P (node))
- GIMPLE_STMT_LOCUS (node) = UNKNOWN_LOCATION;
- else
- EXPR_CHECK (node)->exp.locus = UNKNOWN_LOCATION;
- }
+ EXPR_CHECK (node)->exp.locus = UNKNOWN_LOCATION;
else
- {
- if (GIMPLE_STMT_P (node))
- GIMPLE_STMT_LOCUS (node) = *loc;
- else
- EXPR_CHECK (node)->exp.locus = *loc;
- }
+ EXPR_CHECK (node)->exp.locus = *loc;
}
-/* Return the file name of the location of NODE. */
-const char *
-expr_filename (const_tree node)
-{
- if (GIMPLE_STMT_P (node))
- return LOCATION_FILE (GIMPLE_STMT_LOCUS (node));
- return LOCATION_FILE (EXPR_CHECK (node)->exp.locus);
-}
+/* Like SET_EXPR_LOCATION, but make sure the tree can have a location.
-/* Return the line number of the location of NODE. */
-int
-expr_lineno (const_tree node)
+ LOC is the location to use in tree T. */
+
+void protected_set_expr_location (tree t, location_t loc)
{
- if (GIMPLE_STMT_P (node))
- return LOCATION_LINE (GIMPLE_STMT_LOCUS (node));
- return LOCATION_LINE (EXPR_CHECK (node)->exp.locus);
+ if (t && CAN_HAVE_LOCATION_P (t))
+ SET_EXPR_LOCATION (t, loc);
}
-
\f
/* Return a declaration like DDECL except that its DECL_ATTRIBUTES
is ATTRIBUTE. */
The second instance of `foo' nullifies the dllimport. */
tree
-merge_dllimport_decl_attributes (tree old, tree new)
+merge_dllimport_decl_attributes (tree old, tree new_tree)
{
tree a;
int delete_dllimport_p = 1;
is not dllimport'd. We also remove a `new' dllimport if the old list
contains dllexport: dllexport always overrides dllimport, regardless
of the order of declaration. */
- if (!VAR_OR_FUNCTION_DECL_P (new))
+ if (!VAR_OR_FUNCTION_DECL_P (new_tree))
delete_dllimport_p = 0;
- else if (DECL_DLLIMPORT_P (new)
+ else if (DECL_DLLIMPORT_P (new_tree)
&& lookup_attribute ("dllexport", DECL_ATTRIBUTES (old)))
{
- DECL_DLLIMPORT_P (new) = 0;
+ DECL_DLLIMPORT_P (new_tree) = 0;
warning (OPT_Wattributes, "%q+D already declared with dllexport attribute: "
- "dllimport ignored", new);
+ "dllimport ignored", new_tree);
}
- else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new))
+ else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new_tree))
{
/* Warn about overriding a symbol that has already been used, e.g.:
extern int __attribute__ ((dllimport)) foo;
if (TREE_USED (old))
{
warning (0, "%q+D redeclared without dllimport attribute "
- "after being referenced with dll linkage", new);
+ "after being referenced with dll linkage", new_tree);
/* If we have used a variable's address with dllimport linkage,
keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the
decl may already have had TREE_CONSTANT computed.
We still remove the attribute so that assembler code refers
to '&foo rather than '_imp__foo'. */
if (TREE_CODE (old) == VAR_DECL && TREE_ADDRESSABLE (old))
- DECL_DLLIMPORT_P (new) = 1;
+ DECL_DLLIMPORT_P (new_tree) = 1;
}
/* Let an inline definition silently override the external reference,
but otherwise warn about attribute inconsistency. */
- else if (TREE_CODE (new) == VAR_DECL
- || !DECL_DECLARED_INLINE_P (new))
+ else if (TREE_CODE (new_tree) == VAR_DECL
+ || !DECL_DECLARED_INLINE_P (new_tree))
warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: "
- "previous dllimport ignored", new);
+ "previous dllimport ignored", new_tree);
}
else
delete_dllimport_p = 0;
- a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new));
+ a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new_tree));
if (delete_dllimport_p)
{
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
- if (code1 == NOP_EXPR || code1 == CONVERT_EXPR || code1 == NON_LVALUE_EXPR)
+ if (CONVERT_EXPR_CODE_P (code1) || code1 == NON_LVALUE_EXPR)
{
- if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
+ if (CONVERT_EXPR_CODE_P (code2)
|| code2 == NON_LVALUE_EXPR)
return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
else
return simple_cst_equal (TREE_OPERAND (t1, 0), t2);
}
- else if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
+ else if (CONVERT_EXPR_CODE_P (code2)
|| code2 == NON_LVALUE_EXPR)
return simple_cst_equal (t1, TREE_OPERAND (t2, 0));
}
/* Generate a hash value for an expression. This can be used iteratively
- by passing a previous result as the "val" argument.
+ by passing a previous result as the VAL argument.
This function is intended to produce the same hash for expressions which
would compare equal using operand_equal_p. */
{
int i;
enum tree_code code;
- char class;
+ char tclass;
if (t == NULL_TREE)
return iterative_hash_pointer (t, val);
}
/* else FALL THROUGH */
default:
- class = TREE_CODE_CLASS (code);
+ tclass = TREE_CODE_CLASS (code);
- if (class == tcc_declaration)
+ if (tclass == tcc_declaration)
{
/* DECL's have a unique ID */
val = iterative_hash_host_wide_int (DECL_UID (t), val);
}
else
{
- gcc_assert (IS_EXPR_CODE_CLASS (class));
+ gcc_assert (IS_EXPR_CODE_CLASS (tclass));
val = iterative_hash_object (code, val);
/* Don't hash the type, that can lead to having nodes which
compare equal according to operand_equal_p, but which
have different hash codes. */
- if (code == NOP_EXPR
- || code == CONVERT_EXPR
+ if (CONVERT_EXPR_CODE_P (code)
|| code == NON_LVALUE_EXPR)
{
/* Make sure to include signness in the hash computation. */
break;
}
}
+
+/* Generate a hash value for a pair of expressions. This can be used
+ iteratively by passing a previous result as the VAL argument.
+
+ The same hash value is always returned for a given pair of expressions,
+ regardless of the order in which they are presented. This is useful in
+ hashing the operands of commutative functions. */
+
+hashval_t
+iterative_hash_exprs_commutative (const_tree t1,
+ const_tree t2, hashval_t val)
+{
+ hashval_t one = iterative_hash_expr (t1, 0);
+ hashval_t two = iterative_hash_expr (t2, 0);
+ hashval_t t;
+
+ if (one > two)
+ t = one, one = two, two = t;
+ val = iterative_hash_hashval_t (one, val);
+ val = iterative_hash_hashval_t (two, val);
+
+ return val;
+}
\f
/* Constructors for pointer, array and function types.
(RECORD_TYPE, UNION_TYPE and ENUMERAL_TYPE nodes are
return t;
}
+/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP. */
+
+tree
+build_function_type_skip_args (tree orig_type, bitmap args_to_skip)
+{
+ tree new_type = NULL;
+ tree args, new_args = NULL, t;
+ tree new_reversed;
+ int i = 0;
+
+ for (args = TYPE_ARG_TYPES (orig_type); args && args != void_list_node;
+ args = TREE_CHAIN (args), i++)
+ if (!bitmap_bit_p (args_to_skip, i))
+ new_args = tree_cons (NULL_TREE, TREE_VALUE (args), new_args);
+
+ new_reversed = nreverse (new_args);
+ if (args)
+ {
+ if (new_reversed)
+ TREE_CHAIN (new_args) = void_list_node;
+ else
+ new_reversed = void_list_node;
+ }
+ gcc_assert (new_reversed);
+
+ /* Use copy_node to preserve as much as possible from original type
+ (debug info, attribute lists etc.)
+ Exception is METHOD_TYPEs must have THIS argument.
+ When we are asked to remove it, we need to build new FUNCTION_TYPE
+ instead. */
+ if (TREE_CODE (orig_type) != METHOD_TYPE
+ || !bitmap_bit_p (args_to_skip, 0))
+ {
+ new_type = copy_node (orig_type);
+ TYPE_ARG_TYPES (new_type) = new_reversed;
+ }
+ else
+ {
+ new_type
+ = build_distinct_type_copy (build_function_type (TREE_TYPE (orig_type),
+ new_reversed));
+ TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type);
+ }
+
+ /* This is a new type, not a copy of an old type. Need to reassociate
+ variants. We can handle everything except the main variant lazily. */
+ t = TYPE_MAIN_VARIANT (orig_type);
+ if (orig_type != t)
+ {
+ TYPE_MAIN_VARIANT (new_type) = t;
+ TYPE_NEXT_VARIANT (new_type) = TYPE_NEXT_VARIANT (t);
+ TYPE_NEXT_VARIANT (t) = new_type;
+ }
+ else
+ {
+ TYPE_MAIN_VARIANT (new_type) = new_type;
+ TYPE_NEXT_VARIANT (new_type) = NULL;
+ }
+ return new_type;
+}
+
+/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP.
+
+ Arguments from DECL_ARGUMENTS list can't be removed now, since they are
+ linked by TREE_CHAIN directly. It is caller responsibility to eliminate
+ them when they are being duplicated (i.e. copy_arguments_for_versioning). */
+
+tree
+build_function_decl_skip_args (tree orig_decl, bitmap args_to_skip)
+{
+ tree new_decl = copy_node (orig_decl);
+ tree new_type;
+
+ new_type = TREE_TYPE (orig_decl);
+ if (prototype_p (new_type))
+ new_type = build_function_type_skip_args (new_type, args_to_skip);
+ TREE_TYPE (new_decl) = new_type;
+
+ /* For declarations setting DECL_VINDEX (i.e. methods)
+ we expect first argument to be THIS pointer. */
+ if (bitmap_bit_p (args_to_skip, 0))
+ DECL_VINDEX (new_decl) = NULL_TREE;
+ return new_decl;
+}
+
/* Build a function type. The RETURN_TYPE is the type returned by the
function. If VAARGS is set, no void_type_node is appended to the
the list. ARGP muse be alway be terminated be a NULL_TREE. */
if (vaargs)
{
- last = args;
- if (args != NULL_TREE)
- args = nreverse (args);
+ last = args;
+ if (args != NULL_TREE)
+ args = nreverse (args);
gcc_assert (args != NULL_TREE && last != void_list_node);
}
else if (args == NULL_TREE)
for "unknown if constant fits", 0 for "constant known *not* to fit" and 1
for "constant known to fit". */
+ if (TREE_TYPE (c) == sizetype
+ && TYPE_UNSIGNED (TREE_TYPE (c))
+ && TREE_INT_CST_HIGH (c) == -1
+ && !TREE_OVERFLOW (c))
+ /* So c is an unsigned integer which type is sizetype.
+ sizetype'd integers are sign extended even though they are
+ unsigned. If the integer value fits in the lower end word of c,
+ and if the higher end word has all its bits set to 1, that
+ means the higher end bits are set to 1 only for sign extension.
+ So let's convert c into an equivalent zero extended unsigned
+ integer. */
+ c = force_fit_type_double (size_type_node,
+ TREE_INT_CST_LOW (c),
+ TREE_INT_CST_HIGH (c),
+ false, false);
/* Check if C >= type_low_bound. */
if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST)
{
}
}
-/* auto_var_in_fn_p is called to determine whether VAR is an automatic
- variable defined in function FN. */
+/* Return true if VAR is an automatic variable defined in function FN. */
bool
auto_var_in_fn_p (const_tree var, const_tree fn)
&& TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL)
return TREE_OPERAND (addr, 0);
- /* We couldn't figure out what was being called. Maybe the front
- end has some idea. */
- return lang_hooks.lang_get_callee_fndecl (call);
+ /* We couldn't figure out what was being called. */
+ return NULL_TREE;
}
/* Print debugging information about tree nodes generated during the compile,
idx + 1, len, function, trim_filename (file), line);
}
-/* Similar to above, except that the check is for the bounds of a PHI_NODE's
- (dynamically sized) vector. */
-
-void
-phi_node_elt_check_failed (int idx, int len, const char *file, int line,
- const char *function)
-{
- internal_error
- ("tree check: accessed elt %d of phi_node with %d elts in %s, at %s:%d",
- idx + 1, len, function, trim_filename (file), line);
-}
-
/* Similar to above, except that the check is for the bounds of the operand
vector of an expression node EXP. */
WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len));
}
+ case CHANGE_DYNAMIC_TYPE_EXPR:
+ WALK_SUBTREE (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*tp));
+ WALK_SUBTREE_TAIL (CHANGE_DYNAMIC_TYPE_LOCATION (*tp));
+
case DECL_EXPR:
/* If this is a TYPE_DECL, walk into the fields of the type that it's
defining. We only want to walk into these fields of a type in this
/* FALLTHRU */
default:
- if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
- || IS_GIMPLE_STMT_CODE_CLASS (TREE_CODE_CLASS (code)))
+ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
{
int i, len;
if (len)
{
for (i = 0; i < len - 1; ++i)
- WALK_SUBTREE (GENERIC_TREE_OPERAND (*tp, i));
- WALK_SUBTREE_TAIL (GENERIC_TREE_OPERAND (*tp, len - 1));
+ WALK_SUBTREE (TREE_OPERAND (*tp, i));
+ WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1));
}
}
/* If this is a type, walk the needed fields in the type. */
}
-/* Return true if STMT is an empty statement or contains nothing but
- empty statements. */
-
-bool
-empty_body_p (tree stmt)
-{
- tree_stmt_iterator i;
- tree body;
-
- if (IS_EMPTY_STMT (stmt))
- return true;
- else if (TREE_CODE (stmt) == BIND_EXPR)
- body = BIND_EXPR_BODY (stmt);
- else if (TREE_CODE (stmt) == STATEMENT_LIST)
- body = stmt;
- else
- return false;
-
- for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i))
- if (!empty_body_p (tsi_stmt (i)))
- return false;
-
- return true;
-}
-
tree *
tree_block (tree t)
{
if (IS_EXPR_CODE_CLASS (c))
return &t->exp.block;
- else if (IS_GIMPLE_STMT_CODE_CLASS (c))
- return &GIMPLE_STMT_BLOCK (t);
gcc_unreachable ();
return NULL;
}
-tree *
-generic_tree_operand (tree node, int i)
-{
- if (GIMPLE_STMT_P (node))
- return &GIMPLE_STMT_OPERAND (node, i);
- return &TREE_OPERAND (node, i);
-}
-
-tree *
-generic_tree_type (tree node)
-{
- if (GIMPLE_STMT_P (node))
- return &void_type_node;
- return &TREE_TYPE (node);
-}
-
/* Build and return a TREE_LIST of arguments in the CALL_EXPR exp.
FIXME: don't use this function. It exists for compatibility with
the old representation of CALL_EXPRs where a list was used to hold the
return arglist;
}
+
+/* Create a nameless artificial label and put it in the current function
+ context. Returns the newly created label. */
+
+tree
+create_artificial_label (void)
+{
+ tree lab = build_decl (LABEL_DECL, NULL_TREE, void_type_node);
+
+ DECL_ARTIFICIAL (lab) = 1;
+ DECL_IGNORED_P (lab) = 1;
+ DECL_CONTEXT (lab) = current_function_decl;
+ return lab;
+}
+
+/* Given a tree, try to return a useful variable name that we can use
+ to prefix a temporary that is being assigned the value of the tree.
+ I.E. given <temp> = &A, return A. */
+
+const char *
+get_name (tree t)
+{
+ tree stripped_decl;
+
+ stripped_decl = t;
+ STRIP_NOPS (stripped_decl);
+ if (DECL_P (stripped_decl) && DECL_NAME (stripped_decl))
+ return IDENTIFIER_POINTER (DECL_NAME (stripped_decl));
+ else
+ {
+ switch (TREE_CODE (stripped_decl))
+ {
+ case ADDR_EXPR:
+ return get_name (TREE_OPERAND (stripped_decl, 0));
+ default:
+ return NULL;
+ }
+ }
+}
+
/* Return true if TYPE has a variable argument list. */
bool
{
tree ao = BLOCK_ABSTRACT_ORIGIN (block);
- while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao))
+ while (TREE_CODE (ao) == BLOCK
+ && BLOCK_ABSTRACT_ORIGIN (ao)
+ && BLOCK_ABSTRACT_ORIGIN (ao) != ao)
ao = BLOCK_ABSTRACT_ORIGIN (ao);
if (TREE_CODE (ao) == FUNCTION_DECL)