aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend
diff options
context:
space:
mode:
authorPhilip Herron <herron.philip@googlemail.com>2025-02-10 16:28:30 +0000
committerArthur Cohen <arthur.cohen@embecosm.com>2025-03-24 13:07:04 +0100
commitb5106eeabdb5ebcd4bb6b2fa5dbb6932b9f406f6 (patch)
tree1fd5c7a1f51a7267a4d36b9263261a7fd07393ab /gcc/rust/backend
parent90376526038ec469f9037a90619ab04089e3a7f0 (diff)
downloadgcc-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.cc149
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, &param_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