ExpressionUse use;
use.reference = &expr;
use.ref_scope = current_block;
- use.blocked = access_write;
+ use.blocked = access_write || r_ref_info->blocked;
if(iteration_body && !r_ref_info->trivial)
{
void ExpressionInliner::visit(UnaryExpression &unary)
{
- SetFlag set_write(access_write, access_write || unary.oper->token[1]=='+' || unary.oper->token[1]=='-');
+ SetFlag set_write(access_write, (unary.oper->token[1]=='+' || unary.oper->token[1]=='-'));
visit(unary.expression);
r_trivial = false;
}
r_trivial = true;
visit(assign.right);
- auto i = assignments.find(assign.target);
+ auto i = assignments.find(assign.target.declaration);
if(i!=assignments.end())
{
- if(iteration_body && i->second->expression)
+ if(iteration_body && i->second && i->second->expression)
{
/* Block inlining into previous references within the iteration
statement. On iterations after the first they would refer to the
u.blocked = (k==iteration_body);
}
+ for(; (i!=assignments.end() && i->first.declaration==assign.target.declaration); ++i)
+ if(targets_overlap(i->first, assign.target))
+ i->second->blocked = true;
+
expressions.push_back(ExpressionInfo());
ExpressionInfo &info = expressions.back();
info.target = assign.target;
info.assign_scope = current_block;
info.trivial = r_trivial;
- i->second = &info;
+ assignments[assign.target] = &info;
}
r_trivial = false;
for(const auto &kvp: variables)
{
- if(kvp.second.output)
+ if(!kvp.second.referenced)
+ unused_nodes.insert(kvp.first);
+ else if(kvp.second.output)
{
/* The last visible assignments of output variables are used by the
next stage or the API. */
for(AssignmentInfo *a: kvp.second.assignments)
unused_nodes.erase(a->node);
}
- else if(!kvp.second.referenced)
- unused_nodes.insert(kvp.first);
}
NodeRemover().apply(s, unused_nodes);
{
bool loop_external = false;
for(AssignmentInfo *a: var_info.assignments)
- {
- bool covered = true;
- for(unsigned j=0; (covered && j<a->target.chain_len && j<target.chain_len); ++j)
- {
- Assignment::Target::ChainType type1 = static_cast<Assignment::Target::ChainType>(a->target.chain[j]&0xC0);
- Assignment::Target::ChainType type2 = static_cast<Assignment::Target::ChainType>(target.chain[j]&0xC0);
- unsigned index1 = a->target.chain[j]&0x3F;
- unsigned index2 = target.chain[j]&0x3F;
- if(type1==Assignment::Target::SWIZZLE || type2==Assignment::Target::SWIZZLE)
- {
- if(type1==Assignment::Target::SWIZZLE && type2==Assignment::Target::SWIZZLE)
- covered = index1&index2;
- else if(type1==Assignment::Target::ARRAY && index1<4)
- covered = index2&(1<<index1);
- else if(type2==Assignment::Target::ARRAY && index2<4)
- covered = index1&(1<<index2);
- /* If it's some other combination (shouldn't happen), leave
- covered as true */
- }
- else
- covered = (type1==type2 && (index1==index2 || index1==0x3F || index2==0x3F));
- }
-
- if(covered)
+ if(targets_overlap(a->target, target))
{
a->used_by.push_back(&node);
if(a->in_loop<in_loop)
loop_external = true;
}
- }
if(loop_external)
loop_ext_refs.push_back(&node);
{
if(composite_reference)
r_reference.declaration = var.declaration;
- else
+ else if(var.declaration)
referenced(var.declaration, var);
}
{
if(composite_reference)
r_reference.declaration = iface.declaration;
- else
+ else if(iface.declaration)
referenced(iface.declaration, iface);
}
{
SetFlag clear_assignment(assignment_target, false);
SetFlag clear_composite(composite_reference, false);
+ SetForScope<Assignment::Target> clear_reference(r_reference, Assignment::Target());
binary.right->visit(*this);
}
graphics API. */
var_info.output = (var.interface=="out" && (stage->type==Stage::FRAGMENT || var.linked_declaration || !var.name.compare(0, 3, "gl_")));
+ // Linked outputs are automatically referenced.
+ if(var_info.output && var.linked_declaration)
+ var_info.referenced = true;
+
if(var.init_expression)
{
var_info.initialized = true;
vector<Node *> saved_refs;
swap(loop_ext_refs, saved_refs);
{
+ if(iter.init_statement)
+ iter.init_statement->visit(*this);
SetForScope<unsigned> set_loop(in_loop, in_loop+1);
- TraversingVisitor::visit(iter);
+ if(iter.condition)
+ iter.condition->visit(*this);
+ iter.body.visit(*this);
+ if(iter.loop_expression)
+ iter.loop_expression->visit(*this);
}
swap(loop_ext_refs, saved_refs);