From bfc139e2b190187cb8478f8858cbce6ab9c5d4e7 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 19 Nov 2020 12:18:37 -0800 Subject: [PATCH] c++: Expose constexpr hash table This patch exposes the constexpr hash table so that the modules machinery can save and load constexpr bodies. While there I noticed that we could do a little constification of the hasher and comparator functions. Also combine the saving machinery to a single function returning void -- nothing ever looked at its return value. gcc/cp/ * cp-tree.h (struct constexpr_fundef): Moved from constexpr.c. (maybe_save_constexpr_fundef): Declare. (register_constexpr_fundef): Take constexpr_fundef object, return void. * decl.c (mabe_save_function_definition): Delete, functionality moved to maybe_save_constexpr_fundef. (emit_coro_helper, finish_function): Adjust. * constexpr.c (struct constexpr_fundef): Moved to cp-tree.h. (constexpr_fundef_hasher::equal): Constify. (constexpr_fundef_hasher::hash): Constify. (retrieve_constexpr_fundef): Make non-static. (maybe_save_constexpr_fundef): Break out checking and duplication from ... (register_constexpr_fundef): ... here. Just register the constexpr. --- gcc/cp/constexpr.c | 89 +++++++++++++++++++++++----------------------- gcc/cp/cp-tree.h | 13 ++++++- gcc/cp/decl.c | 18 ++-------- 3 files changed, 59 insertions(+), 61 deletions(-) diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index e6ab5eecd68..625410327b8 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -133,19 +133,10 @@ ensure_literal_type_for_constexpr_object (tree decl) return decl; } -/* Representation of entries in the constexpr function definition table. */ - -struct GTY((for_user)) constexpr_fundef { - tree decl; - tree body; - tree parms; - tree result; -}; - struct constexpr_fundef_hasher : ggc_ptr_hash { - static hashval_t hash (constexpr_fundef *); - static bool equal (constexpr_fundef *, constexpr_fundef *); + static hashval_t hash (const constexpr_fundef *); + static bool equal (const constexpr_fundef *, const constexpr_fundef *); }; /* This table holds all constexpr function definitions seen in @@ -158,7 +149,8 @@ static GTY (()) hash_table *constexpr_fundef_table; same constexpr function. */ inline bool -constexpr_fundef_hasher::equal (constexpr_fundef *lhs, constexpr_fundef *rhs) +constexpr_fundef_hasher::equal (const constexpr_fundef *lhs, + const constexpr_fundef *rhs) { return lhs->decl == rhs->decl; } @@ -167,20 +159,20 @@ constexpr_fundef_hasher::equal (constexpr_fundef *lhs, constexpr_fundef *rhs) Return a hash value for the entry pointed to by Q. */ inline hashval_t -constexpr_fundef_hasher::hash (constexpr_fundef *fundef) +constexpr_fundef_hasher::hash (const constexpr_fundef *fundef) { return DECL_UID (fundef->decl); } /* Return a previously saved definition of function FUN. */ -static constexpr_fundef * +constexpr_fundef * retrieve_constexpr_fundef (tree fun) { if (constexpr_fundef_table == NULL) return NULL; - constexpr_fundef fundef = { fun, NULL, NULL, NULL }; + constexpr_fundef fundef = { fun, NULL_TREE, NULL_TREE, NULL_TREE }; return constexpr_fundef_table->find (&fundef); } @@ -669,7 +661,7 @@ get_function_named_in_call (tree t) return fun; } -/* Subroutine of register_constexpr_fundef. BODY is the body of a function +/* Subroutine of check_constexpr_fundef. BODY is the body of a function declared to be constexpr, or a sub-statement thereof. Returns the return value if suitable, error_mark_node for a statement not allowed in a constexpr function, or NULL_TREE if no return value was found. */ @@ -738,7 +730,7 @@ constexpr_fn_retval (tree body) } } -/* Subroutine of register_constexpr_fundef. BODY is the DECL_SAVED_TREE of +/* Subroutine of check_constexpr_fundef. BODY is the DECL_SAVED_TREE of FUN; do the necessary transformations to turn it into a single expression that we can store in the hash table. */ @@ -868,27 +860,28 @@ cx_check_missing_mem_inits (tree ctype, tree body, bool complain) } /* We are processing the definition of the constexpr function FUN. - Check that its BODY fulfills the propriate requirements and - enter it in the constexpr function definition table. - For constructor BODY is actually the TREE_LIST of the - member-initializer list. */ + Check that its body fulfills the apropriate requirements and + enter it in the constexpr function definition table. */ -tree -register_constexpr_fundef (tree fun, tree body) +void +maybe_save_constexpr_fundef (tree fun) { - constexpr_fundef entry; - constexpr_fundef **slot; + if (processing_template_decl + || !DECL_DECLARED_CONSTEXPR_P (fun) + || cp_function_chain->invalid_constexpr + || DECL_CLONED_FUNCTION_P (fun)) + return; if (!is_valid_constexpr_fn (fun, !DECL_GENERATED_P (fun))) - return NULL; + return; - tree massaged = massage_constexpr_body (fun, body); + tree massaged = massage_constexpr_body (fun, DECL_SAVED_TREE (fun)); if (massaged == NULL_TREE || massaged == error_mark_node) { if (!DECL_CONSTRUCTOR_P (fun)) error ("body of % function %qD not a return-statement", fun); - return NULL; + return; } bool potential = potential_rvalue_constant_expression (massaged); @@ -901,39 +894,47 @@ register_constexpr_fundef (tree fun, tree body) potential = false; if (!potential && !DECL_GENERATED_P (fun)) - return NULL; - - /* Create the constexpr function table if necessary. */ - if (constexpr_fundef_table == NULL) - constexpr_fundef_table - = hash_table::create_ggc (101); + return; - entry.decl = fun; - tree saved_fn = current_function_decl; + constexpr_fundef entry = {fun, NULL_TREE, NULL_TREE, NULL_TREE}; bool clear_ctx = false; - current_function_decl = fun; if (DECL_RESULT (fun) && DECL_CONTEXT (DECL_RESULT (fun)) == NULL_TREE) { clear_ctx = true; DECL_CONTEXT (DECL_RESULT (fun)) = fun; } - entry.body = copy_fn (fun, entry.parms, entry.result); + tree saved_fn = current_function_decl; + current_function_decl = fun; + entry.body = copy_fn (entry.decl, entry.parms, entry.result); current_function_decl = saved_fn; - slot = constexpr_fundef_table->find_slot (&entry, INSERT); if (clear_ctx) - DECL_CONTEXT (DECL_RESULT (fun)) = NULL_TREE; - + DECL_CONTEXT (DECL_RESULT (entry.decl)) = NULL_TREE; if (!potential) /* For a template instantiation, we want to remember the pre-generic body for explain_invalid_constexpr_fn, but do tell cxx_eval_call_expression that it doesn't need to bother trying to expand the function. */ entry.result = error_mark_node; + register_constexpr_fundef (entry); +} + +/* BODY is a validated and massaged definition of a constexpr + function. Register it in the hash table. */ + +void +register_constexpr_fundef (const constexpr_fundef &value) +{ + /* Create the constexpr function table if necessary. */ + if (constexpr_fundef_table == NULL) + constexpr_fundef_table + = hash_table::create_ggc (101); + + constexpr_fundef **slot = constexpr_fundef_table->find_slot + (const_cast (&value), INSERT); + gcc_assert (*slot == NULL); *slot = ggc_alloc (); - **slot = entry; - - return fun; + **slot = value; } /* FUN is a non-constexpr function called in a context that requires a diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 81485de94f9..0c4b74a8895 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7895,9 +7895,20 @@ extern void vtv_recover_class_info (void); extern void vtv_build_vtable_verify_fndecl (void); /* In constexpr.c */ +/* Representation of entries in the constexpr function definition table. */ + +struct GTY((for_user)) constexpr_fundef { + tree decl; + tree body; + tree parms; + tree result; +}; + extern void fini_constexpr (void); extern bool literal_type_p (tree); -extern tree register_constexpr_fundef (tree, tree); +extern void maybe_save_constexpr_fundef (tree); +extern void register_constexpr_fundef (const constexpr_fundef &); +extern constexpr_fundef *retrieve_constexpr_fundef (tree); extern bool is_valid_constexpr_fn (tree, bool); extern bool check_constexpr_ctor_body (tree, tree, bool); extern tree constexpr_fn_retval (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index f5c6f5c0d10..1c6dcdb74db 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -16872,20 +16872,6 @@ record_key_method_defined (tree fndecl) } } -/* Subroutine of finish_function. - Save the body of constexpr functions for possible - future compile time evaluation. */ - -static void -maybe_save_function_definition (tree fun) -{ - if (!processing_template_decl - && DECL_DECLARED_CONSTEXPR_P (fun) - && !cp_function_chain->invalid_constexpr - && !DECL_CLONED_FUNCTION_P (fun)) - register_constexpr_fundef (fun, DECL_SAVED_TREE (fun)); -} - /* Attempt to add a fix-it hint to RICHLOC suggesting the insertion of "return *this;" immediately before its location, using FNDECL's first statement (if any) to give the indentation, if appropriate. */ @@ -16919,7 +16905,7 @@ emit_coro_helper (tree helper) allocate_struct_function (helper, false); cfun->language = ggc_cleared_alloc (); poplevel (1, 0, 1); - maybe_save_function_definition (helper); + maybe_save_constexpr_fundef (helper); /* We must start each function with a clear fold cache. */ clear_fold_cache (); cp_fold_function (helper); @@ -17153,7 +17139,7 @@ finish_function (bool inline_p) /* Save constexpr function body before it gets munged by the NRV transformation. */ - maybe_save_function_definition (fndecl); + maybe_save_constexpr_fundef (fndecl); /* Invoke the pre-genericize plugin before we start munging things. */ if (!processing_template_decl) -- 2.30.2