aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r--gcc/rust/backend/rust-compile-intrinsic.cc32
1 files changed, 32 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index a7225f2..e93480d 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -20,6 +20,8 @@
#include "rust-compile-context.h"
#include "rust-compile-type.h"
#include "rust-compile-fnparam.h"
+#include "rust-diagnostics.h"
+#include "rust-location.h"
#include "rust-tree.h"
#include "tree-core.h"
@@ -477,6 +479,7 @@ transmute_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty)
// setup the params
std::vector<Bvariable *> param_vars;
+ std::vector<tree_node *> compiled_types;
for (auto &parm : fntype->get_params ())
{
auto &referenced_param = parm.first;
@@ -489,6 +492,7 @@ transmute_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty)
compiled_param_type, param_locus);
param_vars.push_back (compiled_param_var);
+ compiled_types.push_back (compiled_param_type);
}
rust_assert (param_vars.size () == 1);
@@ -500,6 +504,34 @@ transmute_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty)
tree convert_me_expr
= ctx->get_backend ()->var_expression (convert_me_param, Location ());
+ // check for transmute pre-conditions
+ tree target_type_expr = TREE_TYPE (DECL_RESULT (fndecl));
+ tree source_type_expr = compiled_types.at (0);
+ tree target_size_expr = TYPE_SIZE (target_type_expr);
+ tree source_size_expr = TYPE_SIZE (source_type_expr);
+ // for some reason, unit types and other zero-sized types return NULL for the
+ // size expressions
+ unsigned HOST_WIDE_INT target_size
+ = target_size_expr ? TREE_INT_CST_LOW (target_size_expr) : 0;
+ unsigned HOST_WIDE_INT source_size
+ = source_size_expr ? TREE_INT_CST_LOW (source_size_expr) : 0;
+
+ // size check for concrete types
+ // TODO(liushuyu): check alignment for pointers; check for dependently-sized
+ // types
+ if (target_size != source_size)
+ {
+ rust_error_at (fntype->get_locus (),
+ "cannot transmute between types of different sizes, or "
+ "dependently-sized types");
+ rust_inform (fntype->get_ident ().locus, "source type: %qs (%lu bits)",
+ fntype->get_params ().at (0).second->as_string ().c_str (),
+ source_size);
+ rust_inform (fntype->get_ident ().locus, "target type: %qs (%lu bits)",
+ fntype->get_return_type ()->as_string ().c_str (),
+ target_size);
+ }
+
tree enclosing_scope = NULL_TREE;
Location start_location = Location ();
Location end_location = Location ();