diff options
Diffstat (limited to 'gcc/rust/backend/rust-builtins.cc')
-rw-r--r-- | gcc/rust/backend/rust-builtins.cc | 350 |
1 files changed, 112 insertions, 238 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; |