add_jump (if_block, then_start_block);
add_jump (if_block, final_block);
- auto &then_end_bb = ctx.basic_blocks[then_end_block];
+ auto &then_end_bb = ctx.basic_blocks[then_end_block.value];
if (then_end_bb.is_goto_terminated () && then_end_bb.successors.empty ())
add_jump (then_end_block, final_block);
}
add_jump (if_end_bb, then_start_bb);
add_jump (if_end_bb, else_start_bb);
- auto &then_bb = ctx.basic_blocks[then_end_bb];
+ auto &then_bb = ctx.basic_blocks[then_end_bb.value];
if (then_bb.is_goto_terminated () && then_bb.successors.empty ())
add_jump (then_end_bb, final_start_bb);
- auto &else_bb = ctx.basic_blocks[else_end_bb];
+ auto &else_bb = ctx.basic_blocks[else_end_bb.value];
if (else_bb.is_goto_terminated () && else_bb.successors.empty ())
add_jump (else_end_bb, final_start_bb);
}
// BIR output
std::vector<BasicBlock> basic_blocks;
- size_t current_bb = 0;
+ BasicBlockId current_bb = ENTRY_BASIC_BLOCK;
/**
* Allocation and lookup of places (variables, temporaries, paths, and
basic_blocks.emplace_back (); // StartBB
}
- BasicBlock &get_current_bb () { return basic_blocks[current_bb]; }
+ BasicBlock &get_current_bb () { return basic_blocks[current_bb.value]; }
const LoopAndLabelCtx &lookup_label (NodeId label)
{
BasicBlockId new_bb ()
{
ctx.basic_blocks.emplace_back ();
- return ctx.basic_blocks.size () - 1;
+ return {ctx.basic_blocks.size () - 1};
}
BasicBlockId start_new_consecutive_bb ()
void add_jump (BasicBlockId from, BasicBlockId to)
{
- ctx.basic_blocks[from].successors.emplace_back (to);
+ ctx.basic_blocks[from.value].successors.emplace_back (to);
}
void add_jump_to (BasicBlockId bb) { add_jump (ctx.current_bb, bb); }
public:
explicit LazyBooleanExprBuilder (BuilderContext &ctx,
PlaceId expr_return_place = INVALID_PLACE)
- : AbstractExprBuilder (ctx, expr_return_place), short_circuit_bb (0)
+ : AbstractExprBuilder (ctx, expr_return_place),
+ short_circuit_bb (ENTRY_BASIC_BLOCK)
{}
PlaceId build (HIR::LazyBooleanExpr &expr)
{
stabilized = true;
// BB0 cannot be folded as it is an entry block.
- for (size_t i = 1; i < func.basic_blocks.size (); ++i)
+ for (BasicBlockId i = {1}; i.value < func.basic_blocks.size (); ++i.value)
{
- const BasicBlock &bb = func.basic_blocks[bb_fold_map[i]];
+ const BasicBlock &bb = func.basic_blocks[bb_fold_map[i.value].value];
if (bb.statements.empty () && bb.is_goto_terminated ())
{
auto dst = bb.successors.at (0);
- if (bb_fold_map[dst] != dst)
+ if (bb_fold_map[dst.value] != dst)
{
rust_error_at (
UNKNOWN_LOCATION,
rust_inform (UNKNOWN_LOCATION,
"Continuing with an unfolded CFG.");
// Reverting the fold map to the original state.
- std::iota (bb_fold_map.begin (), bb_fold_map.end (), 0);
+ for (BasicBlockId i = ENTRY_BASIC_BLOCK;
+ i.value < bb_fold_map.size (); ++i.value)
+ {
+ bb_fold_map[i.value] = i;
+ }
stabilized = true;
break;
}
- bb_fold_map[i] = dst;
+ bb_fold_map[i.value] = dst;
stabilized = false;
}
}
Dump::go (bool enable_simplify_cfg)
{
// To avoid mutation of the BIR, we use indirection through bb_fold_map.
- std::iota (bb_fold_map.begin (), bb_fold_map.end (), 0);
-
+ for (BasicBlockId i = ENTRY_BASIC_BLOCK; i.value < bb_fold_map.size ();
+ ++i.value)
+ {
+ bb_fold_map[i.value] = i;
+ }
for (size_t i = 0; i < place_map.size (); ++i)
{
place_map[i] = {i};
visit_scope (ROOT_SCOPE);
// Print BBs.
- for (statement_bb = 0; statement_bb < func.basic_blocks.size ();
- ++statement_bb)
+ for (statement_bb = ENTRY_BASIC_BLOCK;
+ statement_bb.value < func.basic_blocks.size (); ++statement_bb.value)
{
- if (bb_fold_map[statement_bb] != statement_bb)
+ if (bb_fold_map[statement_bb.value] != statement_bb)
continue; // This BB was folded.
- if (func.basic_blocks[statement_bb].statements.empty ()
- && func.basic_blocks[statement_bb].successors.empty ())
+ if (func.basic_blocks[statement_bb.value].statements.empty ()
+ && func.basic_blocks[statement_bb.value].successors.empty ())
continue;
bb_terminated = false;
- BasicBlock &bb = func.basic_blocks[statement_bb];
+ BasicBlock &bb = func.basic_blocks[statement_bb.value];
stream << "\n";
- stream << indentation << "bb" << bb_fold_map[statement_bb] << ": {\n";
+ stream << indentation << "bb" << bb_fold_map[statement_bb.value].value
+ << ": {\n";
size_t i = 0;
for (auto &stmt : bb.statements)
{
}
if (!bb_terminated)
stream << indentation << indentation << "goto -> bb"
- << bb_fold_map[bb.successors.at (0)] << ";\t\t" << i++ << "\n";
+ << bb_fold_map[bb.successors.at (0).value].value << ";\t\t"
+ << i++ << "\n";
stream << indentation << "}\n";
}
stream << "switchInt(";
visit_move_place (stmt.get_place ());
stream << ") -> [";
- print_comma_separated (stream, func.basic_blocks[statement_bb].successors,
+ print_comma_separated (stream,
+ func.basic_blocks[statement_bb.value].successors,
[this] (BasicBlockId succ) {
- stream << "bb" << bb_fold_map[succ];
+ stream << "bb" << bb_fold_map[succ.value].value;
});
stream << "]";
bb_terminated = true;
bb_terminated = true;
break;
case Statement::Kind::GOTO:
- stream << "goto -> bb"
- << bb_fold_map[func.basic_blocks[statement_bb].successors.at (0)];
+ stream
+ << "goto -> bb"
+ << bb_fold_map
+ [func.basic_blocks[statement_bb.value].successors.at (0).value]
+ .value;
bb_terminated = true;
break;
case Statement::Kind::STORAGE_DEAD:
visit_move_place (place_id);
});
stream << ") -> [";
- print_comma_separated (stream, func.basic_blocks[statement_bb].successors,
+ print_comma_separated (stream,
+ func.basic_blocks[statement_bb.value].successors,
[this] (BasicBlockId succ) {
- stream << "bb" << bb_fold_map[succ];
+ stream << "bb" << bb_fold_map[succ.value].value;
});
stream << "]";
bb_terminated = true;
Resolver::TypeCheckContext &tyctx;
// Collector state.
- BasicBlockId current_bb = 0;
+ BasicBlockId current_bb = ENTRY_BASIC_BLOCK;
uint32_t current_stmt = 0;
PlaceId lhs = INVALID_PLACE;
for (PlaceId arg = PlaceId{FIRST_VARIABLE_PLACE.value + 1};
arg < first_local; ++arg.value)
facts.path_assigned_at_base.emplace_back (
- arg.value, get_point (0, 0, PointPosition::START));
+ arg.value, get_point (ENTRY_BASIC_BLOCK, 0, PointPosition::START));
for (PlaceId place = first_local; place.value < place_db.size ();
++place.value)
{
if (place_db[place].is_var ())
facts.path_moved_at_base.emplace_back (
- place.value, get_point (0, 0, PointPosition::START));
+ place.value,
+ get_point (ENTRY_BASIC_BLOCK, 0, PointPosition::START));
}
}
{
rust_debug ("visit_statemensts");
- for (current_bb = 0; current_bb < basic_blocks.size (); ++current_bb)
+ for (current_bb = ENTRY_BASIC_BLOCK;
+ current_bb.value < basic_blocks.size (); ++current_bb.value)
{
- auto &bb = basic_blocks[current_bb];
+ auto &bb = basic_blocks[current_bb.value];
for (current_stmt = 0; current_stmt < bb.statements.size ();
++current_stmt)
{
visit (bb.statements[current_stmt]);
}
}
- current_bb = 0;
+ current_bb = ENTRY_BASIC_BLOCK;
current_stmt = 0;
}
void visit (const Assignment &expr) override
{
rust_debug ("\t_%u = Assignment(_%u) at %u:%u", lhs.value - 1,
- expr.get_rhs ().value - 1, current_bb, current_stmt);
+ expr.get_rhs ().value - 1, current_bb.value, current_stmt);
issue_read_move (expr.get_rhs ());
push_place_subset (lhs, expr.get_rhs ());
protected: // Statement visitor helpers
WARN_UNUSED_RESULT const BasicBlock &get_current_bb () const
{
- return basic_blocks[current_bb];
+ return basic_blocks[current_bb.value];
}
WARN_UNUSED_RESULT static Polonius::Point
get_point (BasicBlockId bb, uint32_t stmt, PointPosition pos)
{
Polonius::Point point = 0;
- point |= (bb << 16);
+ point |= (bb.value << 16);
point |= (stmt << 1);
point |= (static_cast<uint8_t> (pos) & 1);
return point;
if (!place_db[place_id].should_be_moved ())
return;
- facts.path_moved_at_base.emplace_back (
- place_id.value, initial ? get_point (0, 0, PointPosition::START)
- : get_current_point_mid ());
+ facts.path_moved_at_base.emplace_back (place_id.value,
+ initial
+ ? get_point (ENTRY_BASIC_BLOCK, 0,
+ PointPosition::START)
+ : get_current_point_mid ());
check_move_behind_reference (place_id);
};
/** Unique identifier for a basic block in the BIR. */
-using BasicBlockId = uint32_t;
+struct BasicBlockId
+{
+ uint32_t value;
+ // some overloads for comparision
+ bool operator== (const BasicBlockId &rhs) const { return value == rhs.value; }
+ bool operator!= (const BasicBlockId &rhs) const
+ {
+ return !(operator== (rhs));
+ }
+ bool operator< (const BasicBlockId &rhs) const { return value < rhs.value; }
+ bool operator> (const BasicBlockId &rhs) const { return value > rhs.value; }
+ bool operator<= (const BasicBlockId &rhs) const { return !(operator> (rhs)); }
+ bool operator>= (const BasicBlockId &rhs) const { return !(operator< (rhs)); }
+};
static constexpr BasicBlockId INVALID_BB
- = std::numeric_limits<BasicBlockId>::max ();
+ = {std::numeric_limits<uint32_t>::max ()};
+static constexpr BasicBlockId ENTRY_BASIC_BLOCK = {0};
struct BasicBlock
{