diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-03-11 09:41:37 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-11 09:41:37 +0000 |
commit | ddd087b0efa734cd166231b5812a201f30a4fd2b (patch) | |
tree | 1aac8c264cccddd81497c168203756005000b5fe | |
parent | 1f4e2deb31973f13940a99961042d4898b1a8207 (diff) | |
parent | f05744511998309f6694ad18abcc22fbac025dc2 (diff) | |
download | gcc-ddd087b0efa734cd166231b5812a201f30a4fd2b.zip gcc-ddd087b0efa734cd166231b5812a201f30a4fd2b.tar.gz gcc-ddd087b0efa734cd166231b5812a201f30a4fd2b.tar.bz2 |
Merge #1003
1003: Add more intrinsics and refactor how we implement them r=philberty a=philberty
This patch series implements:
1. offset
2. size_of
3. unreachable
4. abort
It removes the GCC wrapper mappings to make them much easier to implement. It also demonstrates in single commits
the implementation of each of these intrinsic to make it easy to follow in how we implement them.
Addresses #658 #849
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
-rw-r--r-- | gcc/rust/backend/rust-compile-fnparam.h | 8 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-intrinsic.cc | 422 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-resolve-path.cc | 8 | ||||
-rw-r--r-- | gcc/rust/backend/rust-tree.cc | 18 | ||||
-rw-r--r-- | gcc/rust/backend/rust-tree.h | 6 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-type.h | 13 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.cc | 6 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.h | 2 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.cc | 2 | ||||
-rw-r--r-- | gcc/rust/rust-backend.h | 10 | ||||
-rw-r--r-- | gcc/rust/rust-gcc.cc | 103 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.h | 9 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/never_type_err2.rs | 4 |
13 files changed, 439 insertions, 172 deletions
diff --git a/gcc/rust/backend/rust-compile-fnparam.h b/gcc/rust/backend/rust-compile-fnparam.h index 74df725..5e3cfaa 100644 --- a/gcc/rust/backend/rust-compile-fnparam.h +++ b/gcc/rust/backend/rust-compile-fnparam.h @@ -36,6 +36,14 @@ public: return compiler.compiled_param; } + static Bvariable *compile (Context *ctx, tree fndecl, HIR::Pattern *param, + tree decl_type, Location locus) + { + CompileFnParam compiler (ctx, fndecl, decl_type, locus); + param->accept_vis (compiler); + return compiler.compiled_param; + } + void visit (HIR::IdentifierPattern &pattern) override { if (!pattern.is_mut ()) diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index 8c5b073..3665f5d 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -15,10 +15,171 @@ // <http://www.gnu.org/licenses/>. #include "rust-compile-intrinsic.h" +#include "langhooks.h" +#include "rust-compile-type.h" +#include "rust-compile-fnparam.h" +#include "rust-tree.h" namespace Rust { namespace Compile { +// https://github.com/rust-lang/rust/blob/master/library/core/src/intrinsics.rs +// https://github.com/rust-lang/rust/blob/master/compiler/rustc_codegen_llvm/src/intrinsic.rs +// https://github.com/Rust-GCC/gccrs/issues/658 +// +// let llvm_name = match name { +// sym::sqrtf32 => "llvm.sqrt.f32", +// sym::sqrtf64 => "llvm.sqrt.f64", +// sym::powif32 => "llvm.powi.f32", +// sym::powif64 => "llvm.powi.f64", +// sym::sinf32 => "llvm.sin.f32", +// sym::sinf64 => "llvm.sin.f64", +// sym::cosf32 => "llvm.cos.f32", +// sym::cosf64 => "llvm.cos.f64", +// sym::powf32 => "llvm.pow.f32", +// sym::powf64 => "llvm.pow.f64", +// sym::expf32 => "llvm.exp.f32", +// sym::expf64 => "llvm.exp.f64", +// sym::exp2f32 => "llvm.exp2.f32", +// sym::exp2f64 => "llvm.exp2.f64", +// sym::logf32 => "llvm.log.f32", +// sym::logf64 => "llvm.log.f64", +// sym::log10f32 => "llvm.log10.f32", +// sym::log10f64 => "llvm.log10.f64", +// sym::log2f32 => "llvm.log2.f32", +// sym::log2f64 => "llvm.log2.f64", +// sym::fmaf32 => "llvm.fma.f32", +// sym::fmaf64 => "llvm.fma.f64", +// sym::fabsf32 => "llvm.fabs.f32", +// sym::fabsf64 => "llvm.fabs.f64", +// sym::minnumf32 => "llvm.minnum.f32", +// sym::minnumf64 => "llvm.minnum.f64", +// sym::maxnumf32 => "llvm.maxnum.f32", +// sym::maxnumf64 => "llvm.maxnum.f64", +// sym::copysignf32 => "llvm.copysign.f32", +// sym::copysignf64 => "llvm.copysign.f64", +// sym::floorf32 => "llvm.floor.f32", +// sym::floorf64 => "llvm.floor.f64", +// sym::ceilf32 => "llvm.ceil.f32", +// sym::ceilf64 => "llvm.ceil.f64", +// sym::truncf32 => "llvm.trunc.f32", +// sym::truncf64 => "llvm.trunc.f64", +// sym::rintf32 => "llvm.rint.f32", +// sym::rintf64 => "llvm.rint.f64", +// sym::nearbyintf32 => "llvm.nearbyint.f32", +// sym::nearbyintf64 => "llvm.nearbyint.f64", +// sym::roundf32 => "llvm.round.f32", +// sym::roundf64 => "llvm.round.f64", +// _ => return None, +// }; +// Some(cx.get_intrinsic(&llvm_name)) +class SimpleIntrinsics +{ +public: + static SimpleIntrinsics &get () + { + static SimpleIntrinsics instance; + return instance; + } + + bool lookup_simple_builtin (const std::string &name, tree *builtin) + { + auto it = rust_intrinsic_to_gcc_builtin.find (name); + if (it == rust_intrinsic_to_gcc_builtin.end ()) + return false; + + return lookup_gcc_builtin (it->second, builtin); + } + +private: + static const int builtin_const = 1 << 0; + static const int builtin_noreturn = 1 << 1; + static const int builtin_novops = 1 << 2; + + SimpleIntrinsics () { setup (); } + + void setup () + { + tree math_function_type_f32 + = build_function_type_list (float_type_node, float_type_node, NULL_TREE); + + 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_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 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) + { + tree decl = add_builtin_function (name, fntype, bcode, BUILT_IN_NORMAL, + libname, NULL_TREE); + if ((flags & builtin_const) != 0) + TREE_READONLY (decl) = 1; + if ((flags & builtin_noreturn) != 0) + 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] = 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_noreturn) != 0) + TREE_THIS_VOLATILE (decl) = 1; + if ((flags & builtin_novops) != 0) + DECL_IS_NOVOPS (decl) = 1; + this->builtin_functions_[libname] = decl; + } + + rust_intrinsic_to_gcc_builtin[rust_name] = name; + } + + bool lookup_gcc_builtin (const std::string &name, tree *builtin) + { + auto it = builtin_functions_.find (name); + if (it == builtin_functions_.end ()) + return false; + + *builtin = it->second; + return true; + } + + // A mapping of the GCC built-ins exposed to GCC Rust. + std::map<std::string, tree> builtin_functions_; + std::map<std::string, std::string> rust_intrinsic_to_gcc_builtin; +}; + +static tree +offset_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype); +static tree +sizeof_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype); + +static const std::map<std::string, + std::function<tree (Context *, TyTy::BaseType *)>> + generic_intrinsics = {{"offset", &offset_intrinsic_handler}, + {"size_of", &sizeof_intrinsic_handler}}; + Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {} tree @@ -26,67 +187,218 @@ Intrinsics::compile (TyTy::FnType *fntype) { rust_assert (fntype->get_abi () == ABI::INTRINSIC); - // https://github.com/rust-lang/rust/blob/master/library/core/src/intrinsics.rs - // https://github.com/rust-lang/rust/blob/master/compiler/rustc_codegen_llvm/src/intrinsic.rs - // https://github.com/Rust-GCC/gccrs/issues/658 - - // let llvm_name = match name { - // sym::sqrtf32 => "llvm.sqrt.f32", - // sym::sqrtf64 => "llvm.sqrt.f64", - // sym::powif32 => "llvm.powi.f32", - // sym::powif64 => "llvm.powi.f64", - // sym::sinf32 => "llvm.sin.f32", - // sym::sinf64 => "llvm.sin.f64", - // sym::cosf32 => "llvm.cos.f32", - // sym::cosf64 => "llvm.cos.f64", - // sym::powf32 => "llvm.pow.f32", - // sym::powf64 => "llvm.pow.f64", - // sym::expf32 => "llvm.exp.f32", - // sym::expf64 => "llvm.exp.f64", - // sym::exp2f32 => "llvm.exp2.f32", - // sym::exp2f64 => "llvm.exp2.f64", - // sym::logf32 => "llvm.log.f32", - // sym::logf64 => "llvm.log.f64", - // sym::log10f32 => "llvm.log10.f32", - // sym::log10f64 => "llvm.log10.f64", - // sym::log2f32 => "llvm.log2.f32", - // sym::log2f64 => "llvm.log2.f64", - // sym::fmaf32 => "llvm.fma.f32", - // sym::fmaf64 => "llvm.fma.f64", - // sym::fabsf32 => "llvm.fabs.f32", - // sym::fabsf64 => "llvm.fabs.f64", - // sym::minnumf32 => "llvm.minnum.f32", - // sym::minnumf64 => "llvm.minnum.f64", - // sym::maxnumf32 => "llvm.maxnum.f32", - // sym::maxnumf64 => "llvm.maxnum.f64", - // sym::copysignf32 => "llvm.copysign.f32", - // sym::copysignf64 => "llvm.copysign.f64", - // sym::floorf32 => "llvm.floor.f32", - // sym::floorf64 => "llvm.floor.f64", - // sym::ceilf32 => "llvm.ceil.f32", - // sym::ceilf64 => "llvm.ceil.f64", - // sym::truncf32 => "llvm.trunc.f32", - // sym::truncf64 => "llvm.trunc.f64", - // sym::rintf32 => "llvm.rint.f32", - // sym::rintf64 => "llvm.rint.f64", - // sym::nearbyintf32 => "llvm.nearbyint.f32", - // sym::nearbyintf64 => "llvm.nearbyint.f64", - // sym::roundf32 => "llvm.round.f32", - // sym::roundf64 => "llvm.round.f64", - // _ => return None, - // }; - // Some(cx.get_intrinsic(&llvm_name)) - - tree builtin = ctx->get_backend ()->lookup_builtin_by_rust_name ( - fntype->get_identifier ()); - if (builtin != nullptr) + tree builtin = error_mark_node; + SimpleIntrinsics &simple_intrinsics = SimpleIntrinsics::get (); + if (simple_intrinsics.lookup_simple_builtin (fntype->get_identifier (), + &builtin)) return builtin; + // is it an generic builtin? + auto it = generic_intrinsics.find (fntype->get_identifier ()); + if (it != generic_intrinsics.end ()) + return it->second (ctx, fntype); + Location locus = ctx->get_mappings ()->lookup_location (fntype->get_ref ()); - rust_error_at (locus, "unknown builtin"); + rust_error_at (locus, "unknown builtin intrinsic: %s", + fntype->get_identifier ().c_str ()); return error_mark_node; } +static tree +offset_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty) +{ + rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty); + const Resolver::CanonicalPath &canonical_path = fntype->get_ident ().path; + + // items can be forward compiled which means we may not need to invoke this + // code. We might also have already compiled this generic function as well. + tree lookup = NULL_TREE; + if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, + fntype->get_id (), fntype)) + { + // has this been added to the list then it must be finished + if (ctx->function_completed (lookup)) + { + tree dummy = NULL_TREE; + if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) + { + ctx->insert_function_decl (fntype, lookup); + } + return lookup; + } + } + + if (fntype->has_subsititions_defined ()) + { + // override the Hir Lookups for the substituions in this context + fntype->override_context (); + } + + // offset intrinsic has two params dst pointer and offset isize + if (fntype->get_params ().size () != 2) + { + rust_error_at (fntype->get_ident ().locus, + "invalid number of parameters for offset intrinsic"); + return error_mark_node; + } + + tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + std::string ir_symbol_name + = canonical_path.get () + fntype->subst_as_string (); + std::string asm_name = ctx->mangle_item (fntype, canonical_path); + + unsigned int flags = 0; + tree fndecl + = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name, + flags, fntype->get_ident ().locus); + TREE_PUBLIC (fndecl) = 0; + TREE_READONLY (fndecl) = 1; + DECL_ARTIFICIAL (fndecl) = 1; + DECL_EXTERNAL (fndecl) = 0; + DECL_DECLARED_INLINE_P (fndecl) = 1; + + // setup the params + std::vector<Bvariable *> param_vars; + for (auto &parm : fntype->get_params ()) + { + auto &referenced_param = parm.first; + auto ¶m_tyty = parm.second; + auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty); + + Location param_locus = referenced_param->get_locus (); + Bvariable *compiled_param_var + = CompileFnParam::compile (ctx, fndecl, referenced_param, + compiled_param_type, param_locus); + + param_vars.push_back (compiled_param_var); + } + + auto &dst_param = param_vars.at (0); + auto &size_param = param_vars.at (1); + rust_assert (param_vars.size () == 2); + if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars)) + return error_mark_node; + + tree enclosing_scope = NULL_TREE; + Location start_location = Location (); + Location end_location = Location (); + + tree code_block = ctx->get_backend ()->block (fndecl, enclosing_scope, {}, + start_location, end_location); + ctx->push_block (code_block); + + // BUILTIN offset FN BODY BEGIN + tree dst = ctx->get_backend ()->var_expression (dst_param, Location ()); + tree size = ctx->get_backend ()->var_expression (size_param, Location ()); + tree pointer_offset_expr + = pointer_offset_expression (dst, size, BUILTINS_LOCATION); + auto return_statement + = ctx->get_backend ()->return_statement (fndecl, {pointer_offset_expr}, + Location ()); + ctx->add_statement (return_statement); + // BUILTIN offset FN BODY END + + tree bind_tree = ctx->pop_block (); + + gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR); + DECL_SAVED_TREE (fndecl) = bind_tree; + + ctx->pop_fn (); + ctx->push_function (fndecl); + + return fndecl; +} + +static tree +sizeof_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty) +{ + rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty); + const Resolver::CanonicalPath &canonical_path = fntype->get_ident ().path; + + // items can be forward compiled which means we may not need to invoke this + // code. We might also have already compiled this generic function as well. + tree lookup = NULL_TREE; + if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, + fntype->get_id (), fntype)) + { + // has this been added to the list then it must be finished + if (ctx->function_completed (lookup)) + { + tree dummy = NULL_TREE; + if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) + { + ctx->insert_function_decl (fntype, lookup); + } + return lookup; + } + } + + if (fntype->has_subsititions_defined ()) + { + // override the Hir Lookups for the substituions in this context + fntype->override_context (); + } + + // offset intrinsic has two params dst pointer and offset isize + if (fntype->get_params ().size () != 0) + { + rust_error_at (fntype->get_ident ().locus, + "invalid number of parameters for size of intrinsic"); + return error_mark_node; + } + + // get the template parameter type tree fn size_of<T>(); + rust_assert (fntype->get_num_substitutions () == 1); + auto ¶m_mapping = fntype->get_substs ().at (0); + const TyTy::ParamType *param_tyty = param_mapping.get_param_ty (); + TyTy::BaseType *resolved_tyty = param_tyty->resolve (); + tree template_parameter_type + = TyTyResolveCompile::compile (ctx, resolved_tyty); + + // build the intrinsic function + tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + std::string ir_symbol_name + = canonical_path.get () + fntype->subst_as_string (); + std::string asm_name = ctx->mangle_item (fntype, canonical_path); + + unsigned int flags = 0; + tree fndecl + = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name, + flags, fntype->get_ident ().locus); + TREE_PUBLIC (fndecl) = 0; + TREE_READONLY (fndecl) = 1; + DECL_ARTIFICIAL (fndecl) = 1; + DECL_EXTERNAL (fndecl) = 0; + DECL_DECLARED_INLINE_P (fndecl) = 1; + + tree enclosing_scope = NULL_TREE; + Location start_location = Location (); + Location end_location = Location (); + + tree code_block = ctx->get_backend ()->block (fndecl, enclosing_scope, {}, + start_location, end_location); + ctx->push_block (code_block); + + // BUILTIN size_of FN BODY BEGIN + tree size_expr = TYPE_SIZE_UNIT (template_parameter_type); + auto return_statement + = ctx->get_backend ()->return_statement (fndecl, {size_expr}, Location ()); + ctx->add_statement (return_statement); + // BUILTIN size_of FN BODY END + + tree bind_tree = ctx->pop_block (); + + gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR); + DECL_SAVED_TREE (fndecl) = bind_tree; + + ctx->pop_fn (); + ctx->push_function (fndecl); + + return fndecl; +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 09f3860..2ad672d 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -17,6 +17,7 @@ // <http://www.gnu.org/licenses/>. #include "rust-compile-resolve-path.h" +#include "rust-compile-intrinsic.h" #include "rust-compile-item.h" #include "rust-compile-implitem.h" #include "rust-compile-expr.h" @@ -142,6 +143,13 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, TREE_USED (fn) = 1; return address_expression (fn, expr_locus); } + else if (fntype->get_abi () == ABI::INTRINSIC) + { + Intrinsics compile (ctx); + fn = compile.compile (fntype); + TREE_USED (fn) = 1; + return address_expression (fn, expr_locus); + } } // let the query system figure it out diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc index 8e39408..6f7614d 100644 --- a/gcc/rust/backend/rust-tree.cc +++ b/gcc/rust/backend/rust-tree.cc @@ -17,6 +17,7 @@ // <http://www.gnu.org/licenses/>. #include "rust-tree.h" +#include "fold-const.h" #include "stringpool.h" #include "attribs.h" #include "escaped_string.h" @@ -656,4 +657,21 @@ get_fndecl_from_callee (tree fn) return NULL_TREE; } +tree +pointer_offset_expression (tree base_tree, tree index_tree, location_t location) +{ + tree element_type_tree = TREE_TYPE (TREE_TYPE (base_tree)); + if (base_tree == error_mark_node || TREE_TYPE (base_tree) == error_mark_node + || index_tree == error_mark_node || element_type_tree == error_mark_node) + return error_mark_node; + + tree element_size = TYPE_SIZE_UNIT (element_type_tree); + index_tree = fold_convert_loc (location, sizetype, index_tree); + tree offset + = fold_build2_loc (location, MULT_EXPR, sizetype, index_tree, element_size); + + return fold_build2_loc (location, POINTER_PLUS_EXPR, TREE_TYPE (base_tree), + base_tree, offset); +} + } // namespace Rust diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h index c21bf4b..c50e090 100644 --- a/gcc/rust/backend/rust-tree.h +++ b/gcc/rust/backend/rust-tree.h @@ -177,6 +177,12 @@ expr_loc_or_input_loc (const_tree t); extern tree get_fndecl_from_callee (tree fn); +// FIXME some helpers from HIRCompileBase could probably be moved here over time + +// Return an expression for the address of BASE[INDEX], used in offset intrinsic +extern tree +pointer_offset_expression (tree base_tree, tree index_tree, location_t locus); + } // namespace Rust #endif // RUST_TREE diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 3d1690f..a9b4dd8 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -291,6 +291,19 @@ public: translated); } + void visit (AST::NeverType &type) override + { + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, type.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated = new HIR::NeverType (mapping, type.get_locus ()); + + mappings->insert_hir_type (mapping.get_crate_num (), mapping.get_hirid (), + translated); + } + void visit (AST::TraitObjectTypeOneBound &type) override; void visit (AST::TraitObjectType &type) override; diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc index 252d1ca..fd5c056 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ b/gcc/rust/resolve/rust-ast-resolve-type.cc @@ -198,6 +198,12 @@ ResolveType::visit (AST::InferredType &type) } void +ResolveType::visit (AST::NeverType &type) +{ + ok = true; +} + +void ResolveType::visit (AST::SliceType &type) { type.get_elem_type ()->accept_vis (*this); diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index d835e00..e534423 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -386,6 +386,8 @@ public: void visit (AST::InferredType &type) override; + void visit (AST::NeverType &type) override; + void visit (AST::RawPointerType &type) override; void visit (AST::TraitObjectTypeOneBound &type) override; diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 094fa4a..86c159d 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -187,6 +187,7 @@ Resolver::generate_builtins () auto isize = new TyTy::ISizeType (mappings->get_next_hir_id ()); auto char_tyty = new TyTy::CharType (mappings->get_next_hir_id ()); auto str = new TyTy::StrType (mappings->get_next_hir_id ()); + auto never = new TyTy::NeverType (mappings->get_next_hir_id ()); MKBUILTIN_TYPE ("u8", builtins, u8); MKBUILTIN_TYPE ("u16", builtins, u16); @@ -205,6 +206,7 @@ Resolver::generate_builtins () MKBUILTIN_TYPE ("isize", builtins, isize); MKBUILTIN_TYPE ("char", builtins, char_tyty); MKBUILTIN_TYPE ("str", builtins, str); + MKBUILTIN_TYPE ("!", builtins, never); // unit type () TyTy::TupleType *unit_tyty diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index fca09b2..6bfebe3 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -275,10 +275,6 @@ public: const std::vector<tree> &vals, Location) = 0; - // Return an expression for the address of BASE[INDEX]. - // BASE has a pointer type. This is used for slice indexing. - virtual tree pointer_offset_expression (tree base, tree index, Location) = 0; - // Return an expression for ARRAY[INDEX] as an l-value. ARRAY is a valid // fixed-length array, not a slice. virtual tree array_index_expression (tree array, tree index, Location) = 0; @@ -508,12 +504,6 @@ public: const std::vector<Bvariable *> ¶m_vars) = 0; - // Look up a named built-in function in the current backend implementation. - // Returns NULL if no built-in function by that name exists. - virtual tree lookup_gcc_builtin (const std::string &) = 0; - - virtual tree lookup_builtin_by_rust_name (const std::string &) = 0; - // Utility. // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 70c07c1..6ea9ef3 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -246,8 +246,6 @@ public: tree array_constructor_expression (tree, const std::vector<unsigned long> &, const std::vector<tree> &, Location); - tree pointer_offset_expression (tree base, tree offset, Location); - tree array_index_expression (tree array, tree index, Location); tree call_expression (tree caller, tree fn, const std::vector<tree> &args, @@ -346,19 +344,6 @@ private: tree non_zero_size_type (tree); tree 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; - - void define_builtin (const std::string rust_name, built_in_function bcode, - const char *name, const char *libname, tree fntype, - int flags); - - // A mapping of the GCC built-ins exposed to GCCRust. - std::map<std::string, tree> builtin_functions_; - std::map<std::string, std::string> rust_intrinsic_to_gcc_builtin; }; // A helper function to create a GCC identifier from a C++ string. @@ -475,14 +460,6 @@ Gcc_backend::Gcc_backend () // builtin_const); // We provide some functions for the math library. - tree math_function_type_f32 - = build_function_type_list (float_type_node, float_type_node, NULL_TREE); - - this->define_builtin ("sinf32", BUILT_IN_SINF, "__builtin_sinf", "sinf", - math_function_type_f32, builtin_const); - - this->define_builtin ("sqrtf32", BUILT_IN_SQRTF, "__builtin_sqrtf", "sqrtf", - math_function_type_f32, builtin_const); // We use __builtin_return_address in the thunk we build for // functions which call recover, and for runtime.getcallerpc. @@ -1717,27 +1694,6 @@ Gcc_backend::array_constructor_expression ( return ret; } -// Return an expression for the address of BASE[INDEX]. - -tree -Gcc_backend::pointer_offset_expression (tree base_tree, tree index_tree, - Location location) -{ - tree element_type_tree = TREE_TYPE (TREE_TYPE (base_tree)); - if (base_tree == error_mark_node || TREE_TYPE (base_tree) == error_mark_node - || index_tree == error_mark_node || element_type_tree == error_mark_node) - return error_mark_node; - - tree element_size = TYPE_SIZE_UNIT (element_type_tree); - index_tree - = fold_convert_loc (location.gcc_location (), sizetype, index_tree); - tree offset = fold_build2_loc (location.gcc_location (), MULT_EXPR, sizetype, - index_tree, element_size); - tree ptr = fold_build2_loc (location.gcc_location (), POINTER_PLUS_EXPR, - TREE_TYPE (base_tree), base_tree, offset); - return ptr; -} - // Return an expression representing ARRAY[INDEX] tree @@ -2684,27 +2640,6 @@ Gcc_backend::function_set_parameters ( return true; } -// Look up a named built-in function in the current backend implementation. -// Returns NULL if no built-in function by that name exists. - -tree -Gcc_backend::lookup_gcc_builtin (const std::string &name) -{ - if (this->builtin_functions_.count (name) != 0) - return this->builtin_functions_[name]; - return NULL; -} - -tree -Gcc_backend::lookup_builtin_by_rust_name (const std::string &name) -{ - auto it = rust_intrinsic_to_gcc_builtin.find (name); - if (it == rust_intrinsic_to_gcc_builtin.end ()) - return NULL; - - return lookup_gcc_builtin (it->second); -} - // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, // FUNCTION_DECLS, and VARIABLE_DECLS declared globally, as well as // emit early debugging information. @@ -2786,44 +2721,6 @@ Gcc_backend::write_export_data (const char *bytes, unsigned int size) rust_write_export_data (bytes, size); } -// 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 -Gcc_backend::define_builtin (const std::string rust_name, - built_in_function bcode, const char *name, - const char *libname, tree fntype, int flags) -{ - tree decl = add_builtin_function (name, fntype, bcode, BUILT_IN_NORMAL, - libname, NULL_TREE); - if ((flags & builtin_const) != 0) - TREE_READONLY (decl) = 1; - if ((flags & builtin_noreturn) != 0) - 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] = 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_noreturn) != 0) - TREE_THIS_VOLATILE (decl) = 1; - if ((flags & builtin_novops) != 0) - DECL_IS_NOVOPS (decl) = 1; - this->builtin_functions_[libname] = decl; - } - - rust_intrinsic_to_gcc_builtin[rust_name] = name; -} - // Return the backend generator. Backend * diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 400328c..74298e4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -145,6 +145,15 @@ public: type.get_locus ()); } + void visit (HIR::NeverType &type) override + { + TyTy::BaseType *lookup = nullptr; + bool ok = context->lookup_builtin ("!", &lookup); + rust_assert (ok); + + translated = lookup->clone (); + } + void visit (HIR::TraitObjectType &type) override; private: diff --git a/gcc/testsuite/rust/compile/never_type_err2.rs b/gcc/testsuite/rust/compile/never_type_err2.rs deleted file mode 100644 index c94cb82..0000000 --- a/gcc/testsuite/rust/compile/never_type_err2.rs +++ /dev/null @@ -1,4 +0,0 @@ -// FIXME: Unimplemented features -fn foo() -> ! { // { dg-error "unresolved type" } - let a: !; // { dg-error "unresolved type" } -} |