diff options
Diffstat (limited to 'gcc/rust/backend/rust-compile.cc')
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 90 |
1 files changed, 77 insertions, 13 deletions
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 610e3aa..7208ed0 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -207,11 +207,11 @@ CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field) // Shared methods in compilation void -HIRCompileBase::compile_function_body ( - tree fndecl, std::unique_ptr<HIR::BlockExpr> &function_body, - bool has_return_type) +HIRCompileBase::compile_function_body (tree fndecl, + HIR::BlockExpr &function_body, + bool has_return_type) { - for (auto &s : function_body->get_statements ()) + for (auto &s : function_body.get_statements ()) { auto compiled_expr = CompileStmt::Compile (s.get (), ctx); if (compiled_expr != nullptr) @@ -222,12 +222,12 @@ HIRCompileBase::compile_function_body ( } } - if (function_body->has_expr ()) + if (function_body.has_expr ()) { // the previous passes will ensure this is a valid return // or a valid trailing expression tree compiled_expr - = CompileExpr::Compile (function_body->expr.get (), ctx); + = CompileExpr::Compile (function_body.expr.get (), ctx); if (compiled_expr != nullptr) { @@ -238,7 +238,7 @@ HIRCompileBase::compile_function_body ( auto ret = ctx->get_backend ()->return_statement ( fndecl, retstmts, - function_body->get_final_expr ()->get_locus ()); + function_body.get_final_expr ()->get_locus ()); ctx->add_statement (ret); } else @@ -288,21 +288,33 @@ HIRCompileBase::compile_locals_for_block (Resolver::Rib &rib, tree fndecl, } tree -HIRCompileBase::coercion_site (tree compiled_ref, TyTy::BaseType *actual, - TyTy::BaseType *expected, Location locus) +HIRCompileBase::coercion_site (tree rvalue, TyTy::BaseType *actual, + TyTy::BaseType *expected, Location lvalue_locus, + Location rvalue_locus) { auto root_actual_kind = actual->get_root ()->get_kind (); auto root_expected_kind = expected->get_root ()->get_kind (); - if (root_expected_kind == TyTy::TypeKind::DYNAMIC - && root_actual_kind != TyTy::TypeKind::DYNAMIC) + if (root_expected_kind == TyTy::TypeKind::ARRAY + && root_actual_kind == TyTy::TypeKind::ARRAY) + { + tree tree_rval_type + = TyTyResolveCompile::compile (ctx, actual->get_root ()); + tree tree_lval_type + = TyTyResolveCompile::compile (ctx, expected->get_root ()); + if (!verify_array_capacities (tree_lval_type, tree_rval_type, + lvalue_locus, rvalue_locus)) + return error_mark_node; + } + else if (root_expected_kind == TyTy::TypeKind::DYNAMIC + && root_actual_kind != TyTy::TypeKind::DYNAMIC) { const TyTy::DynamicObjectType *dyn = static_cast<const TyTy::DynamicObjectType *> (expected->get_root ()); - return coerce_to_dyn_object (compiled_ref, actual, expected, dyn, locus); + return coerce_to_dyn_object (rvalue, actual, expected, dyn, rvalue_locus); } - return compiled_ref; + return rvalue; } tree @@ -530,5 +542,57 @@ HIRCompileBase::compute_address_for_trait_item ( true, locus); } +bool +HIRCompileBase::verify_array_capacities (tree ltype, tree rtype, + Location lvalue_locus, + Location rvalue_locus) +{ + rust_assert (ltype != NULL_TREE); + rust_assert (rtype != NULL_TREE); + + // lets just return ok as other errors have already occurred + if (ltype == error_mark_node || rtype == error_mark_node) + return true; + + tree ltype_domain = TYPE_DOMAIN (ltype); + if (!ltype_domain) + return false; + + if (!TREE_CONSTANT (TYPE_MAX_VALUE (ltype_domain))) + return false; + + auto ltype_length + = wi::ext (wi::to_offset (TYPE_MAX_VALUE (ltype_domain)) + - wi::to_offset (TYPE_MIN_VALUE (ltype_domain)) + 1, + TYPE_PRECISION (TREE_TYPE (ltype_domain)), + TYPE_SIGN (TREE_TYPE (ltype_domain))) + .to_uhwi (); + + tree rtype_domain = TYPE_DOMAIN (rtype); + if (!rtype_domain) + return false; + + if (!TREE_CONSTANT (TYPE_MAX_VALUE (rtype_domain))) + return false; + + auto rtype_length + = wi::ext (wi::to_offset (TYPE_MAX_VALUE (rtype_domain)) + - wi::to_offset (TYPE_MIN_VALUE (rtype_domain)) + 1, + TYPE_PRECISION (TREE_TYPE (rtype_domain)), + TYPE_SIGN (TREE_TYPE (rtype_domain))) + .to_uhwi (); + + if (ltype_length != rtype_length) + { + rust_error_at (rvalue_locus, + "expected an array with a fixed size of %lu " + "elements, found one with %lu elements", + ltype_length, rtype_length); + return false; + } + + return true; +} + } // namespace Compile } // namespace Rust |