Formatting for all functions done according to GNU standards and fixed testsuite fail bugs

This commit is contained in:
Pranil Dey 2024-10-07 02:23:19 +05:30
parent f5b29909d5
commit c4ab1c5710
1 changed files with 270 additions and 206 deletions

View File

@ -2283,14 +2283,14 @@ same_or_derived_type (tree t1, tree t2)
t2 = TYPE_MAIN_VARIANT (t2); t2 = TYPE_MAIN_VARIANT (t2);
if (t1 == t2) if (t1 == t2)
return true; return true;
while ( (TREE_CODE (t1) == POINTER_TYPE || TREE_CODE (t1) == REFERENCE_TYPE) while ((TREE_CODE (t1) == POINTER_TYPE || TREE_CODE (t1) == REFERENCE_TYPE)
&& TREE_CODE (t1) == TREE_CODE (t2)) && TREE_CODE (t1) == TREE_CODE (t2))
{ {
t1 = TYPE_MAIN_VARIANT (TREE_TYPE (t1)); t1 = TYPE_MAIN_VARIANT (TREE_TYPE (t1));
t2 = TYPE_MAIN_VARIANT (TREE_TYPE (t2)); t2 = TYPE_MAIN_VARIANT (TREE_TYPE (t2));
if (TREE_CODE (t1) == VOID_TYPE) if (TREE_CODE (t1) == VOID_TYPE)
return true; return true;
} }
if (t1 == t2) if (t1 == t2)
return true; return true;
if (TREE_CODE (t2) == NULLPTR_TYPE && TREE_CODE (t1) == POINTER_TYPE) if (TREE_CODE (t2) == NULLPTR_TYPE && TREE_CODE (t1) == POINTER_TYPE)
@ -2300,153 +2300,186 @@ same_or_derived_type (tree t1, tree t2)
return odr_equivalent_or_derived_p (t1, t2); return odr_equivalent_or_derived_p (t1, t2);
} }
// Check if a landing pad can handle any of the given exception types // Check if a region can handle any of the given exception types
static bool match_lp (eh_region region, vec<tree> *exception_types){ static bool
// Ensure the region is of type ERT_TRY match_lp (eh_region region, vec<tree> *exception_types)
if (region && region->type == ERT_TRY) { {
eh_catch_d *catch_handler = region->u.eh_try.first_catch; // 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) { while (catch_handler)
tree type_list = catch_handler->type_list; {
tree type_list = catch_handler->type_list;
if (type_list == NULL) { if (type_list == NULL)
return true; {
return true;
} }
for (tree t = type_list; t; t = TREE_CHAIN (t)) { for (tree t = type_list; t; t = TREE_CHAIN (t))
tree type = TREE_VALUE (t); {
for (unsigned i = 0; i < exception_types->length (); ++i) { tree type = TREE_VALUE (t);
for (unsigned i = 0; i < exception_types->length (); ++i)
{
// match found or a catch-all handler (NULL) // match found or a catch-all handler (NULL)
if (!type || same_or_derived_type (type, (*exception_types)[i])) { if (!type
return true; || same_or_derived_type (type, (*exception_types)[i]))
{
return true;
} }
} }
} }
catch_handler = catch_handler->next_catch; catch_handler = catch_handler->next_catch;
} }
} }
return false; return false;
} }
static void unlink_eh_region(eh_region region) { static void
eh_region *link; unlink_eh_region (eh_region region)
{
eh_region *link;
// Check if region is root // Check if region is root
if (!region->outer) { if (!region->outer)
gcc_unreachable(); {
return; gcc_unreachable ();
}
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;
}
int lp_nr = lookup_stmt_eh_lp_fn (cfun, stmt);
if (lp_nr <= 0) {
return; return;
} }
eh_landing_pad lp = get_eh_landing_pad_from_number (lp_nr); link = &region->outer->inner;
if (!lp) {
return; while (*link && *link != region)
{
link = &(*link)->next_peer;
} }
eh_region region = lp->region; // Ensure the region is in the peer chain
eh_region resx_region = NULL; gcc_assert (*link == region);
bool update = false; *link = region->next_peer;
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 region->outer = NULL;
while (region) { region->next_peer = NULL;
switch (region->type) { }
case ERT_CLEANUP:
if (!update)
return;
if (gimple_code (stmt) == GIMPLE_RESX){ 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); unlink_eh_region (resx_region);
reinsert_eh_region (resx_region, region); reinsert_eh_region (resx_region, region);
} }
remove_stmt_from_eh_lp_fn (cfun, stmt); remove_stmt_from_eh_lp_fn (cfun, stmt);
record_stmt_eh_region (region, stmt); record_stmt_eh_region (region, stmt);
return; return;
}
break;
case ERT_TRY: case ERT_MUST_NOT_THROW:
if (match_lp (region, &exception_types)) { // Undefined behavior, leave edge unchanged
if (!update) return;
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); case ERT_ALLOWED_EXCEPTIONS:
record_stmt_eh_region (region, stmt); /* FIXME: match_lp will always return false. */
return; if (!match_lp (region, &exception_types))
} {
break; return;
}
break;
case ERT_MUST_NOT_THROW: default:
// Undefined behavior, leave edge unchanged break;
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; region = region->outer;
update = true; update = true;
} }
if (!update) if (!update)
return; return;
if (gimple_code (stmt) == GIMPLE_RESX){ if (gimple_code (stmt) == GIMPLE_RESX)
{
unlink_eh_region (resx_region); unlink_eh_region (resx_region);
reinsert_eh_region (resx_region, NULL); reinsert_eh_region (resx_region, NULL);
} }
remove_stmt_from_eh_lp_fn (cfun, stmt); remove_stmt_from_eh_lp_fn (cfun, stmt);
} }
/* Create the single EH edge from STMT to its nearest landing pad, /* Create the single EH edge from STMT to its nearest landing pad,
@ -3091,91 +3124,114 @@ stmt_could_throw_1_p (gassign *stmt)
return false; return false;
} }
bool extract_types_for_call (gcall *call_stmt, vec<tree> *ret_vector) { bool
tree callee = gimple_call_fndecl (call_stmt); extract_types_for_call (gcall *call_stmt, vec<tree> *ret_vector)
if (callee == NULL_TREE) { {
return false; tree callee = gimple_call_fndecl (call_stmt);
if (callee == NULL_TREE)
{
return false;
} }
if (strcmp (IDENTIFIER_POINTER (DECL_NAME (callee)), "__cxa_throw") == 0) { if (strcmp (IDENTIFIER_POINTER (DECL_NAME (callee)), "__cxa_throw") == 0)
// Extracting exception type {
tree exception_type_info = gimple_call_arg (call_stmt, 1); // Extracting exception type
if (exception_type_info && TREE_CODE (exception_type_info) == ADDR_EXPR) { tree exception_type_info = gimple_call_arg (call_stmt, 1);
exception_type_info = TREE_OPERAND (exception_type_info, 0); 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) { 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)); // Converting the typeinfo to a compile-time type
if (exception_type) { tree exception_type
ret_vector->safe_push (exception_type); = TREE_TYPE (decl_assembler_name (exception_type_info));
if (exception_type)
{
ret_vector->safe_push (exception_type);
} }
} }
return true; return true;
} }
return false; return false;
} }
// Determine which types can be thrown by a GIMPLE statement and convert them to compile-time types /* Determine which types can be thrown by a GIMPLE statement and convert them
bool stmt_throw_types (function *fun, gimple *stmt, vec<tree> *ret_vector) { * to compile-time types */
if (!flag_exceptions) { bool
return false; stmt_throw_types (function *, gimple *stmt, vec<tree> *ret_vector)
{
if (!flag_exceptions)
{
return false;
} }
bool type_exists = true; bool type_exists = true;
switch (gimple_code (stmt)) { switch (gimple_code (stmt))
case GIMPLE_RESX: {
type_exists = extract_types_for_resx (as_a<gresx*> (stmt), ret_vector); case GIMPLE_RESX:
return type_exists; type_exists = extract_types_for_resx (as_a<gresx *> (stmt), ret_vector);
return type_exists;
case GIMPLE_CALL: case GIMPLE_CALL:
type_exists = extract_types_for_call (as_a<gcall*> (stmt), ret_vector); type_exists = extract_types_for_call (as_a<gcall *> (stmt), ret_vector);
/* FIXME: if type exists we should have always vector nonempty. */ /* FIXME: if type exists we should have always vector nonempty. */
return type_exists && !ret_vector->is_empty (); return type_exists && !ret_vector->is_empty ();
default: default:
return false; return false;
} }
} }
// To get the all exception types from a resx stmt // To get the all exception types from a resx stmt
static bool extract_types_for_resx (basic_block bb, vec<tree> *ret_vector) { static bool
edge e; extract_types_for_resx (basic_block bb, vec<tree> *ret_vector)
edge_iterator ei; {
edge e;
edge_iterator ei;
// Iterate over edges to walk up the basic blocks // Iterate over edges to walk up the basic blocks
FOR_EACH_EDGE (e, ei, bb->preds) FOR_EACH_EDGE (e, ei, bb->preds)
{ {
// Get the last stmt of the basic block as it is an EH stmt // Get the last stmt of the basic block as it is an EH stmt
bb = e->src; bb = e->src;
gimple_stmt_iterator gsi = gsi_last_bb (bb); gimple_stmt_iterator gsi = gsi_last_bb (bb);
gimple *last_stmt = gsi_stmt (gsi); gimple *last_stmt = gsi_stmt (gsi);
if (bb->aux)continue; if (bb->aux)
bb->aux = (void*)1; continue;
bb->aux = (void *)1;
if (last_stmt && (e->flags & EDGE_EH)){
if (gimple_code (last_stmt) == GIMPLE_CALL) { if (last_stmt && (e->flags & EDGE_EH))
// check if its a throw {
if (!extract_types_for_call (as_a<gcall*> (last_stmt), ret_vector)) if (gimple_code (last_stmt) == GIMPLE_CALL)
return false; {
continue; // 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;
}
} }
else if (gimple_code (last_stmt) == GIMPLE_RESX){
// Recursively processing resx
extract_types_for_resx (last_stmt, ret_vector);
continue;
}
}
/* FIXME: remove recursion here, so we do not run out of stack. */ /* FIXME: remove recursion here, so we do not run out of stack. */
else if (!extract_types_for_resx (last_stmt, ret_vector)) else if (!extract_types_for_resx (e->src, ret_vector))
return false; return false;
} }
return true; return true;
} }
// To get the all exception types from a resx stmt // To get the all exception types from a resx stmt
bool extract_types_for_resx (gimple *resx_stmt, vec<tree> *ret_vector) { bool
extract_types_for_resx (gimple *resx_stmt, vec<tree> *ret_vector)
{
basic_block bb = gimple_bb (resx_stmt); basic_block bb = gimple_bb (resx_stmt);
bool ret = extract_types_for_resx (bb, ret_vector); bool ret = extract_types_for_resx (bb, ret_vector);
/* FIXME: this is non-linear. */ /* FIXME: this is non-linear. */
@ -3184,40 +3240,48 @@ bool extract_types_for_resx (gimple *resx_stmt, vec<tree> *ret_vector) {
} }
// To get the types being thrown outside of a function // To get the types being thrown outside of a function
bool extract_fun_resx_types (function *fun, vec<tree> *ret_vector) { bool
basic_block bb; extract_fun_resx_types (function *fun, vec<tree> *ret_vector)
gimple_stmt_iterator gsi; {
basic_block bb;
gimple_stmt_iterator gsi;
hash_set<tree> types; hash_set<tree> types;
FOR_EACH_BB_FN (bb, fun) FOR_EACH_BB_FN (bb, fun)
{ {
bb->aux = (void*)1; bb->aux = (void *)1;
gsi = gsi_last_bb (bb); gsi = gsi_last_bb (bb);
gimple *stmt = gsi_stmt (gsi); gimple *stmt = gsi_stmt (gsi);
auto_vec<tree> resx_types; auto_vec<tree> resx_types;
if (!stmt || !stmt_can_throw_external (fun, stmt)) if (!stmt || !stmt_can_throw_external (fun, stmt))
continue; 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){ if (gimple_code (stmt) == GIMPLE_RESX)
tree type = resx_types[i]; {
types.add (type); if (!extract_types_for_resx (stmt, &resx_types))
} return false;
} }
for (auto it = types.begin (); it != types.end (); ++it) { else if (gimple_code (stmt) == GIMPLE_CALL)
ret_vector->safe_push (*it); {
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. */ /* Return true if statement STMT within FUN could throw an exception. */