diff options
Diffstat (limited to 'gcc')
35 files changed, 1013 insertions, 1062 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 3554982..dcb2d2c 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -85,7 +85,6 @@ GRS_OBJS = \ rust/rust-tyty-bounds.o \ rust/rust-hir-type-check-util.o \ rust/rust-hir-trait-resolve.o \ - rust/rust-hir-const-fold.o \ rust/rust-hir-type-check-type.o \ rust/rust-hir-type-check-struct.o \ rust/rust-hir-address-taken.o \ @@ -98,6 +97,7 @@ GRS_OBJS = \ rust/rust-base62.o \ rust/rust-compile-expr.o \ rust/rust-compile-type.o \ + rust/rust-constexpr.o \ $(END) # removed object files from here @@ -107,7 +107,7 @@ RUST_ALL_OBJS = $(GRS_OBJS) $(RUST_TARGET_OBJS) rust_OBJS = $(RUST_ALL_OBJS) rust/rustspec.o # The compiler itself is called rust1 (formerly grs1) -rust1$(exeext): $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS) +rust1$(exeext): $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS) +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS) diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index b3ae1f6..2169ea5 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -44,8 +44,9 @@ protected: bool compile_locals_for_block (Resolver::Rib &rib, tree fndecl, std::vector<Bvariable *> &locals); - tree coercion_site (tree compiled_ref, TyTy::BaseType *actual, - TyTy::BaseType *expected, Location locus); + tree coercion_site (tree rvalue, TyTy::BaseType *actual, + TyTy::BaseType *expected, Location lvalue_locus, + Location rvalue_locus); tree coerce_to_dyn_object (tree compiled_ref, const TyTy::BaseType *actual, const TyTy::BaseType *expected, @@ -57,6 +58,9 @@ protected: std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>> &receiver_bounds, const TyTy::BaseType *receiver, const TyTy::BaseType *root, Location locus); + + bool verify_array_capacities (tree ltype, tree rtype, Location ltype_locus, + Location rtype_locus); }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 43c23dd..9be9801 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -27,7 +27,6 @@ #include "rust-compile-tyty.h" #include "rust-ast-full.h" #include "rust-hir-full.h" -#include "rust-hir-const-fold-ctx.h" #include "rust-mangle.h" namespace Rust { @@ -45,8 +44,7 @@ public: Context (::Backend *backend) : backend (backend), resolver (Resolver::Resolver::get ()), tyctx (Resolver::TypeCheckContext::get ()), - mappings (Analysis::Mappings::get ()), - const_ctx (ConstFold::Context::get ()), mangler (Mangler ()) + mappings (Analysis::Mappings::get ()), mangler (Mangler ()) { // insert the builtins auto builtins = resolver->get_builtin_types (); @@ -110,7 +108,6 @@ public: Resolver::Resolver *get_resolver () { return resolver; } Resolver::TypeCheckContext *get_tyctx () { return tyctx; } Analysis::Mappings *get_mappings () { return mappings; } - ConstFold::Context *get_const_ctx () { return const_ctx; } void push_block (tree scope) { @@ -315,7 +312,6 @@ private: Resolver::Resolver *resolver; Resolver::TypeCheckContext *tyctx; Analysis::Mappings *mappings; - ConstFold::Context *const_ctx; std::set<HirId> builtin_range; Mangler mangler; diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 9b04bbf..33237e5 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -25,10 +25,12 @@ #include "rust-hir-type-bounds.h" #include "rust-hir-dot-operator.h" #include "rust-compile-pattern.h" +#include "rust-constexpr.h" #include "fold-const.h" #include "realmpfr.h" #include "convert.h" +#include "print-tree.h" namespace Rust { namespace Compile { @@ -381,7 +383,11 @@ CompileExpr::visit (HIR::CallExpr &expr) rust_assert (ok); // coerce it if required - rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ()); + Location lvalue_locus + = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + Location rvalue_locus = argument->get_locus (); + rvalue = coercion_site (rvalue, actual, expected, lvalue_locus, + rvalue_locus); // add it to the list arguments.push_back (rvalue); @@ -477,7 +483,11 @@ CompileExpr::visit (HIR::CallExpr &expr) rust_assert (ok); // coerce it if required - rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ()); + Location lvalue_locus + = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + Location rvalue_locus = argument->get_locus (); + rvalue + = coercion_site (rvalue, actual, expected, lvalue_locus, rvalue_locus); // add it to the list args.push_back (rvalue); @@ -604,7 +614,11 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) rust_assert (ok); // coerce it if required - rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ()); + Location lvalue_locus + = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + Location rvalue_locus = argument->get_locus (); + rvalue + = coercion_site (rvalue, actual, expected, lvalue_locus, rvalue_locus); // add it to the list args.push_back (rvalue); @@ -1093,5 +1107,220 @@ CompileExpr::type_cast_expression (tree type_to_cast_to, tree expr_tree, expr_tree); } +void +CompileExpr::visit (HIR::ArrayExpr &expr) +{ + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &tyty)) + { + rust_fatal_error (expr.get_locus (), + "did not resolve type for this array expr"); + return; + } + + tree array_type = TyTyResolveCompile::compile (ctx, tyty); + if (TREE_CODE (array_type) != ARRAY_TYPE) + { + translated = error_mark_node; + return; + } + + rust_assert (tyty->get_kind () == TyTy::TypeKind::ARRAY); + const TyTy::ArrayType &array_tyty + = static_cast<const TyTy::ArrayType &> (*tyty); + + HIR::ArrayElems &elements = *expr.get_internal_elements (); + switch (elements.get_array_expr_type ()) + { + case HIR::ArrayElems::ArrayExprType::VALUES: { + HIR::ArrayElemsValues &elems + = static_cast<HIR::ArrayElemsValues &> (elements); + translated + = array_value_expr (expr.get_locus (), array_tyty, array_type, elems); + } + return; + + case HIR::ArrayElems::ArrayExprType::COPIED: + HIR::ArrayElemsCopied &elems + = static_cast<HIR::ArrayElemsCopied &> (elements); + translated + = array_copied_expr (expr.get_locus (), array_tyty, array_type, elems); + } +} + +tree +CompileExpr::array_value_expr (Location expr_locus, + const TyTy::ArrayType &array_tyty, + tree array_type, HIR::ArrayElemsValues &elems) +{ + std::vector<unsigned long> indexes; + std::vector<tree> constructor; + size_t i = 0; + for (auto &elem : elems.get_values ()) + { + tree translated_expr = CompileExpr::Compile (elem.get (), ctx); + constructor.push_back (translated_expr); + indexes.push_back (i++); + } + + return ctx->get_backend ()->array_constructor_expression (array_type, indexes, + constructor, + expr_locus); +} + +tree +CompileExpr::array_copied_expr (Location expr_locus, + const TyTy::ArrayType &array_tyty, + tree array_type, HIR::ArrayElemsCopied &elems) +{ + // see gcc/cp/typeck2.c:1369-1401 + gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE); + tree domain = TYPE_DOMAIN (array_type); + if (!domain) + return error_mark_node; + + if (!TREE_CONSTANT (TYPE_MAX_VALUE (domain))) + { + rust_error_at (expr_locus, "non const capacity domain %qT", array_type); + return error_mark_node; + } + + tree capacity_expr = CompileExpr::Compile (elems.get_num_copies_expr (), ctx); + if (!TREE_CONSTANT (capacity_expr)) + { + rust_error_at (expr_locus, "non const num copies %qT", array_type); + return error_mark_node; + } + + // get the compiled value + tree translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (), ctx); + + tree max_domain = TYPE_MAX_VALUE (domain); + tree min_domain = TYPE_MIN_VALUE (domain); + + auto max = wi::to_offset (max_domain); + auto min = wi::to_offset (min_domain); + auto precision = TYPE_PRECISION (TREE_TYPE (domain)); + auto sign = TYPE_SIGN (TREE_TYPE (domain)); + unsigned HOST_WIDE_INT len + = wi::ext (max - min + 1, precision, sign).to_uhwi (); + + // create the constructor + size_t idx = 0; + std::vector<unsigned long> indexes; + std::vector<tree> constructor; + for (unsigned HOST_WIDE_INT i = 0; i < len; i++) + { + constructor.push_back (translated_expr); + indexes.push_back (idx++); + } + + return ctx->get_backend ()->array_constructor_expression (array_type, indexes, + constructor, + expr_locus); +} + +// tree +// CompileExpr::array_copied_expr (Location expr_locus, tree array_type, +// HIR::ArrayElemsCopied &elems) +// { +// // create tmp for the result +// fncontext fnctx = ctx->peek_fn (); +// Location start_location = expr_locus; +// Location end_location = expr_locus; +// tree fndecl = fnctx.fndecl; +// tree enclosing_scope = ctx->peek_enclosing_scope (); + +// bool is_address_taken = false; +// tree result_var_stmt = nullptr; +// Bvariable *result +// = ctx->get_backend ()->temporary_variable (fnctx.fndecl, +// enclosing_scope, +// array_type, NULL, +// is_address_taken, expr_locus, +// &result_var_stmt); +// ctx->add_statement (result_var_stmt); + +// // get the compiled value +// tree translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (), +// ctx); + +// // lets assign each index in the array +// TyTy::BaseType *capacity_tyty = nullptr; +// HirId capacity_ty_id +// = elems.get_num_copies_expr ()->get_mappings ().get_hirid (); +// bool ok = ctx->get_tyctx ()->lookup_type (capacity_ty_id, +// &capacity_tyty); rust_assert (ok); tree capacity_type = +// TyTyResolveCompile::compile (ctx, capacity_tyty); tree capacity_expr = +// CompileExpr::Compile (elems.get_num_copies_expr (), ctx); + +// // create a loop for this with assignments to array_index exprs +// tree index_type = capacity_type; +// Bvariable *idx +// = ctx->get_backend ()->temporary_variable (fnctx.fndecl, +// enclosing_scope, +// index_type, NULL, +// is_address_taken, expr_locus, +// &result_var_stmt); +// ctx->add_statement (result_var_stmt); + +// // set index to zero +// tree index_lvalue = error_mark_node; +// tree zero = build_int_cst (index_type, 0); +// tree index_assignment +// = ctx->get_backend ()->assignment_statement (fnctx.fndecl, +// index_lvalue, +// zero, expr_locus); +// ctx->add_statement (index_assignment); + +// // BEGIN loop block +// tree loop_body = ctx->get_backend ()->block (fndecl, enclosing_scope, {}, +// start_location, end_location); +// ctx->push_block (loop_body); + +// // loop predicate +// tree loop_predicate +// = fold_build2_loc (expr_locus.gcc_location (), GE_EXPR, +// boolean_type_node, +// ctx->get_backend ()->var_expression (idx, expr_locus), +// capacity_expr); +// tree exit_expr = fold_build1_loc (expr_locus.gcc_location (), EXIT_EXPR, +// void_type_node, loop_predicate); +// tree break_stmt +// = ctx->get_backend ()->expression_statement (fnctx.fndecl, exit_expr); +// ctx->add_statement (break_stmt); + +// // increment index +// tree increment +// = fold_build2_loc (expr_locus.gcc_location (), POSTINCREMENT_EXPR, +// index_type, +// ctx->get_backend ()->var_expression (idx, expr_locus), +// build_int_cst (index_type, 1)); + +// // create index_assess +// tree index_access = ctx->get_backend ()->array_index_expression ( +// ctx->get_backend ()->var_expression (result, expr_locus), increment, +// expr_locus); + +// // create assignment to index_access +// tree array_assignment +// = ctx->get_backend ()->assignment_statement (fnctx.fndecl, +// index_access, +// translated_expr, expr_locus); +// ctx->add_statement (array_assignment); + +// // END loop block +// ctx->pop_block (); + +// tree loop_expr = ctx->get_backend ()->loop_expression (loop_body, +// expr_locus); tree loop_stmt +// = ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr); +// ctx->add_statement (loop_stmt); + +// // result is the tmp +// return ctx->get_backend ()->var_expression (result, expr_locus); +// } + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 2f44621..b5047d0 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -290,7 +290,9 @@ public: expr.get_rhs ()->get_mappings ().get_hirid (), &actual); rust_assert (ok); - rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ()); + rvalue + = coercion_site (rvalue, actual, expected, expr.get_lhs ()->get_locus (), + expr.get_rhs ()->get_locus ()); tree assignment = ctx->get_backend ()->assignment_statement (fn.fndecl, lvalue, rvalue, @@ -332,56 +334,7 @@ public: expr.get_locus ()); } - void visit (HIR::ArrayExpr &expr) override - { - TyTy::BaseType *tyty = nullptr; - if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), - &tyty)) - { - rust_fatal_error (expr.get_locus (), - "did not resolve type for this array expr"); - return; - } - - rust_assert (tyty->get_kind () == TyTy::TypeKind::ARRAY); - TyTy::ArrayType *array_tyty = static_cast<TyTy::ArrayType *> (tyty); - capacity_expr = array_tyty->get_capacity (); - - tree array_type = TyTyResolveCompile::compile (ctx, array_tyty); - rust_assert (array_type != nullptr); - - expr.get_internal_elements ()->accept_vis (*this); - std::vector<unsigned long> indexes; - for (size_t i = 0; i < constructor.size (); i++) - indexes.push_back (i); - - translated - = ctx->get_backend ()->array_constructor_expression (array_type, indexes, - constructor, - expr.get_locus ()); - } - - void visit (HIR::ArrayElemsValues &elems) override - { - for (auto &elem : elems.get_values ()) - { - tree translated_expr = CompileExpr::Compile (elem.get (), ctx); - constructor.push_back (translated_expr); - } - } - - void visit (HIR::ArrayElemsCopied &elems) override - { - tree translated_expr - = CompileExpr::Compile (elems.get_elem_to_copy (), ctx); - - size_t capacity; - bool ok = ctx->get_backend ()->const_size_cast (capacity_expr, &capacity); - rust_assert (ok); - - for (size_t i = 0; i < capacity; ++i) - constructor.push_back (translated_expr); - } + void visit (HIR::ArrayExpr &expr) override; void visit (HIR::ArithmeticOrLogicalExpr &expr) override; @@ -605,14 +558,18 @@ public: std::vector<tree> arguments; for (size_t i = 0; i < struct_expr.get_fields ().size (); i++) { - auto &argument = struct_expr.get_fields ().at (i); - auto rvalue = CompileStructExprField::Compile (argument.get (), ctx); - // assignments are coercion sites so lets convert the rvalue if // necessary auto respective_field = variant->get_field_at_index (i); auto expected = respective_field->get_field_type (); + // process arguments + auto &argument = struct_expr.get_fields ().at (i); + auto lvalue_locus + = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + auto rvalue_locus = argument->get_locus (); + auto rvalue = CompileStructExprField::Compile (argument.get (), ctx); + TyTy::BaseType *actual = nullptr; bool ok = ctx->get_tyctx ()->lookup_type ( argument->get_mappings ().get_hirid (), &actual); @@ -621,8 +578,8 @@ public: // compile/torture/struct_base_init_1.rs if (ok) { - rvalue = coercion_site (rvalue, actual, expected, - argument->get_locus ()); + rvalue = coercion_site (rvalue, actual, expected, lvalue_locus, + rvalue_locus); } // add it to the list @@ -998,15 +955,19 @@ protected: tree type_cast_expression (tree type_to_cast_to, tree expr, Location locus); + tree array_value_expr (Location expr_locus, const TyTy::ArrayType &array_tyty, + tree array_type, HIR::ArrayElemsValues &elems); + + tree array_copied_expr (Location expr_locus, + const TyTy::ArrayType &array_tyty, tree array_type, + HIR::ArrayElemsCopied &elems); + private: CompileExpr (Context *ctx) - : HIRCompileBase (ctx), translated (error_mark_node), - capacity_expr (nullptr) + : HIRCompileBase (ctx), translated (error_mark_node) {} tree translated; - tree capacity_expr; - std::vector<tree> constructor; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 5af9ab3..6174950 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -27,6 +27,7 @@ #include "rust-compile-expr.h" #include "rust-compile-fnparam.h" #include "rust-compile-extern.h" +#include "rust-constexpr.h" namespace Rust { namespace Compile { @@ -97,7 +98,10 @@ public: rust_assert (ok); tree type = TyTyResolveCompile::compile (ctx, resolved_type); + tree const_type = build_qualified_type (type, TYPE_QUAL_CONST); + tree value = CompileExpr::Compile (constant.get_expr (), ctx); + tree folded_expr = ConstCtx::fold (value); const Resolver::CanonicalPath *canonical_path = nullptr; ok = ctx->get_mappings ()->lookup_canonical_path ( @@ -107,7 +111,8 @@ public: std::string ident = canonical_path->get (); tree const_expr - = ctx->get_backend ()->named_constant_expression (type, ident, value, + = ctx->get_backend ()->named_constant_expression (const_type, ident, + folded_expr, constant.get_locus ()); ctx->push_const (const_expr); @@ -183,6 +188,10 @@ public: if (is_main_fn || function.has_visibility ()) flags |= Backend::function_is_visible; + // is it a const function? + if (function.get_qualifiers ().is_const ()) + flags |= Backend::function_read_only; + const Resolver::CanonicalPath *canonical_path = nullptr; bool ok = ctx->get_mappings ()->lookup_canonical_path ( function.get_mappings ().get_crate_num (), diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index 27ee487..ffda652 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -17,6 +17,8 @@ // <http://www.gnu.org/licenses/>. #include "rust-compile-pattern.h" +#include "rust-compile-expr.h" +#include "rust-constexpr.h" namespace Rust { namespace Compile { @@ -46,20 +48,33 @@ CompilePatternCaseLabelExpr::visit (HIR::PathInExpression &pattern) ok = adt->lookup_variant_by_id (variant_id, &variant); rust_assert (ok); - mpz_t disciminantl; - if (variant->get_variant_type () == TyTy::VariantDef::VariantType::NUM) + tree case_low = error_mark_node; + if (variant->is_specified_discriminant_node ()) { - mpz_init_set_ui (disciminantl, variant->get_discriminant ()); + auto discrim_node = variant->get_discriminant_node (); + auto &discrim_expr = discrim_node->get_discriminant_expression (); + + tree discrim_expr_node = CompileExpr::Compile (discrim_expr.get (), ctx); + tree folded_discrim_expr = ConstCtx::fold (discrim_expr_node); + case_low = folded_discrim_expr; } else { - HirId variant_id = variant->get_id (); - mpz_init_set_ui (disciminantl, variant_id); - } + mpz_t disciminantl; + if (variant->get_variant_type () == TyTy::VariantDef::VariantType::NUM) + { + mpz_init_set_ui (disciminantl, variant->get_discriminant ()); + } + else + { + HirId variant_id = variant->get_id (); + mpz_init_set_ui (disciminantl, variant_id); + } - tree t = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx); - tree case_low - = double_int_to_tree (t, mpz_get_double_int (t, disciminantl, true)); + tree t = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx); + case_low + = double_int_to_tree (t, mpz_get_double_int (t, disciminantl, true)); + } case_label_expr = build_case_label (case_low, NULL_TREE, associated_case_label); diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 07133b9..c1d0778 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -95,11 +95,24 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, tree compiled_adt_type = TyTyResolveCompile::compile (ctx, adt); // make the ctor for the union - mpz_t val; - mpz_init_set_ui (val, variant->get_discriminant ()); - tree t = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx); - tree qualifier - = double_int_to_tree (t, mpz_get_double_int (t, val, true)); + tree qualifier = error_mark_node; + if (variant->is_specified_discriminant_node ()) + { + auto discrim_node = variant->get_discriminant_node (); + auto &discrim_expr = discrim_node->get_discriminant_expression (); + + tree discrim_expr_node + = CompileExpr::Compile (discrim_expr.get (), ctx); + tree folded_discrim_expr = ConstCtx::fold (discrim_expr_node); + qualifier = folded_discrim_expr; + } + else + { + mpz_t val; + mpz_init_set_ui (val, variant->get_discriminant ()); + tree t = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx); + qualifier = double_int_to_tree (t, mpz_get_double_int (t, val, true)); + } return ctx->get_backend ()->constructor_expression (compiled_adt_type, true, {qualifier}, diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h index f3ee69d..3e73cce 100644 --- a/gcc/rust/backend/rust-compile-stmt.h +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -112,8 +112,10 @@ public: stmt.get_init_expr ()->get_mappings ().get_hirid (), &actual); rust_assert (ok); + Location lvalue_locus = stmt.get_pattern ()->get_locus (); + Location rvalue_locus = stmt.get_init_expr ()->get_locus (); TyTy::BaseType *expected = ty; - init = coercion_site (init, actual, expected, stmt.get_locus ()); + init = coercion_site (init, actual, expected, lvalue_locus, rvalue_locus); auto fnctx = ctx->peek_fn (); if (ty->is_unit ()) diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index c147a51..d7a8ae5 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -17,8 +17,11 @@ // <http://www.gnu.org/licenses/>. #include "rust-compile-type.h" +#include "rust-compile-expr.h" +#include "rust-constexpr.h" #include "tree.h" +#include "print-tree.h" namespace Rust { namespace Compile { @@ -63,13 +66,15 @@ TyTyResolveCompile::get_implicit_enumeral_node_type (Context *ctx) void TyTyResolveCompile::visit (const TyTy::ErrorType &) { - gcc_unreachable (); + translated = error_mark_node; } + void TyTyResolveCompile::visit (const TyTy::InferType &) { - gcc_unreachable (); + translated = error_mark_node; } + void TyTyResolveCompile::visit (const TyTy::ClosureType &) { @@ -332,8 +337,11 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type) { tree element_type = TyTyResolveCompile::compile (ctx, type.get_element_type ()); + tree capacity_expr = CompileExpr::Compile (&type.get_capacity_expr (), ctx); + tree folded_capacity_expr = ConstCtx::fold (capacity_expr); + translated - = ctx->get_backend ()->array_type (element_type, type.get_capacity ()); + = ctx->get_backend ()->array_type (element_type, folded_capacity_expr); } void diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h index 1e05e5d..4d9c780 100644 --- a/gcc/rust/backend/rust-compile-type.h +++ b/gcc/rust/backend/rust-compile-type.h @@ -63,13 +63,14 @@ public: private: TyTyResolveCompile (Context *ctx, bool trait_object_mode) - : ctx (ctx), trait_object_mode (trait_object_mode), translated (nullptr), - recursion_count (0) + : ctx (ctx), trait_object_mode (trait_object_mode), + translated (error_mark_node), recursion_count (0) {} Context *ctx; bool trait_object_mode; tree translated; + size_t recursion_count; static const size_t kDefaultRecusionLimit = 5; diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 610e3aa..b12860d 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -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 diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc new file mode 100644 index 0000000..293f110 --- /dev/null +++ b/gcc/rust/backend/rust-constexpr.cc @@ -0,0 +1,428 @@ +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-constexpr.h" +#include "rust-location.h" +#include "rust-diagnostics.h" + +#include "fold-const.h" +#include "realmpfr.h" +#include "convert.h" +#include "print-tree.h" +#include "gimplify.h" +#include "tree-iterator.h" + +/* Returns true if NODE is a pointer. */ +#define TYPE_PTR_P(NODE) (TREE_CODE (NODE) == POINTER_TYPE) + +/* Returns true if NODE is a reference. */ +#define TYPE_REF_P(NODE) (TREE_CODE (NODE) == REFERENCE_TYPE) + +/* Returns true if NODE is a pointer or a reference. */ +#define INDIRECT_TYPE_P(NODE) (TYPE_PTR_P (NODE) || TYPE_REF_P (NODE)) + +/* [basic.fundamental] + + Types bool, char, wchar_t, and the signed and unsigned integer types + are collectively called integral types. + + Note that INTEGRAL_TYPE_P, as defined in tree.h, allows enumeration + types as well, which is incorrect in C++. Keep these checks in + ascending code order. */ +#define RS_INTEGRAL_TYPE_P(TYPE) \ + (TREE_CODE (TYPE) == BOOLEAN_TYPE || TREE_CODE (TYPE) == INTEGER_TYPE) + +/* [basic.fundamental] + + Integral and floating types are collectively called arithmetic + types. + + As a GNU extension, we also accept complex types. + + Keep these checks in ascending code order. */ +#define ARITHMETIC_TYPE_P(TYPE) \ + (RS_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == REAL_TYPE \ + || TREE_CODE (TYPE) == COMPLEX_TYPE) + +/* True iff TYPE is cv decltype(nullptr). */ +#define NULLPTR_TYPE_P(TYPE) (TREE_CODE (TYPE) == NULLPTR_TYPE) + +/* [basic.types] + + Arithmetic types, enumeration types, pointer types, + pointer-to-member types, and std::nullptr_t are collectively called + scalar types. + + Keep these checks in ascending code order. */ +#define SCALAR_TYPE_P(TYPE) \ + (TREE_CODE (TYPE) == ENUMERAL_TYPE || ARITHMETIC_TYPE_P (TYPE) \ + || TYPE_PTR_P (TYPE) || NULLPTR_TYPE_P (TYPE)) + +namespace Rust { +namespace Compile { + +static tree +constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p, + bool unshare_p); +tree +decl_constant_value (tree decl, bool unshare_p); + +static void +non_const_var_error (location_t loc, tree r); + +static tree +get_function_named_in_call (tree t); + +ConstCtx::ConstCtx () : constexpr_ops_count (0) {} + +tree +ConstCtx::fold (tree expr) +{ + tree folded = ConstCtx ().constexpr_expression (expr); + rust_assert (folded != NULL_TREE); + return folded; +} + +tree +ConstCtx::constexpr_expression (tree t) +{ + location_t loc = EXPR_LOCATION (t); + if (CONSTANT_CLASS_P (t)) + { + if (TREE_OVERFLOW (t)) + { + rust_error_at (Location (loc), "overflow in constant expression"); + return t; + } + + if (TREE_CODE (t) == INTEGER_CST && TYPE_PTR_P (TREE_TYPE (t)) + && !integer_zerop (t)) + { + // FIXME check does this actually work to print out tree types + rust_error_at (Location (loc), + "value %qE of type %qT is not a constant expression", + t, TREE_TYPE (t)); + return t; + } + + return t; + } + + // Avoid excessively long constexpr evaluations + if (++constexpr_ops_count >= constexpr_ops_limit) + { + rust_error_at ( + Location (loc), + "%<constexpr%> evaluation operation count exceeds limit of " + "%wd (use %<-fconstexpr-ops-limit=%> to increase the limit)", + constexpr_ops_limit); + + return t; + } + + tree r = t; + tree_code tcode = TREE_CODE (t); + switch (tcode) + { + case CONST_DECL: { + r = decl_constant_value (t, /*unshare_p=*/false); + if (TREE_CODE (r) == TARGET_EXPR + && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR) + r = TARGET_EXPR_INITIAL (r); + if (DECL_P (r)) + { + non_const_var_error (loc, r); + return r; + } + } + break; + + case POINTER_PLUS_EXPR: + case POINTER_DIFF_EXPR: + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case CEIL_DIV_EXPR: + case FLOOR_DIV_EXPR: + case ROUND_DIV_EXPR: + case TRUNC_MOD_EXPR: + case CEIL_MOD_EXPR: + case ROUND_MOD_EXPR: + case RDIV_EXPR: + case EXACT_DIV_EXPR: + case MIN_EXPR: + case MAX_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + case LROTATE_EXPR: + case RROTATE_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case BIT_AND_EXPR: + case TRUTH_XOR_EXPR: + case LT_EXPR: + case LE_EXPR: + case GT_EXPR: + case GE_EXPR: + case EQ_EXPR: + case NE_EXPR: + case SPACESHIP_EXPR: + case UNORDERED_EXPR: + case ORDERED_EXPR: + case UNLT_EXPR: + case UNLE_EXPR: + case UNGT_EXPR: + case UNGE_EXPR: + case UNEQ_EXPR: + case LTGT_EXPR: + case RANGE_EXPR: + case COMPLEX_EXPR: + r = eval_binary_expression (t); + break; + + case CALL_EXPR: + r = eval_call_expression (t); + break; + + case RETURN_EXPR: + rust_assert (TREE_OPERAND (t, 0) != NULL_TREE); + r = constexpr_expression (TREE_OPERAND (t, 0)); + break; + + case MODIFY_EXPR: + r = eval_store_expression (t); + break; + + default: + break; + } + + return r; +} + +tree +ConstCtx::eval_store_expression (tree t) +{ + tree init = TREE_OPERAND (t, 1); + if (TREE_CLOBBER_P (init)) + /* Just ignore clobbers. */ + return void_node; + + /* First we figure out where we're storing to. */ + tree target = TREE_OPERAND (t, 0); + + tree type = TREE_TYPE (target); + bool preeval = SCALAR_TYPE_P (type) || TREE_CODE (t) == MODIFY_EXPR; + if (preeval) + { + /* Evaluate the value to be stored without knowing what object it will be + stored in, so that any side-effects happen first. */ + init = ConstCtx::fold (init); + } + + bool evaluated = false; + tree object = NULL_TREE; + for (tree probe = target; object == NULL_TREE;) + { + switch (TREE_CODE (probe)) + { + default: + if (evaluated) + object = probe; + else + { + probe = constexpr_expression (probe); + evaluated = true; + } + break; + } + } + + return init; +} + +/* Subroutine of cxx_eval_constant_expression. + Like cxx_eval_unary_expression, except for binary expressions. */ + +tree +ConstCtx::eval_binary_expression (tree t) +{ + tree orig_lhs = TREE_OPERAND (t, 0); + tree orig_rhs = TREE_OPERAND (t, 1); + tree lhs, rhs; + + lhs = constexpr_expression (orig_lhs); + rhs = constexpr_expression (orig_rhs); + + location_t loc = EXPR_LOCATION (t); + enum tree_code code = TREE_CODE (t); + tree type = TREE_TYPE (t); + + return fold_binary_loc (loc, code, type, lhs, rhs); +} + +// Subroutine of cxx_eval_constant_expression. +// Evaluate the call expression tree T in the context of OLD_CALL expression +// evaluation. +tree +ConstCtx::eval_call_expression (tree t) +{ + tree fun = get_function_named_in_call (t); + return constexpr_fn_retval (DECL_SAVED_TREE (fun)); +} + +// Subroutine of check_constexpr_fundef. BODY is the body of a function +// declared to be constexpr, or a sub-statement thereof. Returns the +// return value if suitable, error_mark_node for a statement not allowed in +// a constexpr function, or NULL_TREE if no return value was found. +tree +ConstCtx::constexpr_fn_retval (tree body) +{ + switch (TREE_CODE (body)) + { + case STATEMENT_LIST: { + tree expr = NULL_TREE; + for (tree stmt : tsi_range (body)) + { + tree s = constexpr_fn_retval (stmt); + if (s == error_mark_node) + return error_mark_node; + else if (s == NULL_TREE) + /* Keep iterating. */; + else if (expr) + /* Multiple return statements. */ + return error_mark_node; + else + expr = s; + } + return expr; + } + + case RETURN_EXPR: + return constexpr_expression (body); + + case DECL_EXPR: { + tree decl = DECL_EXPR_DECL (body); + if (TREE_CODE (decl) == USING_DECL + /* Accept __func__, __FUNCTION__, and __PRETTY_FUNCTION__. */ + || DECL_ARTIFICIAL (decl)) + return NULL_TREE; + return error_mark_node; + } + + case CLEANUP_POINT_EXPR: + return constexpr_fn_retval (TREE_OPERAND (body, 0)); + + case BIND_EXPR: { + tree b = BIND_EXPR_BODY (body); + return constexpr_fn_retval (b); + } + break; + + default: + return error_mark_node; + } + return error_mark_node; +} + +// Taken from cp/constexpr.c +// +// If DECL is a scalar enumeration constant or variable with a +// constant initializer, return the initializer (or, its initializers, +// recursively); otherwise, return DECL. If STRICT_P, the +// initializer is only returned if DECL is a +// constant-expression. If RETURN_AGGREGATE_CST_OK_P, it is ok to +// return an aggregate constant. If UNSHARE_P, return an unshared +// copy of the initializer. +static tree +constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p, + bool unshare_p) +{ + while (TREE_CODE (decl) == CONST_DECL) + { + tree init; + /* If DECL is a static data member in a template + specialization, we must instantiate it here. The + initializer for the static data member is not processed + until needed; we need it now. */ + + init = DECL_INITIAL (decl); + if (init == error_mark_node) + { + if (TREE_CODE (decl) == CONST_DECL) + /* Treat the error as a constant to avoid cascading errors on + excessively recursive template instantiation (c++/9335). */ + return init; + else + return decl; + } + + decl = init; + } + return unshare_p ? unshare_expr (decl) : decl; +} + +// A more relaxed version of decl_really_constant_value, used by the +// common C/C++ code. +tree +decl_constant_value (tree decl, bool unshare_p) +{ + return constant_value_1 (decl, /*strict_p=*/false, + /*return_aggregate_cst_ok_p=*/true, + /*unshare_p=*/unshare_p); +} + +static void +non_const_var_error (location_t loc, tree r) +{ + error_at (loc, + "the value of %qD is not usable in a constant " + "expression", + r); + /* Avoid error cascade. */ + if (DECL_INITIAL (r) == error_mark_node) + return; + + // more in cp/constexpr.c +} + +static tree +get_callee (tree call) +{ + if (call == NULL_TREE) + return call; + else if (TREE_CODE (call) == CALL_EXPR) + return CALL_EXPR_FN (call); + + return NULL_TREE; +} + +// We have an expression tree T that represents a call, either CALL_EXPR +// or AGGR_INIT_EXPR. If the call is lexically to a named function, +// return the _DECL for that function. +static tree +get_function_named_in_call (tree t) +{ + tree fun = get_callee (t); + if (fun && TREE_CODE (fun) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (fun, 0)) == FUNCTION_DECL) + fun = TREE_OPERAND (fun, 0); + return fun; +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-const-fold-ctx.h b/gcc/rust/backend/rust-constexpr.h index a3f5a16..40d9159 100644 --- a/gcc/rust/typecheck/rust-hir-const-fold-ctx.h +++ b/gcc/rust/backend/rust-constexpr.h @@ -1,5 +1,3 @@ -// Copyright (C) 2020-2021 Free Software Foundation, Inc. - // This file is part of GCC. // GCC is free software; you can redistribute it and/or modify it under @@ -16,38 +14,33 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -#ifndef RUST_HIR_CONST_FOLD_CTX_H -#define RUST_HIR_CONST_FOLD_CTX_H +#ifndef RUST_CONSTEXPR +#define RUST_CONSTEXPR -#include "rust-backend.h" -#include "rust-hir-map.h" +#include "rust-system.h" +#include "tree.h" namespace Rust { -namespace ConstFold { +namespace Compile { -class Context +class ConstCtx { public: - ~Context () {} - - static void init (::Backend *backend); - - static Context *get (); - - ::Backend *get_backend () { return backend; } - - bool lookup_const (HirId id, tree *expr); + static tree fold (tree); - void insert_const (HirId, tree expr); + tree constexpr_expression (tree); + tree eval_binary_expression (tree); + tree eval_call_expression (tree); + tree constexpr_fn_retval (tree); + tree eval_store_expression (tree); private: - Context (::Backend *backend); + ConstCtx (); - ::Backend *backend; - std::map<HirId, tree> ctx; + HOST_WIDE_INT constexpr_ops_count; }; -} // namespace ConstFold +} // namespace Compile } // namespace Rust -#endif // RUST_HIR_CONST_FOLD_CTX_H +#endif // RUST_CONSTEXPR diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 43a81f2..98aaae9 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -74,11 +74,6 @@ public: virtual void debug (tree) = 0; virtual void debug (Bvariable *) = 0; - // const folder helpers - virtual bool const_size_cast (tree, size_t *) = 0; - virtual std::string const_size_val_to_string (tree) = 0; - virtual bool const_values_equal (tree, tree) = 0; - static Rust::ABI get_abi_from_string (const std::string &abi, Location locus) { if (abi.compare ("rust") == 0) diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 43716d9..1fdba7a 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -137,45 +137,6 @@ public: tree char_type () { return char_type_node; } - bool const_size_cast (tree expr, size_t *result) - { - rust_assert (TREE_CONSTANT (expr)); - - unsigned char buf[sizeof (size_t) + 1]; - memset (buf, 0, sizeof (buf)); - - int ret = native_encode_expr (expr, buf, sizeof (buf), 0); - if (ret <= 0) - return false; - - size_t *tmp = (size_t *) buf; - *result = *tmp; - return true; - } - - std::string const_size_val_to_string (tree expr) - { - rust_assert (TREE_CONSTANT (expr)); - - unsigned char buf[sizeof (size_t) + 1]; - memset (buf, 0, sizeof (buf)); - - int ret = native_encode_expr (expr, buf, sizeof (buf), 0); - rust_assert (ret > 0); - - size_t *ptr = (size_t *) buf; - return std::to_string (*ptr); - } - - bool const_values_equal (tree a, tree b) - { - return operand_equal_p (a, b, OEP_ONLY_CONST | OEP_PURE_SAME); - // printf ("comparing!\n"); - // debug_tree (a->get_tree ()); - // debug_tree (b->get_tree ()); - // printf ("ok = %s\n", ok ? "true" : "false"); - } - tree wchar_type () { tree wchar = make_unsigned_type (32); @@ -1672,6 +1633,9 @@ Gcc_backend::arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, /* Construct a new tree and build an expression from it. */ auto new_tree = fold_build2_loc (location.gcc_location (), tree_code, tree_type, left_tree, right_tree); + TREE_CONSTANT (new_tree) + = TREE_CONSTANT (left_tree) && TREE_CONSTANT (right_tree); + if (floating_point && extended_type != NULL_TREE) new_tree = convert (original_type, new_tree); return new_tree; diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index b844e3b..dccaffe 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -52,7 +52,6 @@ #include "rust-lint-scan-deadcode.h" #include "rust-tycheck-dump.h" #include "rust-ast-resolve-unused.h" -#include "rust-hir-const-fold.h" #include "rust-compile.h" extern Linemap * @@ -330,9 +329,6 @@ Session::init () // set the default crate name options.set_crate_name (kDefaultCrateName); - - // the constant folder uses gcc - ConstFold::Context::init (backend); } /* Initialise default options. Actually called before handle_option, unlike init diff --git a/gcc/rust/typecheck/rust-hir-const-fold-base.h b/gcc/rust/typecheck/rust-hir-const-fold-base.h deleted file mode 100644 index 2ab4450..0000000 --- a/gcc/rust/typecheck/rust-hir-const-fold-base.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2020-2021 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#ifndef RUST_HIR_CONST_FOLD_BASE_H -#define RUST_HIR_CONST_FOLD_BASE_H - -#include "rust-diagnostics.h" -#include "rust-hir-visitor.h" -#include "rust-hir-map.h" -#include "rust-hir-type-check.h" -#include "rust-name-resolver.h" -#include "rust-hir-const-fold-ctx.h" - -namespace Rust { -namespace ConstFold { - -// base class to allow derivatives to overload as needed -class ConstFoldBase : public HIR::HIRFullVisitorBase -{ -public: - virtual ~ConstFoldBase () {} - -protected: - ConstFoldBase () - : mappings (Analysis::Mappings::get ()), - resolver (Resolver::Resolver::get ()), - tyctx (Resolver::TypeCheckContext::get ()), ctx (Context::get ()) - {} - - Analysis::Mappings *mappings; - Resolver::Resolver *resolver; - Resolver::TypeCheckContext *tyctx; - Context *ctx; -}; - -} // namespace ConstFold -} // namespace Rust - -#endif // RUST_HIR_CONST_FOLD_BASE_H diff --git a/gcc/rust/typecheck/rust-hir-const-fold.cc b/gcc/rust/typecheck/rust-hir-const-fold.cc deleted file mode 100644 index 1545c1a..0000000 --- a/gcc/rust/typecheck/rust-hir-const-fold.cc +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (C) 2020-2021 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-hir-const-fold-ctx.h" -#include "rust-hir-const-fold.h" - -namespace Rust { -namespace ConstFold { - -static Context *context = nullptr; - -Context::Context (::Backend *backend) : backend (backend) {} - -void -Context::init (::Backend *backend) -{ - rust_assert (context == nullptr); - context = new Context (backend); -} - -Context * -Context::get () -{ - rust_assert (context != nullptr); - return context; -} - -bool -Context::lookup_const (HirId id, tree *expr) -{ - auto it = ctx.find (id); - if (it == ctx.end ()) - return false; - - *expr = it->second; - return true; -} - -void -Context::insert_const (HirId id, tree expr) -{ - rust_assert (ctx.find (id) == ctx.end ()); - ctx[id] = expr; -} - -// rust-hir-const-fold.h - -void -ConstFoldItem::visit (HIR::ConstantItem &item) -{ - auto folded_expr = ConstFoldExpr::fold (item.get_expr ()); - - folded = folded_expr; -} - -void -ConstFoldArrayElems::visit (HIR::ArrayElemsValues &elems) -{ - unsigned long index = 0; - std::vector<unsigned long> indices; - std::vector<tree> values; - - TyTy::BaseType *tyty = nullptr; - if (!tyctx->lookup_type (expr.get_mappings ().get_hirid (), &tyty)) - { - rust_fatal_error (expr.get_locus (), - "did not resolve type for array elems values"); - return; - } - - tree type = ConstFoldType::fold (tyty, ctx->get_backend ()); - - for (auto &value : elems.get_values ()) - { - indices.push_back (index++); - values.push_back (ConstFoldExpr::fold (value.get ())); - } - - folded - = ctx->get_backend ()->array_constructor_expression (type, indices, values, - expr.get_locus ()); -} - -void -ConstFoldArrayElems::visit (HIR::ArrayElemsCopied &elems) -{ - std::vector<unsigned long> indices; - std::vector<tree> values; - - TyTy::BaseType *tyty = nullptr; - if (!tyctx->lookup_type (expr.get_mappings ().get_hirid (), &tyty)) - { - rust_fatal_error (expr.get_locus (), - "did not resolve type for array elems"); - return; - } - - tree type = ConstFoldType::fold (tyty, ctx->get_backend ()); - tree elem = ConstFoldExpr::fold (elems.get_elem_to_copy ()); - - // num copies expr was already folded in rust-hir-type-check-expr; lookup the - // earlier result - tree num_copies_expr = ctx->get_backend ()->error_expression (); - ctx->lookup_const (elems.get_num_copies_expr ()->get_mappings ().get_hirid (), - &num_copies_expr); - - size_t copies; - bool ok = ctx->get_backend ()->const_size_cast (num_copies_expr, &copies); - rust_assert (ok); - - for (size_t i = 0; i < copies; i++) - { - indices.push_back (i); - values.push_back (elem); - } - - folded - = ctx->get_backend ()->array_constructor_expression (type, indices, values, - expr.get_locus ()); -} - -} // namespace ConstFold -} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-const-fold.h b/gcc/rust/typecheck/rust-hir-const-fold.h deleted file mode 100644 index 1907816..0000000 --- a/gcc/rust/typecheck/rust-hir-const-fold.h +++ /dev/null @@ -1,499 +0,0 @@ -// Copyright (C) 2020-2021 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#ifndef RUST_HIR_CONST_FOLD_H -#define RUST_HIR_CONST_FOLD_H - -#include "rust-hir-const-fold-base.h" -#include "rust-tyty-visitor.h" - -namespace Rust { -namespace ConstFold { - -class ConstFoldType : public TyTy::TyVisitor -{ -public: - static tree fold (TyTy::BaseType *type, ::Backend *backend) - { - ConstFoldType folder (backend); - type->accept_vis (folder); - return folder.translated; - }; - - void visit (TyTy::ErrorType &) override { gcc_unreachable (); } - - void visit (TyTy::InferType &) override { gcc_unreachable (); } - - void visit (TyTy::ADTType &) override { gcc_unreachable (); } - - void visit (TyTy::ArrayType &type) override - { - tree element_ty = ConstFoldType::fold (type.get_element_type (), backend); - translated = backend->array_type (element_ty, type.get_capacity ()); - } - - void visit (TyTy::ReferenceType &type) override - { - tree base_compiled_type = ConstFoldType::fold (type.get_base (), backend); - if (type.is_mutable ()) - { - translated = backend->reference_type (base_compiled_type); - } - else - { - auto base = backend->immutable_type (base_compiled_type); - translated = backend->reference_type (base); - } - } - - void visit (TyTy::PointerType &type) override - { - tree base_compiled_type = ConstFoldType::fold (type.get_base (), backend); - if (type.is_mutable ()) - { - translated = backend->pointer_type (base_compiled_type); - } - else - { - auto base = backend->immutable_type (base_compiled_type); - translated = backend->pointer_type (base); - } - } - - void visit (TyTy::ParamType &) override { gcc_unreachable (); } - - void visit (TyTy::FnPtr &) override { gcc_unreachable (); } - - void visit (TyTy::FnType &) override { gcc_unreachable (); } - - void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); } - - void visit (TyTy::ProjectionType &) override { gcc_unreachable (); } - - void visit (TyTy::TupleType &type) override - { - if (type.num_fields () == 0) - translated = backend->unit_type (); - else - gcc_unreachable (); - } - - void visit (TyTy::BoolType &) override - { - translated = backend->named_type ("bool", backend->bool_type (), - Linemap::predeclared_location ()); - } - - void visit (TyTy::IntType &type) override - { - switch (type.get_int_kind ()) - { - case TyTy::IntType::I8: - translated - = backend->named_type ("i8", backend->integer_type (false, 8), - Linemap::predeclared_location ()); - return; - - case TyTy::IntType::I16: - translated - = backend->named_type ("i16", backend->integer_type (false, 16), - Linemap::predeclared_location ()); - return; - - case TyTy::IntType::I32: - translated - = backend->named_type ("i32", backend->integer_type (false, 32), - Linemap::predeclared_location ()); - return; - - case TyTy::IntType::I64: - translated - = backend->named_type ("i64", backend->integer_type (false, 64), - Linemap::predeclared_location ()); - return; - - case TyTy::IntType::I128: - translated - = backend->named_type ("i128", backend->integer_type (false, 128), - Linemap::predeclared_location ()); - return; - } - gcc_unreachable (); - } - - void visit (TyTy::UintType &type) override - { - switch (type.get_uint_kind ()) - { - case TyTy::UintType::U8: - translated = backend->named_type ("u8", backend->integer_type (true, 8), - Linemap::predeclared_location ()); - return; - - case TyTy::UintType::U16: - translated - = backend->named_type ("u16", backend->integer_type (true, 16), - Linemap::predeclared_location ()); - return; - - case TyTy::UintType::U32: - translated - = backend->named_type ("u32", backend->integer_type (true, 32), - Linemap::predeclared_location ()); - return; - - case TyTy::UintType::U64: - translated - = backend->named_type ("u64", backend->integer_type (true, 64), - Linemap::predeclared_location ()); - return; - - case TyTy::UintType::U128: - translated - = backend->named_type ("u128", backend->integer_type (true, 128), - Linemap::predeclared_location ()); - return; - } - gcc_unreachable (); - } - - void visit (TyTy::FloatType &type) override - { - switch (type.get_float_kind ()) - { - case TyTy::FloatType::F32: - translated = backend->named_type ("f32", backend->float_type (32), - Linemap::predeclared_location ()); - return; - - case TyTy::FloatType::F64: - translated = backend->named_type ("f64", backend->float_type (64), - Linemap::predeclared_location ()); - return; - } - - gcc_unreachable (); - } - - void visit (TyTy::USizeType &) override - { - translated = backend->named_type ( - "usize", backend->integer_type (true, backend->get_pointer_size ()), - Linemap::predeclared_location ()); - } - - void visit (TyTy::ISizeType &) override - { - translated = backend->named_type ( - "isize", backend->integer_type (false, backend->get_pointer_size ()), - Linemap::predeclared_location ()); - } - - void visit (TyTy::CharType &) override - { - translated = backend->named_type ("char", backend->wchar_type (), - Linemap::predeclared_location ()); - } - - void visit (TyTy::StrType &) override - { - tree raw_str = backend->raw_str_type (); - translated - = backend->named_type ("str", raw_str, Linemap::predeclared_location ()); - } - - void visit (TyTy::NeverType &) override { gcc_unreachable (); } - - void visit (TyTy::DynamicObjectType &) override { gcc_unreachable (); } - - void visit (TyTy::ClosureType &) override { gcc_unreachable (); } - -private: - ConstFoldType (::Backend *backend) - : backend (backend), translated (backend->error_type ()) - {} - - ::Backend *backend; - ::tree translated; -}; - -class ConstFoldItem : public ConstFoldBase -{ - using ConstFoldBase::visit; - -public: - static tree fold (HIR::Item &item) - { - ConstFoldItem folder; - item.accept_vis (folder); - if (folder.ctx->get_backend ()->is_error_expression (folder.folded)) - { - rust_error_at (item.get_locus (), "non const value"); - return nullptr; - } - - folder.ctx->insert_const (item.get_mappings ().get_hirid (), folder.folded); - return folder.folded; - }; - - void visit (HIR::ConstantItem &item) override; - -private: - ConstFoldItem () - : ConstFoldBase (), folded (ctx->get_backend ()->error_expression ()) - {} - - tree folded; -}; - -class ConstFoldArrayElems : public ConstFoldBase -{ - using ConstFoldBase::visit; - -public: - static tree fold (HIR::ArrayExpr &expr) - { - ConstFoldArrayElems folder (expr); - HIR::ArrayElems *elems = expr.get_internal_elements (); - elems->accept_vis (folder); - return folder.folded; - } - - void visit (HIR::ArrayElemsValues &elems) override; - void visit (HIR::ArrayElemsCopied &elems) override; - -private: - ConstFoldArrayElems (HIR::ArrayExpr &expr) - : ConstFoldBase (), folded (ctx->get_backend ()->error_expression ()), - expr (expr) - {} - - tree folded; - HIR::ArrayExpr &expr; -}; - -class ConstFoldExpr : public ConstFoldBase -{ - using ConstFoldBase::visit; - -public: - static tree fold (HIR::Expr *expr) - { - ConstFoldExpr folder; - expr->accept_vis (folder); - if (folder.ctx->get_backend ()->is_error_expression (folder.folded)) - { - rust_error_at (expr->get_locus (), "non const value"); - return folder.ctx->get_backend ()->error_expression (); - } - - folder.ctx->insert_const (expr->get_mappings ().get_hirid (), - folder.folded); - return folder.folded; - }; - - void visit (HIR::IdentifierExpr &expr) override - { - NodeId ast_node_id = expr.get_mappings ().get_nodeid (); - - // then lookup the reference_node_id - NodeId ref_node_id = UNKNOWN_NODEID; - if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - { - // these ref_node_ids will resolve to a pattern declaration but we are - // interested in the definition that this refers to get the parent id - Resolver::Definition def; - if (!resolver->lookup_definition (ref_node_id, &def)) - { - rust_error_at (expr.get_locus (), - "unknown reference for resolved name"); - return; - } - ref_node_id = def.parent; - } - - if (ref_node_id == UNKNOWN_NODEID) - { - rust_error_at (expr.get_locus (), "unresolved node: %s", - expr.as_string ().c_str ()); - return; - } - - // node back to HIR - HirId ref; - if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), - ref_node_id, &ref)) - { - rust_error_at (expr.get_locus (), "reverse lookup failure"); - return; - } - - // lookup constant - ctx->lookup_const (ref, &folded); - } - - void visit (HIR::LiteralExpr &expr) override - { - auto literal_value = expr.get_literal (); - switch (expr.get_lit_type ()) - { - case HIR::Literal::INT: { - mpz_t ival; - if (mpz_init_set_str (ival, literal_value.as_string ().c_str (), 10) - != 0) - { - rust_fatal_error (expr.get_locus (), "bad number in literal"); - return; - } - - TyTy::BaseType *tyty = nullptr; - if (!tyctx->lookup_type (expr.get_mappings ().get_hirid (), &tyty)) - { - rust_fatal_error (expr.get_locus (), - "did not resolve type for this literal expr"); - return; - } - - tree type = ConstFoldType::fold (tyty, ctx->get_backend ()); - folded - = ctx->get_backend ()->integer_constant_expression (type, ival); - } - return; - - case HIR::Literal::BOOL: { - bool bval = literal_value.as_string ().compare ("true") == 0; - folded = ctx->get_backend ()->boolean_constant_expression (bval); - } - return; - - case HIR::Literal::FLOAT: { - mpfr_t fval; - if (mpfr_init_set_str (fval, literal_value.as_string ().c_str (), 10, - MPFR_RNDN) - != 0) - { - rust_fatal_error (expr.get_locus (), - "bad floating-point number in literal"); - return; - } - - TyTy::BaseType *tyty = nullptr; - if (!tyctx->lookup_type (expr.get_mappings ().get_hirid (), &tyty)) - { - rust_fatal_error (expr.get_locus (), - "did not resolve type for this literal expr"); - return; - } - - tree type = ConstFoldType::fold (tyty, ctx->get_backend ()); - folded = ctx->get_backend ()->float_constant_expression (type, fval); - } - return; - - /* handle other literals */ - - default: - gcc_unreachable (); - return; - } - - gcc_unreachable (); - } - - void visit (HIR::ArrayExpr &expr) override - { - folded = ConstFoldArrayElems::fold (expr); - } - - void visit (HIR::ArithmeticOrLogicalExpr &expr) override - { - auto lhs = ConstFoldExpr::fold (expr.get_lhs ()); - auto rhs = ConstFoldExpr::fold (expr.get_rhs ()); - - auto op = expr.get_expr_type (); - auto location = expr.get_locus (); - - folded - = ctx->get_backend ()->arithmetic_or_logical_expression (op, lhs, rhs, - location); - } - - void visit (HIR::NegationExpr &expr) override - { - auto negated_expr = ConstFoldExpr::fold (expr.get_expr ().get ()); - - auto op = expr.get_expr_type (); - auto location = expr.get_locus (); - - folded - = ctx->get_backend ()->negation_expression (op, negated_expr, location); - } - - void visit (HIR::ArrayIndexExpr &expr) override - { - tree array = ConstFoldExpr::fold (expr.get_array_expr ()); - tree index = ConstFoldExpr::fold (expr.get_index_expr ()); - - folded = ctx->get_backend ()->array_index_expression (array, index, - expr.get_locus ()); - } - - void visit (HIR::BorrowExpr &expr) override - { - tree main_expr = ConstFoldExpr::fold (expr.get_expr ().get ()); - - folded - = ctx->get_backend ()->address_expression (main_expr, expr.get_locus ()); - } - - void visit (HIR::DereferenceExpr &expr) override - { - tree main_expr = ConstFoldExpr::fold (expr.get_expr ().get ()); - - TyTy::BaseType *tyty = nullptr; - if (!tyctx->lookup_type (expr.get_mappings ().get_hirid (), &tyty)) - { - rust_fatal_error (expr.get_locus (), - "did not resolve type for this TupleExpr"); - return; - } - - tree expected_type = ConstFoldType::fold (tyty, ctx->get_backend ()); - bool known_valid = true; - folded = ctx->get_backend ()->indirect_expression (expected_type, main_expr, - known_valid, - expr.get_locus ()); - } - - void visit (HIR::GroupedExpr &expr) override - { - folded = ConstFoldExpr::fold (expr.get_expr_in_parens ().get ()); - } - -private: - ConstFoldExpr () - : ConstFoldBase (), folded (ctx->get_backend ()->error_expression ()) - {} - - tree folded; -}; - -} // namespace ConstFold -} // namespace Rust - -#endif // RUST_HIR_CONST_FOLD_H diff --git a/gcc/rust/typecheck/rust-hir-type-check-enumitem.h b/gcc/rust/typecheck/rust-hir-type-check-enumitem.h index 4df7df6..f770bed 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-enumitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-enumitem.h @@ -63,28 +63,16 @@ public: if (capacity_type->get_kind () == TyTy::TypeKind::ERROR) return; - TyTy::USizeType *expected_ty - = new TyTy::USizeType (discriminant->get_mappings ().get_hirid ()); + TyTy::ISizeType *expected_ty + = new TyTy::ISizeType (discriminant->get_mappings ().get_hirid ()); context->insert_type (discriminant->get_mappings (), expected_ty); auto unified = expected_ty->unify (capacity_type); if (unified->get_kind () == TyTy::TypeKind::ERROR) return; - auto backend = rust_get_backend (); - auto folded_discriminant - = ConstFold::ConstFoldExpr::fold (discriminant.get ()); - if (backend->is_error_expression (folded_discriminant)) - return; - - size_t specified_discriminant; - bool ok - = backend->const_size_cast (folded_discriminant, &specified_discriminant); - rust_assert (ok); - - variant - = new TyTy::VariantDef (item.get_mappings ().get_hirid (), - item.get_identifier (), specified_discriminant); + variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), + item.get_identifier (), &item); } void visit (HIR::EnumItemTuple &item) override diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index b636e29..1ac4946 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -27,7 +27,6 @@ #include "rust-hir-type-check-struct-field.h" #include "rust-hir-path-probe.h" #include "rust-substitution-mapper.h" -#include "rust-hir-const-fold.h" #include "rust-hir-trait-resolve.h" #include "rust-hir-type-bounds.h" #include "rust-hir-dot-operator.h" @@ -728,17 +727,17 @@ public: It is a constant, but for fold it to get a tree. */ std::string capacity_str = std::to_string (expr.get_literal ().as_string ().size ()); - HIR::LiteralExpr literal_capacity (capacity_mapping, capacity_str, - HIR::Literal::LitType::INT, - PrimitiveCoreType::CORETYPE_USIZE, - expr.get_locus ()); + HIR::LiteralExpr *literal_capacity + = new HIR::LiteralExpr (capacity_mapping, capacity_str, + HIR::Literal::LitType::INT, + PrimitiveCoreType::CORETYPE_USIZE, + expr.get_locus ()); // mark the type for this implicit node - context->insert_type (capacity_mapping, - new TyTy::USizeType ( - capacity_mapping.get_hirid ())); - - tree capacity = ConstFold::ConstFoldExpr::fold (&literal_capacity); + TyTy::BaseType *expected_ty = nullptr; + ok = context->lookup_builtin ("usize", &expected_ty); + rust_assert (ok); + context->insert_type (capacity_mapping, expected_ty); Analysis::NodeMapping array_mapping (crate_num, UNKNOWN_NODEID, mappings->get_next_hir_id ( @@ -746,7 +745,8 @@ public: UNKNOWN_LOCAL_DEFID); TyTy::ArrayType *array - = new TyTy::ArrayType (array_mapping.get_hirid (), capacity, + = new TyTy::ArrayType (array_mapping.get_hirid (), + *literal_capacity, TyTy::TyVar (u8->get_ref ())); context->insert_type (array_mapping, array); @@ -979,77 +979,75 @@ public: void visit (HIR::ArrayExpr &expr) override { - HIR::ArrayElems *elements = expr.get_internal_elements (); - root_array_expr_locus = expr.get_locus (); - - elements->accept_vis (*this); - if (infered_array_elems == nullptr) - return; - if (folded_array_capacity == nullptr) - return; + HIR::ArrayElems &elements = *expr.get_internal_elements (); - infered - = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), - folded_array_capacity, - TyTy::TyVar (infered_array_elems->get_ref ())); - } - - void visit (HIR::ArrayElemsValues &elems) override - { - std::vector<TyTy::BaseType *> types; - - for (auto &elem : elems.get_values ()) + HIR::Expr *capacity_expr = nullptr; + TyTy::BaseType *element_type = nullptr; + switch (elements.get_array_expr_type ()) { - types.push_back (TypeCheckExpr::Resolve (elem.get (), false)); - } + case HIR::ArrayElems::ArrayExprType::COPIED: { + HIR::ArrayElemsCopied &elems + = static_cast<HIR::ArrayElemsCopied &> (elements); + element_type + = TypeCheckExpr::Resolve (elems.get_elem_to_copy (), false); - infered_array_elems - = TyTy::TyVar::get_implicit_infer_var (root_array_expr_locus).get_tyty (); + auto capacity_type + = TypeCheckExpr::Resolve (elems.get_num_copies_expr (), false); - for (auto &type : types) - { - infered_array_elems = infered_array_elems->unify (type); - } - for (auto &elem : types) - { - infered_array_elems->append_reference (elem->get_ref ()); - } + TyTy::BaseType *expected_ty = nullptr; + bool ok = context->lookup_builtin ("usize", &expected_ty); + rust_assert (ok); + context->insert_type (elems.get_num_copies_expr ()->get_mappings (), + expected_ty); - auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, UNKNOWN_NODEID, - mappings->get_next_hir_id (crate_num), - UNKNOWN_LOCAL_DEFID); - std::string capacity_str = std::to_string (elems.get_num_elements ()); - HIR::LiteralExpr implicit_literal_capacity ( - mapping, capacity_str, HIR::Literal::LitType::INT, - PrimitiveCoreType::CORETYPE_USIZE, Location ()); + auto unified = expected_ty->unify (capacity_type); + if (unified->get_kind () == TyTy::TypeKind::ERROR) + return; - // mark the type for this implicit node - context->insert_type (mapping, new TyTy::USizeType (mapping.get_hirid ())); + capacity_expr = elems.get_num_copies_expr (); + } + break; - folded_array_capacity - = ConstFold::ConstFoldExpr::fold (&implicit_literal_capacity); - } + case HIR::ArrayElems::ArrayExprType::VALUES: { + HIR::ArrayElemsValues &elems + = static_cast<HIR::ArrayElemsValues &> (elements); - void visit (HIR::ArrayElemsCopied &elems) override - { - auto capacity_type - = TypeCheckExpr::Resolve (elems.get_num_copies_expr (), false); + std::vector<TyTy::BaseType *> types; + for (auto &elem : elems.get_values ()) + { + types.push_back (TypeCheckExpr::Resolve (elem.get (), false)); + } - TyTy::USizeType *expected_ty = new TyTy::USizeType ( - elems.get_num_copies_expr ()->get_mappings ().get_hirid ()); - context->insert_type (elems.get_num_copies_expr ()->get_mappings (), - expected_ty); + element_type = TyTy::TyVar::get_implicit_infer_var (expr.get_locus ()) + .get_tyty (); + for (auto &type : types) + { + element_type = element_type->unify (type); + } - auto unified = expected_ty->unify (capacity_type); - if (unified->get_kind () == TyTy::TypeKind::ERROR) - return; + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, UNKNOWN_NODEID, + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + std::string capacity_str = std::to_string (elems.get_num_elements ()); + capacity_expr + = new HIR::LiteralExpr (mapping, capacity_str, + HIR::Literal::LitType::INT, + PrimitiveCoreType::CORETYPE_USIZE, + Location ()); - folded_array_capacity - = ConstFold::ConstFoldExpr::fold (elems.get_num_copies_expr ()); + // mark the type for this implicit node + TyTy::BaseType *expected_ty = nullptr; + bool ok = context->lookup_builtin ("usize", &expected_ty); + rust_assert (ok); + context->insert_type (mapping, expected_ty); + } + break; + } - infered_array_elems - = TypeCheckExpr::Resolve (elems.get_elem_to_copy (), false); + infered + = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), *capacity_expr, + TyTy::TyVar (element_type->get_ref ())); } // empty struct @@ -1547,8 +1545,7 @@ protected: private: TypeCheckExpr (bool inside_loop) - : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr), - folded_array_capacity (nullptr), inside_loop (inside_loop) + : TypeCheckBase (), infered (nullptr), inside_loop (inside_loop) {} // Beware: currently returns Tyty::ErrorType or nullptr in case of error. @@ -1617,14 +1614,8 @@ private: /* The return value of TypeCheckExpr::Resolve */ TyTy::BaseType *infered; - /* The return value of visit(ArrayElemsValues&) and visit(ArrayElemsCopied&) - Stores the type of array elements, if `expr` is ArrayExpr. */ - TyTy::BaseType *infered_array_elems; - tree folded_array_capacity; - Location root_array_expr_locus; - bool inside_loop; -}; // namespace Resolver +}; } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index a860608..25b592c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -170,9 +170,6 @@ public: = TypeCheckExpr::Resolve (constant.get_expr (), false); context->insert_type (constant.get_mappings (), type->unify (expr_type)); - - // notify the constant folder of this - ConstFold::ConstFoldItem::fold (constant); } void visit (HIR::Function &function) override diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index fb0e047..22b6f3f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -64,9 +64,6 @@ public: infered = type->unify (expr_type); context->insert_type (constant.get_mappings (), infered); - - // notify the constant folder of this - ConstFold::ConstFoldItem::fold (constant); } void visit (HIR::LetStmt &stmt) override @@ -98,7 +95,7 @@ public: if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) return; - context->insert_type (stmt.get_mappings (), unified_ty); + context->insert_type (stmt.get_mappings (), specified_ty); } else { diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 7b1dfc9..3733e429 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -315,9 +315,6 @@ public: = TypeCheckExpr::Resolve (constant.get_expr (), false); context->insert_type (constant.get_mappings (), type->unify (expr_type)); - - // notify the constant folder of this - ConstFold::ConstFoldItem::fold (constant); } void visit (HIR::Function &function) override diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index cfe9652..93f46e6 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -18,6 +18,7 @@ #include "rust-hir-type-check-type.h" #include "rust-hir-trait-resolve.h" +#include "rust-hir-type-check-expr.h" namespace Rust { namespace Resolver { @@ -575,5 +576,27 @@ TypeCheckType::visit (HIR::TraitObjectType &type) std::move (specified_bounds)); } +void +TypeCheckType::visit (HIR::ArrayType &type) +{ + auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr (), false); + if (capacity_type->get_kind () == TyTy::TypeKind::ERROR) + return; + + TyTy::BaseType *expected_ty = nullptr; + bool ok = context->lookup_builtin ("usize", &expected_ty); + rust_assert (ok); + context->insert_type (type.get_size_expr ()->get_mappings (), expected_ty); + + auto unified = expected_ty->unify (capacity_type); + if (unified->get_kind () == TyTy::TypeKind::ERROR) + return; + + TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ()); + translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (), + *type.get_size_expr (), + TyTy::TyVar (base->get_ref ())); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index d2da20e..ccde21a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -23,7 +23,6 @@ #include "rust-hir-type-check-expr.h" #include "rust-hir-type-check-struct-field.h" #include "rust-hir-inherent-impl-overlap.h" -#include "rust-hir-const-fold.h" extern bool saw_errors (void); @@ -135,28 +134,6 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ()); } -void -TypeCheckType::visit (HIR::ArrayType &type) -{ - auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr (), false); - if (capacity_type->get_kind () == TyTy::TypeKind::ERROR) - return; - - TyTy::USizeType *expected_ty - = new TyTy::USizeType (type.get_size_expr ()->get_mappings ().get_hirid ()); - context->insert_type (type.get_size_expr ()->get_mappings (), expected_ty); - - auto unified = expected_ty->unify (capacity_type); - if (unified->get_kind () == TyTy::TypeKind::ERROR) - return; - - auto capacity = ConstFold::ConstFoldExpr::fold (type.get_size_expr ()); - - TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ()); - translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (), capacity, - TyTy::TyVar (base->get_ref ())); -} - // rust-hir-trait-ref.h TraitItemReference::TraitItemReference ( diff --git a/gcc/rust/typecheck/rust-tyty-cast.h b/gcc/rust/typecheck/rust-tyty-cast.h index 07fedd0..6036a75 100644 --- a/gcc/rust/typecheck/rust-tyty-cast.h +++ b/gcc/rust/typecheck/rust-tyty-cast.h @@ -806,19 +806,9 @@ public: return; } - auto backend = rust_get_backend (); - - // need to check the base types and capacity - if (!backend->const_values_equal (type.get_capacity (), - base->get_capacity ())) - { - BaseCastRules::visit (type); - return; - } - - resolved - = new ArrayType (type.get_ref (), type.get_ty_ref (), - type.get_capacity (), TyVar (base_resolved->get_ref ())); + resolved = new ArrayType (type.get_ref (), type.get_ty_ref (), + type.get_capacity_expr (), + TyVar (base_resolved->get_ref ())); } private: diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h index 291e590..6347530 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -851,13 +851,6 @@ public: void visit (const ArrayType &type) override { - // need to check the base types and capacity - if (type.get_capacity () != base->get_capacity ()) - { - BaseCmp::visit (type); - return; - } - // check base type const BaseType *base_element = base->get_element_type (); const BaseType *other_element = type.get_element_type (); diff --git a/gcc/rust/typecheck/rust-tyty-coercion.h b/gcc/rust/typecheck/rust-tyty-coercion.h index b483130..25f6810 100644 --- a/gcc/rust/typecheck/rust-tyty-coercion.h +++ b/gcc/rust/typecheck/rust-tyty-coercion.h @@ -824,19 +824,9 @@ public: return; } - auto backend = rust_get_backend (); - - // need to check the base types and capacity - if (!backend->const_values_equal (type.get_capacity (), - base->get_capacity ())) - { - BaseCoercionRules::visit (type); - return; - } - - resolved - = new ArrayType (type.get_ref (), type.get_ty_ref (), - type.get_capacity (), TyVar (base_resolved->get_ref ())); + resolved = new ArrayType (type.get_ref (), type.get_ty_ref (), + type.get_capacity_expr (), + TyVar (base_resolved->get_ref ())); } private: diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 5dc2d2f..450a93f 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -841,19 +841,9 @@ public: return; } - auto backend = rust_get_backend (); - - // need to check the base types and capacity - if (!backend->const_values_equal (type.get_capacity (), - base->get_capacity ())) - { - BaseRules::visit (type); - return; - } - - resolved - = new ArrayType (type.get_ref (), type.get_ty_ref (), - type.get_capacity (), TyVar (base_resolved->get_ref ())); + resolved = new ArrayType (type.get_ref (), type.get_ty_ref (), + type.get_capacity_expr (), + TyVar (base_resolved->get_ref ())); } private: diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index f141a41..679187b 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -1335,14 +1335,7 @@ ArrayType::accept_vis (TyConstVisitor &vis) const std::string ArrayType::as_string () const { - return "[" + get_element_type ()->as_string () + ":" + capacity_string () - + "]"; -} - -std::string -ArrayType::capacity_string () const -{ - return rust_get_backend ()->const_size_val_to_string (get_capacity ()); + return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]"; } BaseType * @@ -1381,8 +1374,6 @@ ArrayType::is_equal (const BaseType &other) const return false; auto other2 = static_cast<const ArrayType &> (other); - if (get_capacity () != other2.get_capacity ()) - return false; auto this_element_type = get_element_type (); auto other_element_type = other2.get_element_type (); @@ -1399,8 +1390,8 @@ ArrayType::get_element_type () const BaseType * ArrayType::clone () const { - return new ArrayType (get_ref (), get_ty_ref (), get_capacity (), - element_type, get_combined_refs ()); + return new ArrayType (get_ref (), get_ty_ref (), capacity_expr, element_type, + get_combined_refs ()); } void diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 40c06a5..bdf85a9 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -19,12 +19,12 @@ #ifndef RUST_TYTY #define RUST_TYTY -#include "rust-backend.h" #include "rust-hir-map.h" #include "rust-hir-full.h" #include "rust-diagnostics.h" #include "rust-abi.h" #include "rust-common.h" +#include "tree.h" namespace Rust { @@ -1034,7 +1034,16 @@ public: } VariantDef (HirId id, std::string identifier, int discriminant) - : id (id), identifier (identifier), discriminant (discriminant) + : id (id), identifier (identifier), discriminant (discriminant), + discriminant_node (nullptr) + { + type = VariantType::NUM; + fields = {}; + } + + VariantDef (HirId id, std::string identifier, + HIR::EnumItemDiscriminant *discriminant) + : id (id), identifier (identifier), discriminant_node (discriminant) { type = VariantType::NUM; fields = {}; @@ -1042,7 +1051,8 @@ public: VariantDef (HirId id, std::string identifier, VariantType type, std::vector<StructFieldType *> fields) - : id (id), identifier (identifier), type (type), fields (fields) + : id (id), identifier (identifier), type (type), fields (fields), + discriminant_node (nullptr) { discriminant = 0; rust_assert (type == VariantType::TUPLE || type == VariantType::STRUCT); @@ -1073,7 +1083,12 @@ public: bool is_dataless_variant () const { return type == VariantType::NUM; } std::string get_identifier () const { return identifier; } - int get_discriminant () const { return discriminant; } + + int get_discriminant () const + { + rust_assert (!is_specified_discriminant_node ()); + return discriminant; + } size_t num_fields () const { return fields.size (); } StructFieldType *get_field_at_index (size_t index) @@ -1109,6 +1124,17 @@ public: return false; } + bool is_specified_discriminant_node () const + { + return discriminant_node != nullptr; + } + + HIR::EnumItemDiscriminant *get_discriminant_node () const + { + rust_assert (is_specified_discriminant_node ()); + return discriminant_node; + } + std::string as_string () const { if (type == VariantType::NUM) @@ -1166,6 +1192,7 @@ private: VariantType type; int discriminant; /* Either discriminant or fields are valid. */ std::vector<StructFieldType *> fields; + HIR::EnumItemDiscriminant *discriminant_node; }; class ADTType : public BaseType, public SubstitutionRef @@ -1595,16 +1622,16 @@ private: class ArrayType : public BaseType { public: - ArrayType (HirId ref, tree capacity, TyVar base, + ArrayType (HirId ref, HIR::Expr &capacity_expr, TyVar base, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ref, TypeKind::ARRAY, refs), capacity (capacity), - element_type (base) + : BaseType (ref, ref, TypeKind::ARRAY, refs), element_type (base), + capacity_expr (capacity_expr) {} - ArrayType (HirId ref, HirId ty_ref, tree capacity, TyVar base, + ArrayType (HirId ref, HirId ty_ref, HIR::Expr &capacity_expr, TyVar base, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ty_ref, TypeKind::ARRAY, refs), capacity (capacity), - element_type (base) + : BaseType (ref, ty_ref, TypeKind::ARRAY, refs), element_type (base), + capacity_expr (capacity_expr) {} void accept_vis (TyVisitor &vis) override; @@ -1622,9 +1649,6 @@ public: bool is_equal (const BaseType &other) const override; - tree get_capacity () const { return capacity; } - std::string capacity_string () const; - BaseType *get_element_type () const; BaseType *clone () const final override; @@ -1634,9 +1658,11 @@ public: return get_element_type ()->is_concrete (); } + HIR::Expr &get_capacity_expr () const { return capacity_expr; } + private: - tree capacity; TyVar element_type; + HIR::Expr &capacity_expr; }; class BoolType : public BaseType diff --git a/gcc/testsuite/rust/compile/arrays2.rs b/gcc/testsuite/rust/compile/arrays2.rs index 9c788db..c96f4f7d 100644 --- a/gcc/testsuite/rust/compile/arrays2.rs +++ b/gcc/testsuite/rust/compile/arrays2.rs @@ -1,4 +1,5 @@ +// { dg-additional-options "-w" } fn main() { let array: [i32; 5] = [1, 2, 3]; - // { dg-error "expected ..i32:5.. got ..i32:3.." "" { target *-*-* } .-1 } + // { dg-error "expected an array with a fixed size of 5 elements, found one with 3 elements" "" { target *-*-* } .-1 } } diff --git a/gcc/testsuite/rust/execute/torture/const_fold1.rs b/gcc/testsuite/rust/execute/torture/const_fold1.rs new file mode 100644 index 0000000..3cd6c0c --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/const_fold1.rs @@ -0,0 +1,13 @@ +// { dg-additional-options "-w" } +const fn const_fn() -> usize { + 4 +} + +const FN_TEST: usize = const_fn(); + +const TEST: usize = 2 + FN_TEST; + +fn main() -> i32 { + let a: [_; 12] = [5; TEST * 2]; + a[6] - 5 +} |