static void lower_gimple_bind (gimple_stmt_iterator *gsi, struct lower_data *data) { tree old_block = data->block; gimple stmt = gsi_stmt (*gsi); tree new_block = gimple_bind_block (stmt); if (new_block) { if (new_block == old_block) { /* The outermost block of the original function may not be the outermost statement chain of the gimplified function. So we may see the outermost block just inside the function. */ gcc_assert (new_block == DECL_INITIAL (current_function_decl)); new_block = NULL; } else { /* We do not expect to handle duplicate blocks. */ gcc_assert (!TREE_ASM_WRITTEN (new_block)); TREE_ASM_WRITTEN (new_block) = 1; /* Block tree may get clobbered by inlining. Normally this would be fixed in rest_of_decl_compilation using block notes, but since we are not going to emit them, it is up to us. */ BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (old_block); BLOCK_SUBBLOCKS (old_block) = new_block; BLOCK_SUBBLOCKS (new_block) = NULL_TREE; BLOCK_SUPERCONTEXT (new_block) = old_block; data->block = new_block; } } record_vars (gimple_bind_vars (stmt)); lower_sequence (gimple_bind_body_ptr (stmt), data); if (new_block) { gcc_assert (data->block == new_block); BLOCK_SUBBLOCKS (new_block) = blocks_nreverse (BLOCK_SUBBLOCKS (new_block)); data->block = old_block; } /* The GIMPLE_BIND no longer carries any useful information -- kill it. */ gsi_insert_seq_before (gsi, gimple_bind_body (stmt), GSI_SAME_STMT); gsi_remove (gsi, false); }
tree walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt, walk_tree_fn callback_op, struct walk_stmt_info *wi) { gimple *ret; tree tree_ret; gimple *stmt = gsi_stmt (*gsi); if (wi) { wi->gsi = *gsi; wi->removed_stmt = false; if (wi->want_locations && gimple_has_location (stmt)) input_location = gimple_location (stmt); } ret = NULL; /* Invoke the statement callback. Return if the callback handled all of STMT operands by itself. */ if (callback_stmt) { bool handled_ops = false; tree_ret = callback_stmt (gsi, &handled_ops, wi); if (handled_ops) return tree_ret; /* If CALLBACK_STMT did not handle operands, it should not have a value to return. */ gcc_assert (tree_ret == NULL); if (wi && wi->removed_stmt) return NULL; /* Re-read stmt in case the callback changed it. */ stmt = gsi_stmt (*gsi); } /* If CALLBACK_OP is defined, invoke it on every operand of STMT. */ if (callback_op) { tree_ret = walk_gimple_op (stmt, callback_op, wi); if (tree_ret) return tree_ret; } /* If STMT can have statements inside (e.g. GIMPLE_BIND), walk them. */ switch (gimple_code (stmt)) { case GIMPLE_BIND: ret = walk_gimple_seq_mod (gimple_bind_body_ptr (as_a <gbind *> (stmt)), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; case GIMPLE_CATCH: ret = walk_gimple_seq_mod (gimple_catch_handler_ptr ( as_a <gcatch *> (stmt)), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; case GIMPLE_EH_FILTER: ret = walk_gimple_seq_mod (gimple_eh_filter_failure_ptr (stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; case GIMPLE_EH_ELSE: { geh_else *eh_else_stmt = as_a <geh_else *> (stmt); ret = walk_gimple_seq_mod (gimple_eh_else_n_body_ptr (eh_else_stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; ret = walk_gimple_seq_mod (gimple_eh_else_e_body_ptr (eh_else_stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; } break; case GIMPLE_TRY: ret = walk_gimple_seq_mod (gimple_try_eval_ptr (stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; ret = walk_gimple_seq_mod (gimple_try_cleanup_ptr (stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; case GIMPLE_OMP_FOR: ret = walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; /* FALL THROUGH. */ case GIMPLE_OMP_CRITICAL: case GIMPLE_OMP_MASTER: case GIMPLE_OMP_TASKGROUP: case GIMPLE_OMP_ORDERED: case GIMPLE_OMP_SECTION: case GIMPLE_OMP_PARALLEL: case GIMPLE_OMP_TASK: case GIMPLE_OMP_SECTIONS: case GIMPLE_OMP_SINGLE: case GIMPLE_OMP_TARGET: case GIMPLE_OMP_TEAMS: ret = walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; case GIMPLE_WITH_CLEANUP_EXPR: ret = walk_gimple_seq_mod (gimple_wce_cleanup_ptr (stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; case GIMPLE_TRANSACTION: ret = walk_gimple_seq_mod (gimple_transaction_body_ptr ( as_a <gtransaction *> (stmt)), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; default: gcc_assert (!gimple_has_substatements (stmt)); break; } return NULL; }
static void lower_gimple_bind (gimple_stmt_iterator *gsi, struct lower_data *data) { tree old_block = data->block; gbind *stmt = as_a <gbind *> (gsi_stmt (*gsi)); tree new_block = gimple_bind_block (stmt); if (new_block) { if (new_block == old_block) { /* The outermost block of the original function may not be the outermost statement chain of the gimplified function. So we may see the outermost block just inside the function. */ gcc_assert (new_block == DECL_INITIAL (current_function_decl)); new_block = NULL; } else { /* We do not expect to handle duplicate blocks. */ gcc_assert (!TREE_ASM_WRITTEN (new_block)); TREE_ASM_WRITTEN (new_block) = 1; /* Block tree may get clobbered by inlining. Normally this would be fixed in rest_of_decl_compilation using block notes, but since we are not going to emit them, it is up to us. */ BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (old_block); BLOCK_SUBBLOCKS (old_block) = new_block; BLOCK_SUBBLOCKS (new_block) = NULL_TREE; BLOCK_SUPERCONTEXT (new_block) = old_block; data->block = new_block; } } record_vars (gimple_bind_vars (stmt)); /* Scrap DECL_CHAIN up to BLOCK_VARS to ease GC after we no longer need gimple_bind_vars. */ tree next; /* BLOCK_VARS and gimple_bind_vars share a common sub-chain. Find it by marking all BLOCK_VARS. */ if (gimple_bind_block (stmt)) for (tree t = BLOCK_VARS (gimple_bind_block (stmt)); t; t = DECL_CHAIN (t)) TREE_VISITED (t) = 1; for (tree var = gimple_bind_vars (stmt); var && ! TREE_VISITED (var); var = next) { next = DECL_CHAIN (var); DECL_CHAIN (var) = NULL_TREE; } /* Unmark BLOCK_VARS. */ if (gimple_bind_block (stmt)) for (tree t = BLOCK_VARS (gimple_bind_block (stmt)); t; t = DECL_CHAIN (t)) TREE_VISITED (t) = 0; lower_sequence (gimple_bind_body_ptr (stmt), data); if (new_block) { gcc_assert (data->block == new_block); BLOCK_SUBBLOCKS (new_block) = blocks_nreverse (BLOCK_SUBBLOCKS (new_block)); data->block = old_block; } /* The GIMPLE_BIND no longer carries any useful information -- kill it. */ gsi_insert_seq_before (gsi, gimple_bind_body (stmt), GSI_SAME_STMT); gsi_remove (gsi, false); }