diff options
-rw-r--r-- | gcc/rust/backend/rust-builtins.cc | 350 | ||||
-rw-r--r-- | gcc/rust/backend/rust-builtins.h | 118 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-intrinsic.cc | 41 | ||||
-rw-r--r-- | gcc/rust/rust-gcc.cc | 8 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/intrinsics-4.rs | 2 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/atomic_load.rs | 4 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/atomic_store.rs | 4 |
7 files changed, 138 insertions, 389 deletions
diff --git a/gcc/rust/backend/rust-builtins.cc b/gcc/rust/backend/rust-builtins.cc index ec65026..66b3bec 100644 --- a/gcc/rust/backend/rust-builtins.cc +++ b/gcc/rust/backend/rust-builtins.cc @@ -14,13 +14,8 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -#include "rust-diagnostics.h" -#include "rust-system.h" #include "rust-builtins.h" -#include "target.h" -#include "stringpool.h" - namespace Rust { namespace Compile { @@ -38,275 +33,154 @@ BuiltinsContext::get () bool BuiltinsContext::lookup_simple_builtin (const std::string &name, tree *builtin) { - auto *to_search = &name; - auto it = rust_intrinsic_to_gcc_builtin.find (name); - if (it != rust_intrinsic_to_gcc_builtin.end ()) - to_search = &it->second; + if (it == rust_intrinsic_to_gcc_builtin.end ()) + return false; - return lookup_gcc_builtin (*to_search, builtin); + return lookup_gcc_builtin (it->second, builtin); } BuiltinsContext::BuiltinsContext () { setup (); } -/** - * Define a function type according to `builtin-types.def` - * - * *Heavily* inspired by the D frontend's `def_fn_type` function - */ void -BuiltinsContext::define_function_type (Type def_idx, Type ret_idx, - bool is_variadic, size_t n, ...) +BuiltinsContext::setup_overflow_fns () { - va_list list; - va_start (list, n); - - auto args = std::vector<tree> (); - - for (size_t i = 0; i < n; i++) - { - auto arg_idx = va_arg (list, size_t); - auto arg_type = builtin_types[arg_idx]; - - args.emplace_back (arg_type); - } - - auto return_type = builtin_types[ret_idx]; - if (return_type == error_mark_node) - { - va_end (list); - return; - } - - auto fn_type = NULL_TREE; - if (is_variadic) - fn_type = build_varargs_function_type_array (return_type, n, args.data ()); - else - fn_type = build_function_type_array (return_type, n, args.data ()); - - builtin_types[def_idx] = fn_type; - va_end (list); + tree overflow_type + = build_varargs_function_type_list (boolean_type_node, NULL_TREE); + + define_builtin ("add_overflow", BUILT_IN_ADD_OVERFLOW, + "__builtin_add_overflow", "add_overflow", overflow_type, 0); + define_builtin ("sub_overflow", BUILT_IN_SUB_OVERFLOW, + "__builtin_sub_overflow", "sub_overflow", overflow_type, 0); + define_builtin ("mul_overflow", BUILT_IN_MUL_OVERFLOW, + "__builtin_mul_overflow", "mul_overflow", overflow_type, 0); } -// Taken directly from the D frontend -static void -build_c_type_nodes (void) +void +BuiltinsContext::setup_math_fns () { - string_type_node = build_pointer_type (char_type_node); - const_string_type_node = build_pointer_type ( - build_qualified_type (char_type_node, TYPE_QUAL_CONST)); - - if (strcmp (UINTMAX_TYPE, "unsigned int") == 0) - { - intmax_type_node = integer_type_node; - uintmax_type_node = unsigned_type_node; - } - else if (strcmp (UINTMAX_TYPE, "long unsigned int") == 0) - { - intmax_type_node = long_integer_type_node; - uintmax_type_node = long_unsigned_type_node; - } - else if (strcmp (UINTMAX_TYPE, "long long unsigned int") == 0) - { - intmax_type_node = long_long_integer_type_node; - uintmax_type_node = long_long_unsigned_type_node; - } - else - gcc_unreachable (); + tree math_function_type_f32 + = build_function_type_list (float_type_node, float_type_node, NULL_TREE); - signed_size_type_node = signed_type_for (size_type_node); - wint_type_node = unsigned_type_node; - pid_type_node = integer_type_node; + define_builtin ("sinf32", BUILT_IN_SINF, "__builtin_sinf", "sinf", + math_function_type_f32, builtin_const); + define_builtin ("sqrtf32", BUILT_IN_SQRTF, "__builtin_sqrtf", "sqrtf", + math_function_type_f32, builtin_const); } -/** - * Define all builtin types in the `builtin_types` array - */ void -BuiltinsContext::define_builtin_types () +BuiltinsContext::setup_atomic_fns () { - // This is taken directly from the D frontend's handling of builtins - auto va_list_ref_type_node = build_reference_type (va_list_type_node); - auto va_list_arg_type_node = va_list_type_node; - - build_c_type_nodes (); - - auto builtin_type_for_size = [] (int size, bool unsignedp) { - tree type = lang_hooks.types.type_for_size (size, unsignedp); - return type ? type : error_mark_node; + auto atomic_store_type + = build_varargs_function_type_list (void_type_node, NULL_TREE); + auto atomic_load_type = [] (tree ret_type_node) { + return build_function_type_list (ret_type_node, + ptr_type_node, // const_ptr_type_node? + integer_type_node, NULL_TREE); }; -#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) builtin_types[ENUM] = VALUE; -#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \ - define_function_type (ENUM, RETURN, 0, 0); -#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, A1) \ - define_function_type (ENUM, RETURN, 0, 1, A1); -#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, A1, A2) \ - define_function_type (ENUM, RETURN, 0, 2, A1, A2); -#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, A1, A2, A3) \ - define_function_type (ENUM, RETURN, 0, 3, A1, A2, A3); -#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, A1, A2, A3, A4) \ - define_function_type (ENUM, RETURN, 0, 4, A1, A2, A3, A4); -#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, A1, A2, A3, A4, A5) \ - define_function_type (ENUM, RETURN, 0, 5, A1, A2, A3, A4, A5); -#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6) \ - define_function_type (ENUM, RETURN, 0, 6, A1, A2, A3, A4, A5, A6); -#define DEF_FUNCTION_TYPE_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7) \ - define_function_type (ENUM, RETURN, 0, 7, A1, A2, A3, A4, A5, A6, A7); -#define DEF_FUNCTION_TYPE_8(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8) \ - define_function_type (ENUM, RETURN, 0, 8, A1, A2, A3, A4, A5, A6, A7, A8); -#define DEF_FUNCTION_TYPE_9(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9) \ - define_function_type (ENUM, RETURN, 0, 9, A1, A2, A3, A4, A5, A6, A7, A8, A9); -#define DEF_FUNCTION_TYPE_10(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \ - A10) \ - define_function_type (ENUM, RETURN, 0, 10, A1, A2, A3, A4, A5, A6, A7, A8, \ - A9, A10); -#define DEF_FUNCTION_TYPE_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \ - A10, A11) \ - define_function_type (ENUM, RETURN, 0, 11, A1, A2, A3, A4, A5, A6, A7, A8, \ - A9, A10, A11); -#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \ - define_function_type (ENUM, RETURN, 1, 0); -#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, A1) \ - define_function_type (ENUM, RETURN, 1, 1, A1); -#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, A1, A2) \ - define_function_type (ENUM, RETURN, 1, 2, A1, A2); -#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, A1, A2, A3) \ - define_function_type (ENUM, RETURN, 1, 3, A1, A2, A3); -#define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, A1, A2, A3, A4) \ - define_function_type (ENUM, RETURN, 1, 4, A1, A2, A3, A4); -#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, A1, A2, A3, A4, A5) \ - define_function_type (ENUM, RETURN, 1, 5, A1, A2, A3, A4, A5); -#define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6) \ - define_function_type (ENUM, RETURN, 1, 6, A1, A2, A3, A4, A5, A6); -#define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7) \ - define_function_type (ENUM, RETURN, 1, 7, A1, A2, A3, A4, A5, A6, A7); -#define DEF_FUNCTION_TYPE_VAR_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, \ - A9, A10, A11) \ - define_function_type (ENUM, RETURN, 1, 11, A1, A2, A3, A4, A5, A6, A7, A8, \ - A9, A10, A11); -#define DEF_POINTER_TYPE(ENUM, TYPE) \ - builtin_types[ENUM] = build_pointer_type (builtin_types[TYPE]); - -#include "builtin-types.def" - -#undef DEF_PRIMITIVE_TYPE -#undef DEF_FUNCTION_TYPE_1 -#undef DEF_FUNCTION_TYPE_2 -#undef DEF_FUNCTION_TYPE_3 -#undef DEF_FUNCTION_TYPE_4 -#undef DEF_FUNCTION_TYPE_5 -#undef DEF_FUNCTION_TYPE_6 -#undef DEF_FUNCTION_TYPE_7 -#undef DEF_FUNCTION_TYPE_8 -#undef DEF_FUNCTION_TYPE_9 -#undef DEF_FUNCTION_TYPE_10 -#undef DEF_FUNCTION_TYPE_11 -#undef DEF_FUNCTION_TYPE_VAR_0 -#undef DEF_FUNCTION_TYPE_VAR_1 -#undef DEF_FUNCTION_TYPE_VAR_2 -#undef DEF_FUNCTION_TYPE_VAR_3 -#undef DEF_FUNCTION_TYPE_VAR_4 -#undef DEF_FUNCTION_TYPE_VAR_5 -#undef DEF_FUNCTION_TYPE_VAR_6 -#undef DEF_FUNCTION_TYPE_VAR_7 -#undef DEF_FUNCTION_TYPE_VAR_11 -#undef DEF_POINTER_TYPE - - builtin_types[Type::BT_LAST] = NULL_TREE; + // FIXME: These should be the definition for the generic version of the + // atomic_store builtins, but I cannot get them to work properly. Revisit + // later. define_builtin ("atomic_store", BUILT_IN_ATOMIC_STORE, + // "__atomic_store", NULL, + // atomic_store_type, 0); + // define_builtin ("atomic_store_n", BUILT_IN_ATOMIC_STORE_N, + // "__atomic_store_n", + // NULL, atomic_store_type, 0); + + define_builtin ("atomic_store_1", BUILT_IN_ATOMIC_STORE_1, "__atomic_store_1", + NULL, atomic_store_type, 0); + define_builtin ("atomic_store_2", BUILT_IN_ATOMIC_STORE_2, "__atomic_store_2", + NULL, atomic_store_type, 0); + define_builtin ("atomic_store_4", BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", + NULL, atomic_store_type, 0); + define_builtin ("atomic_store_8", BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", + NULL, atomic_store_type, 0); + define_builtin ("atomic_store_16", BUILT_IN_ATOMIC_STORE_16, + "__atomic_store_16", NULL, atomic_store_type, 0); + + define_builtin ("atomic_load_1", BUILT_IN_ATOMIC_LOAD_1, "__atomic_load_1", + NULL, atomic_load_type (integer_type_node), 0); + define_builtin ("atomic_load_2", BUILT_IN_ATOMIC_LOAD_2, "__atomic_load_2", + NULL, atomic_load_type (integer_type_node), 0); + define_builtin ("atomic_load_4", BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", + NULL, atomic_load_type (integer_type_node), 0); + define_builtin ("atomic_load_8", BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", + NULL, atomic_load_type (integer_type_node), 0); } -/** - * Define all builtin attributes in the `builtin_types` array - */ void -BuiltinsContext::define_builtin_attributes () - +BuiltinsContext::setup () { - auto *built_in_attributes = builtin_attributes; - -#define DEF_ATTR_NULL_TREE(ENUM) built_in_attributes[(int) ENUM] = NULL_TREE; -#define DEF_ATTR_INT(ENUM, VALUE) \ - built_in_attributes[ENUM] = build_int_cst (NULL_TREE, VALUE); -#define DEF_ATTR_STRING(ENUM, VALUE) \ - built_in_attributes[ENUM] = build_string (strlen (VALUE), VALUE); -#define DEF_ATTR_IDENT(ENUM, STRING) \ - built_in_attributes[ENUM] = get_identifier (STRING); -#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \ - built_in_attributes[ENUM] \ - = tree_cons (built_in_attributes[PURPOSE], built_in_attributes[VALUE], \ - built_in_attributes[CHAIN]); -#include "builtin-attrs.def" -#undef DEF_ATTR_NULL_TREE -#undef DEF_ATTR_INT -#undef DEF_ATTR_STRING -#undef DEF_ATTR_IDENT -#undef DEF_ATTR_TREE_LIST + setup_math_fns (); + setup_overflow_fns (); + setup_atomic_fns (); + + define_builtin ("unreachable", BUILT_IN_UNREACHABLE, "__builtin_unreachable", + NULL, build_function_type (void_type_node, void_list_node), + builtin_const | builtin_noreturn); + + define_builtin ("abort", BUILT_IN_ABORT, "__builtin_abort", "abort", + build_function_type (void_type_node, void_list_node), + builtin_const | builtin_noreturn); + + define_builtin ("breakpoint", BUILT_IN_TRAP, "__builtin_trap", "breakpoint", + build_function_type (void_type_node, void_list_node), + builtin_const | builtin_noreturn); + + define_builtin ("memcpy", BUILT_IN_MEMCPY, "__builtin_memcpy", "memcpy", + build_function_type_list (build_pointer_type (void_type_node), + build_pointer_type (void_type_node), + build_pointer_type (void_type_node), + size_type_node, NULL_TREE), + 0); + + define_builtin ("prefetch", BUILT_IN_PREFETCH, "__builtin_prefetch", + "prefetch", + build_varargs_function_type_list ( + build_pointer_type (const_ptr_type_node), NULL_TREE), + builtin_const); } -/** - * Define all builtin functions during the first initialization of the - * `BuiltinsContext`. - */ -void -BuiltinsContext::define_builtins () +static void +handle_flags (tree decl, int flags) { - auto *built_in_attributes = builtin_attributes; - auto build_builtin = [this] (built_in_function fn_code, const char *fn_name, - built_in_class fn_class, tree fn_type, - bool fallback, tree attributes, bool implicit) { - if (fn_type == error_mark_node) - return; - - static auto to_skip = strlen ("__builtin_"); - - auto libname = fn_name + to_skip; - auto decl = add_builtin_function (fn_name, fn_type, fn_code, fn_class, - fallback ? libname : NULL, attributes); - - set_builtin_decl (fn_code, decl, implicit); - - builtin_functions.insert ({std::string (fn_name), decl}); - }; - -#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \ - NONANSI_P, ATTRS, IMPLICIT, COND) \ - if (NAME && COND) \ - build_builtin (ENUM, NAME, CLASS, builtin_types[TYPE], FALLBACK_P, \ - built_in_attributes[ATTRS], IMPLICIT); -#include "builtins.def" -#undef DEF_BUILTIN + if (flags & builtin_const) + TREE_READONLY (decl) = 1; + if (flags & builtin_noreturn) + TREE_READONLY (decl) = 1; + if (flags & builtin_novops) + DECL_IS_NOVOPS (decl) = 1; } -/** - * Register direct mappings between Rust functions and GCC builtins - */ void -BuiltinsContext::register_rust_mappings () +BuiltinsContext::define_builtin (const std::string rust_name, + built_in_function bcode, const char *name, + const char *libname, tree fntype, int flags) { - rust_intrinsic_to_gcc_builtin = { - {"sinf32", "__builtin_sinf"}, - {"sqrtf32", "__builtin_sqrtf"}, - {"unreachable", "__builtin_unreachable"}, - {"abort", "__builtin_abort"}, - }; -} + tree decl = add_builtin_function (name, fntype, bcode, BUILT_IN_NORMAL, + libname, NULL_TREE); + handle_flags (decl, flags); + set_builtin_decl (bcode, decl, true); -void -BuiltinsContext::setup () -{ - define_builtin_types (); - define_builtin_attributes (); - define_builtins (); + this->builtin_functions_[name] = decl; + if (libname != NULL) + { + decl = add_builtin_function (libname, fntype, bcode, BUILT_IN_NORMAL, + NULL, NULL_TREE); + handle_flags (decl, flags); + + this->builtin_functions_[libname] = decl; + } - register_rust_mappings (); + rust_intrinsic_to_gcc_builtin[rust_name] = name; } bool BuiltinsContext::lookup_gcc_builtin (const std::string &name, tree *builtin) { - auto it = builtin_functions.find (name); - if (it == builtin_functions.end ()) + auto it = builtin_functions_.find (name); + if (it == builtin_functions_.end ()) return false; *builtin = it->second; diff --git a/gcc/rust/backend/rust-builtins.h b/gcc/rust/backend/rust-builtins.h index 5052eda..c282510 100644 --- a/gcc/rust/backend/rust-builtins.h +++ b/gcc/rust/backend/rust-builtins.h @@ -21,7 +21,6 @@ #include "rust-tree.h" #include "langhooks.h" #include "tree.h" -#include "selftest.h" namespace Rust { namespace Compile { @@ -76,7 +75,6 @@ namespace Compile { // _ => return None, // }; // Some(cx.get_intrinsic(&llvm_name)) - class BuiltinsContext { public: @@ -85,110 +83,6 @@ public: bool lookup_simple_builtin (const std::string &name, tree *builtin); private: - enum Type - { -#define DEF_PRIMITIVE_TYPE(NAME, V) NAME, -#define DEF_FUNCTION_TYPE_0(NAME, R) NAME, -#define DEF_FUNCTION_TYPE_1(NAME, R, A1) NAME, -#define DEF_FUNCTION_TYPE_2(NAME, R, A1, A2) NAME, -#define DEF_FUNCTION_TYPE_3(NAME, R, A1, A2, A3) NAME, -#define DEF_FUNCTION_TYPE_4(NAME, R, A1, A2, A3, A4) NAME, -#define DEF_FUNCTION_TYPE_5(NAME, R, A1, A2, A3, A4, A5) NAME, -#define DEF_FUNCTION_TYPE_6(NAME, R, A1, A2, A3, A4, A5, A6) NAME, -#define DEF_FUNCTION_TYPE_7(NAME, R, A1, A2, A3, A4, A5, A6, A7) NAME, -#define DEF_FUNCTION_TYPE_8(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8) NAME, -#define DEF_FUNCTION_TYPE_9(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9) NAME, -#define DEF_FUNCTION_TYPE_10(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) \ - NAME, -#define DEF_FUNCTION_TYPE_11(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, \ - A11) \ - NAME, -#define DEF_FUNCTION_TYPE_VAR_0(NAME, R) NAME, -#define DEF_FUNCTION_TYPE_VAR_1(NAME, R, A1) NAME, -#define DEF_FUNCTION_TYPE_VAR_2(NAME, R, A1, A2) NAME, -#define DEF_FUNCTION_TYPE_VAR_3(NAME, R, A1, A2, A3) NAME, -#define DEF_FUNCTION_TYPE_VAR_4(NAME, R, A1, A2, A3, A4) NAME, -#define DEF_FUNCTION_TYPE_VAR_5(NAME, R, A1, A2, A3, A4, A5) NAME, -#define DEF_FUNCTION_TYPE_VAR_6(NAME, R, A1, A2, A3, A4, A5, A6) NAME, -#define DEF_FUNCTION_TYPE_VAR_7(NAME, R, A1, A2, A3, A4, A5, A6, A7) NAME, -#define DEF_FUNCTION_TYPE_VAR_11(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, \ - A10, A11) \ - NAME, -#define DEF_POINTER_TYPE(NAME, TYPE) NAME, - -#include "builtin-types.def" - -#undef DEF_PRIMITIVE_TYPE -#undef DEF_FUNCTION_TYPE_0 -#undef DEF_FUNCTION_TYPE_1 -#undef DEF_FUNCTION_TYPE_2 -#undef DEF_FUNCTION_TYPE_3 -#undef DEF_FUNCTION_TYPE_4 -#undef DEF_FUNCTION_TYPE_5 -#undef DEF_FUNCTION_TYPE_6 -#undef DEF_FUNCTION_TYPE_7 -#undef DEF_FUNCTION_TYPE_8 -#undef DEF_FUNCTION_TYPE_9 -#undef DEF_FUNCTION_TYPE_10 -#undef DEF_FUNCTION_TYPE_11 -#undef DEF_FUNCTION_TYPE_VAR_0 -#undef DEF_FUNCTION_TYPE_VAR_1 -#undef DEF_FUNCTION_TYPE_VAR_2 -#undef DEF_FUNCTION_TYPE_VAR_3 -#undef DEF_FUNCTION_TYPE_VAR_4 -#undef DEF_FUNCTION_TYPE_VAR_5 -#undef DEF_FUNCTION_TYPE_VAR_6 -#undef DEF_FUNCTION_TYPE_VAR_7 -#undef DEF_FUNCTION_TYPE_VAR_11 -#undef DEF_POINTER_TYPE - - BT_LAST, - }; - - enum Attr - { -#define DEF_ATTR_NULL_TREE(ENUM) ENUM, -#define DEF_ATTR_INT(ENUM, VALUE) ENUM, -#define DEF_ATTR_STRING(ENUM, VALUE) ENUM, -#define DEF_ATTR_IDENT(ENUM, STRING) ENUM, -#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM, - -#include "builtin-attrs.def" - -#undef DEF_ATTR_NULL_TREE -#undef DEF_ATTR_INT -#undef DEF_ATTR_STRING -#undef DEF_ATTR_IDENT -#undef DEF_ATTR_TREE_LIST - - ATTR_LAST, - }; - - /** - * All builtin types, as defined in `builtin-types.def` - * - * This array is filled by the `define_builtin_types` method, during the first - * initialization of the `BuiltinsContext` - */ - tree builtin_types[Type::BT_LAST + 1]; - - /** - * Similarly, this array contains all builtin attributes, as defined in - * `builtin-attr.def` - * - * This array is filled by the `define_builtin_attributes` method, during the - * first initialization of the `BuiltinsContext` - */ - tree builtin_attributes[Attr::ATTR_LAST + 1]; - - void define_function_type (Type def, Type ret, bool is_variadic, size_t n, - ...); - void define_builtin_types (); - void define_builtin_attributes (); - void define_builtins (); - - void register_rust_mappings (); - BuiltinsContext (); void setup_overflow_fns (); @@ -197,10 +91,20 @@ private: void setup (); + // Define a builtin function. BCODE is the builtin function code + // 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. + void define_builtin (const std::string rust_name, built_in_function bcode, + const char *name, const char *libname, tree fntype, + int flags); + bool lookup_gcc_builtin (const std::string &name, tree *builtin); // A mapping of the GCC built-ins exposed to GCC Rust. - std::map<std::string, tree> builtin_functions; + std::map<std::string, tree> builtin_functions_; std::map<std::string, std::string> rust_intrinsic_to_gcc_builtin; }; diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index 3bb9c61..5522211 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -28,8 +28,6 @@ #include "print-tree.h" #include "fold-const.h" #include "langhooks.h" -#include "rust-gcc.h" -#include "rust-constexpr.h" #include "print-tree.h" @@ -201,7 +199,6 @@ Intrinsics::compile (TyTy::FnType *fntype) tree builtin = error_mark_node; BuiltinsContext &builtin_ctx = BuiltinsContext::get (); - if (builtin_ctx.lookup_simple_builtin (fntype->get_identifier (), &builtin)) return builtin; @@ -607,8 +604,7 @@ copy_nonoverlapping_handler (Context *ctx, TyTy::FnType *fntype) = build2 (MULT_EXPR, size_type_node, TYPE_SIZE_UNIT (param_type), count); tree memcpy_raw = nullptr; - BuiltinsContext::get ().lookup_simple_builtin ("__builtin_memcpy", - &memcpy_raw); + BuiltinsContext::get ().lookup_simple_builtin ("memcpy", &memcpy_raw); rust_assert (memcpy_raw); auto memcpy = build_fold_addr_expr_loc (Location ().gcc_location (), memcpy_raw); @@ -660,35 +656,18 @@ prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind) enter_intrinsic_block (ctx, fndecl); auto addr = ctx->get_backend ()->var_expression (args[0], Location ()); - - // The core library technically allows you to pass any i32 value as a - // locality, but LLVM will then complain if the value cannot be constant - // evaluated. For now, we ignore the locality argument and instead always - // pass `3` (the most restrictive value). This allows us to still have - // prefetch behavior, just not as granular as expected. In future Rust - // versions, we hope that prefetch intrinsics will be split up according to - // locality, similarly to atomic intrinsics. - // The solution is to try and perform constant folding for the locality - // argument, or instead of creating a new function definition, modify the call - // site directly This has the bad side-effect of creating warnings about - // `unused name - locality`, which we hack away here: - // TODO: Take care of handling locality properly - ctx->get_backend ()->var_expression (args[1], Location ()); - + auto locality = ctx->get_backend ()->var_expression (args[1], Location ()); auto rw_flag = make_unsigned_long_tree (ctx, kind == Prefetch::Write ? 1 : 0); auto prefetch_raw = NULL_TREE; - auto ok = BuiltinsContext::get ().lookup_simple_builtin ("__builtin_prefetch", - &prefetch_raw); + auto ok + = BuiltinsContext::get ().lookup_simple_builtin ("prefetch", &prefetch_raw); rust_assert (ok); auto prefetch = build_fold_addr_expr_loc (Location ().gcc_location (), prefetch_raw); auto prefetch_call - = ctx->get_backend ()->call_expression (prefetch, - {addr, rw_flag, - // locality arg - make_unsigned_long_tree (ctx, 3)}, + = ctx->get_backend ()->call_expression (prefetch, {addr, rw_flag, locality}, nullptr, Location ()); TREE_READONLY (prefetch_call) = 0; @@ -714,7 +693,7 @@ build_atomic_builtin_name (const std::string &prefix, Location locus, // TODO: Can we maybe get the generic version (atomic_store_n) to work... This // would be so much better - std::string result = "__" + prefix; // + "n"; + std::string result = prefix; auto type_name = operand_type->get_name (); if (type_name == "usize" || type_name == "isize") @@ -724,13 +703,6 @@ build_atomic_builtin_name (const std::string &prefix, Location locus, return ""; } - if (type_name.at (0) == 'i') - { - rust_sorry_at (locus, "atomics are not yet supported for signed " - "integer types (i8, i16, i32, i64, i128)"); - return ""; - } - auto type_size_str = allowed_types.find (type_name); if (!check_for_basic_integer_type ("atomic", locus, operand_type)) @@ -860,7 +832,6 @@ atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering) TREE_SIDE_EFFECTS (load_call) = 1; ctx->add_statement (return_statement); - finalize_intrinsic_block (ctx, fndecl); return fndecl; diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index c725359..e5dc6da 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -1456,20 +1456,20 @@ fetch_overflow_builtins (ArithmeticOrLogicalOperator op) switch (op) { case ArithmeticOrLogicalOperator::ADD: - builtin_ctx.lookup_simple_builtin ("__builtin_add_overflow", &builtin); + builtin_ctx.lookup_simple_builtin ("add_overflow", &builtin); break; case ArithmeticOrLogicalOperator::SUBTRACT: - builtin_ctx.lookup_simple_builtin ("__builtin_sub_overflow", &builtin); + builtin_ctx.lookup_simple_builtin ("sub_overflow", &builtin); break; case ArithmeticOrLogicalOperator::MULTIPLY: - builtin_ctx.lookup_simple_builtin ("__builtin_mul_overflow", &builtin); + builtin_ctx.lookup_simple_builtin ("mul_overflow", &builtin); break; default: gcc_unreachable (); break; }; - builtin_ctx.lookup_simple_builtin ("__builtin_abort", &abort); + builtin_ctx.lookup_simple_builtin ("abort", &abort); rust_assert (abort); rust_assert (builtin); diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs index a42c517..243d446 100644 --- a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs +++ b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs @@ -8,7 +8,7 @@ extern "rust-intrinsic" { } fn main() { - let mut dst = 15u32; + let mut dst = 15; let new_value = 14; unsafe { diff --git a/gcc/testsuite/rust/execute/torture/atomic_load.rs b/gcc/testsuite/rust/execute/torture/atomic_load.rs index 612548b..28ed8ae 100644 --- a/gcc/testsuite/rust/execute/torture/atomic_load.rs +++ b/gcc/testsuite/rust/execute/torture/atomic_load.rs @@ -7,14 +7,14 @@ extern "rust-intrinsic" { pub fn atomic_load_unordered<T: Copy>(src: *const T) -> T; } -fn main() -> u32 { +fn main() -> i32 { let one; let two; let three; let four; unsafe { - let mut src = 1u32; + let mut src = 1; one = atomic_load_seqcst(&src); src = 2; diff --git a/gcc/testsuite/rust/execute/torture/atomic_store.rs b/gcc/testsuite/rust/execute/torture/atomic_store.rs index 88f8a53..9f248b4 100644 --- a/gcc/testsuite/rust/execute/torture/atomic_store.rs +++ b/gcc/testsuite/rust/execute/torture/atomic_store.rs @@ -7,8 +7,8 @@ extern "rust-intrinsic" { pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T); } -fn main() -> u32 { - let mut dst = 15u32; +fn main() -> i32 { + let mut dst = 15; let one; let two; let three; |