diff options
author | Pranil Dey <mkdeyp@gmail.com> | 2024-08-20 22:07:57 +0530 |
---|---|---|
committer | Pranil Dey <mkdeyp@gmail.com> | 2024-08-20 22:47:15 +0530 |
commit | 9b53c7f9484fea5fa0fd23a6444b03071debc4f2 (patch) | |
tree | 9edd9a78f5e7b4e390f5ff538a6b2b5eacba8408 | |
parent | 027bde11d44d58e6ad473af3a69dc21b451bcbc0 (diff) | |
download | gcc-devel/nothrow-detection.zip gcc-devel/nothrow-detection.tar.gz gcc-devel/nothrow-detection.tar.bz2 |
Edge redirection for exceptions.devel/nothrow-detection
This commit is contains change in code for the tree-eh.cc, tree-eh.h, MAINTAINERS and tree-cfg.cc files.
Specifically it contains four functions -
1. void extract_exception_types_for_call which extracts the exception types in a call stmt and adds them into a vector tree.
2. bool stmt_throw_types does the same as stmt_could_throw the difference being that it also gives the list of exception types as given by the
extract_exception_types_for_call function.
3. bool match_lp checks if a landing pad can handle any of the exception types given as input parameters by looking into the catch handlers.
4. update_stmt_eh_region is the function that walks up the EH tree and changes the landing pad for the last statement in a basic block in the control
flow graph so that when the edge by make_eh_edge is created it points to the correct handlers.
Further work to be done regarding RESX stmts.
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | gcc/tree-cfg.cc | 5 | ||||
-rw-r--r-- | gcc/tree-eh.cc | 114 | ||||
-rw-r--r-- | gcc/tree-eh.h | 5 |
4 files changed, 123 insertions, 2 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 595140b..f26db19 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -915,6 +915,7 @@ information. Juergen Christ <jchrist@linux.ibm.com> Robin Dapp <rdapp.gcc@gmail.com> Robin Dapp <rdapp@ventanamicro.com> +Pranil Dey <mkdeyp@gmail.com> Michal Jires <mjires@suse.cz> Matthias Kretz <m.kretz@gsi.de> Prathamesh Kulkarni <prathameshk@nvidia.com> diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc index e6fd129..bb101c8 100644 --- a/gcc/tree-cfg.cc +++ b/gcc/tree-cfg.cc @@ -855,11 +855,12 @@ make_edges_bb (basic_block bb, struct omp_region **pcur_region, int *pomp_index) if (!last) return ret; - + + update_stmt_eh_region(last); switch (gimple_code (last)) { case GIMPLE_GOTO: - if (make_goto_expr_edges (bb)) + if (make_goto_expr_edges (bb)) ret = 1; fallthru = false; break; diff --git a/gcc/tree-eh.cc b/gcc/tree-eh.cc index 9609bdc..eec1e6a 100644 --- a/gcc/tree-eh.cc +++ b/gcc/tree-eh.cc @@ -2271,6 +2271,84 @@ make_eh_dispatch_edges (geh_dispatch *stmt) return true; } +// Check if a landing pad can handle any of the given exception types +bool match_lp(eh_landing_pad lp, vec<tree> *exception_types) { + eh_region region = lp->region; + + // Ensure the region is of type ERT_TRY + if (region && region->type == ERT_TRY) { + eh_catch_d *catch_handler = region->u.eh_try.first_catch; + + while (catch_handler) { + tree type_list = catch_handler->type_list; + + for (tree t = type_list; t; t = TREE_CHAIN(t)) { + tree type = TREE_VALUE(t); + for (unsigned i = 0; i < exception_types->length(); ++i) { + // match found or a catch-all handler (NULL) + if (type == (*exception_types)[i] || !type) { + return true; + } + } + } + catch_handler = catch_handler->next_catch; + } + } + return false; +} + +// Function to update landing pad in throw_stmt_table for a given statement +void update_stmt_eh_region(gimple *stmt) { + auto_vec<tree> exception_types; + if (!stmt_throw_types (cfun, stmt, &exception_types)) { + return; + } + + int lp_nr = lookup_stmt_eh_lp_fn(cfun, stmt); + if (lp_nr <= 0) { + return; + } + + eh_landing_pad lp = get_eh_landing_pad_from_number(lp_nr); + if (!lp) { + return; + } + + eh_region region = lp->region; + + // Walk up the region tree + while (region) { + switch (region->type) { + case ERT_CLEANUP: + *cfun->eh->throw_stmt_table->get(const_cast<gimple *>(stmt)) = lp->index; + return; + + case ERT_TRY: + if (match_lp(lp, &exception_types)) { + *cfun->eh->throw_stmt_table->get(const_cast<gimple *>(stmt)) = lp->index; + return; + } + break; + + case ERT_MUST_NOT_THROW: + // Undefined behavior, leave edge unchanged + return; + + case ERT_ALLOWED_EXCEPTIONS: + if (!match_lp(lp, &exception_types)) { + return; + } + break; + + default: + break; + } + region = region->outer; + } + + remove_stmt_from_eh_lp_fn(cfun, stmt); +} + /* Create the single EH edge from STMT to its nearest landing pad, if there is such a landing pad within the current function. */ @@ -2913,6 +2991,42 @@ stmt_could_throw_1_p (gassign *stmt) return false; } +void extract_exception_types_for_call (gcall *call_stmt, vec<tree> *ret_vector) { + tree callee = gimple_call_fndecl (call_stmt); + if (callee == NULL_TREE) { + return; + } + if (strcmp (IDENTIFIER_POINTER (DECL_NAME (callee)), "__cxa_throw") == 0) { + // Extracting exception type + tree exception_type_info = gimple_call_arg (call_stmt, 1); + if (exception_type_info && TREE_CODE (exception_type_info) == ADDR_EXPR) { + exception_type_info = TREE_OPERAND (exception_type_info, 0); + } + if (exception_type_info && TREE_CODE (exception_type_info) == VAR_DECL) { + // Converting the typeinfo to a compile-time type + tree exception_type = TREE_TYPE (exception_type_info); + if (exception_type) { + ret_vector->safe_push (exception_type); + } + } + } +} + +// Determine which types can be thrown by a GIMPLE statement and convert them to compile-time types +bool stmt_throw_types (function *fun, gimple *stmt, vec<tree> *ret_vector) { + if (!flag_exceptions) { + return false; + } + + switch (gimple_code (stmt)) { + case GIMPLE_CALL: + extract_exception_types_for_call (as_a<gcall*> (stmt), ret_vector); + return !ret_vector->is_empty (); + + default: + return false; + } +} /* Return true if statement STMT within FUN could throw an exception. */ diff --git a/gcc/tree-eh.h b/gcc/tree-eh.h index 2d3f765..f3b2c16 100644 --- a/gcc/tree-eh.h +++ b/gcc/tree-eh.h @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see typedef struct eh_region_d *eh_region; +typedef struct eh_landing_pad_d *eh_landing_pad; extern void using_eh_for_cleanups (void); extern void add_stmt_to_eh_lp (gimple *, int); @@ -30,6 +31,8 @@ extern bool remove_stmt_from_eh_lp (gimple *); extern int lookup_stmt_eh_lp_fn (struct function *, const gimple *); extern int lookup_stmt_eh_lp (const gimple *); extern bool make_eh_dispatch_edges (geh_dispatch *); +extern bool match_lp (eh_landing_pad, vec<tree> *); +extern void update_stmt_eh_region(gimple *); extern edge make_eh_edge (gimple *); extern edge redirect_eh_edge (edge, basic_block); extern void redirect_eh_dispatch_edge (geh_dispatch *, edge, basic_block); @@ -38,6 +41,8 @@ extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool, extern bool operation_could_trap_p (enum tree_code, bool, bool, tree); extern bool tree_could_trap_p (tree); extern tree rewrite_to_non_trapping_overflow (tree); +extern void extract_exception_types_for_call (gcall *, vec<tree> *); +extern bool stmt_throw_types (function *, gimple *, vec<tree> *); extern bool stmt_could_throw_p (function *, gimple *); extern bool stmt_unremovable_because_of_non_call_eh_p (function *, gimple *); extern bool tree_could_throw_p (tree); |