Compare commits

...

23 Commits

Author SHA1 Message Date
Pranil Dey
c756ee328c Fixed extract_types_for_resx function
The function was recursive in nature and there is a chance of runnign out of stack, so now ann iterative approach was used to get the types for resx
2024-10-25 00:57:07 +05:30
Pranil Dey
c4ab1c5710 Formatting for all functions done according to GNU standards and fixed testsuite fail bugs 2024-10-07 02:23:24 +05:30
Pranil Dey
f5b29909d5 Added function bool extract_types_for_resx and fixed more functions for testcases
1. bool extract_types_for_resx (gimple *,vec<tree> *) - This is for intiating the function static bool extract_types_for_resx (basic_block, vec<tree> *)
which gets the resx stmt from a basic block and aclears the aux value for all blocks
2. update_stmt_eh_region - This is changed to unlink and reinsert the regions incase of a resx stmt properly
2024-10-06 18:25:27 +05:30
Pranil Dey
da431b3514 Updated code for unlinking regions and update stmt_eh_regions as well 2024-10-05 10:26:15 +05:30
Pranil Dey
cd716809b8 Updated code for unlinking regions 2024-10-04 13:12:12 +05:30
Pranil Dey
0d0df5179b Updated code for inserting regions and changed the return parameters of extract_types_for call 2024-10-03 10:11:07 +05:30
Pranil Dey
1a736e2570 Added code for inserting regions 2024-10-01 19:50:42 +05:30
Pranil Dey
132a0acfde Updated tree-eh.h 2024-10-01 10:32:27 +05:30
Pranil Dey
27be11a6b2 resolved more conflicts 2024-10-01 10:12:35 +05:30
Pranil Dey
5a924600ea removed conflicts 2024-10-01 10:10:17 +05:30
Pranil Dey
97933e9596 Reolved some conflicts 2024-10-01 10:03:43 +05:30
Pranil Dey
5f1a438ba6 Added functions extract_fun_resx_types 2024-10-01 10:00:59 +05:30
Pranil Dey
6db81730ef Merge remote-tracking branch 'origin/devel/nothrow-detection' into devel/nothrow-detection 2024-10-01 10:00:26 +05:30
Pranil Dey
079ca47d41 Updated parameters of functions and typecasted resx stmts 2024-10-01 09:48:04 +05:30
Pranil Dey
7ec7872003 Integrated the resx functions with stmt_throw_types
update_stmt_eh_region updated for resx stmt support and extract_fun_resx_types fixed
2024-10-01 09:48:04 +05:30
Pranil Dey
47c2d0f6e0 Added the previous functions to the tree-eh.h file
Functions added:
1. void extract_types_for_resx (gimple *, vec<tree> *);
2. void extract_fun_resx_types (function *);
2024-10-01 09:48:04 +05:30
Pranil Dey
d1a84d379d RESX statement processing functions added:
1. extract_types_for_resx - Used as a helper for getting the types from a resx statement to use later in the extract_fun_resx_types
2. extract_fun_resx_types - Used for getting the types thrown and propagated outside a function
2024-10-01 09:48:04 +05:30
Pranil Dey
70505f5757 Fixed some indentations and function names
1. Changed function name extract_exception_types_for_call to extract_types_for_call due to length of the name
2. Fixed space indentation in some places
2024-10-01 09:48:04 +05:30
Pranil Dey
ba70ece436 Added some functions and fixed some testcase failures
1. odr_equivalent_or_derived_p in ipa-devirt.cc
2. same_or_derived_type in in tree-eh.cc
3. Fixed catch-all handling in match_lp function
2024-10-01 09:48:04 +05:30
Pranil Dey
9a70651a21 Edge redirection for exceptions.
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.
2024-10-01 09:48:03 +05:30
Pranil Dey
b602de4ed9 Merge branch 'master' of git+ssh://gcc.gnu.org/git/gcc into devel/nothrow-detection 2024-09-30 19:03:42 +05:30
Jan Hubicka
c16d4a0ae1 Fix handling of types
* ipa-devirt.cc (odr_equivalent_or_derived_p): New.
	* ipa-utils.h (odr_equivalent_or_derived_p): Declare.
	* tree-eh.cc (same_or_derived_type): New.
	(match_lp): Use it.
2024-08-27 13:50:32 +02:00
Pranil Dey
9b53c7f948 Edge redirection for exceptions.
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.
2024-08-20 22:47:15 +05:30
5 changed files with 404 additions and 2 deletions

View File

@@ -1211,6 +1211,30 @@ skip_in_fields_list_p (tree t)
return false;
}
/* Return true if T2 is derived form T1. */
bool
odr_equivalent_or_derived_p (tree t1, tree t2)
{
if (in_lto_p)
{
if (odr_types_equivalent_p (t1, t2))
return true;
}
else
{
if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return true;
}
if (!TYPE_BINFO (t2))
return false;
for (unsigned int i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (t2)); i++)
if (odr_equivalent_or_derived_p
(t1, BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (t2), i))))
return true;
return false;
}
/* Compare T1 and T2, report ODR violations if WARN is true and set
WARNED to true if anything is reported. Return true if types match.
If true is returned, the types are also compatible in the sense of

View File

@@ -106,6 +106,7 @@ cgraph_node *try_speculative_devirtualization (tree, HOST_WIDE_INT,
void warn_types_mismatch (tree t1, tree t2, location_t loc1 = UNKNOWN_LOCATION,
location_t loc2 = UNKNOWN_LOCATION);
bool odr_or_derived_type_p (const_tree t);
bool odr_equivalent_or_derived_p (tree t1, tree t2);
bool odr_types_equivalent_p (tree type1, tree type2);
bool odr_type_violation_reported_p (tree type);
tree prevailing_odr_type (tree type);

View File

@@ -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;

View File

@@ -47,6 +47,11 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "asan.h"
#include "gimplify.h"
#include "print-tree.h"
#include "ipa-utils.h"
#include "print-tree.h"
#include "ipa-utils.h"
#include "hash-set.h"
/* In some instances a tree and a gimple need to be stored in a same table,
i.e. in hash tables. This is a structure to do this. */
@@ -2271,6 +2276,212 @@ make_eh_dispatch_edges (geh_dispatch *stmt)
return true;
}
static bool
same_or_derived_type (tree t1, tree t2)
{
t1 = TYPE_MAIN_VARIANT (t1);
t2 = TYPE_MAIN_VARIANT (t2);
if (t1 == t2)
return true;
while ((TREE_CODE (t1) == POINTER_TYPE || TREE_CODE (t1) == REFERENCE_TYPE)
&& TREE_CODE (t1) == TREE_CODE (t2))
{
t1 = TYPE_MAIN_VARIANT (TREE_TYPE (t1));
t2 = TYPE_MAIN_VARIANT (TREE_TYPE (t2));
if (TREE_CODE (t1) == VOID_TYPE)
return true;
}
if (t1 == t2)
return true;
if (TREE_CODE (t2) == NULLPTR_TYPE && TREE_CODE (t1) == POINTER_TYPE)
return true;
if (!AGGREGATE_TYPE_P (t1) || !AGGREGATE_TYPE_P (t2))
return false;
return odr_equivalent_or_derived_p (t1, t2);
}
// Check if a region can handle any of the given exception types
static bool
match_lp (eh_region region, vec<tree> *exception_types)
{
// 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;
if (type_list == NULL)
{
return true;
}
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
|| same_or_derived_type (type, (*exception_types)[i]))
{
return true;
}
}
}
catch_handler = catch_handler->next_catch;
}
}
return false;
}
static void
unlink_eh_region (eh_region region)
{
eh_region *link;
// Check if region is root
if (!region->outer)
{
gcc_unreachable ();
return;
}
link = &region->outer->inner;
while (*link && *link != region)
{
link = &(*link)->next_peer;
}
// Ensure the region is in the peer chain
gcc_assert (*link == region);
*link = region->next_peer;
region->outer = NULL;
region->next_peer = NULL;
}
static void
reinsert_eh_region (eh_region region, eh_region new_outer)
{
region->outer = new_outer;
// Insert region as the inner of new_outer, or at the top of the tree
if (new_outer)
{
region->next_peer = new_outer->inner;
new_outer->inner = region;
}
else
{
region->next_peer = cfun->eh->region_tree;
cfun->eh->region_tree = region;
}
}
/* Function to update landing pad and region 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;
}
eh_region region;
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;
}
region = lp->region;
eh_region resx_region = NULL;
bool update = false;
if (gimple_code (stmt) == GIMPLE_RESX)
resx_region = get_eh_region_from_number (
gimple_resx_region (as_a<gresx *> (stmt)));
// Walk up the region tree
while (region)
{
switch (region->type)
{
case ERT_CLEANUP:
if (!update)
return;
if (gimple_code (stmt) == GIMPLE_RESX)
{
unlink_eh_region (resx_region);
reinsert_eh_region (resx_region, region);
}
remove_stmt_from_eh_lp_fn (cfun, stmt);
record_stmt_eh_region (region, stmt);
return;
case ERT_TRY:
if (match_lp (region, &exception_types))
{
if (!update)
return;
if (gimple_code (stmt) == GIMPLE_RESX)
{
unlink_eh_region (resx_region);
reinsert_eh_region (resx_region, region);
}
remove_stmt_from_eh_lp_fn (cfun, stmt);
record_stmt_eh_region (region, stmt);
return;
}
break;
case ERT_MUST_NOT_THROW:
// Undefined behavior, leave edge unchanged
return;
case ERT_ALLOWED_EXCEPTIONS:
/* FIXME: match_lp will always return false. */
if (!match_lp (region, &exception_types))
{
return;
}
break;
default:
break;
}
region = region->outer;
update = true;
}
if (!update)
return;
if (gimple_code (stmt) == GIMPLE_RESX)
{
unlink_eh_region (resx_region);
reinsert_eh_region (resx_region, NULL);
}
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 +3124,164 @@ stmt_could_throw_1_p (gassign *stmt)
return false;
}
bool
extract_types_for_call (gcall *call_stmt, vec<tree> *ret_vector)
{
tree callee = gimple_call_fndecl (call_stmt);
if (callee == NULL_TREE)
{
return false;
}
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 (decl_assembler_name (exception_type_info));
if (exception_type)
{
ret_vector->safe_push (exception_type);
}
}
return true;
}
return false;
}
/* Determine which types can be thrown by a GIMPLE statement and convert them
* to compile-time types */
bool
stmt_throw_types (function *, gimple *stmt, vec<tree> *ret_vector)
{
if (!flag_exceptions)
{
return false;
}
bool type_exists = true;
switch (gimple_code (stmt))
{
case GIMPLE_RESX:
type_exists = extract_types_for_resx (as_a<gresx *> (stmt), ret_vector);
return type_exists;
case GIMPLE_CALL:
type_exists = extract_types_for_call (as_a<gcall *> (stmt), ret_vector);
/* FIXME: if type exists we should have always vector nonempty. */
return type_exists && !ret_vector->is_empty ();
default:
return false;
}
}
// To get the all exception types from a resx stmt (iterative version)
bool
extract_types_for_resx (gimple *resx_stmt, vec<tree> *ret_vector)
{
basic_block start_bb = gimple_bb (resx_stmt);
hash_set<basic_block> visited_blocks;
vec<basic_block> block_stack;
block_stack.safe_push(start_bb);
while (!block_stack.is_empty())
{
basic_block bb = block_stack.pop();
if (visited_blocks.contains(bb))
continue;
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)
{
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);
}
}
else
{
block_stack.safe_push(pred_bb);
}
}
}
clear_aux_for_blocks();
return true;
}
// To get the types being thrown outside of a function
bool
extract_fun_resx_types (function *fun, vec<tree> *ret_vector)
{
basic_block bb;
gimple_stmt_iterator gsi;
hash_set<tree> types;
FOR_EACH_BB_FN (bb, fun)
{
bb->aux = (void *)1;
gsi = gsi_last_bb (bb);
gimple *stmt = gsi_stmt (gsi);
auto_vec<tree> resx_types;
if (!stmt || !stmt_can_throw_external (fun, stmt))
continue;
if (gimple_code (stmt) == GIMPLE_RESX)
{
if (!extract_types_for_resx (stmt, &resx_types))
return false;
}
else if (gimple_code (stmt) == GIMPLE_CALL)
{
if (!extract_types_for_call (as_a<gcall *> (stmt), &resx_types))
return false;
}
for (unsigned i = 0; i < resx_types.length (); ++i)
{
tree type = resx_types[i];
types.add (type);
}
}
for (auto it = types.begin (); it != types.end (); ++it)
{
ret_vector->safe_push (*it);
}
return true;
}
/* Return true if statement STMT within FUN could throw an exception. */

View File

@@ -22,6 +22,8 @@ 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;
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 +32,7 @@ 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 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,10 @@ 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 bool extract_types_for_call (gcall *, vec<tree> *);
extern bool stmt_throw_types (function *, gimple *, vec<tree> *);
extern bool extract_types_for_resx (gimple *, vec<tree> *);
extern bool extract_fun_resx_types (function *, 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);