Пример #1
0
void
gimple_replace_ssa_lhs (gimple *stmt, tree nlhs)
{
  if (MAY_HAVE_DEBUG_STMTS)
    {
      tree lhs = gimple_get_lhs (stmt);

      gcc_assert (SSA_NAME_DEF_STMT (lhs) == stmt);

      insert_debug_temp_for_var_def (NULL, lhs);
    }

  gimple_set_lhs (stmt, nlhs);
}
Пример #2
0
void
gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
{
    size_t i, num_ops;
    tree lhs;
    gimple_seq pre = NULL;
    gimple post_stmt = NULL;

    push_gimplify_context (gimple_in_ssa_p (cfun));

    switch (gimple_code (stmt))
    {
    case GIMPLE_COND:
        gimplify_expr (gimple_cond_lhs_ptr (stmt), &pre, NULL,
                       is_gimple_val, fb_rvalue);
        gimplify_expr (gimple_cond_rhs_ptr (stmt), &pre, NULL,
                       is_gimple_val, fb_rvalue);
        break;
    case GIMPLE_SWITCH:
        gimplify_expr (gimple_switch_index_ptr (stmt), &pre, NULL,
                       is_gimple_val, fb_rvalue);
        break;
    case GIMPLE_OMP_ATOMIC_LOAD:
        gimplify_expr (gimple_omp_atomic_load_rhs_ptr (stmt), &pre, NULL,
                       is_gimple_val, fb_rvalue);
        break;
    case GIMPLE_ASM:
    {
        size_t i, noutputs = gimple_asm_noutputs (stmt);
        const char *constraint, **oconstraints;
        bool allows_mem, allows_reg, is_inout;

        oconstraints
            = (const char **) alloca ((noutputs) * sizeof (const char *));
        for (i = 0; i < noutputs; i++)
        {
            tree op = gimple_asm_output_op (stmt, i);
            constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
            oconstraints[i] = constraint;
            parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
                                     &allows_reg, &is_inout);
            gimplify_expr (&TREE_VALUE (op), &pre, NULL,
                           is_inout ? is_gimple_min_lval : is_gimple_lvalue,
                           fb_lvalue | fb_mayfail);
        }
        for (i = 0; i < gimple_asm_ninputs (stmt); i++)
        {
            tree op = gimple_asm_input_op (stmt, i);
            constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
            parse_input_constraint (&constraint, 0, 0, noutputs, 0,
                                    oconstraints, &allows_mem, &allows_reg);
            if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (op))) && allows_mem)
                allows_reg = 0;
            if (!allows_reg && allows_mem)
                gimplify_expr (&TREE_VALUE (op), &pre, NULL,
                               is_gimple_lvalue, fb_lvalue | fb_mayfail);
            else
                gimplify_expr (&TREE_VALUE (op), &pre, NULL,
                               is_gimple_asm_val, fb_rvalue);
        }
    }
    break;
    default:
        /* NOTE: We start gimplifying operands from last to first to
        make sure that side-effects on the RHS of calls, assignments
         and ASMs are executed before the LHS.  The ordering is not
         important for other statements.  */
        num_ops = gimple_num_ops (stmt);
        for (i = num_ops; i > 0; i--)
        {
            tree op = gimple_op (stmt, i - 1);
            if (op == NULL_TREE)
                continue;
            if (i == 1 && (is_gimple_call (stmt) || is_gimple_assign (stmt)))
                gimplify_expr (&op, &pre, NULL, is_gimple_lvalue, fb_lvalue);
            else if (i == 2
                     && is_gimple_assign (stmt)
                     && num_ops == 2
                     && get_gimple_rhs_class (gimple_expr_code (stmt))
                     == GIMPLE_SINGLE_RHS)
                gimplify_expr (&op, &pre, NULL,
                               rhs_predicate_for (gimple_assign_lhs (stmt)),
                               fb_rvalue);
            else if (i == 2 && is_gimple_call (stmt))
            {
                if (TREE_CODE (op) == FUNCTION_DECL)
                    continue;
                gimplify_expr (&op, &pre, NULL, is_gimple_call_addr, fb_rvalue);
            }
            else
                gimplify_expr (&op, &pre, NULL, is_gimple_val, fb_rvalue);
            gimple_set_op (stmt, i - 1, op);
        }

        lhs = gimple_get_lhs (stmt);
        /* If the LHS changed it in a way that requires a simple RHS,
        create temporary.  */
        if (lhs && !is_gimple_reg (lhs))
        {
            bool need_temp = false;

            if (is_gimple_assign (stmt)
                    && num_ops == 2
                    && get_gimple_rhs_class (gimple_expr_code (stmt))
                    == GIMPLE_SINGLE_RHS)
                gimplify_expr (gimple_assign_rhs1_ptr (stmt), &pre, NULL,
                               rhs_predicate_for (gimple_assign_lhs (stmt)),
                               fb_rvalue);
            else if (is_gimple_reg (lhs))
            {
                if (is_gimple_reg_type (TREE_TYPE (lhs)))
                {
                    if (is_gimple_call (stmt))
                    {
                        i = gimple_call_flags (stmt);
                        if ((i & ECF_LOOPING_CONST_OR_PURE)
                                || !(i & (ECF_CONST | ECF_PURE)))
                            need_temp = true;
                    }
                    if (stmt_can_throw_internal (stmt))
                        need_temp = true;
                }
            }
            else
            {
                if (is_gimple_reg_type (TREE_TYPE (lhs)))
                    need_temp = true;
                else if (TYPE_MODE (TREE_TYPE (lhs)) != BLKmode)
                {
                    if (is_gimple_call (stmt))
                    {
                        tree fndecl = gimple_call_fndecl (stmt);

                        if (!aggregate_value_p (TREE_TYPE (lhs), fndecl)
                                && !(fndecl && DECL_RESULT (fndecl)
                                     && DECL_BY_REFERENCE (DECL_RESULT (fndecl))))
                            need_temp = true;
                    }
                    else
                        need_temp = true;
                }
            }
            if (need_temp)
            {
                tree temp = create_tmp_reg (TREE_TYPE (lhs), NULL);
                if (gimple_in_ssa_p (cfun))
                    temp = make_ssa_name (temp, NULL);
                gimple_set_lhs (stmt, temp);
                post_stmt = gimple_build_assign (lhs, temp);
            }
        }
        break;
    }

    if (!gimple_seq_empty_p (pre))
        gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT);
    if (post_stmt)
        gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT);

    pop_gimplify_context (NULL);
}
Пример #3
0
static void insert_call_to_junk_fn(gimple stmt)
{
    tree tv, rv, fn, rhs, tmp;
    gimple gimp;
    gimple_stmt_iterator gsi;
    static bool has_initted;
    static tree decl, proto, decl_get_funcs, proto_get_funcs, fn_ptr_type;
    
    printf("slimer: Inserting junk function call at line: %d\n",
            gimple_lineno(stmt));

    /* Get random value modulo n_funcs for index into runtime __funcs array of
     * junk functions:
     *     rv = time % n_funcs;
     *     fn = __funcs + rv;
     *     call fn
     */

    /* Build instances */
    if (!has_initted)
    {
        proto = build_function_type_list(
            uint64_type_node, ptr_type_node, NULL_TREE);
        decl = build_fn_decl("time", proto);
        DECL_EXTERNAL(decl) = 1;

        proto_get_funcs = build_function_type_list(ptr_type_node, NULL_TREE);
        decl_get_funcs = build_fn_decl("__slimer_get_funcs", proto_get_funcs);

        fn_ptr_type = build_function_type_list(
            void_type_node, void_type_node, NULL_TREE);

        has_initted = true;
    }

    /* time_tmp = time(NULL); */
    tv = create_tmp_var(uint64_type_node, "time_tmp");
    tv = make_ssa_name(tv, NULL);
    gimp = gimple_build_call(decl, 1, null_pointer_node);
    gimple_set_lhs(gimp, tv);
    gsi = gsi_for_stmt(stmt);
    gsi_insert_before(&gsi, gimp, GSI_SAME_STMT);

    /* rv_tmp = time_temp % n_funcs */
    rv = create_tmp_var(uint64_type_node, "rv_tmp");
    rv = make_ssa_name(rv, NULL);
    rhs = build_int_cst(integer_type_node, n_funcs);
    gimp = gimple_build_assign_with_ops(TRUNC_MOD_EXPR, rv, tv, rhs);
    gsi_insert_before(&gsi, gimp, GSI_SAME_STMT);

    /* tmp = __slimer_get_funcs(); TODO: Get rid of __slimer_get_funcs()
     * rv = rv * sizeof(void *)
     * fn_tmp = tmp + rv
     */
    tree pp_type = build_pointer_type(ptr_type_node);
    tmp = create_tmp_var(pp_type, "tmp");
    tmp = make_ssa_name(tmp, NULL);
    gimp = gimple_build_call(decl_get_funcs, 0);
    gimple_set_lhs(gimp, tmp);
    gsi_insert_before(&gsi, gimp, GSI_SAME_STMT);

    /* rv = rv * sizeof(void *))
     * FIXME: THIS IS NOT SUFFICIENT FOR CROSS COMPILING FOR ARCHITECTURES THAT
     * HAVE ADDRESS SIZES sizeof(void *)
     */
    tree addr_size = build_int_cst(integer_type_node, sizeof(void *));
    gimp = gimple_build_assign_with_ops(MULT_EXPR, rv, rv, addr_size);
    gsi_insert_before(&gsi, gimp, GSI_SAME_STMT);

    fn = create_tmp_var(pp_type, "fn_tmp");
    fn = make_ssa_name(fn, NULL);
    gimp = gimple_build_assign_with_ops(PLUS_EXPR, fn, tmp, rv);
    gsi_insert_before(&gsi, gimp, GSI_SAME_STMT);

    /* the_fn = *fn */
    tree f = build_pointer_type(fn_ptr_type); 
    tree the_fn = create_tmp_var(f, "the_func_ptr");
    the_fn = make_ssa_name(the_fn, NULL);
    gimp = gimple_build_assign(the_fn, build_simple_mem_ref(fn));
    gsi_insert_before(&gsi, gimp, GSI_SAME_STMT);

    /* call the_fn */
    gimp = gimple_build_call(the_fn, 0);
    gsi_insert_before(&gsi, gimp, GSI_SAME_STMT);

#ifdef GOAT_DEBUG
    debug_function(cfun->decl, 0);
#endif
}