ir_validate.cpp revision 4dfb89904c0a3d2166e9a3fc0253a254680e91bc
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
42class ir_validate : public ir_hierarchical_visitor {
43public:
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
81ir_visitor_status
82ir_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
102ir_visitor_status
103ir_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
117ir_visitor_status
118ir_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
151ir_visitor_status
152ir_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
176ir_visitor_status
177ir_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
185ir_visitor_status
186ir_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
203ir_visitor_status
204ir_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_binop_add:
279   case ir_binop_sub:
280   case ir_binop_mul:
281   case ir_binop_div:
282   case ir_binop_mod:
283   case ir_binop_min:
284   case ir_binop_max:
285   case ir_binop_pow:
286      if (ir->operands[0]->type->is_scalar())
287	 assert(ir->operands[1]->type == ir->type);
288      else if (ir->operands[1]->type->is_scalar())
289	 assert(ir->operands[0]->type == ir->type);
290      else if (ir->operands[0]->type->is_vector() &&
291	       ir->operands[1]->type->is_vector()) {
292	 assert(ir->operands[0]->type == ir->operands[1]->type);
293	 assert(ir->operands[0]->type == ir->type);
294      }
295      break;
296
297   case ir_binop_less:
298   case ir_binop_greater:
299   case ir_binop_lequal:
300   case ir_binop_gequal:
301   case ir_binop_equal:
302   case ir_binop_nequal:
303      /* The semantics of the IR operators differ from the GLSL <, >, <=, >=,
304       * ==, and != operators.  The IR operators perform a component-wise
305       * comparison on scalar or vector types and return a boolean scalar or
306       * vector type of the same size.
307       */
308      assert(ir->type->base_type == GLSL_TYPE_BOOL);
309      assert(ir->operands[0]->type == ir->operands[1]->type);
310      assert(ir->operands[0]->type->is_vector()
311	     || ir->operands[0]->type->is_scalar());
312      assert(ir->operands[0]->type->vector_elements
313	     == ir->type->vector_elements);
314      break;
315
316   case ir_binop_all_equal:
317   case ir_binop_any_nequal:
318      /* GLSL == and != operate on scalars, vectors, matrices and arrays, and
319       * return a scalar boolean.  The IR matches that.
320       */
321      assert(ir->type == glsl_type::bool_type);
322      assert(ir->operands[0]->type == ir->operands[1]->type);
323      break;
324
325   case ir_binop_lshift:
326   case ir_binop_rshift:
327   case ir_binop_bit_and:
328   case ir_binop_bit_xor:
329   case ir_binop_bit_or:
330      assert(ir->operands[0]->type == ir->operands[1]->type);
331      assert(ir->type == ir->operands[0]->type);
332      assert(ir->type->base_type == GLSL_TYPE_INT ||
333	     ir->type->base_type == GLSL_TYPE_UINT);
334      break;
335
336   case ir_binop_logic_and:
337   case ir_binop_logic_xor:
338   case ir_binop_logic_or:
339      assert(ir->type == glsl_type::bool_type);
340      assert(ir->operands[0]->type == glsl_type::bool_type);
341      assert(ir->operands[1]->type == glsl_type::bool_type);
342      break;
343
344   case ir_binop_dot:
345      assert(ir->type == glsl_type::float_type);
346      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
347      assert(ir->operands[0]->type->is_vector());
348      assert(ir->operands[0]->type == ir->operands[1]->type);
349      break;
350
351   case ir_binop_cross:
352      assert(ir->operands[0]->type == glsl_type::vec3_type);
353      assert(ir->operands[1]->type == glsl_type::vec3_type);
354      assert(ir->type == glsl_type::vec3_type);
355      break;
356   }
357
358   return visit_continue;
359}
360
361ir_visitor_status
362ir_validate::visit(ir_variable *ir)
363{
364   /* An ir_variable is the one thing that can (and will) appear multiple times
365    * in an IR tree.  It is added to the hashtable so that it can be used
366    * in the ir_dereference_variable handler to ensure that a variable is
367    * declared before it is dereferenced.
368    */
369   if (ir->name)
370      assert(talloc_parent(ir->name) == ir);
371
372   hash_table_insert(ht, ir, ir);
373   return visit_continue;
374}
375
376ir_visitor_status
377ir_validate::visit_enter(ir_assignment *ir)
378{
379   const ir_dereference *const lhs = ir->lhs;
380   if (lhs->type->is_scalar() || lhs->type->is_vector()) {
381      if (ir->write_mask == 0) {
382	 printf("Assignment LHS is %s, but write mask is 0:\n",
383		lhs->type->is_scalar() ? "scalar" : "vector");
384	 ir->print();
385	 abort();
386      }
387
388      /* Mask of fields that do not exist in the destination.  These should
389       * not be written by the assignment.
390       */
391      const unsigned invalid_mask = ~((1U << lhs->type->components()) - 1);
392
393      if ((invalid_mask & ir->write_mask) != 0) {
394	 printf("Assignment write mask enables invalid components for "
395		"type %s:\n", lhs->type->name);
396	 ir->print();
397	 abort();
398      }
399   }
400
401   this->validate_ir(ir, this->data);
402
403   return visit_continue;
404}
405
406void
407ir_validate::validate_ir(ir_instruction *ir, void *data)
408{
409   struct hash_table *ht = (struct hash_table *) data;
410
411   if (hash_table_find(ht, ir)) {
412      printf("Instruction node present twice in ir tree:\n");
413      ir->print();
414      printf("\n");
415      abort();
416   }
417   hash_table_insert(ht, ir, ir);
418}
419
420void
421check_node_type(ir_instruction *ir, void *data)
422{
423   (void) data;
424
425   if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
426      printf("Instruction node with unset type\n");
427      ir->print(); printf("\n");
428   }
429   assert(ir->type != glsl_type::error_type);
430}
431
432void
433validate_ir_tree(exec_list *instructions)
434{
435   ir_validate v;
436
437   v.run(instructions);
438
439   foreach_iter(exec_list_iterator, iter, *instructions) {
440      ir_instruction *ir = (ir_instruction *)iter.get();
441
442      visit_tree(ir, check_node_type, NULL);
443   }
444}
445