aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPranil Dey <mkdeyp@gmail.com>2024-08-20 22:07:57 +0530
committerPranil Dey <mkdeyp@gmail.com>2024-08-20 22:47:15 +0530
commit9b53c7f9484fea5fa0fd23a6444b03071debc4f2 (patch)
tree9edd9a78f5e7b4e390f5ff538a6b2b5eacba8408
parent027bde11d44d58e6ad473af3a69dc21b451bcbc0 (diff)
downloadgcc-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--MAINTAINERS1
-rw-r--r--gcc/tree-cfg.cc5
-rw-r--r--gcc/tree-eh.cc114
-rw-r--r--gcc/tree-eh.h5
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);