Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Copyright © 2010 Intel Corporation |
||
3 | * |
||
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
5 | * copy of this software and associated documentation files (the "Software"), |
||
6 | * to deal in the Software without restriction, including without limitation |
||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
8 | * and/or sell copies of the Software, and to permit persons to whom the |
||
9 | * Software is furnished to do so, subject to the following conditions: |
||
10 | * |
||
11 | * The above copyright notice and this permission notice (including the next |
||
12 | * paragraph) shall be included in all copies or substantial portions of the |
||
13 | * Software. |
||
14 | * |
||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||
21 | * DEALINGS IN THE SOFTWARE. |
||
22 | */ |
||
23 | |||
24 | /** |
||
25 | * \file ir_validate.cpp |
||
26 | * |
||
27 | * Attempts to verify that various invariants of the IR tree are true. |
||
28 | * |
||
29 | * In particular, at the moment it makes sure that no single |
||
30 | * ir_instruction node except for ir_variable appears multiple times |
||
31 | * in the ir tree. ir_variable does appear multiple times: Once as a |
||
32 | * declaration in an exec_list, and multiple times as the endpoint of |
||
33 | * a dereference chain. |
||
34 | */ |
||
35 | |||
36 | #include "ir.h" |
||
37 | #include "ir_hierarchical_visitor.h" |
||
38 | #include "program/hash_table.h" |
||
39 | #include "glsl_types.h" |
||
40 | |||
41 | class ir_validate : public ir_hierarchical_visitor { |
||
42 | public: |
||
43 | ir_validate() |
||
44 | { |
||
45 | this->ht = hash_table_ctor(0, hash_table_pointer_hash, |
||
46 | hash_table_pointer_compare); |
||
47 | |||
48 | this->current_function = NULL; |
||
49 | |||
50 | this->callback = ir_validate::validate_ir; |
||
51 | this->data = ht; |
||
52 | } |
||
53 | |||
54 | ~ir_validate() |
||
55 | { |
||
56 | hash_table_dtor(this->ht); |
||
57 | } |
||
58 | |||
59 | virtual ir_visitor_status visit(ir_variable *v); |
||
60 | virtual ir_visitor_status visit(ir_dereference_variable *ir); |
||
61 | |||
62 | virtual ir_visitor_status visit_enter(ir_if *ir); |
||
63 | |||
64 | virtual ir_visitor_status visit_leave(ir_loop *ir); |
||
65 | virtual ir_visitor_status visit_enter(ir_function *ir); |
||
66 | virtual ir_visitor_status visit_leave(ir_function *ir); |
||
67 | virtual ir_visitor_status visit_enter(ir_function_signature *ir); |
||
68 | |||
69 | virtual ir_visitor_status visit_leave(ir_expression *ir); |
||
70 | virtual ir_visitor_status visit_leave(ir_swizzle *ir); |
||
71 | |||
72 | virtual ir_visitor_status visit_enter(class ir_dereference_array *); |
||
73 | |||
74 | virtual ir_visitor_status visit_enter(ir_assignment *ir); |
||
75 | virtual ir_visitor_status visit_enter(ir_call *ir); |
||
76 | |||
77 | static void validate_ir(ir_instruction *ir, void *data); |
||
78 | |||
79 | ir_function *current_function; |
||
80 | |||
81 | struct hash_table *ht; |
||
82 | }; |
||
83 | |||
84 | |||
85 | ir_visitor_status |
||
86 | ir_validate::visit(ir_dereference_variable *ir) |
||
87 | { |
||
88 | if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) { |
||
89 | printf("ir_dereference_variable @ %p does not specify a variable %p\n", |
||
90 | (void *) ir, (void *) ir->var); |
||
91 | abort(); |
||
92 | } |
||
93 | |||
94 | if (hash_table_find(ht, ir->var) == NULL) { |
||
95 | printf("ir_dereference_variable @ %p specifies undeclared variable " |
||
96 | "`%s' @ %p\n", |
||
97 | (void *) ir, ir->var->name, (void *) ir->var); |
||
98 | abort(); |
||
99 | } |
||
100 | |||
101 | this->validate_ir(ir, this->data); |
||
102 | |||
103 | return visit_continue; |
||
104 | } |
||
105 | |||
106 | ir_visitor_status |
||
107 | ir_validate::visit_enter(class ir_dereference_array *ir) |
||
108 | { |
||
109 | if (!ir->array->type->is_array() && !ir->array->type->is_matrix()) { |
||
110 | printf("ir_dereference_array @ %p does not specify an array or a " |
||
111 | "matrix\n", |
||
112 | (void *) ir); |
||
113 | ir->print(); |
||
114 | printf("\n"); |
||
115 | abort(); |
||
116 | } |
||
117 | |||
118 | if (!ir->array_index->type->is_scalar()) { |
||
119 | printf("ir_dereference_array @ %p does not have scalar index: %s\n", |
||
120 | (void *) ir, ir->array_index->type->name); |
||
121 | abort(); |
||
122 | } |
||
123 | |||
124 | if (!ir->array_index->type->is_integer()) { |
||
125 | printf("ir_dereference_array @ %p does not have integer index: %s\n", |
||
126 | (void *) ir, ir->array_index->type->name); |
||
127 | abort(); |
||
128 | } |
||
129 | |||
130 | return visit_continue; |
||
131 | } |
||
132 | |||
133 | ir_visitor_status |
||
134 | ir_validate::visit_enter(ir_if *ir) |
||
135 | { |
||
136 | if (ir->condition->type != glsl_type::bool_type) { |
||
137 | printf("ir_if condition %s type instead of bool.\n", |
||
138 | ir->condition->type->name); |
||
139 | ir->print(); |
||
140 | printf("\n"); |
||
141 | abort(); |
||
142 | } |
||
143 | |||
144 | return visit_continue; |
||
145 | } |
||
146 | |||
147 | |||
148 | ir_visitor_status |
||
149 | ir_validate::visit_leave(ir_loop *ir) |
||
150 | { |
||
151 | if (ir->counter != NULL) { |
||
152 | if ((ir->from == NULL) || (ir->to == NULL) || (ir->increment == NULL)) { |
||
153 | printf("ir_loop has invalid loop controls:\n" |
||
154 | " counter: %p\n" |
||
155 | " from: %p\n" |
||
156 | " to: %p\n" |
||
157 | " increment: %p\n", |
||
158 | (void *) ir->counter, (void *) ir->from, (void *) ir->to, |
||
159 | (void *) ir->increment); |
||
160 | abort(); |
||
161 | } |
||
162 | |||
163 | if ((ir->cmp < ir_binop_less) || (ir->cmp > ir_binop_nequal)) { |
||
164 | printf("ir_loop has invalid comparitor %d\n", ir->cmp); |
||
165 | abort(); |
||
166 | } |
||
167 | } else { |
||
168 | if ((ir->from != NULL) || (ir->to != NULL) || (ir->increment != NULL)) { |
||
169 | printf("ir_loop has invalid loop controls:\n" |
||
170 | " counter: %p\n" |
||
171 | " from: %p\n" |
||
172 | " to: %p\n" |
||
173 | " increment: %p\n", |
||
174 | (void *) ir->counter, (void *) ir->from, (void *) ir->to, |
||
175 | (void *) ir->increment); |
||
176 | abort(); |
||
177 | } |
||
178 | } |
||
179 | |||
180 | return visit_continue; |
||
181 | } |
||
182 | |||
183 | |||
184 | ir_visitor_status |
||
185 | ir_validate::visit_enter(ir_function *ir) |
||
186 | { |
||
187 | /* Function definitions cannot be nested. |
||
188 | */ |
||
189 | if (this->current_function != NULL) { |
||
190 | printf("Function definition nested inside another function " |
||
191 | "definition:\n"); |
||
192 | printf("%s %p inside %s %p\n", |
||
193 | ir->name, (void *) ir, |
||
194 | this->current_function->name, (void *) this->current_function); |
||
195 | abort(); |
||
196 | } |
||
197 | |||
198 | /* Store the current function hierarchy being traversed. This is used |
||
199 | * by the function signature visitor to ensure that the signatures are |
||
200 | * linked with the correct functions. |
||
201 | */ |
||
202 | this->current_function = ir; |
||
203 | |||
204 | this->validate_ir(ir, this->data); |
||
205 | |||
206 | /* Verify that all of the things stored in the list of signatures are, |
||
207 | * in fact, function signatures. |
||
208 | */ |
||
209 | foreach_list(node, &ir->signatures) { |
||
210 | ir_instruction *sig = (ir_instruction *) node; |
||
211 | |||
212 | if (sig->ir_type != ir_type_function_signature) { |
||
213 | printf("Non-signature in signature list of function `%s'\n", |
||
214 | ir->name); |
||
215 | abort(); |
||
216 | } |
||
217 | } |
||
218 | |||
219 | return visit_continue; |
||
220 | } |
||
221 | |||
222 | ir_visitor_status |
||
223 | ir_validate::visit_leave(ir_function *ir) |
||
224 | { |
||
225 | assert(ralloc_parent(ir->name) == ir); |
||
226 | |||
227 | this->current_function = NULL; |
||
228 | return visit_continue; |
||
229 | } |
||
230 | |||
231 | ir_visitor_status |
||
232 | ir_validate::visit_enter(ir_function_signature *ir) |
||
233 | { |
||
234 | if (this->current_function != ir->function()) { |
||
235 | printf("Function signature nested inside wrong function " |
||
236 | "definition:\n"); |
||
237 | printf("%p inside %s %p instead of %s %p\n", |
||
238 | (void *) ir, |
||
239 | this->current_function->name, (void *) this->current_function, |
||
240 | ir->function_name(), (void *) ir->function()); |
||
241 | abort(); |
||
242 | } |
||
243 | |||
244 | if (ir->return_type == NULL) { |
||
245 | printf("Function signature %p for function %s has NULL return type.\n", |
||
246 | (void *) ir, ir->function_name()); |
||
247 | abort(); |
||
248 | } |
||
249 | |||
250 | this->validate_ir(ir, this->data); |
||
251 | |||
252 | return visit_continue; |
||
253 | } |
||
254 | |||
255 | ir_visitor_status |
||
256 | ir_validate::visit_leave(ir_expression *ir) |
||
257 | { |
||
258 | switch (ir->operation) { |
||
259 | case ir_unop_bit_not: |
||
260 | assert(ir->operands[0]->type == ir->type); |
||
261 | break; |
||
262 | case ir_unop_logic_not: |
||
263 | assert(ir->type->base_type == GLSL_TYPE_BOOL); |
||
264 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); |
||
265 | break; |
||
266 | |||
267 | case ir_unop_neg: |
||
268 | case ir_unop_abs: |
||
269 | case ir_unop_sign: |
||
270 | case ir_unop_rcp: |
||
271 | case ir_unop_rsq: |
||
272 | case ir_unop_sqrt: |
||
273 | assert(ir->type == ir->operands[0]->type); |
||
274 | break; |
||
275 | |||
276 | case ir_unop_exp: |
||
277 | case ir_unop_log: |
||
278 | case ir_unop_exp2: |
||
279 | case ir_unop_log2: |
||
280 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); |
||
281 | assert(ir->type == ir->operands[0]->type); |
||
282 | break; |
||
283 | |||
284 | case ir_unop_f2i: |
||
285 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); |
||
286 | assert(ir->type->base_type == GLSL_TYPE_INT); |
||
287 | break; |
||
288 | case ir_unop_f2u: |
||
289 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); |
||
290 | assert(ir->type->base_type == GLSL_TYPE_UINT); |
||
291 | break; |
||
292 | case ir_unop_i2f: |
||
293 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT); |
||
294 | assert(ir->type->base_type == GLSL_TYPE_FLOAT); |
||
295 | break; |
||
296 | case ir_unop_f2b: |
||
297 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); |
||
298 | assert(ir->type->base_type == GLSL_TYPE_BOOL); |
||
299 | break; |
||
300 | case ir_unop_b2f: |
||
301 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); |
||
302 | assert(ir->type->base_type == GLSL_TYPE_FLOAT); |
||
303 | break; |
||
304 | case ir_unop_i2b: |
||
305 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT); |
||
306 | assert(ir->type->base_type == GLSL_TYPE_BOOL); |
||
307 | break; |
||
308 | case ir_unop_b2i: |
||
309 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); |
||
310 | assert(ir->type->base_type == GLSL_TYPE_INT); |
||
311 | break; |
||
312 | case ir_unop_u2f: |
||
313 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT); |
||
314 | assert(ir->type->base_type == GLSL_TYPE_FLOAT); |
||
315 | break; |
||
316 | case ir_unop_i2u: |
||
317 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT); |
||
318 | assert(ir->type->base_type == GLSL_TYPE_UINT); |
||
319 | break; |
||
320 | case ir_unop_u2i: |
||
321 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT); |
||
322 | assert(ir->type->base_type == GLSL_TYPE_INT); |
||
323 | break; |
||
324 | case ir_unop_bitcast_i2f: |
||
325 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT); |
||
326 | assert(ir->type->base_type == GLSL_TYPE_FLOAT); |
||
327 | break; |
||
328 | case ir_unop_bitcast_f2i: |
||
329 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); |
||
330 | assert(ir->type->base_type == GLSL_TYPE_INT); |
||
331 | break; |
||
332 | case ir_unop_bitcast_u2f: |
||
333 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT); |
||
334 | assert(ir->type->base_type == GLSL_TYPE_FLOAT); |
||
335 | break; |
||
336 | case ir_unop_bitcast_f2u: |
||
337 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); |
||
338 | assert(ir->type->base_type == GLSL_TYPE_UINT); |
||
339 | break; |
||
340 | |||
341 | case ir_unop_any: |
||
342 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); |
||
343 | assert(ir->type == glsl_type::bool_type); |
||
344 | break; |
||
345 | |||
346 | case ir_unop_trunc: |
||
347 | case ir_unop_round_even: |
||
348 | case ir_unop_ceil: |
||
349 | case ir_unop_floor: |
||
350 | case ir_unop_fract: |
||
351 | case ir_unop_sin: |
||
352 | case ir_unop_cos: |
||
353 | case ir_unop_sin_reduced: |
||
354 | case ir_unop_cos_reduced: |
||
355 | case ir_unop_dFdx: |
||
356 | case ir_unop_dFdy: |
||
357 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); |
||
358 | assert(ir->operands[0]->type == ir->type); |
||
359 | break; |
||
360 | |||
361 | case ir_unop_pack_snorm_2x16: |
||
362 | case ir_unop_pack_unorm_2x16: |
||
363 | case ir_unop_pack_half_2x16: |
||
364 | assert(ir->type == glsl_type::uint_type); |
||
365 | assert(ir->operands[0]->type == glsl_type::vec2_type); |
||
366 | break; |
||
367 | |||
368 | case ir_unop_pack_snorm_4x8: |
||
369 | case ir_unop_pack_unorm_4x8: |
||
370 | assert(ir->type == glsl_type::uint_type); |
||
371 | assert(ir->operands[0]->type == glsl_type::vec4_type); |
||
372 | break; |
||
373 | |||
374 | case ir_unop_unpack_snorm_2x16: |
||
375 | case ir_unop_unpack_unorm_2x16: |
||
376 | case ir_unop_unpack_half_2x16: |
||
377 | assert(ir->type == glsl_type::vec2_type); |
||
378 | assert(ir->operands[0]->type == glsl_type::uint_type); |
||
379 | break; |
||
380 | |||
381 | case ir_unop_unpack_snorm_4x8: |
||
382 | case ir_unop_unpack_unorm_4x8: |
||
383 | assert(ir->type == glsl_type::vec4_type); |
||
384 | assert(ir->operands[0]->type == glsl_type::uint_type); |
||
385 | break; |
||
386 | |||
387 | case ir_unop_unpack_half_2x16_split_x: |
||
388 | case ir_unop_unpack_half_2x16_split_y: |
||
389 | assert(ir->type == glsl_type::float_type); |
||
390 | assert(ir->operands[0]->type == glsl_type::uint_type); |
||
391 | break; |
||
392 | |||
393 | case ir_unop_bitfield_reverse: |
||
394 | assert(ir->operands[0]->type == ir->type); |
||
395 | assert(ir->type->is_integer()); |
||
396 | break; |
||
397 | |||
398 | case ir_unop_bit_count: |
||
399 | case ir_unop_find_msb: |
||
400 | case ir_unop_find_lsb: |
||
401 | assert(ir->operands[0]->type->vector_elements == ir->type->vector_elements); |
||
402 | assert(ir->operands[0]->type->is_integer()); |
||
403 | assert(ir->type->base_type == GLSL_TYPE_INT); |
||
404 | break; |
||
405 | |||
406 | case ir_unop_noise: |
||
407 | /* XXX what can we assert here? */ |
||
408 | break; |
||
409 | |||
410 | case ir_binop_add: |
||
411 | case ir_binop_sub: |
||
412 | case ir_binop_mul: |
||
413 | case ir_binop_div: |
||
414 | case ir_binop_mod: |
||
415 | case ir_binop_min: |
||
416 | case ir_binop_max: |
||
417 | case ir_binop_pow: |
||
418 | if (ir->operands[0]->type->is_scalar()) |
||
419 | assert(ir->operands[1]->type == ir->type); |
||
420 | else if (ir->operands[1]->type->is_scalar()) |
||
421 | assert(ir->operands[0]->type == ir->type); |
||
422 | else if (ir->operands[0]->type->is_vector() && |
||
423 | ir->operands[1]->type->is_vector()) { |
||
424 | assert(ir->operands[0]->type == ir->operands[1]->type); |
||
425 | assert(ir->operands[0]->type == ir->type); |
||
426 | } |
||
427 | break; |
||
428 | |||
429 | case ir_binop_less: |
||
430 | case ir_binop_greater: |
||
431 | case ir_binop_lequal: |
||
432 | case ir_binop_gequal: |
||
433 | case ir_binop_equal: |
||
434 | case ir_binop_nequal: |
||
435 | /* The semantics of the IR operators differ from the GLSL <, >, <=, >=, |
||
436 | * ==, and != operators. The IR operators perform a component-wise |
||
437 | * comparison on scalar or vector types and return a boolean scalar or |
||
438 | * vector type of the same size. |
||
439 | */ |
||
440 | assert(ir->type->base_type == GLSL_TYPE_BOOL); |
||
441 | assert(ir->operands[0]->type == ir->operands[1]->type); |
||
442 | assert(ir->operands[0]->type->is_vector() |
||
443 | || ir->operands[0]->type->is_scalar()); |
||
444 | assert(ir->operands[0]->type->vector_elements |
||
445 | == ir->type->vector_elements); |
||
446 | break; |
||
447 | |||
448 | case ir_binop_all_equal: |
||
449 | case ir_binop_any_nequal: |
||
450 | /* GLSL == and != operate on scalars, vectors, matrices and arrays, and |
||
451 | * return a scalar boolean. The IR matches that. |
||
452 | */ |
||
453 | assert(ir->type == glsl_type::bool_type); |
||
454 | assert(ir->operands[0]->type == ir->operands[1]->type); |
||
455 | break; |
||
456 | |||
457 | case ir_binop_lshift: |
||
458 | case ir_binop_rshift: |
||
459 | assert(ir->operands[0]->type->is_integer() && |
||
460 | ir->operands[1]->type->is_integer()); |
||
461 | if (ir->operands[0]->type->is_scalar()) { |
||
462 | assert(ir->operands[1]->type->is_scalar()); |
||
463 | } |
||
464 | if (ir->operands[0]->type->is_vector() && |
||
465 | ir->operands[1]->type->is_vector()) { |
||
466 | assert(ir->operands[0]->type->components() == |
||
467 | ir->operands[1]->type->components()); |
||
468 | } |
||
469 | assert(ir->type == ir->operands[0]->type); |
||
470 | break; |
||
471 | |||
472 | case ir_binop_bit_and: |
||
473 | case ir_binop_bit_xor: |
||
474 | case ir_binop_bit_or: |
||
475 | assert(ir->operands[0]->type->base_type == |
||
476 | ir->operands[1]->type->base_type); |
||
477 | assert(ir->type->is_integer()); |
||
478 | if (ir->operands[0]->type->is_vector() && |
||
479 | ir->operands[1]->type->is_vector()) { |
||
480 | assert(ir->operands[0]->type->vector_elements == |
||
481 | ir->operands[1]->type->vector_elements); |
||
482 | } |
||
483 | break; |
||
484 | |||
485 | case ir_binop_logic_and: |
||
486 | case ir_binop_logic_xor: |
||
487 | case ir_binop_logic_or: |
||
488 | assert(ir->type == glsl_type::bool_type); |
||
489 | assert(ir->operands[0]->type == glsl_type::bool_type); |
||
490 | assert(ir->operands[1]->type == glsl_type::bool_type); |
||
491 | break; |
||
492 | |||
493 | case ir_binop_dot: |
||
494 | assert(ir->type == glsl_type::float_type); |
||
495 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); |
||
496 | assert(ir->operands[0]->type->is_vector()); |
||
497 | assert(ir->operands[0]->type == ir->operands[1]->type); |
||
498 | break; |
||
499 | |||
500 | case ir_binop_pack_half_2x16_split: |
||
501 | assert(ir->type == glsl_type::uint_type); |
||
502 | assert(ir->operands[0]->type == glsl_type::float_type); |
||
503 | assert(ir->operands[1]->type == glsl_type::float_type); |
||
504 | break; |
||
505 | |||
506 | case ir_binop_bfm: |
||
507 | assert(ir->type->is_integer()); |
||
508 | assert(ir->operands[0]->type->is_integer()); |
||
509 | assert(ir->operands[1]->type->is_integer()); |
||
510 | break; |
||
511 | |||
512 | case ir_binop_ubo_load: |
||
513 | assert(ir->operands[0]->as_constant()); |
||
514 | assert(ir->operands[0]->type == glsl_type::uint_type); |
||
515 | |||
516 | assert(ir->operands[1]->type == glsl_type::uint_type); |
||
517 | break; |
||
518 | |||
519 | case ir_binop_vector_extract: |
||
520 | assert(ir->operands[0]->type->is_vector()); |
||
521 | assert(ir->operands[1]->type->is_scalar() |
||
522 | && ir->operands[1]->type->is_integer()); |
||
523 | break; |
||
524 | |||
525 | case ir_triop_lrp: |
||
526 | assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); |
||
527 | assert(ir->operands[0]->type == ir->operands[1]->type); |
||
528 | assert(ir->operands[2]->type == ir->operands[0]->type || ir->operands[2]->type == glsl_type::float_type); |
||
529 | break; |
||
530 | |||
531 | case ir_triop_bfi: |
||
532 | assert(ir->operands[0]->type->is_integer()); |
||
533 | assert(ir->operands[1]->type == ir->operands[2]->type); |
||
534 | assert(ir->operands[1]->type == ir->type); |
||
535 | break; |
||
536 | |||
537 | case ir_triop_bitfield_extract: |
||
538 | assert(ir->operands[0]->type == ir->type); |
||
539 | assert(ir->operands[1]->type == glsl_type::int_type); |
||
540 | assert(ir->operands[2]->type == glsl_type::int_type); |
||
541 | break; |
||
542 | |||
543 | case ir_triop_vector_insert: |
||
544 | assert(ir->operands[0]->type->is_vector()); |
||
545 | assert(ir->operands[1]->type->is_scalar()); |
||
546 | assert(ir->operands[0]->type->base_type == ir->operands[1]->type->base_type); |
||
547 | assert(ir->operands[2]->type->is_scalar() |
||
548 | && ir->operands[2]->type->is_integer()); |
||
549 | assert(ir->type == ir->operands[0]->type); |
||
550 | break; |
||
551 | |||
552 | case ir_quadop_bitfield_insert: |
||
553 | assert(ir->operands[0]->type == ir->type); |
||
554 | assert(ir->operands[1]->type == ir->type); |
||
555 | assert(ir->operands[2]->type == glsl_type::int_type); |
||
556 | assert(ir->operands[3]->type == glsl_type::int_type); |
||
557 | break; |
||
558 | |||
559 | case ir_quadop_vector: |
||
560 | /* The vector operator collects some number of scalars and generates a |
||
561 | * vector from them. |
||
562 | * |
||
563 | * - All of the operands must be scalar. |
||
564 | * - Number of operands must matche the size of the resulting vector. |
||
565 | * - Base type of the operands must match the base type of the result. |
||
566 | */ |
||
567 | assert(ir->type->is_vector()); |
||
568 | switch (ir->type->vector_elements) { |
||
569 | case 2: |
||
570 | assert(ir->operands[0]->type->is_scalar()); |
||
571 | assert(ir->operands[0]->type->base_type == ir->type->base_type); |
||
572 | assert(ir->operands[1]->type->is_scalar()); |
||
573 | assert(ir->operands[1]->type->base_type == ir->type->base_type); |
||
574 | assert(ir->operands[2] == NULL); |
||
575 | assert(ir->operands[3] == NULL); |
||
576 | break; |
||
577 | case 3: |
||
578 | assert(ir->operands[0]->type->is_scalar()); |
||
579 | assert(ir->operands[0]->type->base_type == ir->type->base_type); |
||
580 | assert(ir->operands[1]->type->is_scalar()); |
||
581 | assert(ir->operands[1]->type->base_type == ir->type->base_type); |
||
582 | assert(ir->operands[2]->type->is_scalar()); |
||
583 | assert(ir->operands[2]->type->base_type == ir->type->base_type); |
||
584 | assert(ir->operands[3] == NULL); |
||
585 | break; |
||
586 | case 4: |
||
587 | assert(ir->operands[0]->type->is_scalar()); |
||
588 | assert(ir->operands[0]->type->base_type == ir->type->base_type); |
||
589 | assert(ir->operands[1]->type->is_scalar()); |
||
590 | assert(ir->operands[1]->type->base_type == ir->type->base_type); |
||
591 | assert(ir->operands[2]->type->is_scalar()); |
||
592 | assert(ir->operands[2]->type->base_type == ir->type->base_type); |
||
593 | assert(ir->operands[3]->type->is_scalar()); |
||
594 | assert(ir->operands[3]->type->base_type == ir->type->base_type); |
||
595 | break; |
||
596 | default: |
||
597 | /* The is_vector assertion above should prevent execution from ever |
||
598 | * getting here. |
||
599 | */ |
||
600 | assert(!"Should not get here."); |
||
601 | break; |
||
602 | } |
||
603 | } |
||
604 | |||
605 | return visit_continue; |
||
606 | } |
||
607 | |||
608 | ir_visitor_status |
||
609 | ir_validate::visit_leave(ir_swizzle *ir) |
||
610 | { |
||
611 | unsigned int chans[4] = {ir->mask.x, ir->mask.y, ir->mask.z, ir->mask.w}; |
||
612 | |||
613 | for (unsigned int i = 0; i < ir->type->vector_elements; i++) { |
||
614 | if (chans[i] >= ir->val->type->vector_elements) { |
||
615 | printf("ir_swizzle @ %p specifies a channel not present " |
||
616 | "in the value.\n", (void *) ir); |
||
617 | ir->print(); |
||
618 | abort(); |
||
619 | } |
||
620 | } |
||
621 | |||
622 | return visit_continue; |
||
623 | } |
||
624 | |||
625 | ir_visitor_status |
||
626 | ir_validate::visit(ir_variable *ir) |
||
627 | { |
||
628 | /* An ir_variable is the one thing that can (and will) appear multiple times |
||
629 | * in an IR tree. It is added to the hashtable so that it can be used |
||
630 | * in the ir_dereference_variable handler to ensure that a variable is |
||
631 | * declared before it is dereferenced. |
||
632 | */ |
||
633 | if (ir->name) |
||
634 | assert(ralloc_parent(ir->name) == ir); |
||
635 | |||
636 | hash_table_insert(ht, ir, ir); |
||
637 | |||
638 | |||
639 | /* If a variable is an array, verify that the maximum array index is in |
||
640 | * bounds. There was once an error in AST-to-HIR conversion that set this |
||
641 | * to be out of bounds. |
||
642 | */ |
||
643 | if (ir->type->array_size() > 0) { |
||
644 | if (ir->max_array_access >= ir->type->length) { |
||
645 | printf("ir_variable has maximum access out of bounds (%d vs %d)\n", |
||
646 | ir->max_array_access, ir->type->length - 1); |
||
647 | ir->print(); |
||
648 | abort(); |
||
649 | } |
||
650 | } |
||
651 | |||
652 | if (ir->constant_initializer != NULL && !ir->has_initializer) { |
||
653 | printf("ir_variable didn't have an initializer, but has a constant " |
||
654 | "initializer value.\n"); |
||
655 | ir->print(); |
||
656 | abort(); |
||
657 | } |
||
658 | |||
659 | return visit_continue; |
||
660 | } |
||
661 | |||
662 | ir_visitor_status |
||
663 | ir_validate::visit_enter(ir_assignment *ir) |
||
664 | { |
||
665 | const ir_dereference *const lhs = ir->lhs; |
||
666 | if (lhs->type->is_scalar() || lhs->type->is_vector()) { |
||
667 | if (ir->write_mask == 0) { |
||
668 | printf("Assignment LHS is %s, but write mask is 0:\n", |
||
669 | lhs->type->is_scalar() ? "scalar" : "vector"); |
||
670 | ir->print(); |
||
671 | abort(); |
||
672 | } |
||
673 | |||
674 | int lhs_components = 0; |
||
675 | for (int i = 0; i < 4; i++) { |
||
676 | if (ir->write_mask & (1 << i)) |
||
677 | lhs_components++; |
||
678 | } |
||
679 | |||
680 | if (lhs_components != ir->rhs->type->vector_elements) { |
||
681 | printf("Assignment count of LHS write mask channels enabled not\n" |
||
682 | "matching RHS vector size (%d LHS, %d RHS).\n", |
||
683 | lhs_components, ir->rhs->type->vector_elements); |
||
684 | ir->print(); |
||
685 | abort(); |
||
686 | } |
||
687 | } |
||
688 | |||
689 | this->validate_ir(ir, this->data); |
||
690 | |||
691 | return visit_continue; |
||
692 | } |
||
693 | |||
694 | ir_visitor_status |
||
695 | ir_validate::visit_enter(ir_call *ir) |
||
696 | { |
||
697 | ir_function_signature *const callee = ir->callee; |
||
698 | |||
699 | if (callee->ir_type != ir_type_function_signature) { |
||
700 | printf("IR called by ir_call is not ir_function_signature!\n"); |
||
701 | abort(); |
||
702 | } |
||
703 | |||
704 | if (ir->return_deref) { |
||
705 | if (ir->return_deref->type != callee->return_type) { |
||
706 | printf("callee type %s does not match return storage type %s\n", |
||
707 | callee->return_type->name, ir->return_deref->type->name); |
||
708 | abort(); |
||
709 | } |
||
710 | } else if (callee->return_type != glsl_type::void_type) { |
||
711 | printf("ir_call has non-void callee but no return storage\n"); |
||
712 | abort(); |
||
713 | } |
||
714 | |||
715 | const exec_node *formal_param_node = callee->parameters.head; |
||
716 | const exec_node *actual_param_node = ir->actual_parameters.head; |
||
717 | while (true) { |
||
718 | if (formal_param_node->is_tail_sentinel() |
||
719 | != actual_param_node->is_tail_sentinel()) { |
||
720 | printf("ir_call has the wrong number of parameters:\n"); |
||
721 | goto dump_ir; |
||
722 | } |
||
723 | if (formal_param_node->is_tail_sentinel()) { |
||
724 | break; |
||
725 | } |
||
726 | const ir_variable *formal_param |
||
727 | = (const ir_variable *) formal_param_node; |
||
728 | const ir_rvalue *actual_param |
||
729 | = (const ir_rvalue *) actual_param_node; |
||
730 | if (formal_param->type != actual_param->type) { |
||
731 | printf("ir_call parameter type mismatch:\n"); |
||
732 | goto dump_ir; |
||
733 | } |
||
734 | if (formal_param->mode == ir_var_function_out |
||
735 | || formal_param->mode == ir_var_function_inout) { |
||
736 | if (!actual_param->is_lvalue()) { |
||
737 | printf("ir_call out/inout parameters must be lvalues:\n"); |
||
738 | goto dump_ir; |
||
739 | } |
||
740 | } |
||
741 | formal_param_node = formal_param_node->next; |
||
742 | actual_param_node = actual_param_node->next; |
||
743 | } |
||
744 | |||
745 | return visit_continue; |
||
746 | |||
747 | dump_ir: |
||
748 | ir->print(); |
||
749 | printf("callee:\n"); |
||
750 | callee->print(); |
||
751 | abort(); |
||
752 | return visit_stop; |
||
753 | } |
||
754 | |||
755 | void |
||
756 | ir_validate::validate_ir(ir_instruction *ir, void *data) |
||
757 | { |
||
758 | struct hash_table *ht = (struct hash_table *) data; |
||
759 | |||
760 | if (hash_table_find(ht, ir)) { |
||
761 | printf("Instruction node present twice in ir tree:\n"); |
||
762 | ir->print(); |
||
763 | printf("\n"); |
||
764 | abort(); |
||
765 | } |
||
766 | hash_table_insert(ht, ir, ir); |
||
767 | } |
||
768 | |||
769 | void |
||
770 | check_node_type(ir_instruction *ir, void *data) |
||
771 | { |
||
772 | (void) data; |
||
773 | |||
774 | if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) { |
||
775 | printf("Instruction node with unset type\n"); |
||
776 | ir->print(); printf("\n"); |
||
777 | } |
||
778 | ir_rvalue *value = ir->as_rvalue(); |
||
779 | if (value != NULL) |
||
780 | assert(value->type != glsl_type::error_type); |
||
781 | } |
||
782 | |||
783 | void |
||
784 | validate_ir_tree(exec_list *instructions) |
||
785 | { |
||
786 | /* We shouldn't have any reason to validate IR in a release build, |
||
787 | * and it's half composed of assert()s anyway which wouldn't do |
||
788 | * anything. |
||
789 | */ |
||
790 | #ifdef DEBUG |
||
791 | ir_validate v; |
||
792 | |||
793 | v.run(instructions); |
||
794 | |||
795 | foreach_iter(exec_list_iterator, iter, *instructions) { |
||
796 | ir_instruction *ir = (ir_instruction *)iter.get(); |
||
797 | |||
798 | visit_tree(ir, check_node_type, NULL); |
||
799 | } |
||
800 | #endif |
||
801 | }=>><>>>=,>,>> |