diff options
Diffstat (limited to 'gcc/rust/backend/rust-compile-intrinsic.cc')
-rw-r--r-- | gcc/rust/backend/rust-compile-intrinsic.cc | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index 1f93e82..28c69d5 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -90,6 +90,8 @@ static tree assume_handler (Context *ctx, TyTy::FnType *fntype); static tree discriminant_value_handler (Context *ctx, TyTy::FnType *fntype); +static tree +variant_count_handler (Context *ctx, TyTy::FnType *fntype); enum class Prefetch { @@ -252,7 +254,8 @@ static const std::map<std::string, {"assume", assume_handler}, {"try", try_handler (false)}, {"catch_unwind", try_handler (true)}, - {"discriminant_value", discriminant_value_handler}}; + {"discriminant_value", discriminant_value_handler}, + {"variant_count", variant_count_handler}}; Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {} @@ -1436,5 +1439,56 @@ discriminant_value_handler (Context *ctx, TyTy::FnType *fntype) return fndecl; } +static tree +variant_count_handler (Context *ctx, TyTy::FnType *fntype) +{ + rust_assert (fntype->get_num_type_params () == 1); + auto &mapping = fntype->get_substs ().at (0); + auto param_ty = mapping.get_param_ty (); + rust_assert (param_ty->can_resolve ()); + auto resolved = param_ty->resolve (); + + size_t variant_count = 0; + bool is_adt = resolved->is<TyTy::ADTType> (); + if (is_adt) + { + const auto &adt = *static_cast<TyTy::ADTType *> (resolved); + variant_count = adt.number_of_variants (); + } + + tree lookup = NULL_TREE; + if (check_for_cached_intrinsic (ctx, fntype, &lookup)) + return lookup; + + auto fndecl = compile_intrinsic_function (ctx, fntype); + + std::vector<Bvariable *> param_vars; + compile_fn_params (ctx, fntype, fndecl, ¶m_vars); + + if (!Backend::function_set_parameters (fndecl, param_vars)) + return error_mark_node; + + enter_intrinsic_block (ctx, fndecl); + + // BUILTIN disriminant_value FN BODY BEGIN + tree result_decl = DECL_RESULT (fndecl); + tree type = TREE_TYPE (result_decl); + + mpz_t ival; + mpz_init_set_ui (ival, variant_count); + tree result = wide_int_to_tree (type, wi::from_mpz (type, ival, true)); + mpz_clear (ival); + + auto return_statement + = Backend::return_statement (fndecl, result, BUILTINS_LOCATION); + ctx->add_statement (return_statement); + + // BUILTIN disriminant_value FN BODY END + + finalize_intrinsic_block (ctx, fndecl); + + return fndecl; +} + } // namespace Compile } // namespace Rust |