https://gcc.gnu.org/g:8aba3758c4fe9acff8919a6f716c81021a482cb8
commit 8aba3758c4fe9acff8919a6f716c81021a482cb8 Author: Mikael Morin <mik...@gcc.gnu.org> Date: Thu Mar 6 10:55:01 2025 +0100 Prise en charges des functions sans valeur de retour + free Diff: --- gcc/cgraphunit.cc | 96 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 72 insertions(+), 24 deletions(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index cc59fece0984..c7c2e2f2e24f 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -213,6 +213,7 @@ along with GCC; see the file COPYING3. If not see #include "wide-int.h" #include "selftest.h" #include "tree-ssanames.h" +#include <optional> /* Queue of cgraph nodes scheduled to be added into cgraph. This is a secondary queue used during optimization to accommodate passes that @@ -2590,7 +2591,7 @@ public: }; -static data_value +static std::optional <data_value> execute (struct function *func, exec_context &caller, context_printer & printer, vec<tree> * args); @@ -2656,7 +2657,7 @@ public: data_storage & get_storage (unsigned idx) const; context_printer & get_printer () const { return printer; } data_value evaluate (tree expr) const; - data_value execute_function (struct function *); + std::optional <data_value> execute_function (struct function *); edge select_leaving_edge (basic_block bb, gimple *last_stmt); void jump (edge e); }; @@ -4137,11 +4138,39 @@ exec_context::execute_assign (gassign *g) } +static bool +is_ignored_function_call (gcall *g) +{ + if (gimple_call_builtin_p (g, BUILT_IN_FREE)) + return true; + + tree fn = gimple_call_fn (g); + if (TREE_CODE (fn) == ADDR_EXPR) + fn = TREE_OPERAND (fn, 0); + gcc_assert (TREE_CODE (fn) == FUNCTION_DECL); + const char *fn_name = IDENTIFIER_POINTER (DECL_NAME (fn)); + if (strcmp (fn_name, "_gfortran_set_args") == 0 + || strcmp (fn_name, "_gfortran_set_options") == 0) + return true; + + return false; +} + + + void exec_context::execute_call (gcall *g) { + if (is_ignored_function_call (g)) + return; + + tree lhs = gimple_call_lhs (g); + std::optional <data_value> result; if (gimple_call_builtin_p (g, BUILT_IN_MALLOC)) { + gcc_assert (lhs != NULL_TREE); + result.emplace (data_value (TREE_TYPE (lhs))); + gcc_assert (gimple_call_num_args (g) == 1); tree arg = gimple_call_arg (g, 0); data_value size = evaluate (arg); @@ -4151,16 +4180,8 @@ exec_context::execute_call (gcall *g) HOST_WIDE_INT alloc_amount = wi_size.to_uhwi (); data_storage &storage = allocate (alloc_amount); - tree lhs = gimple_call_lhs (g); - gcc_assert (lhs != NULL_TREE); - data_value ptr (TREE_TYPE (lhs)); storage_address address (storage.get_ref (), 0); - ptr.set_address (address); - - printer.print_value_update (*this, lhs, ptr); - data_storage *lhs_strg = find_var (lhs); - gcc_assert (lhs_strg != nullptr); - lhs_strg->set (ptr); + result->set_address (address); } else { @@ -4168,12 +4189,7 @@ exec_context::execute_call (gcall *g) if (TREE_CODE (fn) == ADDR_EXPR) fn = TREE_OPERAND (fn, 0); gcc_assert (TREE_CODE (fn) == FUNCTION_DECL); - const char *fn_name = IDENTIFIER_POINTER (DECL_NAME (fn)); - if (strcmp (fn_name, "_gfortran_set_args") == 0 - || strcmp (fn_name, "_gfortran_set_options") == 0) - return; - tree lhs = gimple_call_lhs (g); unsigned nargs = gimple_call_num_args (g); auto_vec <tree> arguments; arguments.reserve (nargs); @@ -4181,13 +4197,17 @@ exec_context::execute_call (gcall *g) for (unsigned i = 0; i < nargs; i++) arguments.quick_push (gimple_call_arg (g, i)); - data_value result = ::execute (DECL_STRUCT_FUNCTION (fn), *this, printer, - &arguments); - printer.print_value_update (*this, lhs, result); - data_storage *lhs_strg = find_var (lhs); - gcc_assert (lhs_strg != nullptr); - lhs_strg->set (result); + result = ::execute (DECL_STRUCT_FUNCTION (fn), *this, printer, + &arguments); } + + if (lhs == NULL_TREE) + return; + + printer.print_value_update (*this, lhs, *result); + data_storage *lhs_strg = find_var (lhs); + gcc_assert (lhs_strg != nullptr); + lhs_strg->set (*result); } @@ -4303,7 +4323,7 @@ exec_context::jump (edge e) } -data_value +std::optional <data_value> exec_context::execute_function (struct function *func) { printer.print_function_entry (func); @@ -4321,19 +4341,26 @@ exec_context::execute_function (struct function *func) break; } + if (bb == EXIT_BLOCK_PTR_FOR_FN (func)) + break; + edge e = select_leaving_edge (bb, last_stmt); jump (e); bb = e->dest; } + if (final_stmt == nullptr) + return {}; tree retexpr = gimple_return_retval (final_stmt); + if (retexpr == NULL_TREE) + return {}; data_value result = evaluate (retexpr); printer.print_function_exit (func); return result; } -static data_value +static std::optional <data_value> execute (struct function * func, exec_context & caller, context_printer & printer, vec<tree> * arg_values) { @@ -7137,6 +7164,27 @@ exec_context_execute_call_tests () data_value p_val5 = p_strg5->get_value (); ASSERT_EQ (p_val5.classify (), VAL_ADDRESS); ASSERT_EQ (&p_val5.get_address ()->storage.get (), alloc_strg5); + + + tree simple_type = build_function_type (void_type_node, NULL_TREE); + layout_type (simple_type); + + exec_context ctx6 = context_builder ().build (mem, printer); + + tree simple_func = build_decl (input_location, FUNCTION_DECL, + get_identifier ("simple_func"), + simple_type); + tree void_result = build_decl (input_location, RESULT_DECL, + get_identifier ("void_result"), + void_type_node); + DECL_CONTEXT (void_result) = simple_func; + DECL_RESULT (simple_func) = void_result; + + init_lowered_empty_function (simple_func, true, profile_count::one ()); + + gcall * simple_call = gimple_build_call (simple_func, 0); + + ctx6.execute (simple_call); } void