From 0006c07b7ac6594195d5db322e39907203be4c2a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 5 Feb 2025 10:14:57 -0800 Subject: [PATCH] go: update builtin function attributes PR go/118746 * go-gcc.cc (class Gcc_backend): Define builtin_cold, builtin_leaf, builtin_nonnull. Alphabetize constants. (Gcc_backend::Gcc_backend): Update attributes for builtin functions to match builtins.def. (Gcc_backend::define_builtin): Split out attribute setting into set_attribtues. (Gcc_backend::set_attribtues): New method split out of define_builtin. Support new flag values. --- gcc/go/go-gcc.cc | 262 +++++++++++++++++++++++++---------------------- 1 file changed, 141 insertions(+), 121 deletions(-) diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index cf0c84b9fe3..9917812d0ea 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -540,16 +540,22 @@ class Gcc_backend : public Backend convert_tree(tree, tree, Location); private: - static const int builtin_const = 1 << 0; - static const int builtin_noreturn = 1 << 1; - static const int builtin_novops = 1 << 2; - static const int builtin_pure = 1 << 3; - static const int builtin_nothrow = 1 << 4; + static const int builtin_cold = 1 << 0; + static const int builtin_const = 1 << 1; + static const int builtin_leaf = 1 << 2; + static const int builtin_nonnull = 1 << 3; + static const int builtin_noreturn = 1 << 4; + static const int builtin_nothrow = 1 << 5; + static const int builtin_novops = 1 << 6; + static const int builtin_pure = 1 << 7; void define_builtin(built_in_function bcode, const char* name, const char* libname, tree fntype, int flags); + void + set_attributes(tree decl, int flags); + // A mapping of the GCC built-ins exposed to GCCGo. std::map builtin_functions_; }; @@ -571,22 +577,26 @@ Gcc_backend::Gcc_backend() tree t = this->integer_type(true, BITS_PER_UNIT)->get_tree(); tree p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE)); this->define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_1, "__sync_fetch_and_add_1", - NULL, build_function_type_list(t, p, t, NULL_TREE), 0); + NULL, build_function_type_list(t, p, t, NULL_TREE), + builtin_leaf); t = this->integer_type(true, BITS_PER_UNIT * 2)->get_tree(); p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE)); this->define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_2, "__sync_fetch_and_add_2", - NULL, build_function_type_list(t, p, t, NULL_TREE), 0); + NULL, build_function_type_list(t, p, t, NULL_TREE), + builtin_leaf); t = this->integer_type(true, BITS_PER_UNIT * 4)->get_tree(); p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE)); this->define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_4, "__sync_fetch_and_add_4", - NULL, build_function_type_list(t, p, t, NULL_TREE), 0); + NULL, build_function_type_list(t, p, t, NULL_TREE), + builtin_leaf); t = this->integer_type(true, BITS_PER_UNIT * 8)->get_tree(); p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE)); this->define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_8, "__sync_fetch_and_add_8", - NULL, build_function_type_list(t, p, t, NULL_TREE), 0); + NULL, build_function_type_list(t, p, t, NULL_TREE), + builtin_leaf); // We use __builtin_expect for magic import functions. this->define_builtin(BUILT_IN_EXPECT, "__builtin_expect", NULL, @@ -594,7 +604,7 @@ Gcc_backend::Gcc_backend() long_integer_type_node, long_integer_type_node, NULL_TREE), - builtin_const); + builtin_const | builtin_nothrow | builtin_leaf); // We use __builtin_memcmp for struct comparisons. this->define_builtin(BUILT_IN_MEMCMP, "__builtin_memcmp", "memcmp", @@ -603,7 +613,7 @@ Gcc_backend::Gcc_backend() const_ptr_type_node, size_type_node, NULL_TREE), - builtin_pure | builtin_nothrow); + builtin_pure | builtin_nothrow | builtin_nonnull); // We use __builtin_memmove for copying data. this->define_builtin(BUILT_IN_MEMMOVE, "__builtin_memmove", "memmove", @@ -612,7 +622,7 @@ Gcc_backend::Gcc_backend() const_ptr_type_node, size_type_node, NULL_TREE), - 0); + builtin_nothrow | builtin_nonnull); // We use __builtin_memset for zeroing data. this->define_builtin(BUILT_IN_MEMSET, "__builtin_memset", "memset", @@ -621,64 +631,64 @@ Gcc_backend::Gcc_backend() integer_type_node, size_type_node, NULL_TREE), - 0); + builtin_nothrow | builtin_nonnull); // Used by runtime/internal/sys and math/bits. this->define_builtin(BUILT_IN_CTZ, "__builtin_ctz", "ctz", build_function_type_list(integer_type_node, unsigned_type_node, NULL_TREE), - builtin_const); + builtin_const | builtin_nothrow | builtin_leaf); this->define_builtin(BUILT_IN_CTZL, "__builtin_ctzl", "ctzl", build_function_type_list(integer_type_node, long_unsigned_type_node, NULL_TREE), - builtin_const); + builtin_const | builtin_nothrow | builtin_leaf); this->define_builtin(BUILT_IN_CTZLL, "__builtin_ctzll", "ctzll", build_function_type_list(integer_type_node, long_long_unsigned_type_node, NULL_TREE), - builtin_const); + builtin_const | builtin_nothrow | builtin_leaf); this->define_builtin(BUILT_IN_CLZ, "__builtin_clz", "clz", build_function_type_list(integer_type_node, unsigned_type_node, NULL_TREE), - builtin_const); + builtin_const | builtin_nothrow | builtin_leaf); this->define_builtin(BUILT_IN_CLZL, "__builtin_clzl", "clzl", build_function_type_list(integer_type_node, long_unsigned_type_node, NULL_TREE), - builtin_const); + builtin_const | builtin_nothrow | builtin_leaf); this->define_builtin(BUILT_IN_CLZLL, "__builtin_clzll", "clzll", build_function_type_list(integer_type_node, long_long_unsigned_type_node, NULL_TREE), - builtin_const); + builtin_const | builtin_nothrow | builtin_leaf); this->define_builtin(BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount", build_function_type_list(integer_type_node, unsigned_type_node, NULL_TREE), - builtin_const); + builtin_const | builtin_nothrow | builtin_leaf); this->define_builtin(BUILT_IN_POPCOUNTLL, "__builtin_popcountll", "popcountll", build_function_type_list(integer_type_node, long_long_unsigned_type_node, NULL_TREE), - builtin_const); + builtin_const | builtin_nothrow | builtin_leaf); this->define_builtin(BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16", build_function_type_list(uint16_type_node, uint16_type_node, NULL_TREE), - builtin_const); + builtin_const | builtin_nothrow | builtin_leaf); this->define_builtin(BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32", build_function_type_list(uint32_type_node, uint32_type_node, NULL_TREE), - builtin_const); + builtin_const | builtin_nothrow | builtin_leaf); this->define_builtin(BUILT_IN_BSWAP64, "__builtin_bswap64", "bswap64", build_function_type_list(uint64_type_node, uint64_type_node, NULL_TREE), - builtin_const); + builtin_const | builtin_nothrow | builtin_leaf); // We provide some functions for the math library. tree math_function_type = build_function_type_list(double_type_node, @@ -787,7 +797,7 @@ Gcc_backend::Gcc_backend() // functions which call recover, and for runtime.getcallerpc. t = build_function_type_list(ptr_type_node, unsigned_type_node, NULL_TREE); this->define_builtin(BUILT_IN_RETURN_ADDRESS, "__builtin_return_address", - NULL, t, 0); + NULL, t, builtin_leaf); // The runtime calls __builtin_dwarf_cfa for runtime.getcallersp. t = build_function_type_list(ptr_type_node, NULL_TREE); @@ -801,123 +811,126 @@ Gcc_backend::Gcc_backend() build_function_type_list(ptr_type_node, ptr_type_node, NULL_TREE), - 0); + builtin_leaf); // The compiler uses __builtin_trap for some exception handling // cases. this->define_builtin(BUILT_IN_TRAP, "__builtin_trap", NULL, build_function_type(void_type_node, void_list_node), - builtin_noreturn); + (builtin_noreturn | builtin_nothrow | builtin_leaf + | builtin_cold)); // The runtime uses __builtin_prefetch. this->define_builtin(BUILT_IN_PREFETCH, "__builtin_prefetch", NULL, build_varargs_function_type_list(void_type_node, const_ptr_type_node, NULL_TREE), - builtin_novops); + builtin_novops | builtin_leaf); // The compiler uses __builtin_unreachable for cases that cannot // occur. this->define_builtin(BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL, build_function_type(void_type_node, void_list_node), - builtin_const | builtin_noreturn); + (builtin_const | builtin_noreturn | builtin_nothrow + | builtin_leaf | builtin_cold)); // We provide some atomic functions. t = build_function_type_list(uint32_type_node, - ptr_type_node, - integer_type_node, - NULL_TREE); + ptr_type_node, + integer_type_node, + NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL, - t, 0); + t, builtin_leaf); t = build_function_type_list(uint64_type_node, - ptr_type_node, - integer_type_node, - NULL_TREE); + ptr_type_node, + integer_type_node, + NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL, - t, 0); + t, builtin_leaf); t = build_function_type_list(void_type_node, - ptr_type_node, - uint32_type_node, - integer_type_node, - NULL_TREE); + ptr_type_node, + uint32_type_node, + integer_type_node, + NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL, - t, 0); + t, builtin_leaf); t = build_function_type_list(void_type_node, - ptr_type_node, - uint64_type_node, - integer_type_node, - NULL_TREE); + ptr_type_node, + uint64_type_node, + integer_type_node, + NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL, - t, 0); + t, builtin_leaf); t = build_function_type_list(uint32_type_node, - ptr_type_node, - uint32_type_node, - integer_type_node, - NULL_TREE); + ptr_type_node, + uint32_type_node, + integer_type_node, + NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_EXCHANGE_4, "__atomic_exchange_4", NULL, - t, 0); + t, builtin_leaf); t = build_function_type_list(uint64_type_node, - ptr_type_node, - uint64_type_node, - integer_type_node, - NULL_TREE); + ptr_type_node, + uint64_type_node, + integer_type_node, + NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_EXCHANGE_8, "__atomic_exchange_8", NULL, - t, 0); + t, builtin_leaf); t = build_function_type_list(boolean_type_node, - ptr_type_node, - ptr_type_node, - uint32_type_node, - boolean_type_node, - integer_type_node, - integer_type_node, - NULL_TREE); + ptr_type_node, + ptr_type_node, + uint32_type_node, + boolean_type_node, + integer_type_node, + integer_type_node, + NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4, - "__atomic_compare_exchange_4", NULL, - t, 0); + "__atomic_compare_exchange_4", NULL, + t, builtin_leaf); t = build_function_type_list(boolean_type_node, - ptr_type_node, - ptr_type_node, - uint64_type_node, - boolean_type_node, - integer_type_node, - integer_type_node, - NULL_TREE); + ptr_type_node, + ptr_type_node, + uint64_type_node, + boolean_type_node, + integer_type_node, + integer_type_node, + NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8, - "__atomic_compare_exchange_8", NULL, - t, 0); + "__atomic_compare_exchange_8", NULL, + t, builtin_leaf); t = build_function_type_list(uint32_type_node, - ptr_type_node, - uint32_type_node, - integer_type_node, - NULL_TREE); + ptr_type_node, + uint32_type_node, + integer_type_node, + NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4", - NULL, t, 0); + NULL, t, builtin_leaf); this->define_builtin(BUILT_IN_ATOMIC_FETCH_ADD_4, "__atomic_fetch_add_4", - NULL, t, 0); + NULL, t, builtin_leaf); t = build_function_type_list(uint64_type_node, - ptr_type_node, - uint64_type_node, - integer_type_node, - NULL_TREE); + ptr_type_node, + uint64_type_node, + integer_type_node, + NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8", - NULL, t, 0); + NULL, t, builtin_leaf); this->define_builtin(BUILT_IN_ATOMIC_FETCH_ADD_8, "__atomic_fetch_add_8", - NULL, t, 0); + NULL, t, builtin_leaf); t = build_function_type_list(unsigned_char_type_node, ptr_type_node, integer_type_node, NULL_TREE); - this->define_builtin(BUILT_IN_ATOMIC_LOAD_1, "__atomic_load_1", NULL, t, 0); + this->define_builtin(BUILT_IN_ATOMIC_LOAD_1, "__atomic_load_1", NULL, t, + builtin_leaf); t = build_function_type_list(void_type_node, ptr_type_node, @@ -925,27 +938,27 @@ Gcc_backend::Gcc_backend() integer_type_node, NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_STORE_1, "__atomic_store_1", NULL, - t, 0); + t, builtin_leaf); t = build_function_type_list(unsigned_char_type_node, - ptr_type_node, - unsigned_char_type_node, - integer_type_node, - NULL_TREE); + ptr_type_node, + unsigned_char_type_node, + integer_type_node, + NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1", NULL, - t, 0); + t, builtin_leaf); this->define_builtin(BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1", NULL, - t, 0); + t, builtin_leaf); t = build_function_type_list(unsigned_char_type_node, - ptr_type_node, - unsigned_char_type_node, - integer_type_node, - NULL_TREE); + ptr_type_node, + unsigned_char_type_node, + integer_type_node, + NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1", NULL, - t, 0); + t, builtin_leaf); this->define_builtin(BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1", NULL, - t, 0); + t, builtin_leaf); } // Get an unnamed integer type. @@ -3587,8 +3600,7 @@ Gcc_backend::write_export_data(const char* bytes, unsigned int size) // defined by builtins.def. NAME is the name of the builtin function. // LIBNAME is the name of the corresponding library function, and is // NULL if there isn't one. FNTYPE is the type of the function. -// CONST_P is true if the function has the const attribute. -// NORETURN_P is true if the function has the noreturn attribute. +// FLAGS are the attributes to add, a bitset of builtin_xxx consts. void Gcc_backend::define_builtin(built_in_function bcode, const char* name, @@ -3596,6 +3608,23 @@ Gcc_backend::define_builtin(built_in_function bcode, const char* name, { tree decl = add_builtin_function(name, fntype, bcode, BUILT_IN_NORMAL, libname, NULL_TREE); + this->set_attributes(decl, flags); + set_builtin_decl(bcode, decl, true); + this->builtin_functions_[name] = this->make_function(decl); + if (libname != NULL) + { + decl = add_builtin_function(libname, fntype, bcode, BUILT_IN_NORMAL, + NULL, NULL_TREE); + this->set_attributes(decl, flags); + this->builtin_functions_[libname] = this->make_function(decl); + } +} + +// Set the attributes of DECL based on FLAGS. + +void +Gcc_backend::set_attributes(tree decl, int flags) +{ if ((flags & builtin_const) != 0) TREE_READONLY(decl) = 1; if ((flags & builtin_pure) != 0) @@ -3606,24 +3635,15 @@ Gcc_backend::define_builtin(built_in_function bcode, const char* name, TREE_THIS_VOLATILE(decl) = 1; if ((flags & builtin_novops) != 0) DECL_IS_NOVOPS(decl) = 1; - set_builtin_decl(bcode, decl, true); - this->builtin_functions_[name] = this->make_function(decl); - if (libname != NULL) - { - decl = add_builtin_function(libname, fntype, bcode, BUILT_IN_NORMAL, - NULL, NULL_TREE); - if ((flags & builtin_const) != 0) - TREE_READONLY(decl) = 1; - if ((flags & builtin_pure) != 0) - DECL_PURE_P(decl) = 1; - if ((flags & builtin_nothrow) != 0) - TREE_NOTHROW (decl) = 1; - if ((flags & builtin_noreturn) != 0) - TREE_THIS_VOLATILE(decl) = 1; - if ((flags & builtin_novops) != 0) - DECL_IS_NOVOPS(decl) = 1; - this->builtin_functions_[libname] = this->make_function(decl); - } + if ((flags & builtin_leaf) != 0) + DECL_ATTRIBUTES(decl) = tree_cons(get_identifier("leaf"), NULL_TREE, + DECL_ATTRIBUTES(decl)); + if ((flags & builtin_nonnull) != 0) + DECL_ATTRIBUTES(decl) = tree_cons(get_identifier("nonnull"), NULL_TREE, + DECL_ATTRIBUTES(decl)); + if ((flags & builtin_cold) != 0) + DECL_ATTRIBUTES(decl) = tree_cons(get_identifier("cold"), NULL_TREE, + DECL_ATTRIBUTES(decl)); } // Return the backend generator.