class Statement_inserter
{
public:
+ typedef Unordered_set(Statement*) Statements;
+
// Empty constructor.
Statement_inserter()
- : block_(NULL), pindex_(NULL), gogo_(NULL), var_(NULL)
+ : block_(NULL), pindex_(NULL), gogo_(NULL), var_(NULL),
+ statements_added_(NULL)
{ }
// Constructor for a statement in a block.
- Statement_inserter(Block* block, size_t *pindex)
- : block_(block), pindex_(pindex), gogo_(NULL), var_(NULL)
+ Statement_inserter(Block* block, size_t *pindex, Statements *added = NULL)
+ : block_(block), pindex_(pindex), gogo_(NULL), var_(NULL),
+ statements_added_(added)
{ }
// Constructor for a global variable.
- Statement_inserter(Gogo* gogo, Variable* var)
- : block_(NULL), pindex_(NULL), gogo_(gogo), var_(var)
+ Statement_inserter(Gogo* gogo, Variable* var, Statements *added = NULL)
+ : block_(NULL), pindex_(NULL), gogo_(gogo), var_(var),
+ statements_added_(added)
{ go_assert(var->is_global()); }
// We use the default copy constructor and assignment operator.
Gogo* gogo_;
// The global variable, when looking at an initializer expression.
Variable* var_;
+ // If non-null, a set to record new statements inserted (non-owned).
+ Statements* statements_added_;
};
// When translating the gogo IR into the backend data structure, this
public:
Write_barriers(Gogo* gogo)
: Traverse(traverse_functions | traverse_variables | traverse_statements),
- gogo_(gogo), function_(NULL)
+ gogo_(gogo), function_(NULL), statements_added_()
{ }
int
Gogo* gogo_;
// Current function.
Function* function_;
+ // Statements introduced.
+ Statement_inserter::Statements statements_added_;
};
// Traverse a function. Just record it for later.
Location loc = init->location();
Expression* ref = Expression::make_var_reference(no, loc);
- Statement_inserter inserter(this->gogo_, var);
+ Statement_inserter inserter(this->gogo_, var, &this->statements_added_);
Statement* s = this->gogo_->assign_with_write_barrier(NULL, NULL, &inserter,
ref, init, loc);
+ this->statements_added_.insert(s);
var->add_preinit_statement(this->gogo_, s);
var->clear_init();
int
Write_barriers::statement(Block* block, size_t* pindex, Statement* s)
{
+ if (this->statements_added_.find(s) != this->statements_added_.end())
+ return TRAVERSE_SKIP_COMPONENTS;
+
switch (s->classification())
{
default:
Function* function = this->function_;
Location loc = init->location();
- Statement_inserter inserter(block, pindex);
+ Statement_inserter inserter(block, pindex, &this->statements_added_);
// Insert the variable declaration statement with no
// initializer, so that the variable exists.
&inserter,
ref, init,
loc);
+ this->statements_added_.insert(assign);
// Replace the old variable declaration statement with the new
// initialization.
// Change the assignment to use a write barrier.
Function* function = this->function_;
Location loc = as->location();
- Statement_inserter inserter = Statement_inserter(block, pindex);
+ Statement_inserter inserter =
+ Statement_inserter(block, pindex, &this->statements_added_);
Statement* assign = this->gogo_->assign_with_write_barrier(function,
block,
&inserter,
lhs, rhs,
loc);
+ this->statements_added_.insert(assign);
block->replace_statement(*pindex, assign);
}
break;