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); }
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); }
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 }