This patch updates the attributes for the relatively few builtin functions defined by the Go frontend to the current ones in builtins.def. This fixes PR 118746. Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed to mainline.
Ian 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.
ec1bc21633d15267e49ecdabad2c8a0131133412 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<std::string, Bfunction*> 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.