diff options
author | Philip Herron <herron.philip@googlemail.com> | 2025-02-10 16:28:30 +0000 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2025-03-24 13:07:04 +0100 |
commit | b5106eeabdb5ebcd4bb6b2fa5dbb6932b9f406f6 (patch) | |
tree | 1fd5c7a1f51a7267a4d36b9263261a7fd07393ab /gcc/rust/backend | |
parent | 90376526038ec469f9037a90619ab04089e3a7f0 (diff) | |
download | gcc-b5106eeabdb5ebcd4bb6b2fa5dbb6932b9f406f6.zip gcc-b5106eeabdb5ebcd4bb6b2fa5dbb6932b9f406f6.tar.gz gcc-b5106eeabdb5ebcd4bb6b2fa5dbb6932b9f406f6.tar.bz2 |
gccrs: add discriminant value intrinsic
This is pretty nasty piece of rust in my opinion the return type of this
intrinsic results into a lang item associated type:
<T as DiscriminantKind>::Discriminant
This is a special case which needs to support mapping onto the repr type
of the associated ADT that is passed in, but defaults to iszie otherwise.
This patch assumes we only come accross this case in a HIR::CALL_EXPR, so
and makes assumutions that its always of this function signiture. I will
do some checking in libcore to verify that assumption. More work is needed
to parse the repr type on enums but the code is there to support this when
its in to change the types etc.
Addresses Rust-GCC#3348
gcc/rust/ChangeLog:
* backend/rust-compile-intrinsic.cc (discriminant_value_handler): new handler
* typecheck/rust-hir-trait-resolve.cc (TraitItemReference::resolve_item): track the defid
* typecheck/rust-hir-type-check-base.cc (TypeCheckBase::parse_repr_options): default isize
* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): special case CallExpr
* typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): parse repr options enum
* typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): remove bad diagnostic
* typecheck/rust-tyty.cc (PlaceholderType::PlaceholderType): track defid
(PlaceholderType::clone): likewise
(PlaceholderType::get_def_id): likeiwse
* typecheck/rust-tyty.h: placeholder track defid
* util/rust-lang-item.cc: add new lang items
* util/rust-lang-item.h: likewise
gcc/testsuite/ChangeLog:
* rust/execute/torture/enum_intrinsics1.rs: New test.
Signed-off-by: Philip Herron <herron.philip@googlemail.com>
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r-- | gcc/rust/backend/rust-compile-intrinsic.cc | 149 |
1 files changed, 105 insertions, 44 deletions
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index 0f05458..1f93e82 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -17,7 +17,6 @@ #include "rust-compile-intrinsic.h" #include "rust-compile-context.h" #include "rust-compile-type.h" -#include "rust-compile-expr.h" #include "rust-compile-fnparam.h" #include "rust-builtins.h" #include "rust-diagnostics.h" @@ -27,14 +26,10 @@ #include "rust-tree.h" #include "tree-core.h" #include "rust-gcc.h" -#include "print-tree.h" #include "fold-const.h" #include "langhooks.h" -#include "rust-gcc.h" #include "rust-constexpr.h" -#include "print-tree.h" - // declaration taken from "stringpool.h" // the get_identifier macro causes compilation issues extern tree @@ -93,6 +88,8 @@ static tree move_val_init_handler (Context *ctx, TyTy::FnType *fntype); static tree assume_handler (Context *ctx, TyTy::FnType *fntype); +static tree +discriminant_value_handler (Context *ctx, TyTy::FnType *fntype); enum class Prefetch { @@ -217,45 +214,45 @@ sorry_handler (Context *ctx, TyTy::FnType *fntype) static const std::map<std::string, std::function<tree (Context *, TyTy::FnType *)>> - generic_intrinsics = { - {"offset", offset_handler}, - {"size_of", sizeof_handler}, - {"transmute", transmute_handler}, - {"rotate_left", rotate_left_handler}, - {"rotate_right", rotate_right_handler}, - {"wrapping_add", wrapping_op_handler (PLUS_EXPR)}, - {"wrapping_sub", wrapping_op_handler (MINUS_EXPR)}, - {"wrapping_mul", wrapping_op_handler (MULT_EXPR)}, - {"add_with_overflow", op_with_overflow (PLUS_EXPR)}, - {"sub_with_overflow", op_with_overflow (MINUS_EXPR)}, - {"mul_with_overflow", op_with_overflow (MULT_EXPR)}, - {"copy", copy_handler (true)}, - {"copy_nonoverlapping", copy_handler (false)}, - {"prefetch_read_data", prefetch_read_data}, - {"prefetch_write_data", prefetch_write_data}, - {"atomic_store_seqcst", atomic_store_handler (__ATOMIC_SEQ_CST)}, - {"atomic_store_release", atomic_store_handler (__ATOMIC_RELEASE)}, - {"atomic_store_relaxed", atomic_store_handler (__ATOMIC_RELAXED)}, - {"atomic_store_unordered", atomic_store_handler (__ATOMIC_RELAXED)}, - {"atomic_load_seqcst", atomic_load_handler (__ATOMIC_SEQ_CST)}, - {"atomic_load_acquire", atomic_load_handler (__ATOMIC_ACQUIRE)}, - {"atomic_load_relaxed", atomic_load_handler (__ATOMIC_RELAXED)}, - {"atomic_load_unordered", atomic_load_handler (__ATOMIC_RELAXED)}, - {"unchecked_add", unchecked_op_handler (PLUS_EXPR)}, - {"unchecked_sub", unchecked_op_handler (MINUS_EXPR)}, - {"unchecked_mul", unchecked_op_handler (MULT_EXPR)}, - {"unchecked_div", unchecked_op_handler (TRUNC_DIV_EXPR)}, - {"unchecked_rem", unchecked_op_handler (TRUNC_MOD_EXPR)}, - {"unchecked_shl", unchecked_op_handler (LSHIFT_EXPR)}, - {"unchecked_shr", unchecked_op_handler (RSHIFT_EXPR)}, - {"uninit", uninit_handler}, - {"move_val_init", move_val_init_handler}, - {"likely", expect_handler (true)}, - {"unlikely", expect_handler (false)}, - {"assume", assume_handler}, - {"try", try_handler (false)}, - {"catch_unwind", try_handler (true)}, -}; + generic_intrinsics + = {{"offset", offset_handler}, + {"size_of", sizeof_handler}, + {"transmute", transmute_handler}, + {"rotate_left", rotate_left_handler}, + {"rotate_right", rotate_right_handler}, + {"wrapping_add", wrapping_op_handler (PLUS_EXPR)}, + {"wrapping_sub", wrapping_op_handler (MINUS_EXPR)}, + {"wrapping_mul", wrapping_op_handler (MULT_EXPR)}, + {"add_with_overflow", op_with_overflow (PLUS_EXPR)}, + {"sub_with_overflow", op_with_overflow (MINUS_EXPR)}, + {"mul_with_overflow", op_with_overflow (MULT_EXPR)}, + {"copy", copy_handler (true)}, + {"copy_nonoverlapping", copy_handler (false)}, + {"prefetch_read_data", prefetch_read_data}, + {"prefetch_write_data", prefetch_write_data}, + {"atomic_store_seqcst", atomic_store_handler (__ATOMIC_SEQ_CST)}, + {"atomic_store_release", atomic_store_handler (__ATOMIC_RELEASE)}, + {"atomic_store_relaxed", atomic_store_handler (__ATOMIC_RELAXED)}, + {"atomic_store_unordered", atomic_store_handler (__ATOMIC_RELAXED)}, + {"atomic_load_seqcst", atomic_load_handler (__ATOMIC_SEQ_CST)}, + {"atomic_load_acquire", atomic_load_handler (__ATOMIC_ACQUIRE)}, + {"atomic_load_relaxed", atomic_load_handler (__ATOMIC_RELAXED)}, + {"atomic_load_unordered", atomic_load_handler (__ATOMIC_RELAXED)}, + {"unchecked_add", unchecked_op_handler (PLUS_EXPR)}, + {"unchecked_sub", unchecked_op_handler (MINUS_EXPR)}, + {"unchecked_mul", unchecked_op_handler (MULT_EXPR)}, + {"unchecked_div", unchecked_op_handler (TRUNC_DIV_EXPR)}, + {"unchecked_rem", unchecked_op_handler (TRUNC_MOD_EXPR)}, + {"unchecked_shl", unchecked_op_handler (LSHIFT_EXPR)}, + {"unchecked_shr", unchecked_op_handler (RSHIFT_EXPR)}, + {"uninit", uninit_handler}, + {"move_val_init", move_val_init_handler}, + {"likely", expect_handler (true)}, + {"unlikely", expect_handler (false)}, + {"assume", assume_handler}, + {"try", try_handler (false)}, + {"catch_unwind", try_handler (true)}, + {"discriminant_value", discriminant_value_handler}}; Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {} @@ -1375,5 +1372,69 @@ try_handler_inner (Context *ctx, TyTy::FnType *fntype, bool is_new_api) return fndecl; } +static tree +discriminant_value_handler (Context *ctx, TyTy::FnType *fntype) +{ + rust_assert (fntype->get_params ().size () == 1); + rust_assert (fntype->get_return_type ()->is<TyTy::PlaceholderType> ()); + rust_assert (fntype->has_substitutions ()); + 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 (); + auto p = static_cast<TyTy::PlaceholderType *> (fntype->get_return_type ()); + + TyTy::BaseType *return_type = nullptr; + bool ok = ctx->get_tyctx ()->lookup_builtin ("isize", &return_type); + rust_assert (ok); + + bool is_adt = resolved->is<TyTy::ADTType> (); + bool is_enum = false; + if (is_adt) + { + const auto &adt = *static_cast<TyTy::ADTType *> (resolved); + return_type = adt.get_repr_options ().repr; + rust_assert (return_type != nullptr); + is_enum = adt.is_enum (); + } + + p->set_associated_type (return_type->get_ref ()); + + 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 = integer_zero_node; + if (is_enum) + { + tree val = Backend::var_expression (param_vars[0], UNDEF_LOCATION); + tree deref = build_fold_indirect_ref_loc (UNKNOWN_LOCATION, val); + result = Backend::struct_field_expression (deref, 0, UNKNOWN_LOCATION); + } + + 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 |