From: Jakub Dupak <d...@jakubdupak.com> gcc/rust/ChangeLog:
* checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Emit moves. * checks/errors/borrowck/rust-bir-builder-internal.h: Emit moves. * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Emit moves. * checks/errors/borrowck/rust-bir-dump.cc (Dump::visit_move_place): Emit moves. (Dump::visit): Emit moves. * checks/errors/borrowck/rust-bir-place.h (struct Place): Emit moves. * checks/errors/borrowck/rust-bir-visitor.h: Emit moves. * checks/errors/borrowck/rust-bir.h (enum class): Emit moves. (class AbstractExpr): Emit moves. (BasicBlock::is_terminated): Emit moves. Signed-off-by: Jakub Dupak <d...@jakubdupak.com> --- .../borrowck/rust-bir-builder-expr-stmt.cc | 15 +++-- .../borrowck/rust-bir-builder-internal.h | 35 ++++------ .../borrowck/rust-bir-builder-lazyboolexpr.h | 2 +- .../checks/errors/borrowck/rust-bir-dump.cc | 11 +++- .../checks/errors/borrowck/rust-bir-place.h | 50 ++++++-------- .../checks/errors/borrowck/rust-bir-visitor.h | 4 ++ gcc/rust/checks/errors/borrowck/rust-bir.h | 66 +++++++++++++------ 7 files changed, 103 insertions(+), 80 deletions(-) diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc index 89352d84f6b..922894cc5d5 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc @@ -84,7 +84,7 @@ ExprStmtBuilder::visit (HIR::ClosureExpr &expr) { captures.push_back (ctx.place_db.lookup_variable (capture)); } - make_args (captures); + move_all (captures); // Note: Not a coercion site for captures. return_expr (new InitializerExpr (std::move (captures)), lookup_type (expr)); @@ -96,7 +96,7 @@ ExprStmtBuilder::visit (HIR::StructExprStructFields &fields) auto struct_ty = lookup_type (fields)->as<TyTy::ADTType> ()->get_variants ().at (0); auto init_values = StructBuilder (ctx, struct_ty).build (fields); - make_args (init_values); + move_all (init_values); return_expr (new InitializerExpr (std::move (init_values)), lookup_type (fields)); } @@ -141,7 +141,7 @@ void ExprStmtBuilder::visit (HIR::NegationExpr &expr) { PlaceId operand = visit_expr (*expr.get_expr ()); - return_expr (new Operator<1> ({make_arg (operand)}), lookup_type (expr)); + return_expr (new Operator<1> ({move_place (operand)}), lookup_type (expr)); } void @@ -149,7 +149,7 @@ ExprStmtBuilder::visit (HIR::ArithmeticOrLogicalExpr &expr) { PlaceId lhs = visit_expr (*expr.get_lhs ()); PlaceId rhs = visit_expr (*expr.get_rhs ()); - return_expr (new Operator<2> ({make_arg (lhs), make_arg (rhs)}), + return_expr (new Operator<2> ({move_place (lhs), move_place (rhs)}), lookup_type (expr)); } @@ -158,7 +158,7 @@ ExprStmtBuilder::visit (HIR::ComparisonExpr &expr) { PlaceId lhs = visit_expr (*expr.get_lhs ()); PlaceId rhs = visit_expr (*expr.get_rhs ()); - return_expr (new Operator<2> ({make_arg (lhs), make_arg (rhs)}), + return_expr (new Operator<2> ({move_place (lhs), move_place (rhs)}), lookup_type (expr)); } @@ -208,7 +208,7 @@ ExprStmtBuilder::visit (HIR::ArrayExpr &expr) case HIR::ArrayElems::VALUES: { auto &elem_vals = (static_cast<HIR::ArrayElemsValues &> (*elems)); auto init_values = visit_list (elem_vals.get_values ()); - make_args (init_values); + move_all (init_values); return_expr (new InitializerExpr (std::move (init_values)), lookup_type (expr)); break; @@ -264,6 +264,7 @@ ExprStmtBuilder::visit (HIR::CallExpr &expr) coercion_site (arguments[i], fn_type->get_param_type_at (i)); } + move_all (arguments); return_expr (new CallExpr (fn, std::move (arguments)), lookup_type (expr), true); } @@ -502,7 +503,7 @@ ExprStmtBuilder::visit (HIR::IfExpr &expr) void ExprStmtBuilder::visit (HIR::IfExprConseqElse &expr) { - push_switch (make_arg (visit_expr (*expr.get_if_condition ()))); + push_switch (move_place (visit_expr (*expr.get_if_condition ()))); BasicBlockId if_end_bb = ctx.current_bb; PlaceId result = take_or_create_return_place (lookup_type (expr)); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h index 55f00aa50ac..b421ba43fba 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h @@ -230,10 +230,15 @@ protected: // Helpers to add BIR statements push_assignment (tmp, rhs); } + void push_tmp_assignment (PlaceId rhs) + { + push_tmp_assignment (new Assignment (rhs), ctx.place_db[rhs].tyty); + } + void push_switch (PlaceId switch_val, std::initializer_list<BasicBlockId> destinations = {}) { - auto copy = make_arg (switch_val); + auto copy = move_place (switch_val); ctx.get_current_bb ().statements.emplace_back (Statement::Kind::SWITCH, copy); ctx.get_current_bb ().successors.insert ( @@ -259,33 +264,21 @@ protected: // Helpers to add BIR statements Statement::Kind::STORAGE_DEAD, place); } - PlaceId declare_rvalue (PlaceId place) + PlaceId move_place (PlaceId arg) { - ctx.place_db[place].is_rvalue = true; - return place; - } - - void declare_rvalues (std::vector<PlaceId> &places) - { - for (auto &place : places) - declare_rvalue (place); - } - - PlaceId make_arg (PlaceId arg) - { - auto copy = ctx.place_db.into_rvalue (arg); - if (copy != arg) + if (ctx.place_db[arg].is_lvalue ()) { - push_storage_live (copy); - push_assignment (copy, arg); + push_tmp_assignment (arg); + arg = translated; } - return copy; + + return arg; } - void make_args (std::vector<PlaceId> &args) + template <typename T> void move_all (T &args) { std::transform (args.begin (), args.end (), args.begin (), - [this] (PlaceId arg) { return make_arg (arg); }); + [this] (PlaceId arg) { return move_place (arg); }); } protected: // CFG helpers diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h index fb0c75b4f72..1cc55569c7c 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h @@ -62,7 +62,7 @@ protected: void visit (HIR::LazyBooleanExpr &expr) override { auto lhs = visit_expr (*expr.get_lhs ()); - push_switch (make_arg (lhs), {short_circuit_bb}); + push_switch (move_place (lhs), {short_circuit_bb}); start_new_consecutive_bb (); return_place (visit_expr (*expr.get_rhs ())); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc index 4dea27e3038..320b653f830 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc @@ -241,7 +241,7 @@ void Dump::visit_move_place (PlaceId place_id) { const Place &place = func.place_db[place_id]; - if (place.is_rvalue || !place.is_copy) + if (!place.is_constant ()) stream << "move "; visit_place (place_id); } @@ -325,7 +325,14 @@ Dump::visit (Operator<2> &expr) void Dump::visit (Assignment &expr) { - visit_move_place (expr.get_rhs ()); + if (func.place_db[expr.get_rhs ()].is_rvalue ()) + { + visit_move_place (expr.get_rhs ()); + } + else + { + visit_place (expr.get_rhs ()); + } } std::ostream & diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h index 61e90d58d26..546890d797c 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h @@ -91,18 +91,26 @@ struct Place } path; /** Copy trait */ bool is_copy; - /** This place can be moved from safety. */ - bool is_rvalue; + bool has_drop = false; Lifetime lifetime; TyTy::BaseType *tyty; +public: Place (Kind kind, uint32_t variable_or_field_index, const Path &path, - bool is_copy, bool is_rvalue, const Lifetime &lifetime, - TyTy::BaseType *tyty) + bool is_copy, const Lifetime &lifetime, TyTy::BaseType *tyty) : kind (kind), variable_or_field_index (variable_or_field_index), - path (path), is_copy (is_copy), is_rvalue (is_rvalue), - lifetime (lifetime), tyty (tyty) + path (path), is_copy (is_copy), lifetime (lifetime), tyty (tyty) {} + +public: + [[nodiscard]] bool is_lvalue () const + { + return kind == VARIABLE || kind == FIELD || kind == INDEX || kind == DEREF; + } + + [[nodiscard]] bool is_rvalue () const { return kind == TEMPORARY; } + + bool is_constant () const { return kind == CONSTANT; } }; using ScopeId = uint32_t; @@ -134,8 +142,7 @@ public: PlaceDB () { // Reserved index for invalid place. - places.push_back ( - {Place::INVALID, 0, {}, false, false, NO_LIFETIME, nullptr}); + places.push_back ({Place::INVALID, 0, {}, false, NO_LIFETIME, nullptr}); scopes.emplace_back (); // Root scope. } @@ -193,8 +200,7 @@ public: PlaceId add_variable (NodeId id, TyTy::BaseType *tyty) { return add_place ( - {Place::VARIABLE, id, {}, is_type_copy (tyty), false, NO_LIFETIME, tyty}, - 0); + {Place::VARIABLE, id, {}, is_type_copy (tyty), NO_LIFETIME, tyty}, 0); } WARN_UNUSED_RESULT PlaceId lookup_or_add_path (Place::Kind kind, @@ -217,15 +223,14 @@ public: } } return add_place ({kind, id, Place::Path{parent, 0, 0}, is_type_copy (tyty), - false, NO_LIFETIME, tyty}, + NO_LIFETIME, tyty}, current); } PlaceId add_temporary (TyTy::BaseType *tyty) { return add_place ( - {Place::TEMPORARY, 0, {}, is_type_copy (tyty), false, NO_LIFETIME, tyty}, - 0); + {Place::TEMPORARY, 0, {}, is_type_copy (tyty), NO_LIFETIME, tyty}, 0); } PlaceId get_constant (TyTy::BaseType *tyty) @@ -235,8 +240,7 @@ public: return lookup->second; Lifetime lifetime = tyty->get_kind () == TyTy::REF ? STATIC_LIFETIME : NO_LIFETIME; - Place place - = {Place::CONSTANT, 0, {}, is_type_copy (tyty), false, lifetime, tyty}; + Place place = {Place::CONSTANT, 0, {}, is_type_copy (tyty), lifetime, tyty}; places.push_back (place); return places.size () - 1; } @@ -261,24 +265,10 @@ public: if (lookup != INVALID_PLACE) return lookup; add_place ( - {Place::VARIABLE, id, {}, is_type_copy (tyty), false, NO_LIFETIME, tyty}); + {Place::VARIABLE, id, {}, is_type_copy (tyty), NO_LIFETIME, tyty}); return places.size () - 1; }; - PlaceId into_rvalue (PlaceId place) - { - if (places[place].is_rvalue || places[place].kind == Place::CONSTANT - || places[place].tyty->get_kind () == TyTy::REF) - return place; - return add_place ({Place::TEMPORARY, - 0, - {}, - places[place].is_copy, - true, - NO_LIFETIME, - places[place].tyty}); - } - template <typename FN> void for_each_path_from_root (PlaceId var, FN fn) const { PlaceId current = var; diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h index 0b3a4bddbec..7ad62f700db 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h @@ -50,6 +50,10 @@ public: template <typename BASE, typename T> class VisitableImpl : public BASE { public: + template <typename... Args> + explicit VisitableImpl (Args &&... args) : BASE (std::forward<Args> (args)...) + {} + void accept_vis (Visitor &visitor) override { visitor.visit (static_cast<T &> (*this)); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir.h b/gcc/rust/checks/errors/borrowck/rust-bir.h index 746b2dc7e38..f8a2151aaf8 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir.h @@ -97,20 +97,7 @@ struct BasicBlock std::vector<BasicBlockId> successors; public: - WARN_UNUSED_RESULT bool is_terminated () const - { - if (statements.empty ()) - return false; - switch (statements.back ().get_kind ()) - { - case Statement::Kind::GOTO: - case Statement::Kind::RETURN: - case Statement::Kind::SWITCH: - return true; - default: - return false; - } - } + WARN_UNUSED_RESULT bool is_terminated () const; WARN_UNUSED_RESULT bool is_goto_terminated () const { @@ -119,9 +106,23 @@ public: } }; +enum class ExprKind +{ + INITIALIZER, + OPERATOR, + BORROW, + ASSIGNMENT, + CALL, +}; + // Rhs expression of BIR assignment statements (abstract). class AbstractExpr : public Visitable { + ExprKind kind; + +public: + explicit AbstractExpr (ExprKind kind) : kind (kind) {} + [[nodiscard]] ExprKind get_kind () const { return kind; } }; class InitializerExpr : public VisitableImpl<AbstractExpr, InitializerExpr> @@ -129,7 +130,10 @@ class InitializerExpr : public VisitableImpl<AbstractExpr, InitializerExpr> std::vector<PlaceId> values; public: - explicit InitializerExpr (std::vector<PlaceId> &&values) : values (values) {} + explicit InitializerExpr (std::vector<PlaceId> &&values) + : VisitableImpl<AbstractExpr, InitializerExpr> (ExprKind::INITIALIZER), + values (values) + {} public: std::vector<PlaceId> &get_values () { return values; } @@ -142,7 +146,8 @@ class Operator : public VisitableImpl<AbstractExpr, Operator<ARITY>> public: explicit Operator (std::array<PlaceId, ARITY> &&operands) - : operands (operands) + : VisitableImpl<AbstractExpr, Operator<ARITY>> (ExprKind::OPERATOR), + operands (operands) {} public: @@ -158,7 +163,9 @@ class BorrowExpr : public VisitableImpl<AbstractExpr, BorrowExpr> PlaceId place; public: - explicit BorrowExpr (PlaceId place) : place (place) {} + explicit BorrowExpr (PlaceId place) + : VisitableImpl<AbstractExpr, BorrowExpr> (ExprKind::BORROW), place (place) + {} WARN_UNUSED_RESULT PlaceId get_place () const { return place; } }; @@ -172,7 +179,9 @@ class Assignment : public VisitableImpl<AbstractExpr, Assignment> PlaceId rhs; public: - explicit Assignment (PlaceId rhs) : rhs (rhs) {} + explicit Assignment (PlaceId rhs) + : VisitableImpl<AbstractExpr, Assignment> (ExprKind::ASSIGNMENT), rhs (rhs) + {} public: WARN_UNUSED_RESULT PlaceId get_rhs () const { return rhs; } @@ -185,7 +194,8 @@ class CallExpr : public VisitableImpl<AbstractExpr, CallExpr> public: explicit CallExpr (PlaceId callable, std::vector<PlaceId> &&arguments) - : arguments (arguments), callable (callable) + : VisitableImpl<AbstractExpr, CallExpr> (ExprKind::CALL), + arguments (arguments), callable (callable) {} public: @@ -193,6 +203,24 @@ public: WARN_UNUSED_RESULT PlaceId get_callable () const { return callable; } }; +inline bool +BasicBlock::is_terminated () const +{ + if (statements.empty ()) + return false; + switch (statements.back ().get_kind ()) + { + case Statement::Kind::GOTO: + case Statement::Kind::RETURN: + case Statement::Kind::SWITCH: + return true; + case Statement::Kind::ASSIGNMENT: + return statements.back ().get_expr ().get_kind () == ExprKind::CALL; + default: + return false; + } +} + } // namespace BIR } // namespace Rust -- 2.45.2