Merge branch 'master' into glsl2
[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 <stdint.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_enter(ir_function *ir);
65    virtual ir_visitor_status visit_leave(ir_function *ir);
66    virtual ir_visitor_status visit_enter(ir_function_signature *ir);
67
68    virtual ir_visitor_status visit_leave(ir_expression *ir);
69
70    virtual ir_visitor_status visit_enter(ir_assignment *ir);
71
72    static void validate_ir(ir_instruction *ir, void *data);
73
74    ir_function *current_function;
75
76    struct hash_table *ht;
77 };
78
79
80 ir_visitor_status
81 ir_validate::visit(ir_dereference_variable *ir)
82 {
83    if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) {
84       printf("ir_dereference_variable @ %p does not specify a variable %p\n",
85              (void *) ir, (void *) ir->var);
86       abort();
87    }
88
89    if (hash_table_find(ht, ir->var) == NULL) {
90       printf("ir_dereference_variable @ %p specifies undeclared variable "
91              "`%s' @ %p\n",
92              (void *) ir, ir->var->name, (void *) ir->var);
93       abort();
94    }
95
96    this->validate_ir(ir, this->data);
97
98    return visit_continue;
99 }
100
101 ir_visitor_status
102 ir_validate::visit(ir_if *ir)
103 {
104    if (ir->condition->type != glsl_type::bool_type) {
105       printf("ir_if condition %s type instead of bool.\n",
106              ir->condition->type->name);
107       ir->print();
108       printf("\n");
109       abort();
110    }
111
112    return visit_continue;
113 }
114
115
116 ir_visitor_status
117 ir_validate::visit_enter(ir_function *ir)
118 {
119    /* Function definitions cannot be nested.
120     */
121    if (this->current_function != NULL) {
122       printf("Function definition nested inside another function "
123              "definition:\n");
124       printf("%s %p inside %s %p\n",
125              ir->name, (void *) ir,
126              this->current_function->name, (void *) this->current_function);
127       abort();
128    }
129
130    /* Store the current function hierarchy being traversed.  This is used
131     * by the function signature visitor to ensure that the signatures are
132     * linked with the correct functions.
133     */
134    this->current_function = ir;
135
136    this->validate_ir(ir, this->data);
137
138    return visit_continue;
139 }
140
141 ir_visitor_status
142 ir_validate::visit_leave(ir_function *ir)
143 {
144    assert(talloc_parent(ir->name) == ir);
145
146    this->current_function = NULL;
147    return visit_continue;
148 }
149
150 ir_visitor_status
151 ir_validate::visit_enter(ir_function_signature *ir)
152 {
153    if (this->current_function != ir->function()) {
154       printf("Function signature nested inside wrong function "
155              "definition:\n");
156       printf("%p inside %s %p instead of %s %p\n",
157              (void *) ir,
158              this->current_function->name, (void *) this->current_function,
159              ir->function_name(), (void *) ir->function());
160       abort();
161    }
162
163    this->validate_ir(ir, this->data);
164
165    return visit_continue;
166 }
167
168 ir_visitor_status
169 ir_validate::visit_leave(ir_expression *ir)
170 {
171    switch (ir->operation) {
172    case ir_unop_bit_not:
173       assert(ir->operands[0]->type == ir->type);
174       break;
175    case ir_unop_logic_not:
176       assert(ir->type->base_type == GLSL_TYPE_BOOL);
177       assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
178       break;
179
180    case ir_unop_neg:
181    case ir_unop_abs:
182    case ir_unop_sign:
183    case ir_unop_rcp:
184    case ir_unop_rsq:
185    case ir_unop_sqrt:
186       assert(ir->type == ir->operands[0]->type);
187       break;
188
189    case ir_unop_exp:
190    case ir_unop_log:
191    case ir_unop_exp2:
192    case ir_unop_log2:
193       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
194       assert(ir->type == ir->operands[0]->type);
195       break;
196
197    case ir_unop_f2i:
198       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
199       assert(ir->type->base_type == GLSL_TYPE_INT);
200       break;
201    case ir_unop_i2f:
202       assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
203       assert(ir->type->base_type == GLSL_TYPE_FLOAT);
204       break;
205    case ir_unop_f2b:
206       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
207       assert(ir->type->base_type == GLSL_TYPE_BOOL);
208       break;
209    case ir_unop_b2f:
210       assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
211       assert(ir->type->base_type == GLSL_TYPE_FLOAT);
212       break;
213    case ir_unop_i2b:
214       assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
215       assert(ir->type->base_type == GLSL_TYPE_BOOL);
216       break;
217    case ir_unop_b2i:
218       assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
219       assert(ir->type->base_type == GLSL_TYPE_INT);
220       break;
221    case ir_unop_u2f:
222       assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT);
223       assert(ir->type->base_type == GLSL_TYPE_FLOAT);
224       break;
225
226    case ir_unop_trunc:
227    case ir_unop_ceil:
228    case ir_unop_floor:
229    case ir_unop_fract:
230    case ir_unop_sin:
231    case ir_unop_cos:
232    case ir_unop_dFdx:
233    case ir_unop_dFdy:
234       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
235       assert(ir->operands[0]->type == ir->type);
236       break;
237
238    case ir_binop_add:
239    case ir_binop_sub:
240    case ir_binop_mul:
241    case ir_binop_div:
242    case ir_binop_mod:
243    case ir_binop_min:
244    case ir_binop_max:
245    case ir_binop_pow:
246       if (ir->operands[0]->type->is_scalar())
247          assert(ir->operands[1]->type == ir->type);
248       else if (ir->operands[1]->type->is_scalar())
249          assert(ir->operands[0]->type == ir->type);
250       else if (ir->operands[0]->type->is_vector() &&
251                ir->operands[1]->type->is_vector()) {
252          assert(ir->operands[0]->type == ir->operands[1]->type);
253          assert(ir->operands[0]->type == ir->type);
254       }
255       break;
256    case ir_binop_less:
257    case ir_binop_greater:
258    case ir_binop_lequal:
259    case ir_binop_gequal:
260       /* GLSL < > <= >= operators take scalar floats/ints, but in the
261        * IR we may want to do them for vectors instead to support the
262        * lessEqual() and friends builtins.
263        */
264       assert(ir->type == glsl_type::bool_type);
265       assert(ir->operands[0]->type == ir->operands[1]->type);
266       break;
267
268    case ir_binop_equal:
269    case ir_binop_nequal:
270       /* GLSL == and != operate on vectors and return a bool, and the
271        * IR matches that.  We may want to switch up the IR to work on
272        * vectors and return a bvec and make the operators break down
273        * to ANDing/ORing the results of the vector comparison.
274        */
275       assert(ir->type == glsl_type::bool_type);
276       assert(ir->operands[0]->type == ir->operands[1]->type);
277       break;
278
279    case ir_binop_lshift:
280    case ir_binop_rshift:
281    case ir_binop_bit_and:
282    case ir_binop_bit_xor:
283    case ir_binop_bit_or:
284       assert(ir->operands[0]->type == ir->operands[1]->type);
285       assert(ir->type == ir->operands[0]->type);
286       assert(ir->type->base_type == GLSL_TYPE_INT ||
287              ir->type->base_type == GLSL_TYPE_UINT);
288       break;
289
290    case ir_binop_logic_and:
291    case ir_binop_logic_xor:
292    case ir_binop_logic_or:
293       assert(ir->type == glsl_type::bool_type);
294       assert(ir->operands[0]->type == glsl_type::bool_type);
295       assert(ir->operands[1]->type == glsl_type::bool_type);
296       break;
297
298    case ir_binop_dot:
299       assert(ir->type == glsl_type::float_type);
300       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
301       assert(ir->operands[0]->type == ir->operands[1]->type);
302       break;
303
304    case ir_binop_cross:
305       assert(ir->operands[0]->type == glsl_type::vec3_type);
306       assert(ir->operands[1]->type == glsl_type::vec3_type);
307       assert(ir->type == glsl_type::vec3_type);
308       break;
309    }
310
311    return visit_continue;
312 }
313
314 ir_visitor_status
315 ir_validate::visit(ir_variable *ir)
316 {
317    /* An ir_variable is the one thing that can (and will) appear multiple times
318     * in an IR tree.  It is added to the hashtable so that it can be used
319     * in the ir_dereference_variable handler to ensure that a variable is
320     * declared before it is dereferenced.
321     */
322    if (ir->name)
323       assert(talloc_parent(ir->name) == ir);
324
325    hash_table_insert(ht, ir, ir);
326    return visit_continue;
327 }
328
329 ir_visitor_status
330 ir_validate::visit_enter(ir_assignment *ir)
331 {
332    const ir_dereference *const lhs = ir->lhs;
333    if (lhs->type->is_scalar() || lhs->type->is_vector()) {
334       if (ir->write_mask == 0) {
335          printf("Assignment LHS is %s, but write mask is 0:\n",
336                 lhs->type->is_scalar() ? "scalar" : "vector");
337          ir->print();
338          abort();
339       }
340
341       /* Mask of fields that do not exist in the destination.  These should
342        * not be written by the assignment.
343        */
344       const unsigned invalid_mask = ~((1U << lhs->type->components()) - 1);
345
346       if ((invalid_mask & ir->write_mask) != 0) {
347          printf("Assignment write mask enables invalid components for "
348                 "type %s:\n", lhs->type->name);
349          ir->print();
350          abort();
351       }
352    }
353
354    this->validate_ir(ir, this->data);
355
356    return visit_continue;
357 }
358
359 void
360 ir_validate::validate_ir(ir_instruction *ir, void *data)
361 {
362    struct hash_table *ht = (struct hash_table *) data;
363
364    if (hash_table_find(ht, ir)) {
365       printf("Instruction node present twice in ir tree:\n");
366       ir->print();
367       printf("\n");
368       abort();
369    }
370    hash_table_insert(ht, ir, ir);
371 }
372
373 void
374 check_node_type(ir_instruction *ir, void *data)
375 {
376    (void) data;
377
378    if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
379       printf("Instruction node with unset type\n");
380       ir->print(); printf("\n");
381    }
382    assert(ir->type != glsl_type::error_type);
383 }
384
385 void
386 validate_ir_tree(exec_list *instructions)
387 {
388    ir_validate v;
389
390    v.run(instructions);
391
392    foreach_iter(exec_list_iterator, iter, *instructions) {
393       ir_instruction *ir = (ir_instruction *)iter.get();
394
395       visit_tree(ir, check_node_type, NULL);
396    }
397 }