void tree_code_output_expression_statement (tree code, unsigned char* filename, int lineno) { /* Output the line number information. */ emit_line_note ((const char *)filename, lineno); TREE_USED (code) = 1; TREE_SIDE_EFFECTS (code) = 1; expand_expr_stmt (code); }
void tree_code_generate_return (tree type, tree exp) { tree setret; tree param; for (param = DECL_ARGUMENTS (current_function_decl); param; param = TREE_CHAIN (param)) { if (DECL_CONTEXT (param) != current_function_decl) abort (); } if (exp) { setret = build (MODIFY_EXPR, type, DECL_RESULT (current_function_decl), build1 (CONVERT_EXPR, type, exp)); TREE_SIDE_EFFECTS (setret) = 1; TREE_USED (setret) = 1; expand_expr_stmt (setret); } expand_return (DECL_RESULT (current_function_decl)); }
static basic_block expand_gimple_tailcall (basic_block bb, tree stmt, bool *can_fallthru) { rtx last2, last; edge e; edge_iterator ei; int probability; gcov_type count; last2 = last = get_last_insn (); expand_expr_stmt (stmt); for (last = NEXT_INSN (last); last; last = NEXT_INSN (last)) if (CALL_P (last) && SIBLING_CALL_P (last)) goto found; maybe_dump_rtl_for_tree_stmt (stmt, last2); *can_fallthru = true; return NULL; found: /* ??? Wouldn't it be better to just reset any pending stack adjust? Any instructions emitted here are about to be deleted. */ do_pending_stack_adjust (); /* Remove any non-eh, non-abnormal edges that don't go to exit. */ /* ??? I.e. the fallthrough edge. HOWEVER! If there were to be EH or abnormal edges, we shouldn't have created a tail call in the first place. So it seems to me we should just be removing all edges here, or redirecting the existing fallthru edge to the exit block. */ probability = 0; count = 0; for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); ) { if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH))) { if (e->dest != EXIT_BLOCK_PTR) { e->dest->count -= e->count; e->dest->frequency -= EDGE_FREQUENCY (e); if (e->dest->count < 0) e->dest->count = 0; if (e->dest->frequency < 0) e->dest->frequency = 0; } count += e->count; probability += e->probability; remove_edge (e); } else ei_next (&ei); } /* This is somewhat ugly: the call_expr expander often emits instructions after the sibcall (to perform the function return). These confuse the find_sub_basic_blocks code, so we need to get rid of these. */ last = NEXT_INSN (last); gcc_assert (BARRIER_P (last)); *can_fallthru = false; while (NEXT_INSN (last)) { /* For instance an sqrt builtin expander expands if with sibcall in the then and label for `else`. */ if (LABEL_P (NEXT_INSN (last))) { *can_fallthru = true; break; } delete_insn (NEXT_INSN (last)); } e = make_edge (bb, EXIT_BLOCK_PTR, EDGE_ABNORMAL | EDGE_SIBCALL); e->probability += probability; e->count += count; BB_END (bb) = last; update_bb_for_insn (bb); if (NEXT_INSN (last)) { bb = create_basic_block (NEXT_INSN (last), get_last_insn (), bb); last = BB_END (bb); if (BARRIER_P (last)) BB_END (bb) = PREV_INSN (last); } maybe_dump_rtl_for_tree_stmt (stmt, last2); return bb; }
static basic_block expand_gimple_basic_block (basic_block bb, FILE * dump_file) { block_stmt_iterator bsi = bsi_start (bb); tree stmt = NULL; rtx note, last; edge e; edge_iterator ei; if (dump_file) { fprintf (dump_file, "\n;; Generating RTL for tree basic block %d\n", bb->index); } if (!bsi_end_p (bsi)) stmt = bsi_stmt (bsi); if (stmt && TREE_CODE (stmt) == LABEL_EXPR) { last = get_last_insn (); expand_expr_stmt (stmt); /* Java emits line number notes in the top of labels. ??? Make this go away once line number notes are obsoleted. */ BB_HEAD (bb) = NEXT_INSN (last); if (NOTE_P (BB_HEAD (bb))) BB_HEAD (bb) = NEXT_INSN (BB_HEAD (bb)); bsi_next (&bsi); note = emit_note_after (NOTE_INSN_BASIC_BLOCK, BB_HEAD (bb)); maybe_dump_rtl_for_tree_stmt (stmt, last); } else note = BB_HEAD (bb) = emit_note (NOTE_INSN_BASIC_BLOCK); NOTE_BASIC_BLOCK (note) = bb; for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); ) { /* Clear EDGE_EXECUTABLE. This flag is never used in the backend. */ e->flags &= ~EDGE_EXECUTABLE; /* At the moment not all abnormal edges match the RTL representation. It is safe to remove them here as find_sub_basic_blocks will rediscover them. In the future we should get this fixed properly. */ if (e->flags & EDGE_ABNORMAL) remove_edge (e); else ei_next (&ei); } for (; !bsi_end_p (bsi); bsi_next (&bsi)) { tree stmt = bsi_stmt (bsi); basic_block new_bb; if (!stmt) continue; /* Expand this statement, then evaluate the resulting RTL and fixup the CFG accordingly. */ if (TREE_CODE (stmt) == COND_EXPR) { new_bb = expand_gimple_cond_expr (bb, stmt); if (new_bb) return new_bb; } else { tree call = get_call_expr_in (stmt); if (call && CALL_EXPR_TAILCALL (call)) { bool can_fallthru; new_bb = expand_gimple_tailcall (bb, stmt, &can_fallthru); if (new_bb) { if (can_fallthru) bb = new_bb; else return new_bb; } } else { last = get_last_insn (); expand_expr_stmt (stmt); maybe_dump_rtl_for_tree_stmt (stmt, last); } } } do_pending_stack_adjust (); /* Find the block tail. The last insn in the block is the insn before a barrier and/or table jump insn. */ last = get_last_insn (); if (BARRIER_P (last)) last = PREV_INSN (last); if (JUMP_TABLE_DATA_P (last)) last = PREV_INSN (PREV_INSN (last)); BB_END (bb) = last; update_bb_for_insn (bb); return bb; }
void expand_stmt_with_iterators_1 (void) { extern void expand_expr_stmt (void); expand_expr_stmt (); }