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