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
43 ScopeType scope = GLOBAL;
44 InterfaceLayout *iface_layout = 0;
45 VariableDeclaration *iface_block = 0;
46 VariableDeclaration *variable = 0;
47 bool have_input_primitive = false;
48 bool have_output_primitive = false;
49 bool have_output_vertex_count = false;
50 bool have_workgroup_size = false;
53 void apply(Stage &, const Features &);
56 static const char *describe_variable(ScopeType);
58 virtual void visit(Layout &);
59 virtual void visit(InterfaceLayout &);
60 virtual void visit(BasicTypeDeclaration &);
61 virtual void visit(ImageTypeDeclaration &);
62 virtual void visit(StructDeclaration &);
63 virtual void visit(VariableDeclaration &);
64 virtual void visit(FunctionDeclaration &);
67 /** Verifies that identifiers are unique or, in the case of functions, are
68 overloaded only in valid ways. */
69 class IdentifierValidator: private Validator
72 typedef std::map<std::string, Statement *> BlockDeclarationMap;
74 std::map<Block *, BlockDeclarationMap> declarations;
75 std::map<std::string, VariableDeclaration *> interface_blocks;
76 std::map<std::string, FunctionDeclaration *> overloaded_functions;
77 bool anonymous_block = false;
80 void apply(Stage &s) { stage = &s; s.content.visit(*this); }
83 void multiple_definition(const std::string &, Statement &, Statement &);
84 Statement *find_definition(const std::string &);
85 void check_definition(const std::string &, Statement &);
86 void record_definition(const std::string &, Statement &);
88 virtual void visit(TypeDeclaration &);
89 virtual void visit(BasicTypeDeclaration &t) { visit(static_cast<TypeDeclaration &>(t)); }
90 virtual void visit(ImageTypeDeclaration &t) { visit(static_cast<TypeDeclaration &>(t)); }
91 virtual void visit(StructDeclaration &);
92 virtual void visit(VariableDeclaration &);
93 virtual void visit(FunctionDeclaration &);
96 /** Verifies that there are no unresolved references. */
97 class ReferenceValidator: private Validator
100 void apply(Stage &s) { stage = &s; s.content.visit(*this); }
103 virtual void visit(BasicTypeDeclaration &);
104 virtual void visit(ImageTypeDeclaration &);
105 virtual void visit(VariableReference &);
106 virtual void visit(MemberAccess &);
107 virtual void visit(FunctionCall &);
108 virtual void visit(VariableDeclaration &);
109 virtual void visit(FunctionDeclaration &);
112 /** Verifies that expressions are valid. In most cases an invalid expression
113 is indicated by a null result type. */
114 class ExpressionValidator: private Validator
124 FunctionDeclaration *current_function = 0;
125 bool in_struct = false;
126 ConstantKind constant_expression = NOT_CONSTANT;
129 void apply(Stage &s) { stage = &s; s.content.visit(*this); }
132 virtual void visit(VariableReference &);
133 virtual void visit(Swizzle &);
134 virtual void visit(UnaryExpression &);
135 virtual void visit(BinaryExpression &);
136 virtual void visit(Assignment &);
137 virtual void visit(TernaryExpression &);
138 virtual void visit(StructDeclaration &);
139 virtual void visit(VariableDeclaration &);
140 virtual void visit(FunctionDeclaration &);
141 virtual void visit(Conditional &);
142 virtual void visit(Iteration &);
143 virtual void visit(Return &);
146 /** Verifies flow control constructs. Functions returning non-void must have
147 return statements. Warnings are given about dead code. */
148 class FlowControlValidator: private Validator
151 bool reachable = true;
154 void apply(Stage &s) { stage = &s; s.content.visit(*this); }
157 virtual void visit(Block &);
158 virtual void visit(FunctionDeclaration &);
159 virtual void visit(Conditional &);
160 virtual void visit(Iteration &);
161 virtual void visit(Return &) { reachable = false; }
162 virtual void visit(Jump &) { reachable = false; }
165 /** Verifies that stage input and output interfaces are valid. Linked
166 variables must have matching types and locations and there must not be any
167 overlap in locations. */
168 class StageInterfaceValidator: private Validator
171 std::map<std::string, std::map<unsigned, VariableDeclaration *> > used_locations;
174 void apply(Stage &s) { stage = &s; s.content.visit(*this); }
177 virtual void visit(VariableDeclaration &);
178 virtual void visit(FunctionDeclaration &) { }
181 /** Verifies that uniform interfaces are valid across the entire module.
182 Variables declared with the same binding must have the same name and type. */
183 class GlobalInterfaceValidator: private Validator
189 TypeDeclaration *type = 0;
192 unsigned loc_count = 1;
197 std::list<Uniform> uniforms;
198 std::map<std::string, const Uniform *> used_names;
199 std::map<unsigned, const Uniform *> used_locations;
200 std::map<unsigned, std::map<unsigned, const Uniform *> > used_bindings;
203 void apply(Module &);
206 void check_uniform(const Uniform &);
208 virtual void visit(VariableDeclaration &);
209 virtual void visit(FunctionDeclaration &) { }