annotated_branch(text, *memacc.left);
}
+void DumpTree::visit(Swizzle &swizzle)
+{
+ static const char components[4] = { 'x', 'y', 'z', 'w' };
+ string text = "Swizzle: .";
+ for(unsigned i=0; i<swizzle.count; ++i)
+ text += components[swizzle.components[i]];
+ text += format(" -> %s", format_type(swizzle.type));
+ annotated_branch(text, *swizzle.left);
+}
+
void DumpTree::visit(UnaryExpression &unary)
{
string text = format("Unary: %s, %sfix -> %s", unary.oper->token, (unary.oper->type==Operator::PREFIX ? "pre" : "post"), format_type(unary.type));
virtual void visit(VariableReference &);
virtual void visit(InterfaceBlockReference &);
virtual void visit(MemberAccess &);
+ virtual void visit(Swizzle &);
virtual void visit(UnaryExpression &);
virtual void visit(BinaryExpression &);
virtual void visit(Assignment &);
+#include <algorithm>
#include <msp/core/hash.h>
#include <msp/core/raii.h>
#include <msp/strings/lexicalcast.h>
if(i!=strct->members.variables.end())
declaration = i->second;
}
+ else if(BasicTypeDeclaration *basic = dynamic_cast<BasicTypeDeclaration *>(memacc.left->type))
+ {
+ bool scalar_swizzle = ((basic->kind==BasicTypeDeclaration::INT || basic->kind==BasicTypeDeclaration::FLOAT) && memacc.member.size()==1);
+ bool vector_swizzle = (basic->kind==BasicTypeDeclaration::VECTOR && memacc.member.size()<=4);
+ if(scalar_swizzle || vector_swizzle)
+ {
+ static const char component_names[] = { 'x', 'r', 's', 'y', 'g', 't', 'z', 'b', 'p', 'w', 'a', 'q' };
+
+ bool ok = true;
+ UInt8 components[4] = { };
+ for(unsigned i=0; (ok && i<memacc.member.size()); ++i)
+ ok = ((components[i] = (find(component_names, component_names+12, memacc.member[i])-component_names)/3) < 4);
+
+ if(ok)
+ {
+ Swizzle *swizzle = new Swizzle;
+ swizzle->source = memacc.source;
+ swizzle->line = memacc.line;
+ swizzle->oper = memacc.oper;
+ swizzle->left = memacc.left;
+ swizzle->component_group = memacc.member;
+ swizzle->count = memacc.member.size();
+ copy(components, components+memacc.member.size(), swizzle->components);
+ r_replacement_expr = swizzle;
+ }
+ }
+ }
r_any_resolved |= (declaration!=memacc.declaration);
memacc.declaration = declaration;
}
+void VariableResolver::visit(Swizzle &swizzle)
+{
+ visit_and_replace(swizzle.left);
+}
+
void VariableResolver::visit(UnaryExpression &unary)
{
visit_and_replace(unary.expression);
resolve(memacc, memacc.declaration->type_declaration, memacc.left->lvalue);
}
+void ExpressionResolver::visit(Swizzle &swizzle)
+{
+ TraversingVisitor::visit(swizzle);
+
+ if(BasicTypeDeclaration *left_basic = dynamic_cast<BasicTypeDeclaration *>(swizzle.left->type))
+ {
+ BasicTypeDeclaration *left_elem = get_element_type(*left_basic);
+ if(swizzle.count==1)
+ resolve(swizzle, left_elem, swizzle.left->lvalue);
+ else if(left_basic->kind==BasicTypeDeclaration::VECTOR && left_elem)
+ resolve(swizzle, find_type(*left_elem, left_basic->kind, swizzle.count), swizzle.left->lvalue);
+ }
+}
+
void ExpressionResolver::visit(UnaryExpression &unary)
{
TraversingVisitor::visit(unary);
virtual void visit(VariableReference &);
virtual void visit(InterfaceBlockReference &);
virtual void visit(MemberAccess &);
+ virtual void visit(Swizzle &);
virtual void visit(UnaryExpression &);
virtual void visit(BinaryExpression &);
virtual void visit(Assignment &);
virtual void visit(VariableReference &);
virtual void visit(InterfaceBlockReference &);
virtual void visit(MemberAccess &);
+ virtual void visit(Swizzle &);
virtual void visit(UnaryExpression &);
void visit(BinaryExpression &, bool);
virtual void visit(BinaryExpression &);
visit_and_inline(memacc.left);
}
+void FunctionInliner::visit(Swizzle &swizzle)
+{
+ visit_and_inline(swizzle.left);
+}
+
void FunctionInliner::visit(FunctionCall &call)
{
for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
r_trivial = false;
}
+void ExpressionInliner::visit(Swizzle &swizzle)
+{
+ visit_and_record(swizzle.left, swizzle.oper, false);
+ r_oper = swizzle.oper;
+ r_trivial = false;
+}
+
void ExpressionInliner::visit(UnaryExpression &unary)
{
SetFlag set_target(mutating, mutating || unary.oper->token[1]=='+' || unary.oper->token[1]=='-');
unused_nodes.erase(memacc.declaration);
}
+void UnusedVariableRemover::visit(Swizzle &swizzle)
+{
+ if(assignment_target)
+ r_assign_to_subfield = true;
+ TraversingVisitor::visit(swizzle);
+}
+
void UnusedVariableRemover::visit(UnaryExpression &unary)
{
TraversingVisitor::visit(unary);
virtual void visit(BinaryExpression &);
virtual void visit(Assignment &a) { visit(static_cast<BinaryExpression &>(a)); }
virtual void visit(MemberAccess &);
+ virtual void visit(Swizzle &);
virtual void visit(FunctionCall &);
virtual void visit(ExpressionStatement &);
virtual void visit(VariableDeclaration &);
virtual void visit(Block &);
virtual void visit(VariableReference &);
virtual void visit(MemberAccess &);
+ virtual void visit(Swizzle &);
virtual void visit(UnaryExpression &);
virtual void visit(BinaryExpression &);
virtual void visit(Assignment &);
virtual void visit(VariableReference &);
virtual void visit(InterfaceBlockReference &);
virtual void visit(MemberAccess &);
+ virtual void visit(Swizzle &);
virtual void visit(UnaryExpression &);
virtual void visit(BinaryExpression &);
virtual void visit(Assignment &);
append(format(".%s", memacc.member));
}
+void Formatter::visit(Swizzle &swizzle)
+{
+ swizzle.left->visit(*this);
+ append(format(".%s", swizzle.component_group));
+}
+
void Formatter::visit(UnaryExpression &unary)
{
if(unary.oper->type==Operator::PREFIX)
virtual void visit(VariableReference &);
virtual void visit(InterfaceBlockReference &);
virtual void visit(MemberAccess &);
+ virtual void visit(Swizzle &);
virtual void visit(UnaryExpression &);
virtual void visit(BinaryExpression &);
virtual void visit(Assignment &);
}
+Swizzle::Swizzle():
+ count(0)
+{
+ fill(components, components+4, 0);
+}
+
+void Swizzle::visit(NodeVisitor &visitor)
+{
+ visitor.visit(*this);
+}
+
+
void UnaryExpression::visit(NodeVisitor &visitor)
{
visitor.visit(*this);
#include <set>
#include <string>
#include <vector>
+#include <msp/core/inttypes.h>
#include <msp/core/refptr.h>
#include <msp/core/variant.h>
#include "features.h"
virtual void visit(NodeVisitor &);
};
+struct Swizzle: Expression
+{
+ NodePtr<Expression> left;
+ std::string component_group;
+ unsigned count;
+ UInt8 components[4];
+
+ Swizzle();
+
+ virtual Swizzle *clone() const { return new Swizzle(*this); }
+ virtual void visit(NodeVisitor &);
+};
+
struct UnaryExpression: Expression
{
NodePtr<Expression> expression;
+#include <algorithm>
#include <cstring>
#include <msp/core/raii.h>
#include <msp/strings/format.h>
}
+void ExpressionValidator::visit(Swizzle &swizzle)
+{
+ unsigned size = 0;
+ if(BasicTypeDeclaration *basic = dynamic_cast<BasicTypeDeclaration *>(swizzle.left->type))
+ {
+ if(basic->kind==BasicTypeDeclaration::INT || basic->kind==BasicTypeDeclaration::FLOAT)
+ size = 1;
+ else if(basic->kind==BasicTypeDeclaration::VECTOR)
+ size = basic->size;
+ }
+
+ if(size)
+ {
+ static const char component_names[] = { 'x', 'y', 'z', 'w', 'r', 'g', 'b', 'a', 's', 't', 'p', 'q' };
+ int flavour = -1;
+ for(unsigned i=0; i<swizzle.count; ++i)
+ {
+ unsigned component_flavour = (find(component_names, component_names+12, swizzle.component_group[i])-component_names)/4;
+ if(flavour==-1)
+ flavour = component_flavour;
+ else if(flavour>=0 && component_flavour!=static_cast<unsigned>(flavour))
+ {
+ error(swizzle, format("Flavour of swizzle component '%c' is inconsistent with '%c'",
+ swizzle.component_group[i], swizzle.component_group[0]));
+ flavour = -2;
+ }
+
+ if(swizzle.components[i]>=size)
+ error(swizzle, format("Access to component '%c' which is not present in '%s'",
+ swizzle.component_group[i], swizzle.left->type->name));
+ }
+ }
+ else if(swizzle.left->type)
+ error(swizzle, format("Swizzle applied to '%s' which is neither a scalar nor a vector", swizzle.left->type->name));
+
+ TraversingVisitor::visit(swizzle);
+}
+
void ExpressionValidator::visit(UnaryExpression &unary)
{
if(unary.expression->type)
void apply(Stage &s) { stage = &s; s.content.visit(*this); }
private:
+ virtual void visit(Swizzle &);
virtual void visit(UnaryExpression &);
virtual void visit(BinaryExpression &);
virtual void visit(Assignment &);
memacc.left->visit(*this);
}
+void TraversingVisitor::visit(Swizzle &swizzle)
+{
+ swizzle.left->visit(*this);
+}
+
void TraversingVisitor::visit(UnaryExpression &unary)
{
unary.expression->visit(*this);
virtual void visit(VariableReference &) { }
virtual void visit(InterfaceBlockReference &) { }
virtual void visit(MemberAccess &) { }
+ virtual void visit(Swizzle &) { }
virtual void visit(UnaryExpression &) { }
virtual void visit(BinaryExpression &) { }
virtual void visit(Assignment &) { }
virtual void visit(Block &);
virtual void visit(ParenthesizedExpression &);
virtual void visit(MemberAccess &);
+ virtual void visit(Swizzle &);
virtual void visit(UnaryExpression &);
virtual void visit(BinaryExpression &);
virtual void visit(Assignment &);
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in vec2 texcoord;
+void main()
+{
+ vec2 bad_component = texcoord.xz;
+ vec4 mixed = position.xyba;
+ gl_Position = position.xyzwx.xyzw;
+}
+
+/* Expected error:
+<test>:6: Access to component 'z' which is not present in 'vec2'
+<test>:7: Flavour of swizzle component 'b' is inconsistent with 'x'
+<test>:8: Use of undeclared member 'xyzwx'
+*/