void add_phi_node_to_bb (gimple phi, basic_block bb) { gimple_stmt_iterator gsi; /* Add the new PHI node to the list of PHI nodes for block BB. */ if (phi_nodes (bb) == NULL) set_phi_nodes (bb, gimple_seq_alloc ()); gsi = gsi_last (phi_nodes (bb)); gsi_insert_after (&gsi, phi, GSI_NEW_STMT); /* Associate BB to the PHI node. */ gimple_set_bb (phi, bb); }
void gsi_replace_with_seq (gimple_stmt_iterator *gsi, gimple_seq seq, bool update_eh_info) { gimple_stmt_iterator seqi; gimple *last; if (gimple_seq_empty_p (seq)) { gsi_remove (gsi, true); return; } seqi = gsi_last (seq); last = gsi_stmt (seqi); gsi_remove (&seqi, false); gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT); gsi_replace (gsi, last, update_eh_info); }
static unsigned int lower_function_body (void) { struct lower_data data; gimple_seq body = gimple_body (current_function_decl); gimple_seq lowered_body; gimple_stmt_iterator i; gimple bind; tree t; gimple x; /* The gimplifier should've left a body of exactly one statement, namely a GIMPLE_BIND. */ gcc_assert (gimple_seq_first (body) == gimple_seq_last (body) && gimple_code (gimple_seq_first_stmt (body)) == GIMPLE_BIND); memset (&data, 0, sizeof (data)); data.block = DECL_INITIAL (current_function_decl); BLOCK_SUBBLOCKS (data.block) = NULL_TREE; BLOCK_CHAIN (data.block) = NULL_TREE; TREE_ASM_WRITTEN (data.block) = 1; data.return_statements.create (8); bind = gimple_seq_first_stmt (body); lowered_body = NULL; gimple_seq_add_stmt (&lowered_body, bind); i = gsi_start (lowered_body); lower_gimple_bind (&i, &data); i = gsi_last (lowered_body); /* If the function falls off the end, we need a null return statement. If we've already got one in the return_statements vector, we don't need to do anything special. Otherwise build one by hand. */ if (gimple_seq_may_fallthru (lowered_body) && (data.return_statements.is_empty () || gimple_return_retval (data.return_statements.last().stmt) != NULL)) { x = gimple_build_return (NULL); gimple_set_location (x, cfun->function_end_locus); gimple_set_block (x, DECL_INITIAL (current_function_decl)); gsi_insert_after (&i, x, GSI_CONTINUE_LINKING); } /* If we lowered any return statements, emit the representative at the end of the function. */ while (!data.return_statements.is_empty ()) { return_statements_t t = data.return_statements.pop (); x = gimple_build_label (t.label); gsi_insert_after (&i, x, GSI_CONTINUE_LINKING); gsi_insert_after (&i, t.stmt, GSI_CONTINUE_LINKING); } /* If the function calls __builtin_setjmp, we need to emit the computed goto that will serve as the unique dispatcher for all the receivers. */ if (data.calls_builtin_setjmp) { tree disp_label, disp_var, arg; /* Build 'DISP_LABEL:' and insert. */ disp_label = create_artificial_label (cfun->function_end_locus); /* This mark will create forward edges from every call site. */ DECL_NONLOCAL (disp_label) = 1; cfun->has_nonlocal_label = 1; x = gimple_build_label (disp_label); gsi_insert_after (&i, x, GSI_CONTINUE_LINKING); /* Build 'DISP_VAR = __builtin_setjmp_dispatcher (DISP_LABEL);' and insert. */ disp_var = create_tmp_var (ptr_type_node, "setjmpvar"); arg = build_addr (disp_label, current_function_decl); t = builtin_decl_implicit (BUILT_IN_SETJMP_DISPATCHER); x = gimple_build_call (t, 1, arg); gimple_call_set_lhs (x, disp_var); /* Build 'goto DISP_VAR;' and insert. */ gsi_insert_after (&i, x, GSI_CONTINUE_LINKING); x = gimple_build_goto (disp_var); gsi_insert_after (&i, x, GSI_CONTINUE_LINKING); } /* Once the old body has been lowered, replace it with the new lowered sequence. */ gimple_set_body (current_function_decl, lowered_body); gcc_assert (data.block == DECL_INITIAL (current_function_decl)); BLOCK_SUBBLOCKS (data.block) = blocks_nreverse (BLOCK_SUBBLOCKS (data.block)); clear_block_marks (data.block); data.return_statements.release (); return 0; }
static unsigned int lower_function_body (void) { struct lower_data data; gimple_seq body = gimple_body (current_function_decl); gimple_seq lowered_body; gimple_stmt_iterator i; gimple bind; gimple x; /* The gimplifier should've left a body of exactly one statement, namely a GIMPLE_BIND. */ gcc_assert (gimple_seq_first (body) == gimple_seq_last (body) && gimple_code (gimple_seq_first_stmt (body)) == GIMPLE_BIND); memset (&data, 0, sizeof (data)); data.block = DECL_INITIAL (current_function_decl); BLOCK_SUBBLOCKS (data.block) = NULL_TREE; BLOCK_CHAIN (data.block) = NULL_TREE; TREE_ASM_WRITTEN (data.block) = 1; data.return_statements.create (8); bind = gimple_seq_first_stmt (body); lowered_body = NULL; gimple_seq_add_stmt (&lowered_body, bind); i = gsi_start (lowered_body); lower_gimple_bind (&i, &data); i = gsi_last (lowered_body); /* If the function falls off the end, we need a null return statement. If we've already got one in the return_statements vector, we don't need to do anything special. Otherwise build one by hand. */ if (gimple_seq_may_fallthru (lowered_body) && (data.return_statements.is_empty () || (gimple_return_retval (data.return_statements.last().stmt) != NULL))) { x = gimple_build_return (NULL); gimple_set_location (x, cfun->function_end_locus); gimple_set_block (x, DECL_INITIAL (current_function_decl)); gsi_insert_after (&i, x, GSI_CONTINUE_LINKING); } /* If we lowered any return statements, emit the representative at the end of the function. */ while (!data.return_statements.is_empty ()) { return_statements_t t = data.return_statements.pop (); x = gimple_build_label (t.label); gsi_insert_after (&i, x, GSI_CONTINUE_LINKING); gsi_insert_after (&i, t.stmt, GSI_CONTINUE_LINKING); } /* Once the old body has been lowered, replace it with the new lowered sequence. */ gimple_set_body (current_function_decl, lowered_body); gcc_assert (data.block == DECL_INITIAL (current_function_decl)); BLOCK_SUBBLOCKS (data.block) = blocks_nreverse (BLOCK_SUBBLOCKS (data.block)); clear_block_marks (data.block); data.return_statements.release (); return 0; }
static unsigned int lower_function_body (void) { struct lower_data data; gimple_seq body = gimple_body (current_function_decl); gimple_seq lowered_body; gimple_stmt_iterator i; gimple *bind; gimple *x; /* The gimplifier should've left a body of exactly one statement, namely a GIMPLE_BIND. */ gcc_assert (gimple_seq_first (body) == gimple_seq_last (body) && gimple_code (gimple_seq_first_stmt (body)) == GIMPLE_BIND); memset (&data, 0, sizeof (data)); data.block = DECL_INITIAL (current_function_decl); BLOCK_SUBBLOCKS (data.block) = NULL_TREE; BLOCK_CHAIN (data.block) = NULL_TREE; TREE_ASM_WRITTEN (data.block) = 1; data.return_statements.create (8); bind = gimple_seq_first_stmt (body); lowered_body = NULL; gimple_seq_add_stmt (&lowered_body, bind); i = gsi_start (lowered_body); lower_gimple_bind (&i, &data); i = gsi_last (lowered_body); /* If we had begin stmt markers from e.g. PCH, but this compilation doesn't want them, lower_stmt will have cleaned them up; we can now clear the flag that indicates we had them. */ if (!MAY_HAVE_DEBUG_MARKER_STMTS && cfun->debug_nonbind_markers) { /* This counter needs not be exact, but before lowering it will most certainly be. */ gcc_assert (cfun->debug_marker_count == 0); cfun->debug_nonbind_markers = false; } /* If the function falls off the end, we need a null return statement. If we've already got one in the return_statements vector, we don't need to do anything special. Otherwise build one by hand. */ bool may_fallthru = gimple_seq_may_fallthru (lowered_body); if (may_fallthru && (data.return_statements.is_empty () || (gimple_return_retval (data.return_statements.last().stmt) != NULL))) { x = gimple_build_return (NULL); gimple_set_location (x, cfun->function_end_locus); gimple_set_block (x, DECL_INITIAL (current_function_decl)); gsi_insert_after (&i, x, GSI_CONTINUE_LINKING); may_fallthru = false; } /* If we lowered any return statements, emit the representative at the end of the function. */ while (!data.return_statements.is_empty ()) { return_statements_t t = data.return_statements.pop (); x = gimple_build_label (t.label); gsi_insert_after (&i, x, GSI_CONTINUE_LINKING); gsi_insert_after (&i, t.stmt, GSI_CONTINUE_LINKING); if (may_fallthru) { /* Remove the line number from the representative return statement. It now fills in for the fallthru too. Failure to remove this will result in incorrect results for coverage analysis. */ gimple_set_location (t.stmt, UNKNOWN_LOCATION); may_fallthru = false; } } /* Once the old body has been lowered, replace it with the new lowered sequence. */ gimple_set_body (current_function_decl, lowered_body); gcc_assert (data.block == DECL_INITIAL (current_function_decl)); BLOCK_SUBBLOCKS (data.block) = blocks_nreverse (BLOCK_SUBBLOCKS (data.block)); clear_block_marks (data.block); data.return_statements.release (); return 0; }
static void gen_alloca_stmts(gimple_seq* stmts_, tree* sp_) { /* doc: tree-complex.c, c-common.c, omp-low.c */ /* create the stmt sequence so that: *sp = alloca(sizeof(type)); type: the type to be stacked stmts: the allocation sequence sp: the allocated area ptr */ gimple call; gimple_seq stmts; tree binop; tree mul; tree val; tree count; tree sizeuf; tree sp; tree ref; gimple assign; gimple_stmt_iterator gsi; /* build an empty sequence */ stmts = gimple_seq_alloc(); gsi = gsi_last(stmts); #if 0 /* fixme */ sp = create_tmp_var(ptr_type_node, NULL); #else /* from varpool.c */ sp = add_new_static_var(ptr_type_node); #endif /* sp = __builtin_alloca(count * sizeof(uintptr_t)); */ count = build_int_cst(integer_type_node, 2); sizeuf = build_int_cst(integer_type_node, sizeof(uintptr_t)); mul = build2(MULT_EXPR, integer_type_node, count, sizeuf); /* call = gimple_build_call(built_in_decls[BUILT_IN_ALLOCA], 1, mul); */ call = gimple_build_call(kaapi_pushdata_aligned_decl, 1, mul); gimple_call_set_lhs(call, sp); gsi_insert_after(&gsi, call, GSI_CONTINUE_LINKING); /* *(sp + 0) = 42; */ ref = build1(INDIRECT_REF, TREE_TYPE(sp), sp); val = build_int_cst(ptr_type_node, 0xdeadc0d3); assign = gimple_build_assign(ref, val); gsi_insert_after(&gsi, assign, GSI_CONTINUE_LINKING); /* *(sp + 8) = 24 */ binop = build_binary_op (0, PLUS_EXPR, convert(integer_type_node, sp), sizeuf, 0); ref = build1(INDIRECT_REF, TREE_TYPE(binop), binop); val = build_int_cst(ptr_type_node, 0xdeadc003); assign = gimple_build_assign(ref, val); gsi_insert_after(&gsi, assign, GSI_CONTINUE_LINKING); /* affect results */ *sp_ = sp; *stmts_ = stmts; }