Merge remote branch 'origin/nv50-compiler'
[profile/ivi/mesa.git] / src / glsl / ir_validate.cpp
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 <inttypes.h>
37 #include "ir.h"
38 #include "ir_hierarchical_visitor.h"
39 #include "program/hash_table.h"
40 #include "glsl_types.h"
41
42 class ir_validate : public ir_hierarchical_visitor {
43 public:
44    ir_validate()
45    {
46       this->ht = hash_table_ctor(0, hash_table_pointer_hash,
47                                  hash_table_pointer_compare);
48
49       this->current_function = NULL;
50
51       this->callback = ir_validate::validate_ir;
52       this->data = ht;
53    }
54
55    ~ir_validate()
56    {
57       hash_table_dtor(this->ht);
58    }
59
60    virtual ir_visitor_status visit(ir_variable *v);
61    virtual ir_visitor_status visit(ir_dereference_variable *ir);
62    virtual ir_visitor_status visit(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
71    virtual ir_visitor_status visit_enter(ir_assignment *ir);
72
73    static void validate_ir(ir_instruction *ir, void *data);
74
75    ir_function *current_function;
76
77    struct hash_table *ht;
78 };
79
80
81 ir_visitor_status
82 ir_validate::visit(ir_dereference_variable *ir)
83 {
84    if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) {
85       printf("ir_dereference_variable @ %p does not specify a variable %p\n",
86              (void *) ir, (void *) ir->var);
87       abort();
88    }
89
90    if (hash_table_find(ht, ir->var) == NULL) {
91       printf("ir_dereference_variable @ %p specifies undeclared variable "
92              "`%s' @ %p\n",
93              (void *) ir, ir->var->name, (void *) ir->var);
94       abort();
95    }
96
97    this->validate_ir(ir, this->data);
98
99    return visit_continue;
100 }
101
102 ir_visitor_status
103 ir_validate::visit(ir_if *ir)
104 {
105    if (ir->condition->type != glsl_type::bool_type) {
106       printf("ir_if condition %s type instead of bool.\n",
107              ir->condition->type->name);
108       ir->print();
109       printf("\n");
110       abort();
111    }
112
113    return visit_continue;
114 }
115
116
117 ir_visitor_status
118 ir_validate::visit_leave(ir_loop *ir)
119 {
120    if (ir->counter != NULL) {
121       if ((ir->from == NULL) || (ir->from == NULL) || (ir->increment == NULL)) {
122          printf("ir_loop has invalid loop controls:\n"
123                 "    counter:   %p\n"
124                 "    from:      %p\n"
125                 "    to:        %p\n"
126                 "    increment: %p\n",
127                 ir->counter, ir->from, ir->to, ir->increment);
128          abort();
129       }
130
131       if ((ir->cmp < ir_binop_less) || (ir->cmp > ir_binop_nequal)) {
132          printf("ir_loop has invalid comparitor %d\n", ir->cmp);
133          abort();
134       }
135    } else {
136       if ((ir->from != NULL) || (ir->from != NULL) || (ir->increment != NULL)) {
137          printf("ir_loop has invalid loop controls:\n"
138                 "    counter:   %p\n"
139                 "    from:      %p\n"
140                 "    to:        %p\n"
141                 "    increment: %p\n",
142                 ir->counter, ir->from, ir->to, ir->increment);
143          abort();
144       }
145    }
146
147    return visit_continue;
148 }
149
150
151 ir_visitor_status
152 ir_validate::visit_enter(ir_function *ir)
153 {
154    /* Function definitions cannot be nested.
155     */
156    if (this->current_function != NULL) {
157       printf("Function definition nested inside another function "
158              "definition:\n");
159       printf("%s %p inside %s %p\n",
160              ir->name, (void *) ir,
161              this->current_function->name, (void *) this->current_function);
162       abort();
163    }
164
165    /* Store the current function hierarchy being traversed.  This is used
166     * by the function signature visitor to ensure that the signatures are
167     * linked with the correct functions.
168     */
169    this->current_function = ir;
170
171    this->validate_ir(ir, this->data);
172
173    return visit_continue;
174 }
175
176 ir_visitor_status
177 ir_validate::visit_leave(ir_function *ir)
178 {
179    assert(talloc_parent(ir->name) == ir);
180
181    this->current_function = NULL;
182    return visit_continue;
183 }
184
185 ir_visitor_status
186 ir_validate::visit_enter(ir_function_signature *ir)
187 {
188    if (this->current_function != ir->function()) {
189       printf("Function signature nested inside wrong function "
190              "definition:\n");
191       printf("%p inside %s %p instead of %s %p\n",
192              (void *) ir,
193              this->current_function->name, (void *) this->current_function,
194              ir->function_name(), (void *) ir->function());
195       abort();
196    }
197
198    this->validate_ir(ir, this->data);
199
200    return visit_continue;
201 }
202
203 ir_visitor_status
204 ir_validate::visit_leave(ir_expression *ir)
205 {
206    switch (ir->operation) {
207    case ir_unop_bit_not:
208       assert(ir->operands[0]->type == ir->type);
209       break;
210    case ir_unop_logic_not:
211       assert(ir->type->base_type == GLSL_TYPE_BOOL);
212       assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
213       break;
214
215    case ir_unop_neg:
216    case ir_unop_abs:
217    case ir_unop_sign:
218    case ir_unop_rcp:
219    case ir_unop_rsq:
220    case ir_unop_sqrt:
221       assert(ir->type == ir->operands[0]->type);
222       break;
223
224    case ir_unop_exp:
225    case ir_unop_log:
226    case ir_unop_exp2:
227    case ir_unop_log2:
228       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
229       assert(ir->type == ir->operands[0]->type);
230       break;
231
232    case ir_unop_f2i:
233       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
234       assert(ir->type->base_type == GLSL_TYPE_INT);
235       break;
236    case ir_unop_i2f:
237       assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
238       assert(ir->type->base_type == GLSL_TYPE_FLOAT);
239       break;
240    case ir_unop_f2b:
241       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
242       assert(ir->type->base_type == GLSL_TYPE_BOOL);
243       break;
244    case ir_unop_b2f:
245       assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
246       assert(ir->type->base_type == GLSL_TYPE_FLOAT);
247       break;
248    case ir_unop_i2b:
249       assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
250       assert(ir->type->base_type == GLSL_TYPE_BOOL);
251       break;
252    case ir_unop_b2i:
253       assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
254       assert(ir->type->base_type == GLSL_TYPE_INT);
255       break;
256    case ir_unop_u2f:
257       assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT);
258       assert(ir->type->base_type == GLSL_TYPE_FLOAT);
259       break;
260
261    case ir_unop_any:
262       assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
263       assert(ir->type == glsl_type::bool_type);
264       break;
265
266    case ir_unop_trunc:
267    case ir_unop_ceil:
268    case ir_unop_floor:
269    case ir_unop_fract:
270    case ir_unop_sin:
271    case ir_unop_cos:
272    case ir_unop_dFdx:
273    case ir_unop_dFdy:
274       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
275       assert(ir->operands[0]->type == ir->type);
276       break;
277
278    case ir_unop_noise:
279       /* XXX what can we assert here? */
280       break;
281
282    case ir_binop_add:
283    case ir_binop_sub:
284    case ir_binop_mul:
285    case ir_binop_div:
286    case ir_binop_mod:
287    case ir_binop_min:
288    case ir_binop_max:
289    case ir_binop_pow:
290       if (ir->operands[0]->type->is_scalar())
291          assert(ir->operands[1]->type == ir->type);
292       else if (ir->operands[1]->type->is_scalar())
293          assert(ir->operands[0]->type == ir->type);
294       else if (ir->operands[0]->type->is_vector() &&
295                ir->operands[1]->type->is_vector()) {
296          assert(ir->operands[0]->type == ir->operands[1]->type);
297          assert(ir->operands[0]->type == ir->type);
298       }
299       break;
300
301    case ir_binop_less:
302    case ir_binop_greater:
303    case ir_binop_lequal:
304    case ir_binop_gequal:
305    case ir_binop_equal:
306    case ir_binop_nequal:
307       /* The semantics of the IR operators differ from the GLSL <, >, <=, >=,
308        * ==, and != operators.  The IR operators perform a component-wise
309        * comparison on scalar or vector types and return a boolean scalar or
310        * vector type of the same size.
311        */
312       assert(ir->type->base_type == GLSL_TYPE_BOOL);
313       assert(ir->operands[0]->type == ir->operands[1]->type);
314       assert(ir->operands[0]->type->is_vector()
315              || ir->operands[0]->type->is_scalar());
316       assert(ir->operands[0]->type->vector_elements
317              == ir->type->vector_elements);
318       break;
319
320    case ir_binop_all_equal:
321    case ir_binop_any_nequal:
322       /* GLSL == and != operate on scalars, vectors, matrices and arrays, and
323        * return a scalar boolean.  The IR matches that.
324        */
325       assert(ir->type == glsl_type::bool_type);
326       assert(ir->operands[0]->type == ir->operands[1]->type);
327       break;
328
329    case ir_binop_lshift:
330    case ir_binop_rshift:
331    case ir_binop_bit_and:
332    case ir_binop_bit_xor:
333    case ir_binop_bit_or:
334       assert(ir->operands[0]->type == ir->operands[1]->type);
335       assert(ir->type == ir->operands[0]->type);
336       assert(ir->type->base_type == GLSL_TYPE_INT ||
337              ir->type->base_type == GLSL_TYPE_UINT);
338       break;
339
340    case ir_binop_logic_and:
341    case ir_binop_logic_xor:
342    case ir_binop_logic_or:
343       assert(ir->type == glsl_type::bool_type);
344       assert(ir->operands[0]->type == glsl_type::bool_type);
345       assert(ir->operands[1]->type == glsl_type::bool_type);
346       break;
347
348    case ir_binop_dot:
349       assert(ir->type == glsl_type::float_type);
350       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
351       assert(ir->operands[0]->type->is_vector());
352       assert(ir->operands[0]->type == ir->operands[1]->type);
353       break;
354
355    case ir_binop_cross:
356       assert(ir->operands[0]->type == glsl_type::vec3_type);
357       assert(ir->operands[1]->type == glsl_type::vec3_type);
358       assert(ir->type == glsl_type::vec3_type);
359       break;
360    }
361
362    return visit_continue;
363 }
364
365 ir_visitor_status
366 ir_validate::visit(ir_variable *ir)
367 {
368    /* An ir_variable is the one thing that can (and will) appear multiple times
369     * in an IR tree.  It is added to the hashtable so that it can be used
370     * in the ir_dereference_variable handler to ensure that a variable is
371     * declared before it is dereferenced.
372     */
373    if (ir->name)
374       assert(talloc_parent(ir->name) == ir);
375
376    hash_table_insert(ht, ir, ir);
377    return visit_continue;
378 }
379
380 ir_visitor_status
381 ir_validate::visit_enter(ir_assignment *ir)
382 {
383    const ir_dereference *const lhs = ir->lhs;
384    if (lhs->type->is_scalar() || lhs->type->is_vector()) {
385       if (ir->write_mask == 0) {
386          printf("Assignment LHS is %s, but write mask is 0:\n",
387                 lhs->type->is_scalar() ? "scalar" : "vector");
388          ir->print();
389          abort();
390       }
391
392       /* Mask of fields that do not exist in the destination.  These should
393        * not be written by the assignment.
394        */
395       const unsigned invalid_mask = ~((1U << lhs->type->components()) - 1);
396
397       if ((invalid_mask & ir->write_mask) != 0) {
398          printf("Assignment write mask enables invalid components for "
399                 "type %s:\n", lhs->type->name);
400          ir->print();
401          abort();
402       }
403    }
404
405    this->validate_ir(ir, this->data);
406
407    return visit_continue;
408 }
409
410 void
411 ir_validate::validate_ir(ir_instruction *ir, void *data)
412 {
413    struct hash_table *ht = (struct hash_table *) data;
414
415    if (hash_table_find(ht, ir)) {
416       printf("Instruction node present twice in ir tree:\n");
417       ir->print();
418       printf("\n");
419       abort();
420    }
421    hash_table_insert(ht, ir, ir);
422 }
423
424 void
425 check_node_type(ir_instruction *ir, void *data)
426 {
427    (void) data;
428
429    if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
430       printf("Instruction node with unset type\n");
431       ir->print(); printf("\n");
432    }
433    assert(ir->type != glsl_type::error_type);
434 }
435
436 void
437 validate_ir_tree(exec_list *instructions)
438 {
439    ir_validate v;
440
441    v.run(instructions);
442
443    foreach_iter(exec_list_iterator, iter, *instructions) {
444       ir_instruction *ir = (ir_instruction *)iter.get();
445
446       visit_tree(ir, check_node_type, NULL);
447    }
448 }