@@ -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));
@@ -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
@@ -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 ()));
@@ -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 &
@@ -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;
@@ -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));
@@ -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