diff options
author | Philip Herron <philip.herron@embecosm.com> | 2022-01-13 22:01:59 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2022-01-14 12:32:40 +0000 |
commit | 52780af6602763fac6297f7983878b38e0188bb9 (patch) | |
tree | 41a8d89d018f527b3f20159da1279f67aac71f40 /gcc/rust/backend/rust-compile-expr.h | |
parent | 06c2a74f557ec98896c9f71ba666bd969c4735d2 (diff) | |
download | gcc-52780af6602763fac6297f7983878b38e0188bb9.zip gcc-52780af6602763fac6297f7983878b38e0188bb9.tar.gz gcc-52780af6602763fac6297f7983878b38e0188bb9.tar.bz2 |
Redesign constant folding from the typechecking pass to the backend
In Rust the ArrayType has a constant capacity constraint, this means it
allows for bounds checking at compile time as no variable length arrays are
allowed. In order to typecheck this case we had a constant folding pass as
part of the typechecking system which generated gcc tree's for the IR
and enforced the constant checking along the way.
Also after doing some testing GCC with optimizations turned on is capable
of constant folding/propogating the compilation unit fully. Which meant we
need a method of doing with regardless of optimization level to be able
to be on par with what the Rust language expects we need a full proof
method. Turns out the CPP front-end already does this via its constexpr
mechanism to ensure that these _do_ fold correclty. Another major reason
to do this change is that the original const fold pass was a striped down
copy of what the backend is _already_ doing which is creating a duplication
of the code generation pass. With this all unified into the code generation
pass all we need to do is port over gcc/cp/constexpr.c to enforce the const
rules fully but at the GCC tree level not at the typed HIR level.
Now that we have unified the pass when we hit a const function we can
simply emit a normal GCC function and outside of const expressions GCC
will simply emit a normal CallExpr and depending on optimization level
fully optimize this. If we are in a ConstDecl we will follow the
rust-constexpr.cc and fold the values or error_mark_node with an apropriate
error. By reusing the CPP constexpr code we _know_ it works so reusing it
as much as possible is a good idea in general for this front-end.
Addresses #799
Diffstat (limited to 'gcc/rust/backend/rust-compile-expr.h')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 81 |
1 files changed, 21 insertions, 60 deletions
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 |