diff options
Diffstat (limited to 'gcc/tree-eh.cc')
-rw-r--r-- | gcc/tree-eh.cc | 89 |
1 files changed, 44 insertions, 45 deletions
diff --git a/gcc/tree-eh.cc b/gcc/tree-eh.cc index df90d1b..e62fed9 100644 --- a/gcc/tree-eh.cc +++ b/gcc/tree-eh.cc @@ -3183,60 +3183,59 @@ stmt_throw_types (function *, gimple *stmt, vec<tree> *ret_vector) } } -// To get the all exception types from a resx stmt -static bool -extract_types_for_resx (basic_block bb, vec<tree> *ret_vector) +// To get the all exception types from a resx stmt (iterative version) +bool +extract_types_for_resx (gimple *resx_stmt, vec<tree> *ret_vector) { - edge e; - edge_iterator ei; + basic_block start_bb = gimple_bb (resx_stmt); + hash_set<basic_block> visited_blocks; + vec<basic_block> block_stack; - // Iterate over edges to walk up the basic blocks - FOR_EACH_EDGE (e, ei, bb->preds) - { - // Get the last stmt of the basic block as it is an EH stmt - bb = e->src; - gimple_stmt_iterator gsi = gsi_last_bb (bb); - gimple *last_stmt = gsi_stmt (gsi); + block_stack.safe_push(start_bb); - if (bb->aux) + while (!block_stack.is_empty()) + { + basic_block bb = block_stack.pop(); + if (visited_blocks.contains(bb)) continue; - bb->aux = (void *)1; - if (last_stmt && (e->flags & EDGE_EH)) + visited_blocks.add(bb); + + edge e; + edge_iterator ei; + gimple_stmt_iterator gsi = gsi_last_bb(bb); + gimple *last_stmt = gsi_stmt(gsi); + + + FOR_EACH_EDGE(e, ei, bb->preds) + { + basic_block pred_bb = e->src; + + if (e->flags & EDGE_EH) { - if (gimple_code (last_stmt) == GIMPLE_CALL) - { - // check if its a throw - if (!extract_types_for_call (as_a<gcall *> (last_stmt), - ret_vector)) - return false; - continue; - } - else if (gimple_code (last_stmt) == GIMPLE_RESX) - { - // Recursively processing resx - // FIXME: to get this linear, we should cache results. - if (!extract_types_for_resx (last_stmt, ret_vector)) - return false; - continue; - } + gimple_stmt_iterator pred_gsi = gsi_last_bb(pred_bb); + gimple *pred_last_stmt = gsi_stmt(pred_gsi); + + if (gimple_code(pred_last_stmt) == GIMPLE_CALL) + { + if (!extract_types_for_call(as_a<gcall*>(pred_last_stmt), ret_vector)) + return false; + } + else if (gimple_code(pred_last_stmt) == GIMPLE_RESX) + { + // Add the predecessor block to the stack for further exploration + block_stack.safe_push(pred_bb); + } } - /* FIXME: remove recursion here, so we do not run out of stack. */ - else if (!extract_types_for_resx (e->src, ret_vector)) - return false; + else + { + block_stack.safe_push(pred_bb); + } + } } - return true; -} -// To get the all exception types from a resx stmt -bool -extract_types_for_resx (gimple *resx_stmt, vec<tree> *ret_vector) -{ - basic_block bb = gimple_bb (resx_stmt); - bool ret = extract_types_for_resx (bb, ret_vector); - /* FIXME: this is non-linear. */ - clear_aux_for_blocks (); - return ret; + clear_aux_for_blocks(); + return true; } // To get the types being thrown outside of a function |