#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "ggc.h"
#include "tm.h"
#include "tree.h"
#include "tree-gimple.h"
#include "tree-flow.h"
#include "output.h"
#include "rtl.h"
#include "expr.h"
#include "bitmap.h"
bool
is_gimple_formal_tmp_rhs (tree t)
{
enum tree_code code = TREE_CODE (t);
switch (TREE_CODE_CLASS (code))
{
case tcc_unary:
case tcc_binary:
case tcc_comparison:
return true;
default:
break;
}
switch (code)
{
case TRUTH_NOT_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
case ADDR_EXPR:
case CALL_EXPR:
case CONSTRUCTOR:
case COMPLEX_EXPR:
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
case COMPLEX_CST:
case VECTOR_CST:
case OBJ_TYPE_REF:
case ASSERT_EXPR:
return true;
default:
break;
}
return is_gimple_lvalue (t) || is_gimple_val (t);
}
bool
is_gimple_reg_rhs (tree t)
{
if (is_gimple_reg_type (TREE_TYPE (t))
&& ((TREE_CODE (t) == CALL_EXPR && TREE_SIDE_EFFECTS (t))
|| tree_could_throw_p (t)))
return false;
return is_gimple_formal_tmp_rhs (t);
}
bool
is_gimple_mem_rhs (tree t)
{
if (is_gimple_reg_type (TREE_TYPE (t))
|| (TYPE_MODE (TREE_TYPE (t)) != BLKmode
&& (TREE_CODE (t) != CALL_EXPR
|| ! aggregate_value_p (t, t))))
return is_gimple_val (t);
else
return is_gimple_formal_tmp_rhs (t);
}
gimple_predicate
rhs_predicate_for (tree lhs)
{
if (is_gimple_formal_tmp_var (lhs))
return is_gimple_formal_tmp_rhs;
else if (is_gimple_reg (lhs))
return is_gimple_reg_rhs;
else
return is_gimple_mem_rhs;
}
bool
is_gimple_lvalue (tree t)
{
return (is_gimple_addressable (t)
|| TREE_CODE (t) == WITH_SIZE_EXPR
|| TREE_CODE (t) == BIT_FIELD_REF);
}
bool
is_gimple_condexpr (tree t)
{
return (is_gimple_val (t) || COMPARISON_CLASS_P (t));
}
#ifdef ENABLE_LLVM
static inline bool
llvm_is_array_arrayref_extension(tree t)
{
t = t;
#ifdef ENABLE_LLVM
if (TREE_CODE (t) == ARRAY_REF &&
TREE_CODE (TREE_TYPE (TREE_OPERAND(t, 0))) != ARRAY_TYPE)
return true;
#endif
return false;
}
#endif
bool
is_gimple_addressable (tree t)
{
return (is_gimple_id (t) || handled_component_p (t)
#ifdef ENABLE_LLVM
|| llvm_is_array_arrayref_extension (t)
#endif
|| INDIRECT_REF_P (t));
}
bool
is_gimple_min_invariant (tree t)
{
switch (TREE_CODE (t))
{
case ADDR_EXPR:
return TREE_INVARIANT (t);
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
case COMPLEX_CST:
case VECTOR_CST:
return true;
default:
return false;
}
}
bool
is_gimple_stmt (tree t)
{
enum tree_code code = TREE_CODE (t);
switch (code)
{
case NOP_EXPR:
return IS_EMPTY_STMT (t);
case BIND_EXPR:
case COND_EXPR:
return TREE_TYPE (t) == NULL || VOID_TYPE_P (TREE_TYPE (t));
case SWITCH_EXPR:
case GOTO_EXPR:
case RETURN_EXPR:
case LABEL_EXPR:
case CASE_LABEL_EXPR:
case TRY_CATCH_EXPR:
case TRY_FINALLY_EXPR:
case EH_FILTER_EXPR:
case CATCH_EXPR:
case ASM_EXPR:
case RESX_EXPR:
case PHI_NODE:
case STATEMENT_LIST:
case OMP_PARALLEL:
case OMP_FOR:
case OMP_SECTIONS:
case OMP_SECTION:
case OMP_SINGLE:
case OMP_MASTER:
case OMP_ORDERED:
case OMP_CRITICAL:
case OMP_RETURN:
case OMP_CONTINUE:
return true;
case CALL_EXPR:
case MODIFY_EXPR:
return true;
default:
return false;
}
}
bool
is_gimple_variable (tree t)
{
return (TREE_CODE (t) == VAR_DECL
|| TREE_CODE (t) == PARM_DECL
|| TREE_CODE (t) == RESULT_DECL
|| TREE_CODE (t) == SSA_NAME);
}
bool
is_gimple_id (tree t)
{
return (is_gimple_variable (t)
|| TREE_CODE (t) == FUNCTION_DECL
|| TREE_CODE (t) == LABEL_DECL
|| TREE_CODE (t) == CONST_DECL
|| TREE_CODE (t) == STRING_CST);
}
bool
is_gimple_reg_type (tree type)
{
return !AGGREGATE_TYPE_P (type);
}
bool
is_gimple_reg (tree t)
{
if (TREE_CODE (t) == SSA_NAME)
t = SSA_NAME_VAR (t);
if (MTAG_P (t))
return false;
if (!is_gimple_variable (t))
return false;
if (!is_gimple_reg_type (TREE_TYPE (t)))
return false;
if (TREE_THIS_VOLATILE (t))
return false;
if (needs_to_live_in_memory (t))
return false;
if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
return false;
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
return DECL_COMPLEX_GIMPLE_REG_P (t);
return true;
}
bool
is_gimple_formal_tmp_var (tree t)
{
if (TREE_CODE (t) == SSA_NAME)
return true;
return TREE_CODE (t) == VAR_DECL && DECL_GIMPLE_FORMAL_TEMP_P (t);
}
bool
is_gimple_formal_tmp_reg (tree t)
{
if (TREE_CODE (t) == SSA_NAME)
return true;
if (!is_gimple_formal_tmp_var (t))
return false;
return is_gimple_reg (t);
}
bool
is_gimple_non_addressable (tree t)
{
if (TREE_CODE (t) == SSA_NAME)
t = SSA_NAME_VAR (t);
return (is_gimple_variable (t) && ! needs_to_live_in_memory (t));
}
bool
is_gimple_val (tree t)
{
if (is_gimple_variable (t)
&& is_gimple_reg_type (TREE_TYPE (t))
&& !is_gimple_reg (t))
return false;
if (TREE_CODE (t) == EXC_PTR_EXPR || TREE_CODE (t) == FILTER_EXPR)
return 1;
return (is_gimple_variable (t) || is_gimple_min_invariant (t));
}
bool
is_gimple_asm_val (tree t)
{
if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
return true;
return is_gimple_val (t);
}
bool
is_gimple_min_lval (tree t)
{
return (is_gimple_id (t)
|| TREE_CODE (t) == INDIRECT_REF);
}
bool
is_gimple_cast (tree t)
{
return (TREE_CODE (t) == NOP_EXPR
|| TREE_CODE (t) == CONVERT_EXPR
|| TREE_CODE (t) == FIX_TRUNC_EXPR
|| TREE_CODE (t) == FIX_CEIL_EXPR
|| TREE_CODE (t) == FIX_FLOOR_EXPR
|| TREE_CODE (t) == FIX_ROUND_EXPR);
}
bool
is_gimple_call_addr (tree t)
{
return (TREE_CODE (t) == OBJ_TYPE_REF
|| is_gimple_val (t));
}
tree
get_call_expr_in (tree t)
{
if (TREE_CODE (t) == MODIFY_EXPR)
t = TREE_OPERAND (t, 1);
if (TREE_CODE (t) == WITH_SIZE_EXPR)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == CALL_EXPR)
return t;
return NULL_TREE;
}
tree
get_base_address (tree t)
{
#ifndef ENABLE_LLVM
while (handled_component_p (t))
#else
while (handled_component_p (t) || TREE_CODE(t) == ARRAY_REF)
#endif
t = TREE_OPERAND (t, 0);
if (SSA_VAR_P (t)
|| TREE_CODE (t) == STRING_CST
|| TREE_CODE (t) == CONSTRUCTOR
|| INDIRECT_REF_P (t))
return t;
else
return NULL_TREE;
}
void
recalculate_side_effects (tree t)
{
enum tree_code code = TREE_CODE (t);
int len = TREE_CODE_LENGTH (code);
int i;
switch (TREE_CODE_CLASS (code))
{
case tcc_expression:
switch (code)
{
case INIT_EXPR:
case MODIFY_EXPR:
case VA_ARG_EXPR:
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
return;
default:
break;
}
case tcc_comparison:
case tcc_unary:
case tcc_binary:
case tcc_reference:
TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t);
for (i = 0; i < len; ++i)
{
tree op = TREE_OPERAND (t, i);
if (op && TREE_SIDE_EFFECTS (op))
TREE_SIDE_EFFECTS (t) = 1;
}
break;
default:
gcc_unreachable ();
}
}