ir_validate.cpp revision c67016de960c988c748ffdb11247072543a8f328
153cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt/*
253cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * Copyright © 2010 Intel Corporation
353cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt *
453cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * Permission is hereby granted, free of charge, to any person obtaining a
553cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * copy of this software and associated documentation files (the "Software"),
653cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * to deal in the Software without restriction, including without limitation
753cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * the rights to use, copy, modify, merge, publish, distribute, sublicense,
853cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * and/or sell copies of the Software, and to permit persons to whom the
953cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * Software is furnished to do so, subject to the following conditions:
1053cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt *
1153cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * The above copyright notice and this permission notice (including the next
1253cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * paragraph) shall be included in all copies or substantial portions of the
1353cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * Software.
1453cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt *
1553cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1653cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1753cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1853cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1953cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2053cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2153cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * DEALINGS IN THE SOFTWARE.
2253cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt */
2353cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
2453cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt/**
2553cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * \file ir_validate.cpp
2653cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt *
2753cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * Attempts to verify that various invariants of the IR tree are true.
2853cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt *
2953cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * In particular, at the moment it makes sure that no single
3053cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * ir_instruction node except for ir_variable appears multiple times
3153cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * in the ir tree.  ir_variable does appear multiple times: Once as a
3253cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * declaration in an exec_list, and multiple times as the endpoint of
3353cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt * a dereference chain.
3453cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt */
3553cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
3653cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt#include <inttypes.h>
3753cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt#include "ir.h"
38865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick#include "ir_hierarchical_visitor.h"
3953cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt#include "hash_table.h"
4053cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
4153cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
42865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanickclass ir_validate : public ir_hierarchical_visitor {
43865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanickpublic:
44865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   ir_validate()
45865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   {
46d1a1ee583e7e8338243b3e9768d2fc5312a1145dIan Romanick      this->ht = hash_table_ctor(0, hash_table_pointer_hash,
47d1a1ee583e7e8338243b3e9768d2fc5312a1145dIan Romanick				 hash_table_pointer_compare);
4853cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
49c67016de960c988c748ffdb11247072543a8f328Ian Romanick      this->current_function = NULL;
50c67016de960c988c748ffdb11247072543a8f328Ian Romanick
51865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick      this->callback = ir_validate::validate_ir;
52865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick      this->data = ht;
53865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   }
5453cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
55865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   ~ir_validate()
56865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   {
57865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick      hash_table_dtor(this->ht);
58865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   }
5953cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
60865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   virtual ir_visitor_status visit(ir_variable *v);
6153cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
62c67016de960c988c748ffdb11247072543a8f328Ian Romanick   virtual ir_visitor_status visit_enter(ir_function *ir);
63c67016de960c988c748ffdb11247072543a8f328Ian Romanick   virtual ir_visitor_status visit_leave(ir_function *ir);
64c67016de960c988c748ffdb11247072543a8f328Ian Romanick   virtual ir_visitor_status visit_enter(ir_function_signature *ir);
65c67016de960c988c748ffdb11247072543a8f328Ian Romanick
66865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   static void validate_ir(ir_instruction *ir, void *data);
6753cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
68c67016de960c988c748ffdb11247072543a8f328Ian Romanick   ir_function *current_function;
69c67016de960c988c748ffdb11247072543a8f328Ian Romanick
70865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   struct hash_table *ht;
71865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick};
7253cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
7353cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholtir_visitor_status
74c67016de960c988c748ffdb11247072543a8f328Ian Romanickir_validate::visit_enter(ir_function *ir)
75c67016de960c988c748ffdb11247072543a8f328Ian Romanick{
76c67016de960c988c748ffdb11247072543a8f328Ian Romanick   /* Function definitions cannot be nested.
77c67016de960c988c748ffdb11247072543a8f328Ian Romanick    */
78c67016de960c988c748ffdb11247072543a8f328Ian Romanick   if (this->current_function != NULL) {
79c67016de960c988c748ffdb11247072543a8f328Ian Romanick      printf("Function definition nested inside another function "
80c67016de960c988c748ffdb11247072543a8f328Ian Romanick	     "definition:\n");
81c67016de960c988c748ffdb11247072543a8f328Ian Romanick      printf("%s %p inside %s %p\n",
82c67016de960c988c748ffdb11247072543a8f328Ian Romanick	     ir->name, ir,
83c67016de960c988c748ffdb11247072543a8f328Ian Romanick	     this->current_function->name, this->current_function);
84c67016de960c988c748ffdb11247072543a8f328Ian Romanick      abort();
85c67016de960c988c748ffdb11247072543a8f328Ian Romanick   }
86c67016de960c988c748ffdb11247072543a8f328Ian Romanick
87c67016de960c988c748ffdb11247072543a8f328Ian Romanick   /* Store the current function hierarchy being traversed.  This is used
88c67016de960c988c748ffdb11247072543a8f328Ian Romanick    * by the function signature visitor to ensure that the signatures are
89c67016de960c988c748ffdb11247072543a8f328Ian Romanick    * linked with the correct functions.
90c67016de960c988c748ffdb11247072543a8f328Ian Romanick    */
91c67016de960c988c748ffdb11247072543a8f328Ian Romanick   this->current_function = ir;
92c67016de960c988c748ffdb11247072543a8f328Ian Romanick
93c67016de960c988c748ffdb11247072543a8f328Ian Romanick   this->validate_ir(ir, this->data);
94c67016de960c988c748ffdb11247072543a8f328Ian Romanick
95c67016de960c988c748ffdb11247072543a8f328Ian Romanick   return visit_continue;
96c67016de960c988c748ffdb11247072543a8f328Ian Romanick}
97c67016de960c988c748ffdb11247072543a8f328Ian Romanick
98c67016de960c988c748ffdb11247072543a8f328Ian Romanickir_visitor_status
99c67016de960c988c748ffdb11247072543a8f328Ian Romanickir_validate::visit_leave(ir_function *ir)
100c67016de960c988c748ffdb11247072543a8f328Ian Romanick{
101c67016de960c988c748ffdb11247072543a8f328Ian Romanick   (void) ir;
102c67016de960c988c748ffdb11247072543a8f328Ian Romanick
103c67016de960c988c748ffdb11247072543a8f328Ian Romanick   this->current_function = NULL;
104c67016de960c988c748ffdb11247072543a8f328Ian Romanick   return visit_continue;
105c67016de960c988c748ffdb11247072543a8f328Ian Romanick}
106c67016de960c988c748ffdb11247072543a8f328Ian Romanick
107c67016de960c988c748ffdb11247072543a8f328Ian Romanickir_visitor_status
108c67016de960c988c748ffdb11247072543a8f328Ian Romanickir_validate::visit_enter(ir_function_signature *ir)
109c67016de960c988c748ffdb11247072543a8f328Ian Romanick{
110c67016de960c988c748ffdb11247072543a8f328Ian Romanick   if (this->current_function != ir->function()) {
111c67016de960c988c748ffdb11247072543a8f328Ian Romanick      printf("Function signature nested inside wrong function "
112c67016de960c988c748ffdb11247072543a8f328Ian Romanick	     "definition:\n");
113c67016de960c988c748ffdb11247072543a8f328Ian Romanick      printf("%p inside %s %p instead of %s %p\n",
114c67016de960c988c748ffdb11247072543a8f328Ian Romanick	     ir,
115c67016de960c988c748ffdb11247072543a8f328Ian Romanick	     this->current_function->name, this->current_function,
116c67016de960c988c748ffdb11247072543a8f328Ian Romanick	     ir->function_name(), ir->function());
117c67016de960c988c748ffdb11247072543a8f328Ian Romanick      abort();
118c67016de960c988c748ffdb11247072543a8f328Ian Romanick   }
119c67016de960c988c748ffdb11247072543a8f328Ian Romanick
120c67016de960c988c748ffdb11247072543a8f328Ian Romanick   this->validate_ir(ir, this->data);
121c67016de960c988c748ffdb11247072543a8f328Ian Romanick
122c67016de960c988c748ffdb11247072543a8f328Ian Romanick   return visit_continue;
123c67016de960c988c748ffdb11247072543a8f328Ian Romanick}
124c67016de960c988c748ffdb11247072543a8f328Ian Romanick
125c67016de960c988c748ffdb11247072543a8f328Ian Romanickir_visitor_status
126865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanickir_validate::visit(ir_variable *ir)
12753cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt{
128865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   /* An ir_variable is the one thing that can (and will) appear multiple times
129865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick    * in an IR tree.
130865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick    */
131865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   (void) ir;
13253cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt   return visit_continue;
13353cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt}
13453cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
135865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanickvoid
136865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanickir_validate::validate_ir(ir_instruction *ir, void *data)
13753cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt{
138865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   struct hash_table *ht = (struct hash_table *) data;
13953cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
140865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   if (hash_table_find(ht, ir)) {
141865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick      printf("Instruction node present twice in ir tree:\n");
142865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick      ir->print();
143865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick      printf("\n");
144865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick      abort();
145865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   }
146865cf2d1f5e499916d360a246ad85554f3ff5b02Ian Romanick   hash_table_insert(ht, ir, ir);
14753cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt}
14853cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
14953cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholtvoid
15053cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholtvalidate_ir_tree(exec_list *instructions)
15153cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt{
15253cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt   ir_validate v;
15353cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt
15453cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt   v.run(instructions);
15553cdb7e51d85d4b4a35fba3ec200b27991b8488bEric Anholt}
156