From: Eric Anholt Date: Tue, 22 Jun 2010 19:07:21 +0000 (-0700) Subject: ir_validate: New pass for checking our invariants. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=53cdb7e51d85d4b4a35fba3ec200b27991b8488b;p=mesa.git ir_validate: New pass for checking our invariants. --- diff --git a/Makefile.am b/Makefile.am index f24f06d0aa7..b65b8bab526 100644 --- a/Makefile.am +++ b/Makefile.am @@ -56,6 +56,7 @@ glsl_SOURCES = \ ir_hierarchical_visitor.h \ ir_hierarchical_visitor.cpp \ ir_swizzle_swizzle.cpp \ + ir_validate.cpp \ ir_vec_index_to_swizzle.cpp \ linker.cpp diff --git a/ir.h b/ir.h index 7454947c97c..d02f3caab97 100644 --- a/ir.h +++ b/ir.h @@ -1112,6 +1112,8 @@ private: void visit_exec_list(exec_list *list, ir_visitor *visitor); +void validate_ir_tree(exec_list *instructions); + extern void _mesa_glsl_initialize_variables(exec_list *instructions, struct _mesa_glsl_parse_state *state); diff --git a/ir_validate.cpp b/ir_validate.cpp new file mode 100644 index 00000000000..c6c18df51a7 --- /dev/null +++ b/ir_validate.cpp @@ -0,0 +1,192 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file ir_validate.cpp + * + * Attempts to verify that various invariants of the IR tree are true. + * + * In particular, at the moment it makes sure that no single + * ir_instruction node except for ir_variable appears multiple times + * in the ir tree. ir_variable does appear multiple times: Once as a + * declaration in an exec_list, and multiple times as the endpoint of + * a dereference chain. + */ + +#include +#include "ir.h" +#include "ir_visitor.h" +#include "ir_optimization.h" +#include "glsl_types.h" +#include "hash_table.h" + +/** + * Visitor class for replacing expressions with ir_constant values. + */ + + +class ir_validate : public ir_hierarchical_visitor { +public: + virtual ir_visitor_status visit_enter(class ir_constant *); + virtual ir_visitor_status visit_enter(class ir_loop *); + virtual ir_visitor_status visit_enter(class ir_function_signature *); + virtual ir_visitor_status visit_enter(class ir_function *); + virtual ir_visitor_status visit_enter(class ir_expression *); + virtual ir_visitor_status visit_enter(class ir_texture *); + virtual ir_visitor_status visit_enter(class ir_swizzle *); + virtual ir_visitor_status visit_enter(class ir_dereference_array *); + virtual ir_visitor_status visit_enter(class ir_dereference_record *); + virtual ir_visitor_status visit_enter(class ir_assignment *); + virtual ir_visitor_status visit_enter(class ir_call *); + virtual ir_visitor_status visit_enter(class ir_return *); + virtual ir_visitor_status visit_enter(class ir_if *); + + void validate_ir(ir_instruction *ir); + + struct hash_table *ht; +}; + +unsigned int hash_func(const void *key) +{ + return (unsigned int)(uintptr_t)key; +} + +int hash_compare_func(const void *key1, const void *key2) +{ + return key1 == key2 ? 0 : 1; +} + +void +ir_validate::validate_ir(ir_instruction *ir) +{ + if (hash_table_find(this->ht, ir)) { + printf("Instruction node present twice in ir tree:\n"); + ir->print(); + printf("\n"); + abort(); + } + hash_table_insert(this->ht, ir, ir); +} + +ir_visitor_status +ir_validate::visit_enter(ir_constant *ir) +{ + validate_ir(ir); + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_enter(ir_loop *ir) +{ + validate_ir(ir); + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_enter(ir_function_signature *ir) +{ + validate_ir(ir); + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_enter(ir_function *ir) +{ + validate_ir(ir); + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_enter(ir_expression *ir) +{ + validate_ir(ir); + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_enter(ir_texture *ir) +{ + validate_ir(ir); + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_enter(ir_swizzle *ir) +{ + validate_ir(ir); + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_enter(ir_dereference_array *ir) +{ + validate_ir(ir); + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_enter(ir_dereference_record *ir) +{ + validate_ir(ir); + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_enter(ir_assignment *ir) +{ + validate_ir(ir); + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_enter(ir_call *ir) +{ + validate_ir(ir); + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_enter(ir_return *ir) +{ + validate_ir(ir); + return visit_continue; +} + +ir_visitor_status +ir_validate::visit_enter(ir_if *ir) +{ + validate_ir(ir); + return visit_continue; +} + +void +validate_ir_tree(exec_list *instructions) +{ + ir_validate v; + + v.ht = hash_table_ctor(0, hash_func, hash_compare_func); + + v.run(instructions); + + hash_table_dtor(v.ht); +} diff --git a/main.cpp b/main.cpp index 7f094f8e3e4..17f25d741e4 100644 --- a/main.cpp +++ b/main.cpp @@ -148,6 +148,8 @@ compile_shader(struct glsl_shader *shader) if (!state.error && !state.translation_unit.is_empty()) _mesa_ast_to_hir(&shader->ir, &state); + validate_ir_tree(&shader->ir); + /* Optimization passes */ if (!state.error && !shader->ir.is_empty()) { bool progress; @@ -166,6 +168,8 @@ compile_shader(struct glsl_shader *shader) } while (progress); } + validate_ir_tree(&shader->ir); + /* Print out the resulting IR */ if (!state.error && dump_lir) { _mesa_print_ir(&shader->ir, &state);