1 #ifndef MSP_GL_SL_VALIDATE_H_
2 #define MSP_GL_SL_VALIDATE_H_
6 #include "glsl_error.h"
13 /** Base class for validators. Contains some utilities for adding diagnostic
15 class Validator: protected TraversingVisitor
19 Node *last_provoker = 0;
21 Validator() = default;
23 void diagnose(Node &, Node &, Diagnostic::Severity, const std::string &);
24 void diagnose(Node &n, Diagnostic::Severity s, const std::string &m) { diagnose(n, n, s, m); }
25 void error(Node &n, const std::string &m) { diagnose(n, Diagnostic::ERR, m); }
26 void add_info(Node &, const std::string &);
29 /** Verifies that declarations are valid in isolation. */
30 class DeclarationValidator: private Validator
42 ScopeType scope = GLOBAL;
43 InterfaceLayout *iface_layout = 0;
44 InterfaceBlock *iface_block = 0;
45 VariableDeclaration *variable = 0;
48 void apply(Stage &s) { stage = &s; s.content.visit(*this); }
51 static const char *describe_variable(ScopeType);
53 virtual void visit(Layout &);
54 virtual void visit(InterfaceLayout &);
55 virtual void visit(BasicTypeDeclaration &);
56 virtual void visit(ImageTypeDeclaration &);
57 virtual void visit(StructDeclaration &);
58 virtual void visit(VariableDeclaration &);
59 virtual void visit(InterfaceBlock &);
60 virtual void visit(FunctionDeclaration &);
63 /** Verifies that identifiers are unique or, in the case of functions, are
64 overloaded only in valid ways. */
65 class IdentifierValidator: private Validator
68 typedef std::map<std::string, Statement *> BlockDeclarationMap;
70 std::map<Block *, BlockDeclarationMap> declarations;
71 std::map<std::string, InterfaceBlock *> interface_blocks;
72 std::map<std::string, FunctionDeclaration *> overloaded_functions;
73 bool anonymous_block = false;
76 void apply(Stage &s) { stage = &s; s.content.visit(*this); }
79 void multiple_definition(const std::string &, Statement &, Statement &);
80 Statement *find_definition(const std::string &);
81 void check_definition(const std::string &, Statement &);
82 void record_definition(const std::string &, Statement &);
84 virtual void visit(TypeDeclaration &);
85 virtual void visit(BasicTypeDeclaration &t) { visit(static_cast<TypeDeclaration &>(t)); }
86 virtual void visit(ImageTypeDeclaration &t) { visit(static_cast<TypeDeclaration &>(t)); }
87 virtual void visit(StructDeclaration &);
88 virtual void visit(VariableDeclaration &);
89 virtual void visit(InterfaceBlock &);
90 virtual void visit(FunctionDeclaration &);
93 /** Verifies that there are no unresolved references. */
94 class ReferenceValidator: private Validator
97 void apply(Stage &s) { stage = &s; s.content.visit(*this); }
100 virtual void visit(BasicTypeDeclaration &);
101 virtual void visit(ImageTypeDeclaration &);
102 virtual void visit(VariableReference &);
103 virtual void visit(MemberAccess &);
104 virtual void visit(InterfaceBlockReference &);
105 virtual void visit(FunctionCall &);
106 virtual void visit(VariableDeclaration &);
107 virtual void visit(InterfaceBlock &);
108 virtual void visit(FunctionDeclaration &);
111 /** Verifies that expressions are valid. In most cases an invalid expression
112 is indicated by a null result type. */
113 class ExpressionValidator: private Validator
116 FunctionDeclaration *current_function = 0;
117 bool constant_expression = false;
120 void apply(Stage &s) { stage = &s; s.content.visit(*this); }
123 virtual void visit(VariableReference &);
124 virtual void visit(InterfaceBlockReference &);
125 virtual void visit(Swizzle &);
126 virtual void visit(UnaryExpression &);
127 virtual void visit(BinaryExpression &);
128 virtual void visit(Assignment &);
129 virtual void visit(TernaryExpression &);
130 virtual void visit(VariableDeclaration &);
131 virtual void visit(FunctionDeclaration &);
132 virtual void visit(Conditional &);
133 virtual void visit(Iteration &);
134 virtual void visit(Return &);
137 /** Verifies flow control constructs. Functions returning non-void must have
138 return statements. Warnings are given about dead code. */
139 class FlowControlValidator: private Validator
142 bool reachable = true;
145 void apply(Stage &s) { stage = &s; s.content.visit(*this); }
148 virtual void visit(Block &);
149 virtual void visit(FunctionDeclaration &);
150 virtual void visit(Conditional &);
151 virtual void visit(Iteration &);
152 virtual void visit(Return &) { reachable = false; }
153 virtual void visit(Jump &) { reachable = false; }
156 /** Verifies that stage input and output interfaces are valid. Linked
157 variables must have matching types and locations and there must not be any
158 overlap in locations. */
159 class StageInterfaceValidator: private Validator
162 std::map<std::string, std::map<unsigned, VariableDeclaration *> > used_locations;
165 void apply(Stage &s) { stage = &s; s.content.visit(*this); }
168 int get_location(const Layout &);
170 virtual void visit(VariableDeclaration &);
171 virtual void visit(FunctionDeclaration &) { }
174 /** Verifies that uniform interfaces are valid across the entire module.
175 Variables declared with the same binding must have the same name and type. */
176 class GlobalInterfaceValidator: private Validator
182 TypeDeclaration *type = 0;
185 unsigned loc_count = 1;
190 std::list<Uniform> uniforms;
191 std::map<std::string, const Uniform *> used_names;
192 std::map<unsigned, const Uniform *> used_locations;
193 std::map<unsigned, std::map<unsigned, const Uniform *> > used_bindings;
196 void apply(Module &);
199 void check_uniform(const Uniform &);
201 virtual void visit(VariableDeclaration &);
202 virtual void visit(InterfaceBlock &);
203 virtual void visit(FunctionDeclaration &) { }