101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2014 Intel Corporation 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg * 2301e04c3fSmrg * Authors: 2401e04c3fSmrg * Connor Abbott (cwabbott0@gmail.com) 2501e04c3fSmrg * 2601e04c3fSmrg */ 2701e04c3fSmrg 2801e04c3fSmrg#include "nir.h" 297e102996Smaya#include "c11/threads.h" 3001e04c3fSmrg#include <assert.h> 3101e04c3fSmrg 3201e04c3fSmrg/* 3301e04c3fSmrg * This file checks for invalid IR indicating a bug somewhere in the compiler. 3401e04c3fSmrg */ 3501e04c3fSmrg 3601e04c3fSmrg/* Since this file is just a pile of asserts, don't bother compiling it if 3701e04c3fSmrg * we're not building a debug build. 3801e04c3fSmrg */ 3901e04c3fSmrg#ifndef NDEBUG 4001e04c3fSmrg 4101e04c3fSmrg/* 4201e04c3fSmrg * Per-register validation state. 4301e04c3fSmrg */ 4401e04c3fSmrg 4501e04c3fSmrgtypedef struct { 4601e04c3fSmrg /* 4701e04c3fSmrg * equivalent to the uses and defs in nir_register, but built up by the 4801e04c3fSmrg * validator. At the end, we verify that the sets have the same entries. 4901e04c3fSmrg */ 5001e04c3fSmrg struct set *uses, *if_uses, *defs; 5101e04c3fSmrg nir_function_impl *where_defined; /* NULL for global registers */ 5201e04c3fSmrg} reg_validate_state; 5301e04c3fSmrg 5401e04c3fSmrgtypedef struct { 557ec681f3Smrg void *mem_ctx; 5601e04c3fSmrg 5701e04c3fSmrg /* map of register -> validation state (struct above) */ 5801e04c3fSmrg struct hash_table *regs; 5901e04c3fSmrg 6001e04c3fSmrg /* the current shader being validated */ 6101e04c3fSmrg nir_shader *shader; 6201e04c3fSmrg 6301e04c3fSmrg /* the current instruction being validated */ 6401e04c3fSmrg nir_instr *instr; 6501e04c3fSmrg 6601e04c3fSmrg /* the current variable being validated */ 6701e04c3fSmrg nir_variable *var; 6801e04c3fSmrg 6901e04c3fSmrg /* the current basic block being validated */ 7001e04c3fSmrg nir_block *block; 7101e04c3fSmrg 7201e04c3fSmrg /* the current if statement being validated */ 7301e04c3fSmrg nir_if *if_stmt; 7401e04c3fSmrg 7501e04c3fSmrg /* the current loop being visited */ 7601e04c3fSmrg nir_loop *loop; 7701e04c3fSmrg 7801e04c3fSmrg /* the parent of the current cf node being visited */ 7901e04c3fSmrg nir_cf_node *parent_node; 8001e04c3fSmrg 8101e04c3fSmrg /* the current function implementation being validated */ 8201e04c3fSmrg nir_function_impl *impl; 8301e04c3fSmrg 847ec681f3Smrg /* Set of all blocks in the list */ 857ec681f3Smrg struct set *blocks; 867ec681f3Smrg 877ec681f3Smrg /* Set of seen SSA sources */ 887ec681f3Smrg struct set *ssa_srcs; 8901e04c3fSmrg 9001e04c3fSmrg /* bitset of ssa definitions we have found; used to check uniqueness */ 9101e04c3fSmrg BITSET_WORD *ssa_defs_found; 9201e04c3fSmrg 9301e04c3fSmrg /* bitset of registers we have currently found; used to check uniqueness */ 9401e04c3fSmrg BITSET_WORD *regs_found; 9501e04c3fSmrg 9601e04c3fSmrg /* map of variable -> function implementation where it is defined or NULL 9701e04c3fSmrg * if it is a global variable 9801e04c3fSmrg */ 9901e04c3fSmrg struct hash_table *var_defs; 10001e04c3fSmrg 10101e04c3fSmrg /* map of instruction/var/etc to failed assert string */ 10201e04c3fSmrg struct hash_table *errors; 1037ec681f3Smrg 1047ec681f3Smrg struct set *shader_gc_list; 10501e04c3fSmrg} validate_state; 10601e04c3fSmrg 10701e04c3fSmrgstatic void 10801e04c3fSmrglog_error(validate_state *state, const char *cond, const char *file, int line) 10901e04c3fSmrg{ 11001e04c3fSmrg const void *obj; 11101e04c3fSmrg 11201e04c3fSmrg if (state->instr) 11301e04c3fSmrg obj = state->instr; 11401e04c3fSmrg else if (state->var) 11501e04c3fSmrg obj = state->var; 11601e04c3fSmrg else 11701e04c3fSmrg obj = cond; 11801e04c3fSmrg 11901e04c3fSmrg char *msg = ralloc_asprintf(state->errors, "error: %s (%s:%d)", 12001e04c3fSmrg cond, file, line); 12101e04c3fSmrg 12201e04c3fSmrg _mesa_hash_table_insert(state->errors, obj, msg); 12301e04c3fSmrg} 12401e04c3fSmrg 1257ec681f3Smrgstatic bool 1267ec681f3Smrgvalidate_assert_impl(validate_state *state, bool cond, const char *str, 1277ec681f3Smrg const char *file, unsigned line) 1287ec681f3Smrg{ 1297ec681f3Smrg if (!cond) 1307ec681f3Smrg log_error(state, str, file, line); 1317ec681f3Smrg return cond; 1327ec681f3Smrg} 1337ec681f3Smrg 1347ec681f3Smrg#define validate_assert(state, cond) \ 1357ec681f3Smrg validate_assert_impl(state, (cond), #cond, __FILE__, __LINE__) 1367ec681f3Smrg 13701e04c3fSmrg 13801e04c3fSmrgstatic void validate_src(nir_src *src, validate_state *state, 1397e102996Smaya unsigned bit_sizes, unsigned num_components); 14001e04c3fSmrg 1417ec681f3Smrgstatic void 1427ec681f3Smrgvalidate_num_components(validate_state *state, unsigned num_components) 1437ec681f3Smrg{ 1447ec681f3Smrg validate_assert(state, nir_num_components_valid(num_components)); 1457ec681f3Smrg} 1467ec681f3Smrg 14701e04c3fSmrgstatic void 14801e04c3fSmrgvalidate_reg_src(nir_src *src, validate_state *state, 1497e102996Smaya unsigned bit_sizes, unsigned num_components) 15001e04c3fSmrg{ 15101e04c3fSmrg validate_assert(state, src->reg.reg != NULL); 15201e04c3fSmrg 15301e04c3fSmrg struct hash_entry *entry; 15401e04c3fSmrg entry = _mesa_hash_table_search(state->regs, src->reg.reg); 15501e04c3fSmrg validate_assert(state, entry); 15601e04c3fSmrg 15701e04c3fSmrg reg_validate_state *reg_state = (reg_validate_state *) entry->data; 15801e04c3fSmrg 15901e04c3fSmrg if (state->instr) { 16001e04c3fSmrg _mesa_set_add(reg_state->uses, src); 16101e04c3fSmrg } else { 16201e04c3fSmrg validate_assert(state, state->if_stmt); 16301e04c3fSmrg _mesa_set_add(reg_state->if_uses, src); 16401e04c3fSmrg } 16501e04c3fSmrg 1667e102996Smaya validate_assert(state, reg_state->where_defined == state->impl && 1677e102996Smaya "using a register declared in a different function"); 16801e04c3fSmrg 1697e102996Smaya if (bit_sizes) 1707e102996Smaya validate_assert(state, src->reg.reg->bit_size & bit_sizes); 1717e102996Smaya if (num_components) 1727e102996Smaya validate_assert(state, src->reg.reg->num_components == num_components); 17301e04c3fSmrg 17401e04c3fSmrg validate_assert(state, (src->reg.reg->num_array_elems == 0 || 17501e04c3fSmrg src->reg.base_offset < src->reg.reg->num_array_elems) && 17601e04c3fSmrg "definitely out-of-bounds array access"); 17701e04c3fSmrg 17801e04c3fSmrg if (src->reg.indirect) { 17901e04c3fSmrg validate_assert(state, src->reg.reg->num_array_elems != 0); 18001e04c3fSmrg validate_assert(state, (src->reg.indirect->is_ssa || 18101e04c3fSmrg src->reg.indirect->reg.indirect == NULL) && 18201e04c3fSmrg "only one level of indirection allowed"); 18301e04c3fSmrg validate_src(src->reg.indirect, state, 32, 1); 18401e04c3fSmrg } 18501e04c3fSmrg} 18601e04c3fSmrg 1877ec681f3Smrg#define SET_PTR_BIT(ptr, bit) \ 1887ec681f3Smrg (void *)(((uintptr_t)(ptr)) | (((uintptr_t)1) << bit)) 1897ec681f3Smrg 19001e04c3fSmrgstatic void 19101e04c3fSmrgvalidate_ssa_src(nir_src *src, validate_state *state, 1927e102996Smaya unsigned bit_sizes, unsigned num_components) 19301e04c3fSmrg{ 19401e04c3fSmrg validate_assert(state, src->ssa != NULL); 19501e04c3fSmrg 1967ec681f3Smrg /* As we walk SSA defs, we add every use to this set. We need to make sure 1977ec681f3Smrg * our use is seen in a use list. 1987ec681f3Smrg */ 1997ec681f3Smrg struct set_entry *entry; 20001e04c3fSmrg if (state->instr) { 2017ec681f3Smrg entry = _mesa_set_search(state->ssa_srcs, src); 20201e04c3fSmrg } else { 2037ec681f3Smrg entry = _mesa_set_search(state->ssa_srcs, SET_PTR_BIT(src, 0)); 20401e04c3fSmrg } 2057ec681f3Smrg validate_assert(state, entry); 2067ec681f3Smrg 2077ec681f3Smrg /* This will let us prove that we've seen all the sources */ 2087ec681f3Smrg if (entry) 2097ec681f3Smrg _mesa_set_remove(state->ssa_srcs, entry); 21001e04c3fSmrg 2117e102996Smaya if (bit_sizes) 2127e102996Smaya validate_assert(state, src->ssa->bit_size & bit_sizes); 21301e04c3fSmrg if (num_components) 21401e04c3fSmrg validate_assert(state, src->ssa->num_components == num_components); 21501e04c3fSmrg 21601e04c3fSmrg /* TODO validate that the use is dominated by the definition */ 21701e04c3fSmrg} 21801e04c3fSmrg 21901e04c3fSmrgstatic void 22001e04c3fSmrgvalidate_src(nir_src *src, validate_state *state, 2217e102996Smaya unsigned bit_sizes, unsigned num_components) 22201e04c3fSmrg{ 22301e04c3fSmrg if (state->instr) 22401e04c3fSmrg validate_assert(state, src->parent_instr == state->instr); 22501e04c3fSmrg else 22601e04c3fSmrg validate_assert(state, src->parent_if == state->if_stmt); 22701e04c3fSmrg 22801e04c3fSmrg if (src->is_ssa) 2297e102996Smaya validate_ssa_src(src, state, bit_sizes, num_components); 23001e04c3fSmrg else 2317e102996Smaya validate_reg_src(src, state, bit_sizes, num_components); 23201e04c3fSmrg} 23301e04c3fSmrg 23401e04c3fSmrgstatic void 23501e04c3fSmrgvalidate_alu_src(nir_alu_instr *instr, unsigned index, validate_state *state) 23601e04c3fSmrg{ 23701e04c3fSmrg nir_alu_src *src = &instr->src[index]; 23801e04c3fSmrg 2397ec681f3Smrg if (instr->op == nir_op_mov) 2407ec681f3Smrg assert(!src->abs && !src->negate); 2417ec681f3Smrg 24201e04c3fSmrg unsigned num_components = nir_src_num_components(src->src); 24301e04c3fSmrg for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++) { 24401e04c3fSmrg validate_assert(state, src->swizzle[i] < NIR_MAX_VEC_COMPONENTS); 24501e04c3fSmrg 24601e04c3fSmrg if (nir_alu_instr_channel_used(instr, index, i)) 24701e04c3fSmrg validate_assert(state, src->swizzle[i] < num_components); 24801e04c3fSmrg } 24901e04c3fSmrg 25001e04c3fSmrg validate_src(&src->src, state, 0, 0); 25101e04c3fSmrg} 25201e04c3fSmrg 25301e04c3fSmrgstatic void 25401e04c3fSmrgvalidate_reg_dest(nir_reg_dest *dest, validate_state *state, 2557e102996Smaya unsigned bit_sizes, unsigned num_components) 25601e04c3fSmrg{ 25701e04c3fSmrg validate_assert(state, dest->reg != NULL); 25801e04c3fSmrg 25901e04c3fSmrg validate_assert(state, dest->parent_instr == state->instr); 26001e04c3fSmrg 26101e04c3fSmrg struct hash_entry *entry2; 26201e04c3fSmrg entry2 = _mesa_hash_table_search(state->regs, dest->reg); 26301e04c3fSmrg 26401e04c3fSmrg validate_assert(state, entry2); 26501e04c3fSmrg 26601e04c3fSmrg reg_validate_state *reg_state = (reg_validate_state *) entry2->data; 26701e04c3fSmrg _mesa_set_add(reg_state->defs, dest); 26801e04c3fSmrg 2697e102996Smaya validate_assert(state, reg_state->where_defined == state->impl && 2707e102996Smaya "writing to a register declared in a different function"); 27101e04c3fSmrg 2727e102996Smaya if (bit_sizes) 2737e102996Smaya validate_assert(state, dest->reg->bit_size & bit_sizes); 2747e102996Smaya if (num_components) 2757e102996Smaya validate_assert(state, dest->reg->num_components == num_components); 27601e04c3fSmrg 27701e04c3fSmrg validate_assert(state, (dest->reg->num_array_elems == 0 || 27801e04c3fSmrg dest->base_offset < dest->reg->num_array_elems) && 27901e04c3fSmrg "definitely out-of-bounds array access"); 28001e04c3fSmrg 28101e04c3fSmrg if (dest->indirect) { 28201e04c3fSmrg validate_assert(state, dest->reg->num_array_elems != 0); 28301e04c3fSmrg validate_assert(state, (dest->indirect->is_ssa || dest->indirect->reg.indirect == NULL) && 28401e04c3fSmrg "only one level of indirection allowed"); 28501e04c3fSmrg validate_src(dest->indirect, state, 32, 1); 28601e04c3fSmrg } 28701e04c3fSmrg} 28801e04c3fSmrg 28901e04c3fSmrgstatic void 29001e04c3fSmrgvalidate_ssa_def(nir_ssa_def *def, validate_state *state) 29101e04c3fSmrg{ 29201e04c3fSmrg validate_assert(state, def->index < state->impl->ssa_alloc); 29301e04c3fSmrg validate_assert(state, !BITSET_TEST(state->ssa_defs_found, def->index)); 29401e04c3fSmrg BITSET_SET(state->ssa_defs_found, def->index); 29501e04c3fSmrg 29601e04c3fSmrg validate_assert(state, def->parent_instr == state->instr); 2977ec681f3Smrg validate_num_components(state, def->num_components); 29801e04c3fSmrg 29901e04c3fSmrg list_validate(&def->uses); 3007ec681f3Smrg nir_foreach_use(src, def) { 3017ec681f3Smrg validate_assert(state, src->is_ssa); 3027ec681f3Smrg validate_assert(state, src->ssa == def); 3037ec681f3Smrg bool already_seen = false; 3047ec681f3Smrg _mesa_set_search_and_add(state->ssa_srcs, src, &already_seen); 3057ec681f3Smrg /* A nir_src should only appear once and only in one SSA def use list */ 3067ec681f3Smrg validate_assert(state, !already_seen); 3077ec681f3Smrg } 30801e04c3fSmrg 3097ec681f3Smrg list_validate(&def->if_uses); 3107ec681f3Smrg nir_foreach_if_use(src, def) { 3117ec681f3Smrg validate_assert(state, src->is_ssa); 3127ec681f3Smrg validate_assert(state, src->ssa == def); 3137ec681f3Smrg bool already_seen = false; 3147ec681f3Smrg _mesa_set_search_and_add(state->ssa_srcs, SET_PTR_BIT(src, 0), 3157ec681f3Smrg &already_seen); 3167ec681f3Smrg /* A nir_src should only appear once and only in one SSA def use list */ 3177ec681f3Smrg validate_assert(state, !already_seen); 3187ec681f3Smrg } 31901e04c3fSmrg} 32001e04c3fSmrg 32101e04c3fSmrgstatic void 32201e04c3fSmrgvalidate_dest(nir_dest *dest, validate_state *state, 3237e102996Smaya unsigned bit_sizes, unsigned num_components) 32401e04c3fSmrg{ 32501e04c3fSmrg if (dest->is_ssa) { 3267e102996Smaya if (bit_sizes) 3277e102996Smaya validate_assert(state, dest->ssa.bit_size & bit_sizes); 32801e04c3fSmrg if (num_components) 32901e04c3fSmrg validate_assert(state, dest->ssa.num_components == num_components); 33001e04c3fSmrg validate_ssa_def(&dest->ssa, state); 33101e04c3fSmrg } else { 3327e102996Smaya validate_reg_dest(&dest->reg, state, bit_sizes, num_components); 33301e04c3fSmrg } 33401e04c3fSmrg} 33501e04c3fSmrg 33601e04c3fSmrgstatic void 33701e04c3fSmrgvalidate_alu_dest(nir_alu_instr *instr, validate_state *state) 33801e04c3fSmrg{ 33901e04c3fSmrg nir_alu_dest *dest = &instr->dest; 34001e04c3fSmrg 3417ec681f3Smrg if (instr->op == nir_op_mov) 3427ec681f3Smrg assert(!dest->saturate); 3437ec681f3Smrg 34401e04c3fSmrg unsigned dest_size = nir_dest_num_components(dest->dest); 34501e04c3fSmrg /* 34601e04c3fSmrg * validate that the instruction doesn't write to components not in the 34701e04c3fSmrg * register/SSA value 34801e04c3fSmrg */ 3497e102996Smaya validate_assert(state, !(dest->write_mask & ~((1 << dest_size) - 1))); 35001e04c3fSmrg 35101e04c3fSmrg /* validate that saturate is only ever used on instructions with 35201e04c3fSmrg * destinations of type float 35301e04c3fSmrg */ 35401e04c3fSmrg nir_alu_instr *alu = nir_instr_as_alu(state->instr); 35501e04c3fSmrg validate_assert(state, 35601e04c3fSmrg (nir_alu_type_get_base_type(nir_op_infos[alu->op].output_type) == 35701e04c3fSmrg nir_type_float) || 35801e04c3fSmrg !dest->saturate); 35901e04c3fSmrg 36001e04c3fSmrg validate_dest(&dest->dest, state, 0, 0); 36101e04c3fSmrg} 36201e04c3fSmrg 36301e04c3fSmrgstatic void 36401e04c3fSmrgvalidate_alu_instr(nir_alu_instr *instr, validate_state *state) 36501e04c3fSmrg{ 36601e04c3fSmrg validate_assert(state, instr->op < nir_num_opcodes); 36701e04c3fSmrg 36801e04c3fSmrg unsigned instr_bit_size = 0; 36901e04c3fSmrg for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) { 37001e04c3fSmrg nir_alu_type src_type = nir_op_infos[instr->op].input_types[i]; 37101e04c3fSmrg unsigned src_bit_size = nir_src_bit_size(instr->src[i].src); 37201e04c3fSmrg if (nir_alu_type_get_type_size(src_type)) { 37301e04c3fSmrg validate_assert(state, src_bit_size == nir_alu_type_get_type_size(src_type)); 37401e04c3fSmrg } else if (instr_bit_size) { 37501e04c3fSmrg validate_assert(state, src_bit_size == instr_bit_size); 37601e04c3fSmrg } else { 37701e04c3fSmrg instr_bit_size = src_bit_size; 37801e04c3fSmrg } 37901e04c3fSmrg 38001e04c3fSmrg if (nir_alu_type_get_base_type(src_type) == nir_type_float) { 38101e04c3fSmrg /* 8-bit float isn't a thing */ 38201e04c3fSmrg validate_assert(state, src_bit_size == 16 || src_bit_size == 32 || 38301e04c3fSmrg src_bit_size == 64); 38401e04c3fSmrg } 38501e04c3fSmrg 38601e04c3fSmrg validate_alu_src(instr, i, state); 38701e04c3fSmrg } 38801e04c3fSmrg 38901e04c3fSmrg nir_alu_type dest_type = nir_op_infos[instr->op].output_type; 39001e04c3fSmrg unsigned dest_bit_size = nir_dest_bit_size(instr->dest.dest); 39101e04c3fSmrg if (nir_alu_type_get_type_size(dest_type)) { 39201e04c3fSmrg validate_assert(state, dest_bit_size == nir_alu_type_get_type_size(dest_type)); 39301e04c3fSmrg } else if (instr_bit_size) { 39401e04c3fSmrg validate_assert(state, dest_bit_size == instr_bit_size); 39501e04c3fSmrg } else { 39601e04c3fSmrg /* The only unsized thing is the destination so it's vacuously valid */ 39701e04c3fSmrg } 39801e04c3fSmrg 39901e04c3fSmrg if (nir_alu_type_get_base_type(dest_type) == nir_type_float) { 40001e04c3fSmrg /* 8-bit float isn't a thing */ 40101e04c3fSmrg validate_assert(state, dest_bit_size == 16 || dest_bit_size == 32 || 40201e04c3fSmrg dest_bit_size == 64); 40301e04c3fSmrg } 40401e04c3fSmrg 40501e04c3fSmrg validate_alu_dest(instr, state); 40601e04c3fSmrg} 40701e04c3fSmrg 40801e04c3fSmrgstatic void 40901e04c3fSmrgvalidate_var_use(nir_variable *var, validate_state *state) 41001e04c3fSmrg{ 41101e04c3fSmrg struct hash_entry *entry = _mesa_hash_table_search(state->var_defs, var); 41201e04c3fSmrg validate_assert(state, entry); 4137ec681f3Smrg if (entry && var->data.mode == nir_var_function_temp) 41401e04c3fSmrg validate_assert(state, (nir_function_impl *) entry->data == state->impl); 41501e04c3fSmrg} 41601e04c3fSmrg 41701e04c3fSmrgstatic void 41801e04c3fSmrgvalidate_deref_instr(nir_deref_instr *instr, validate_state *state) 41901e04c3fSmrg{ 42001e04c3fSmrg if (instr->deref_type == nir_deref_type_var) { 42101e04c3fSmrg /* Variable dereferences are stupid simple. */ 4227ec681f3Smrg validate_assert(state, instr->modes == instr->var->data.mode); 42301e04c3fSmrg validate_assert(state, instr->type == instr->var->type); 42401e04c3fSmrg validate_var_use(instr->var, state); 42501e04c3fSmrg } else if (instr->deref_type == nir_deref_type_cast) { 42601e04c3fSmrg /* For cast, we simply have to trust the instruction. It's up to 42701e04c3fSmrg * lowering passes and front/back-ends to make them sane. 42801e04c3fSmrg */ 42901e04c3fSmrg validate_src(&instr->parent, state, 0, 0); 43001e04c3fSmrg 4317ec681f3Smrg /* Most variable modes in NIR can only exist by themselves. */ 4327ec681f3Smrg if (instr->modes & ~nir_var_mem_generic) 4337ec681f3Smrg validate_assert(state, util_bitcount(instr->modes) == 1); 4347ec681f3Smrg 4357ec681f3Smrg nir_deref_instr *parent = nir_src_as_deref(instr->parent); 4367ec681f3Smrg if (parent) { 4377ec681f3Smrg /* Casts can change the mode but it can't change completely. The new 4387ec681f3Smrg * mode must have some bits in common with the old. 4397ec681f3Smrg */ 4407ec681f3Smrg validate_assert(state, instr->modes & parent->modes); 4417ec681f3Smrg } else { 4427ec681f3Smrg /* If our parent isn't a deref, just assert the mode is there */ 4437ec681f3Smrg validate_assert(state, instr->modes != 0); 4447ec681f3Smrg } 4457ec681f3Smrg 4467ec681f3Smrg /* We just validate that the type is there */ 44701e04c3fSmrg validate_assert(state, instr->type); 4487ec681f3Smrg if (instr->cast.align_mul > 0) { 4497ec681f3Smrg validate_assert(state, util_is_power_of_two_nonzero(instr->cast.align_mul)); 4507ec681f3Smrg validate_assert(state, instr->cast.align_offset < instr->cast.align_mul); 4517ec681f3Smrg } else { 4527ec681f3Smrg validate_assert(state, instr->cast.align_offset == 0); 4537ec681f3Smrg } 45401e04c3fSmrg } else { 45501e04c3fSmrg /* We require the parent to be SSA. This may be lifted in the future */ 45601e04c3fSmrg validate_assert(state, instr->parent.is_ssa); 45701e04c3fSmrg 45801e04c3fSmrg /* The parent pointer value must have the same number of components 45901e04c3fSmrg * as the destination. 46001e04c3fSmrg */ 46101e04c3fSmrg validate_src(&instr->parent, state, nir_dest_bit_size(instr->dest), 46201e04c3fSmrg nir_dest_num_components(instr->dest)); 46301e04c3fSmrg 46401e04c3fSmrg nir_instr *parent_instr = instr->parent.ssa->parent_instr; 46501e04c3fSmrg 46601e04c3fSmrg /* The parent must come from another deref instruction */ 46701e04c3fSmrg validate_assert(state, parent_instr->type == nir_instr_type_deref); 46801e04c3fSmrg 46901e04c3fSmrg nir_deref_instr *parent = nir_instr_as_deref(parent_instr); 47001e04c3fSmrg 4717ec681f3Smrg validate_assert(state, instr->modes == parent->modes); 47201e04c3fSmrg 47301e04c3fSmrg switch (instr->deref_type) { 47401e04c3fSmrg case nir_deref_type_struct: 4757e102996Smaya validate_assert(state, glsl_type_is_struct_or_ifc(parent->type)); 47601e04c3fSmrg validate_assert(state, 47701e04c3fSmrg instr->strct.index < glsl_get_length(parent->type)); 47801e04c3fSmrg validate_assert(state, instr->type == 47901e04c3fSmrg glsl_get_struct_field(parent->type, instr->strct.index)); 48001e04c3fSmrg break; 48101e04c3fSmrg 48201e04c3fSmrg case nir_deref_type_array: 48301e04c3fSmrg case nir_deref_type_array_wildcard: 4847ec681f3Smrg if (instr->modes & nir_var_vec_indexable_modes) { 4857e102996Smaya /* Shared variables and UBO/SSBOs have a bit more relaxed rules 4867e102996Smaya * because we need to be able to handle array derefs on vectors. 4877e102996Smaya * Fortunately, nir_lower_io handles these just fine. 48801e04c3fSmrg */ 48901e04c3fSmrg validate_assert(state, glsl_type_is_array(parent->type) || 49001e04c3fSmrg glsl_type_is_matrix(parent->type) || 49101e04c3fSmrg glsl_type_is_vector(parent->type)); 49201e04c3fSmrg } else { 49301e04c3fSmrg /* Most of NIR cannot handle array derefs on vectors */ 49401e04c3fSmrg validate_assert(state, glsl_type_is_array(parent->type) || 49501e04c3fSmrg glsl_type_is_matrix(parent->type)); 49601e04c3fSmrg } 49701e04c3fSmrg validate_assert(state, 49801e04c3fSmrg instr->type == glsl_get_array_element(parent->type)); 49901e04c3fSmrg 5007e102996Smaya if (instr->deref_type == nir_deref_type_array) { 5017e102996Smaya validate_src(&instr->arr.index, state, 5027e102996Smaya nir_dest_bit_size(instr->dest), 1); 5037e102996Smaya } 5047e102996Smaya break; 5057e102996Smaya 5067e102996Smaya case nir_deref_type_ptr_as_array: 5077e102996Smaya /* ptr_as_array derefs must have a parent that is either an array, 5087e102996Smaya * ptr_as_array, or cast. If the parent is a cast, we get the stride 5097e102996Smaya * information (if any) from the cast deref. 5107e102996Smaya */ 5117e102996Smaya validate_assert(state, 5127e102996Smaya parent->deref_type == nir_deref_type_array || 5137e102996Smaya parent->deref_type == nir_deref_type_ptr_as_array || 5147e102996Smaya parent->deref_type == nir_deref_type_cast); 5157e102996Smaya validate_src(&instr->arr.index, state, 5167e102996Smaya nir_dest_bit_size(instr->dest), 1); 51701e04c3fSmrg break; 51801e04c3fSmrg 51901e04c3fSmrg default: 52001e04c3fSmrg unreachable("Invalid deref instruction type"); 52101e04c3fSmrg } 52201e04c3fSmrg } 52301e04c3fSmrg 52401e04c3fSmrg /* We intentionally don't validate the size of the destination because we 52501e04c3fSmrg * want to let other compiler components such as SPIR-V decide how big 52601e04c3fSmrg * pointers should be. 52701e04c3fSmrg */ 52801e04c3fSmrg validate_dest(&instr->dest, state, 0, 0); 5297e102996Smaya 5307e102996Smaya /* Deref instructions as if conditions don't make sense because if 5317e102996Smaya * conditions expect well-formed Booleans. If you want to compare with 5327e102996Smaya * NULL, an explicit comparison operation should be used. 5337e102996Smaya */ 5347ec681f3Smrg validate_assert(state, list_is_empty(&instr->dest.ssa.if_uses)); 5357ec681f3Smrg 5367ec681f3Smrg /* Certain modes cannot be used as sources for phi instructions because 5377ec681f3Smrg * way too many passes assume that they can always chase deref chains. 5387ec681f3Smrg */ 5397ec681f3Smrg nir_foreach_use(use, &instr->dest.ssa) { 5407ec681f3Smrg if (use->parent_instr->type == nir_instr_type_phi) { 5417ec681f3Smrg validate_assert(state, !(instr->modes & (nir_var_shader_in | 5427ec681f3Smrg nir_var_shader_out | 5437ec681f3Smrg nir_var_shader_out | 5447ec681f3Smrg nir_var_uniform))); 5457ec681f3Smrg } 5467ec681f3Smrg } 5477ec681f3Smrg} 5487ec681f3Smrg 5497ec681f3Smrgstatic bool 5507ec681f3Smrgvectorized_intrinsic(nir_intrinsic_instr *intr) 5517ec681f3Smrg{ 5527ec681f3Smrg const nir_intrinsic_info *info = &nir_intrinsic_infos[intr->intrinsic]; 5537ec681f3Smrg 5547ec681f3Smrg if (info->dest_components == 0) 5557ec681f3Smrg return true; 5567ec681f3Smrg 5577ec681f3Smrg for (unsigned i = 0; i < info->num_srcs; i++) 5587ec681f3Smrg if (info->src_components[i] == 0) 5597ec681f3Smrg return true; 5607ec681f3Smrg 5617ec681f3Smrg return false; 5627ec681f3Smrg} 5637ec681f3Smrg 5647ec681f3Smrg/** Returns the image format or PIPE_FORMAT_COUNT for incomplete derefs 5657ec681f3Smrg * 5667ec681f3Smrg * We use PIPE_FORMAT_COUNT for incomplete derefs because PIPE_FORMAT_NONE 5677ec681f3Smrg * indicates that we found the variable but it has no format specified. 5687ec681f3Smrg */ 5697ec681f3Smrgstatic enum pipe_format 5707ec681f3Smrgimage_intrin_format(nir_intrinsic_instr *instr) 5717ec681f3Smrg{ 5727ec681f3Smrg if (nir_intrinsic_format(instr) != PIPE_FORMAT_NONE) 5737ec681f3Smrg return nir_intrinsic_format(instr); 5747ec681f3Smrg 5757ec681f3Smrg /* If this not a deref intrinsic, PIPE_FORMAT_NONE is the best we can do */ 5767ec681f3Smrg if (nir_intrinsic_infos[instr->intrinsic].src_components[0] != -1) 5777ec681f3Smrg return PIPE_FORMAT_NONE; 5787ec681f3Smrg 5797ec681f3Smrg nir_variable *var = nir_intrinsic_get_var(instr, 0); 5807ec681f3Smrg if (var == NULL) 5817ec681f3Smrg return PIPE_FORMAT_COUNT; 5827ec681f3Smrg 5837ec681f3Smrg return var->data.image.format; 58401e04c3fSmrg} 58501e04c3fSmrg 58601e04c3fSmrgstatic void 58701e04c3fSmrgvalidate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state) 58801e04c3fSmrg{ 58901e04c3fSmrg unsigned dest_bit_size = 0; 59001e04c3fSmrg unsigned src_bit_sizes[NIR_INTRINSIC_MAX_INPUTS] = { 0, }; 59101e04c3fSmrg switch (instr->intrinsic) { 5927ec681f3Smrg case nir_intrinsic_convert_alu_types: { 5937ec681f3Smrg nir_alu_type src_type = nir_intrinsic_src_type(instr); 5947ec681f3Smrg nir_alu_type dest_type = nir_intrinsic_dest_type(instr); 5957ec681f3Smrg dest_bit_size = nir_alu_type_get_type_size(dest_type); 5967ec681f3Smrg src_bit_sizes[0] = nir_alu_type_get_type_size(src_type); 5977ec681f3Smrg validate_assert(state, dest_bit_size != 0); 5987ec681f3Smrg validate_assert(state, src_bit_sizes[0] != 0); 5997ec681f3Smrg break; 6007ec681f3Smrg } 6017ec681f3Smrg 60201e04c3fSmrg case nir_intrinsic_load_param: { 60301e04c3fSmrg unsigned param_idx = nir_intrinsic_param_idx(instr); 60401e04c3fSmrg validate_assert(state, param_idx < state->impl->function->num_params); 60501e04c3fSmrg nir_parameter *param = &state->impl->function->params[param_idx]; 60601e04c3fSmrg validate_assert(state, instr->num_components == param->num_components); 60701e04c3fSmrg dest_bit_size = param->bit_size; 60801e04c3fSmrg break; 60901e04c3fSmrg } 61001e04c3fSmrg 61101e04c3fSmrg case nir_intrinsic_load_deref: { 61201e04c3fSmrg nir_deref_instr *src = nir_src_as_deref(instr->src[0]); 6137ec681f3Smrg assert(src); 61401e04c3fSmrg validate_assert(state, glsl_type_is_vector_or_scalar(src->type) || 6157ec681f3Smrg (src->modes == nir_var_uniform && 61601e04c3fSmrg glsl_get_base_type(src->type) == GLSL_TYPE_SUBROUTINE)); 61701e04c3fSmrg validate_assert(state, instr->num_components == 61801e04c3fSmrg glsl_get_vector_elements(src->type)); 61901e04c3fSmrg dest_bit_size = glsl_get_bit_size(src->type); 6207e102996Smaya /* Also allow 32-bit boolean load operations */ 6217e102996Smaya if (glsl_type_is_boolean(src->type)) 6227e102996Smaya dest_bit_size |= 32; 62301e04c3fSmrg break; 62401e04c3fSmrg } 62501e04c3fSmrg 62601e04c3fSmrg case nir_intrinsic_store_deref: { 62701e04c3fSmrg nir_deref_instr *dst = nir_src_as_deref(instr->src[0]); 6287ec681f3Smrg assert(dst); 62901e04c3fSmrg validate_assert(state, glsl_type_is_vector_or_scalar(dst->type)); 63001e04c3fSmrg validate_assert(state, instr->num_components == 63101e04c3fSmrg glsl_get_vector_elements(dst->type)); 63201e04c3fSmrg src_bit_sizes[1] = glsl_get_bit_size(dst->type); 6337e102996Smaya /* Also allow 32-bit boolean store operations */ 6347e102996Smaya if (glsl_type_is_boolean(dst->type)) 6357e102996Smaya src_bit_sizes[1] |= 32; 6367ec681f3Smrg validate_assert(state, !nir_deref_mode_may_be(dst, nir_var_read_only_modes)); 63701e04c3fSmrg validate_assert(state, (nir_intrinsic_write_mask(instr) & ~((1 << instr->num_components) - 1)) == 0); 63801e04c3fSmrg break; 63901e04c3fSmrg } 64001e04c3fSmrg 64101e04c3fSmrg case nir_intrinsic_copy_deref: { 64201e04c3fSmrg nir_deref_instr *dst = nir_src_as_deref(instr->src[0]); 64301e04c3fSmrg nir_deref_instr *src = nir_src_as_deref(instr->src[1]); 6447e102996Smaya validate_assert(state, glsl_get_bare_type(dst->type) == 6457e102996Smaya glsl_get_bare_type(src->type)); 6467ec681f3Smrg validate_assert(state, !nir_deref_mode_may_be(dst, nir_var_read_only_modes)); 6477ec681f3Smrg break; 6487ec681f3Smrg } 6497ec681f3Smrg 6507ec681f3Smrg case nir_intrinsic_load_ubo_vec4: { 6517ec681f3Smrg int bit_size = nir_dest_bit_size(instr->dest); 6527ec681f3Smrg validate_assert(state, bit_size >= 8); 6537ec681f3Smrg validate_assert(state, (nir_intrinsic_component(instr) + 6547ec681f3Smrg instr->num_components) * (bit_size / 8) <= 16); 6557ec681f3Smrg break; 6567ec681f3Smrg } 6577ec681f3Smrg 6587ec681f3Smrg case nir_intrinsic_load_ubo: 6597ec681f3Smrg /* Make sure that the creator didn't forget to set the range_base+range. */ 6607ec681f3Smrg validate_assert(state, nir_intrinsic_range(instr) != 0); 6617ec681f3Smrg FALLTHROUGH; 6627ec681f3Smrg case nir_intrinsic_load_ssbo: 6637ec681f3Smrg case nir_intrinsic_load_shared: 6647ec681f3Smrg case nir_intrinsic_load_global: 6657ec681f3Smrg case nir_intrinsic_load_global_constant: 6667ec681f3Smrg case nir_intrinsic_load_scratch: 6677ec681f3Smrg case nir_intrinsic_load_constant: 6687ec681f3Smrg /* These memory load operations must have alignments */ 6697ec681f3Smrg validate_assert(state, 6707ec681f3Smrg util_is_power_of_two_nonzero(nir_intrinsic_align_mul(instr))); 6717ec681f3Smrg validate_assert(state, nir_intrinsic_align_offset(instr) < 6727ec681f3Smrg nir_intrinsic_align_mul(instr)); 6737ec681f3Smrg FALLTHROUGH; 6747ec681f3Smrg 6757ec681f3Smrg case nir_intrinsic_load_uniform: 6767ec681f3Smrg case nir_intrinsic_load_input: 6777ec681f3Smrg case nir_intrinsic_load_per_vertex_input: 6787ec681f3Smrg case nir_intrinsic_load_interpolated_input: 6797ec681f3Smrg case nir_intrinsic_load_output: 6807ec681f3Smrg case nir_intrinsic_load_per_vertex_output: 6817ec681f3Smrg case nir_intrinsic_load_per_primitive_output: 6827ec681f3Smrg case nir_intrinsic_load_push_constant: 6837ec681f3Smrg /* All memory load operations must load at least a byte */ 6847ec681f3Smrg validate_assert(state, nir_dest_bit_size(instr->dest) >= 8); 6857ec681f3Smrg break; 6867ec681f3Smrg 6877ec681f3Smrg case nir_intrinsic_store_ssbo: 6887ec681f3Smrg case nir_intrinsic_store_shared: 6897ec681f3Smrg case nir_intrinsic_store_global: 6907ec681f3Smrg case nir_intrinsic_store_scratch: 6917ec681f3Smrg /* These memory store operations must also have alignments */ 6927ec681f3Smrg validate_assert(state, 6937ec681f3Smrg util_is_power_of_two_nonzero(nir_intrinsic_align_mul(instr))); 6947ec681f3Smrg validate_assert(state, nir_intrinsic_align_offset(instr) < 6957ec681f3Smrg nir_intrinsic_align_mul(instr)); 6967ec681f3Smrg FALLTHROUGH; 6977ec681f3Smrg 6987ec681f3Smrg case nir_intrinsic_store_output: 6997ec681f3Smrg case nir_intrinsic_store_per_vertex_output: 7007ec681f3Smrg /* All memory store operations must store at least a byte */ 7017ec681f3Smrg validate_assert(state, nir_src_bit_size(instr->src[0]) >= 8); 7027ec681f3Smrg break; 7037ec681f3Smrg 7047ec681f3Smrg case nir_intrinsic_deref_mode_is: 7057ec681f3Smrg case nir_intrinsic_addr_mode_is: 7067ec681f3Smrg validate_assert(state, 7077ec681f3Smrg util_bitcount(nir_intrinsic_memory_modes(instr)) == 1); 7087ec681f3Smrg break; 7097ec681f3Smrg 7107ec681f3Smrg case nir_intrinsic_image_deref_atomic_add: 7117ec681f3Smrg case nir_intrinsic_image_deref_atomic_imin: 7127ec681f3Smrg case nir_intrinsic_image_deref_atomic_umin: 7137ec681f3Smrg case nir_intrinsic_image_deref_atomic_imax: 7147ec681f3Smrg case nir_intrinsic_image_deref_atomic_umax: 7157ec681f3Smrg case nir_intrinsic_image_deref_atomic_and: 7167ec681f3Smrg case nir_intrinsic_image_deref_atomic_or: 7177ec681f3Smrg case nir_intrinsic_image_deref_atomic_xor: 7187ec681f3Smrg case nir_intrinsic_image_deref_atomic_comp_swap: 7197ec681f3Smrg case nir_intrinsic_image_atomic_add: 7207ec681f3Smrg case nir_intrinsic_image_atomic_imin: 7217ec681f3Smrg case nir_intrinsic_image_atomic_umin: 7227ec681f3Smrg case nir_intrinsic_image_atomic_imax: 7237ec681f3Smrg case nir_intrinsic_image_atomic_umax: 7247ec681f3Smrg case nir_intrinsic_image_atomic_and: 7257ec681f3Smrg case nir_intrinsic_image_atomic_or: 7267ec681f3Smrg case nir_intrinsic_image_atomic_xor: 7277ec681f3Smrg case nir_intrinsic_image_atomic_comp_swap: 7287ec681f3Smrg case nir_intrinsic_bindless_image_atomic_add: 7297ec681f3Smrg case nir_intrinsic_bindless_image_atomic_imin: 7307ec681f3Smrg case nir_intrinsic_bindless_image_atomic_umin: 7317ec681f3Smrg case nir_intrinsic_bindless_image_atomic_imax: 7327ec681f3Smrg case nir_intrinsic_bindless_image_atomic_umax: 7337ec681f3Smrg case nir_intrinsic_bindless_image_atomic_and: 7347ec681f3Smrg case nir_intrinsic_bindless_image_atomic_or: 7357ec681f3Smrg case nir_intrinsic_bindless_image_atomic_xor: 7367ec681f3Smrg case nir_intrinsic_bindless_image_atomic_comp_swap: { 7377ec681f3Smrg enum pipe_format format = image_intrin_format(instr); 7387ec681f3Smrg if (format != PIPE_FORMAT_COUNT) { 7397ec681f3Smrg validate_assert(state, format == PIPE_FORMAT_R32_UINT || 7407ec681f3Smrg format == PIPE_FORMAT_R32_SINT || 7417ec681f3Smrg format == PIPE_FORMAT_R64_UINT || 7427ec681f3Smrg format == PIPE_FORMAT_R64_SINT); 7437ec681f3Smrg validate_assert(state, nir_dest_bit_size(instr->dest) == 7447ec681f3Smrg util_format_get_blocksizebits(format)); 7457ec681f3Smrg } 7467ec681f3Smrg break; 7477ec681f3Smrg } 7487ec681f3Smrg 7497ec681f3Smrg case nir_intrinsic_image_deref_atomic_exchange: 7507ec681f3Smrg case nir_intrinsic_image_atomic_exchange: 7517ec681f3Smrg case nir_intrinsic_bindless_image_atomic_exchange: { 7527ec681f3Smrg enum pipe_format format = image_intrin_format(instr); 7537ec681f3Smrg if (format != PIPE_FORMAT_COUNT) { 7547ec681f3Smrg validate_assert(state, format == PIPE_FORMAT_R32_UINT || 7557ec681f3Smrg format == PIPE_FORMAT_R32_SINT || 7567ec681f3Smrg format == PIPE_FORMAT_R32_FLOAT || 7577ec681f3Smrg format == PIPE_FORMAT_R64_UINT || 7587ec681f3Smrg format == PIPE_FORMAT_R64_SINT); 7597ec681f3Smrg validate_assert(state, nir_dest_bit_size(instr->dest) == 7607ec681f3Smrg util_format_get_blocksizebits(format)); 7617ec681f3Smrg } 7627ec681f3Smrg break; 7637ec681f3Smrg } 7647ec681f3Smrg 7657ec681f3Smrg case nir_intrinsic_image_deref_atomic_fadd: 7667ec681f3Smrg case nir_intrinsic_image_atomic_fadd: 7677ec681f3Smrg case nir_intrinsic_bindless_image_atomic_fadd: { 7687ec681f3Smrg enum pipe_format format = image_intrin_format(instr); 7697ec681f3Smrg validate_assert(state, format == PIPE_FORMAT_COUNT || 7707ec681f3Smrg format == PIPE_FORMAT_R32_FLOAT); 7717ec681f3Smrg validate_assert(state, nir_dest_bit_size(instr->dest) == 32); 7727ec681f3Smrg break; 7737ec681f3Smrg } 7747ec681f3Smrg 7757ec681f3Smrg case nir_intrinsic_image_deref_atomic_fmin: 7767ec681f3Smrg case nir_intrinsic_image_deref_atomic_fmax: 7777ec681f3Smrg case nir_intrinsic_image_atomic_fmin: 7787ec681f3Smrg case nir_intrinsic_image_atomic_fmax: 7797ec681f3Smrg case nir_intrinsic_bindless_image_atomic_fmin: 7807ec681f3Smrg case nir_intrinsic_bindless_image_atomic_fmax: { 7817ec681f3Smrg enum pipe_format format = image_intrin_format(instr); 7827ec681f3Smrg validate_assert(state, format == PIPE_FORMAT_COUNT || 7837ec681f3Smrg format == PIPE_FORMAT_R16_FLOAT || 7847ec681f3Smrg format == PIPE_FORMAT_R32_FLOAT || 7857ec681f3Smrg format == PIPE_FORMAT_R64_FLOAT); 7867ec681f3Smrg validate_assert(state, nir_dest_bit_size(instr->dest) == 7877ec681f3Smrg util_format_get_blocksizebits(format)); 78801e04c3fSmrg break; 78901e04c3fSmrg } 79001e04c3fSmrg 79101e04c3fSmrg default: 79201e04c3fSmrg break; 79301e04c3fSmrg } 79401e04c3fSmrg 7957ec681f3Smrg if (instr->num_components > 0) 7967ec681f3Smrg validate_num_components(state, instr->num_components); 7977ec681f3Smrg 7987ec681f3Smrg const nir_intrinsic_info *info = &nir_intrinsic_infos[instr->intrinsic]; 7997ec681f3Smrg unsigned num_srcs = info->num_srcs; 80001e04c3fSmrg for (unsigned i = 0; i < num_srcs; i++) { 80101e04c3fSmrg unsigned components_read = nir_intrinsic_src_components(instr, i); 80201e04c3fSmrg 8037ec681f3Smrg validate_num_components(state, components_read); 80401e04c3fSmrg 80501e04c3fSmrg validate_src(&instr->src[i], state, src_bit_sizes[i], components_read); 80601e04c3fSmrg } 80701e04c3fSmrg 80801e04c3fSmrg if (nir_intrinsic_infos[instr->intrinsic].has_dest) { 80901e04c3fSmrg unsigned components_written = nir_intrinsic_dest_components(instr); 8107ec681f3Smrg unsigned bit_sizes = info->dest_bit_sizes; 8117ec681f3Smrg if (!bit_sizes && info->bit_size_src >= 0) 8127ec681f3Smrg bit_sizes = nir_src_bit_size(instr->src[info->bit_size_src]); 81301e04c3fSmrg 8147ec681f3Smrg validate_num_components(state, components_written); 8157e102996Smaya if (dest_bit_size && bit_sizes) 8167e102996Smaya validate_assert(state, dest_bit_size & bit_sizes); 8177e102996Smaya else 8187e102996Smaya dest_bit_size = dest_bit_size ? dest_bit_size : bit_sizes; 8197e102996Smaya 82001e04c3fSmrg validate_dest(&instr->dest, state, dest_bit_size, components_written); 82101e04c3fSmrg } 8227ec681f3Smrg 8237ec681f3Smrg if (!vectorized_intrinsic(instr)) 8247ec681f3Smrg validate_assert(state, instr->num_components == 0); 82501e04c3fSmrg} 82601e04c3fSmrg 82701e04c3fSmrgstatic void 82801e04c3fSmrgvalidate_tex_instr(nir_tex_instr *instr, validate_state *state) 82901e04c3fSmrg{ 83001e04c3fSmrg bool src_type_seen[nir_num_tex_src_types]; 83101e04c3fSmrg for (unsigned i = 0; i < nir_num_tex_src_types; i++) 83201e04c3fSmrg src_type_seen[i] = false; 83301e04c3fSmrg 83401e04c3fSmrg for (unsigned i = 0; i < instr->num_srcs; i++) { 83501e04c3fSmrg validate_assert(state, !src_type_seen[instr->src[i].src_type]); 83601e04c3fSmrg src_type_seen[instr->src[i].src_type] = true; 83701e04c3fSmrg validate_src(&instr->src[i].src, state, 83801e04c3fSmrg 0, nir_tex_instr_src_size(instr, i)); 8397e102996Smaya 8407e102996Smaya switch (instr->src[i].src_type) { 8417ec681f3Smrg case nir_tex_src_coord: 8427ec681f3Smrg validate_assert(state, nir_src_num_components(instr->src[i].src) == 8437ec681f3Smrg instr->coord_components); 8447ec681f3Smrg break; 8457ec681f3Smrg 8467ec681f3Smrg case nir_tex_src_projector: 8477ec681f3Smrg validate_assert(state, nir_src_num_components(instr->src[i].src) == 1); 8487ec681f3Smrg break; 8497ec681f3Smrg 8507ec681f3Smrg case nir_tex_src_comparator: 8517ec681f3Smrg validate_assert(state, instr->is_shadow); 8527ec681f3Smrg validate_assert(state, nir_src_num_components(instr->src[i].src) == 1); 8537ec681f3Smrg break; 8547ec681f3Smrg 8557ec681f3Smrg case nir_tex_src_offset: 8567ec681f3Smrg validate_assert(state, nir_src_num_components(instr->src[i].src) == 8577ec681f3Smrg instr->coord_components - instr->is_array); 8587ec681f3Smrg break; 8597ec681f3Smrg 8607ec681f3Smrg case nir_tex_src_bias: 8617ec681f3Smrg validate_assert(state, instr->op == nir_texop_txb || 8627ec681f3Smrg instr->op == nir_texop_tg4); 8637ec681f3Smrg validate_assert(state, nir_src_num_components(instr->src[i].src) == 1); 8647ec681f3Smrg break; 8657ec681f3Smrg 8667ec681f3Smrg case nir_tex_src_lod: 8677ec681f3Smrg validate_assert(state, instr->op != nir_texop_tex && 8687ec681f3Smrg instr->op != nir_texop_txb && 8697ec681f3Smrg instr->op != nir_texop_txd && 8707ec681f3Smrg instr->op != nir_texop_lod); 8717ec681f3Smrg validate_assert(state, nir_src_num_components(instr->src[i].src) == 1); 8727ec681f3Smrg break; 8737ec681f3Smrg 8747ec681f3Smrg case nir_tex_src_min_lod: 8757ec681f3Smrg case nir_tex_src_ms_index: 8767ec681f3Smrg validate_assert(state, nir_src_num_components(instr->src[i].src) == 1); 8777ec681f3Smrg break; 8787ec681f3Smrg 8797ec681f3Smrg case nir_tex_src_ddx: 8807ec681f3Smrg case nir_tex_src_ddy: 8817ec681f3Smrg validate_assert(state, instr->op == nir_texop_txd); 8827ec681f3Smrg validate_assert(state, nir_src_num_components(instr->src[i].src) == 8837ec681f3Smrg instr->coord_components - instr->is_array); 8847ec681f3Smrg break; 8857ec681f3Smrg 8867ec681f3Smrg case nir_tex_src_texture_deref: { 8877ec681f3Smrg nir_deref_instr *deref = nir_src_as_deref(instr->src[i].src); 8887ec681f3Smrg if (!validate_assert(state, deref)) 8897ec681f3Smrg break; 8907ec681f3Smrg 8917ec681f3Smrg validate_assert(state, glsl_type_is_image(deref->type) || 8927ec681f3Smrg glsl_type_is_sampler(deref->type)); 8937ec681f3Smrg break; 8947ec681f3Smrg } 8957ec681f3Smrg 8967ec681f3Smrg case nir_tex_src_sampler_deref: { 8977ec681f3Smrg nir_deref_instr *deref = nir_src_as_deref(instr->src[i].src); 8987ec681f3Smrg if (!validate_assert(state, deref)) 8997ec681f3Smrg break; 9007ec681f3Smrg 9017ec681f3Smrg validate_assert(state, glsl_type_is_sampler(deref->type)); 9027ec681f3Smrg break; 9037ec681f3Smrg } 9047ec681f3Smrg 9057ec681f3Smrg case nir_tex_src_texture_offset: 9067ec681f3Smrg case nir_tex_src_sampler_offset: 9077ec681f3Smrg case nir_tex_src_plane: 9087ec681f3Smrg validate_assert(state, nir_src_num_components(instr->src[i].src) == 1); 9097e102996Smaya break; 9107ec681f3Smrg 9117ec681f3Smrg case nir_tex_src_texture_handle: 9127ec681f3Smrg case nir_tex_src_sampler_handle: 9137ec681f3Smrg break; 9147ec681f3Smrg 9157e102996Smaya default: 9167e102996Smaya break; 9177e102996Smaya } 9187e102996Smaya } 9197e102996Smaya 9207ec681f3Smrg if (instr->op != nir_texop_tg4) 9217ec681f3Smrg validate_assert(state, instr->component == 0); 9227ec681f3Smrg 9237e102996Smaya if (nir_tex_instr_has_explicit_tg4_offsets(instr)) { 9247e102996Smaya validate_assert(state, instr->op == nir_texop_tg4); 9257e102996Smaya validate_assert(state, !src_type_seen[nir_tex_src_offset]); 92601e04c3fSmrg } 92701e04c3fSmrg 92801e04c3fSmrg validate_dest(&instr->dest, state, 0, nir_tex_instr_dest_size(instr)); 9297ec681f3Smrg 9307ec681f3Smrg validate_assert(state, 9317ec681f3Smrg nir_alu_type_get_type_size(instr->dest_type) == 9327ec681f3Smrg nir_dest_bit_size(instr->dest)); 93301e04c3fSmrg} 93401e04c3fSmrg 93501e04c3fSmrgstatic void 93601e04c3fSmrgvalidate_call_instr(nir_call_instr *instr, validate_state *state) 93701e04c3fSmrg{ 93801e04c3fSmrg validate_assert(state, instr->num_params == instr->callee->num_params); 93901e04c3fSmrg 94001e04c3fSmrg for (unsigned i = 0; i < instr->num_params; i++) { 94101e04c3fSmrg validate_src(&instr->params[i], state, 94201e04c3fSmrg instr->callee->params[i].bit_size, 94301e04c3fSmrg instr->callee->params[i].num_components); 94401e04c3fSmrg } 94501e04c3fSmrg} 94601e04c3fSmrg 9477e102996Smayastatic void 9487e102996Smayavalidate_const_value(nir_const_value *val, unsigned bit_size, 9497e102996Smaya validate_state *state) 9507e102996Smaya{ 9517e102996Smaya /* In order for block copies to work properly for things like instruction 9527e102996Smaya * comparisons and [de]serialization, we require the unused bits of the 9537e102996Smaya * nir_const_value to be zero. 9547e102996Smaya */ 9557e102996Smaya nir_const_value cmp_val; 9567e102996Smaya memset(&cmp_val, 0, sizeof(cmp_val)); 9577e102996Smaya switch (bit_size) { 9587e102996Smaya case 1: 9597e102996Smaya cmp_val.b = val->b; 9607e102996Smaya break; 9617e102996Smaya case 8: 9627e102996Smaya cmp_val.u8 = val->u8; 9637e102996Smaya break; 9647e102996Smaya case 16: 9657e102996Smaya cmp_val.u16 = val->u16; 9667e102996Smaya break; 9677e102996Smaya case 32: 9687e102996Smaya cmp_val.u32 = val->u32; 9697e102996Smaya break; 9707e102996Smaya case 64: 9717e102996Smaya cmp_val.u64 = val->u64; 9727e102996Smaya break; 9737e102996Smaya default: 9747e102996Smaya validate_assert(state, !"Invalid load_const bit size"); 9757e102996Smaya } 9767e102996Smaya validate_assert(state, memcmp(val, &cmp_val, sizeof(cmp_val)) == 0); 9777e102996Smaya} 9787e102996Smaya 97901e04c3fSmrgstatic void 98001e04c3fSmrgvalidate_load_const_instr(nir_load_const_instr *instr, validate_state *state) 98101e04c3fSmrg{ 98201e04c3fSmrg validate_ssa_def(&instr->def, state); 9837e102996Smaya 9847e102996Smaya for (unsigned i = 0; i < instr->def.num_components; i++) 9857e102996Smaya validate_const_value(&instr->value[i], instr->def.bit_size, state); 98601e04c3fSmrg} 98701e04c3fSmrg 98801e04c3fSmrgstatic void 98901e04c3fSmrgvalidate_ssa_undef_instr(nir_ssa_undef_instr *instr, validate_state *state) 99001e04c3fSmrg{ 99101e04c3fSmrg validate_ssa_def(&instr->def, state); 99201e04c3fSmrg} 99301e04c3fSmrg 99401e04c3fSmrgstatic void 99501e04c3fSmrgvalidate_phi_instr(nir_phi_instr *instr, validate_state *state) 99601e04c3fSmrg{ 99701e04c3fSmrg /* 99801e04c3fSmrg * don't validate the sources until we get to them from their predecessor 99901e04c3fSmrg * basic blocks, to avoid validating an SSA use before its definition. 100001e04c3fSmrg */ 100101e04c3fSmrg 100201e04c3fSmrg validate_dest(&instr->dest, state, 0, 0); 100301e04c3fSmrg 100401e04c3fSmrg exec_list_validate(&instr->srcs); 100501e04c3fSmrg validate_assert(state, exec_list_length(&instr->srcs) == 100601e04c3fSmrg state->block->predecessors->entries); 100701e04c3fSmrg} 100801e04c3fSmrg 10097ec681f3Smrgstatic void 10107ec681f3Smrgvalidate_jump_instr(nir_jump_instr *instr, validate_state *state) 10117ec681f3Smrg{ 10127ec681f3Smrg nir_block *block = state->block; 10137ec681f3Smrg validate_assert(state, &instr->instr == nir_block_last_instr(block)); 10147ec681f3Smrg 10157ec681f3Smrg switch (instr->type) { 10167ec681f3Smrg case nir_jump_return: 10177ec681f3Smrg case nir_jump_halt: 10187ec681f3Smrg validate_assert(state, block->successors[0] == state->impl->end_block); 10197ec681f3Smrg validate_assert(state, block->successors[1] == NULL); 10207ec681f3Smrg validate_assert(state, instr->target == NULL); 10217ec681f3Smrg validate_assert(state, instr->else_target == NULL); 10227ec681f3Smrg break; 10237ec681f3Smrg 10247ec681f3Smrg case nir_jump_break: 10257ec681f3Smrg validate_assert(state, state->impl->structured); 10267ec681f3Smrg validate_assert(state, state->loop != NULL); 10277ec681f3Smrg if (state->loop) { 10287ec681f3Smrg nir_block *after = 10297ec681f3Smrg nir_cf_node_as_block(nir_cf_node_next(&state->loop->cf_node)); 10307ec681f3Smrg validate_assert(state, block->successors[0] == after); 10317ec681f3Smrg } 10327ec681f3Smrg validate_assert(state, block->successors[1] == NULL); 10337ec681f3Smrg validate_assert(state, instr->target == NULL); 10347ec681f3Smrg validate_assert(state, instr->else_target == NULL); 10357ec681f3Smrg break; 10367ec681f3Smrg 10377ec681f3Smrg case nir_jump_continue: 10387ec681f3Smrg validate_assert(state, state->impl->structured); 10397ec681f3Smrg validate_assert(state, state->loop != NULL); 10407ec681f3Smrg if (state->loop) { 10417ec681f3Smrg nir_block *first = nir_loop_first_block(state->loop); 10427ec681f3Smrg validate_assert(state, block->successors[0] == first); 10437ec681f3Smrg } 10447ec681f3Smrg validate_assert(state, block->successors[1] == NULL); 10457ec681f3Smrg validate_assert(state, instr->target == NULL); 10467ec681f3Smrg validate_assert(state, instr->else_target == NULL); 10477ec681f3Smrg break; 10487ec681f3Smrg 10497ec681f3Smrg case nir_jump_goto: 10507ec681f3Smrg validate_assert(state, !state->impl->structured); 10517ec681f3Smrg validate_assert(state, instr->target == block->successors[0]); 10527ec681f3Smrg validate_assert(state, instr->target != NULL); 10537ec681f3Smrg validate_assert(state, instr->else_target == NULL); 10547ec681f3Smrg break; 10557ec681f3Smrg 10567ec681f3Smrg case nir_jump_goto_if: 10577ec681f3Smrg validate_assert(state, !state->impl->structured); 10587ec681f3Smrg validate_assert(state, instr->target == block->successors[1]); 10597ec681f3Smrg validate_assert(state, instr->else_target == block->successors[0]); 10607ec681f3Smrg validate_src(&instr->condition, state, 0, 1); 10617ec681f3Smrg validate_assert(state, instr->target != NULL); 10627ec681f3Smrg validate_assert(state, instr->else_target != NULL); 10637ec681f3Smrg break; 10647ec681f3Smrg 10657ec681f3Smrg default: 10667ec681f3Smrg validate_assert(state, !"Invalid jump instruction type"); 10677ec681f3Smrg break; 10687ec681f3Smrg } 10697ec681f3Smrg} 10707ec681f3Smrg 107101e04c3fSmrgstatic void 107201e04c3fSmrgvalidate_instr(nir_instr *instr, validate_state *state) 107301e04c3fSmrg{ 107401e04c3fSmrg validate_assert(state, instr->block == state->block); 107501e04c3fSmrg 107601e04c3fSmrg state->instr = instr; 107701e04c3fSmrg 10787ec681f3Smrg validate_assert(state, _mesa_set_search(state->shader_gc_list, instr)); 10797ec681f3Smrg 108001e04c3fSmrg switch (instr->type) { 108101e04c3fSmrg case nir_instr_type_alu: 108201e04c3fSmrg validate_alu_instr(nir_instr_as_alu(instr), state); 108301e04c3fSmrg break; 108401e04c3fSmrg 108501e04c3fSmrg case nir_instr_type_deref: 108601e04c3fSmrg validate_deref_instr(nir_instr_as_deref(instr), state); 108701e04c3fSmrg break; 108801e04c3fSmrg 108901e04c3fSmrg case nir_instr_type_call: 109001e04c3fSmrg validate_call_instr(nir_instr_as_call(instr), state); 109101e04c3fSmrg break; 109201e04c3fSmrg 109301e04c3fSmrg case nir_instr_type_intrinsic: 109401e04c3fSmrg validate_intrinsic_instr(nir_instr_as_intrinsic(instr), state); 109501e04c3fSmrg break; 109601e04c3fSmrg 109701e04c3fSmrg case nir_instr_type_tex: 109801e04c3fSmrg validate_tex_instr(nir_instr_as_tex(instr), state); 109901e04c3fSmrg break; 110001e04c3fSmrg 110101e04c3fSmrg case nir_instr_type_load_const: 110201e04c3fSmrg validate_load_const_instr(nir_instr_as_load_const(instr), state); 110301e04c3fSmrg break; 110401e04c3fSmrg 110501e04c3fSmrg case nir_instr_type_phi: 110601e04c3fSmrg validate_phi_instr(nir_instr_as_phi(instr), state); 110701e04c3fSmrg break; 110801e04c3fSmrg 110901e04c3fSmrg case nir_instr_type_ssa_undef: 111001e04c3fSmrg validate_ssa_undef_instr(nir_instr_as_ssa_undef(instr), state); 111101e04c3fSmrg break; 111201e04c3fSmrg 111301e04c3fSmrg case nir_instr_type_jump: 11147ec681f3Smrg validate_jump_instr(nir_instr_as_jump(instr), state); 111501e04c3fSmrg break; 111601e04c3fSmrg 111701e04c3fSmrg default: 111801e04c3fSmrg validate_assert(state, !"Invalid ALU instruction type"); 111901e04c3fSmrg break; 112001e04c3fSmrg } 112101e04c3fSmrg 112201e04c3fSmrg state->instr = NULL; 112301e04c3fSmrg} 112401e04c3fSmrg 112501e04c3fSmrgstatic void 112601e04c3fSmrgvalidate_phi_src(nir_phi_instr *instr, nir_block *pred, validate_state *state) 112701e04c3fSmrg{ 112801e04c3fSmrg state->instr = &instr->instr; 112901e04c3fSmrg 113001e04c3fSmrg validate_assert(state, instr->dest.is_ssa); 113101e04c3fSmrg 113201e04c3fSmrg exec_list_validate(&instr->srcs); 113301e04c3fSmrg nir_foreach_phi_src(src, instr) { 113401e04c3fSmrg if (src->pred == pred) { 113501e04c3fSmrg validate_assert(state, src->src.is_ssa); 113601e04c3fSmrg validate_src(&src->src, state, instr->dest.ssa.bit_size, 113701e04c3fSmrg instr->dest.ssa.num_components); 113801e04c3fSmrg state->instr = NULL; 113901e04c3fSmrg return; 114001e04c3fSmrg } 114101e04c3fSmrg } 11427ec681f3Smrg validate_assert(state, !"Phi does not have a source corresponding to one " 11437ec681f3Smrg "of its predecessor blocks"); 114401e04c3fSmrg} 114501e04c3fSmrg 114601e04c3fSmrgstatic void 114701e04c3fSmrgvalidate_phi_srcs(nir_block *block, nir_block *succ, validate_state *state) 114801e04c3fSmrg{ 114901e04c3fSmrg nir_foreach_instr(instr, succ) { 115001e04c3fSmrg if (instr->type != nir_instr_type_phi) 115101e04c3fSmrg break; 115201e04c3fSmrg 115301e04c3fSmrg validate_phi_src(nir_instr_as_phi(instr), block, state); 115401e04c3fSmrg } 115501e04c3fSmrg} 115601e04c3fSmrg 115701e04c3fSmrgstatic void 11587ec681f3Smrgcollect_blocks(struct exec_list *cf_list, validate_state *state) 115901e04c3fSmrg{ 11607ec681f3Smrg /* We walk the blocks manually here rather than using nir_foreach_block for 11617ec681f3Smrg * a few reasons: 11627ec681f3Smrg * 11637ec681f3Smrg * 1. nir_foreach_block() doesn't work properly for unstructured NIR and 11647ec681f3Smrg * we need to be able to handle all forms of NIR here. 11657ec681f3Smrg * 11667ec681f3Smrg * 2. We want to call exec_list_validate() on every linked list in the IR 11677ec681f3Smrg * which means we need to touch every linked and just walking blocks 11687ec681f3Smrg * with nir_foreach_block() would make that difficult. In particular, 11697ec681f3Smrg * we want to validate each list before the first time we walk it so 11707ec681f3Smrg * that we catch broken lists in exec_list_validate() instead of 11717ec681f3Smrg * getting stuck in a hard-to-debug infinite loop in the validator. 11727ec681f3Smrg * 11737ec681f3Smrg * 3. nir_foreach_block() depends on several invariants of the CF node 11747ec681f3Smrg * hierarchy which nir_validate_shader() is responsible for verifying. 11757ec681f3Smrg * If we used nir_foreach_block() in nir_validate_shader(), we could 11767ec681f3Smrg * end up blowing up on a bad list walk instead of throwing the much 11777ec681f3Smrg * easier to debug validation error. 11787ec681f3Smrg */ 11797ec681f3Smrg exec_list_validate(cf_list); 11807ec681f3Smrg foreach_list_typed(nir_cf_node, node, node, cf_list) { 11817ec681f3Smrg switch (node->type) { 11827ec681f3Smrg case nir_cf_node_block: 11837ec681f3Smrg _mesa_set_add(state->blocks, nir_cf_node_as_block(node)); 11847ec681f3Smrg break; 118501e04c3fSmrg 11867ec681f3Smrg case nir_cf_node_if: 11877ec681f3Smrg collect_blocks(&nir_cf_node_as_if(node)->then_list, state); 11887ec681f3Smrg collect_blocks(&nir_cf_node_as_if(node)->else_list, state); 11897ec681f3Smrg break; 119001e04c3fSmrg 11917ec681f3Smrg case nir_cf_node_loop: 11927ec681f3Smrg collect_blocks(&nir_cf_node_as_loop(node)->body, state); 11937ec681f3Smrg break; 119401e04c3fSmrg 11957ec681f3Smrg default: 11967ec681f3Smrg unreachable("Invalid CF node type"); 119701e04c3fSmrg } 119801e04c3fSmrg } 11997ec681f3Smrg} 120001e04c3fSmrg 12017ec681f3Smrgstatic void validate_cf_node(nir_cf_node *node, validate_state *state); 120201e04c3fSmrg 12037ec681f3Smrgstatic void 12047ec681f3Smrgvalidate_block_predecessors(nir_block *block, validate_state *state) 12057ec681f3Smrg{ 120601e04c3fSmrg for (unsigned i = 0; i < 2; i++) { 12077ec681f3Smrg if (block->successors[i] == NULL) 12087ec681f3Smrg continue; 120901e04c3fSmrg 12107ec681f3Smrg /* The block has to exist in the nir_function_impl */ 12117ec681f3Smrg validate_assert(state, _mesa_set_search(state->blocks, 12127ec681f3Smrg block->successors[i])); 12137ec681f3Smrg 12147ec681f3Smrg /* And we have to be in our successor's predecessors set */ 12157ec681f3Smrg validate_assert(state, 12167ec681f3Smrg _mesa_set_search(block->successors[i]->predecessors, block)); 12177ec681f3Smrg 12187ec681f3Smrg validate_phi_srcs(block, block->successors[i], state); 121901e04c3fSmrg } 122001e04c3fSmrg 12217ec681f3Smrg /* The start block cannot have any predecessors */ 12227ec681f3Smrg if (block == nir_start_block(state->impl)) 12237ec681f3Smrg validate_assert(state, block->predecessors->entries == 0); 12247ec681f3Smrg 122501e04c3fSmrg set_foreach(block->predecessors, entry) { 122601e04c3fSmrg const nir_block *pred = entry->key; 12277ec681f3Smrg validate_assert(state, _mesa_set_search(state->blocks, pred)); 122801e04c3fSmrg validate_assert(state, pred->successors[0] == block || 12297ec681f3Smrg pred->successors[1] == block); 123001e04c3fSmrg } 12317ec681f3Smrg} 123201e04c3fSmrg 12337ec681f3Smrgstatic void 12347ec681f3Smrgvalidate_block(nir_block *block, validate_state *state) 12357ec681f3Smrg{ 12367ec681f3Smrg validate_assert(state, block->cf_node.parent == state->parent_node); 123701e04c3fSmrg 12387ec681f3Smrg state->block = block; 12397ec681f3Smrg 12407ec681f3Smrg exec_list_validate(&block->instr_list); 12417ec681f3Smrg nir_foreach_instr(instr, block) { 12427ec681f3Smrg if (instr->type == nir_instr_type_phi) { 12437ec681f3Smrg validate_assert(state, instr == nir_block_first_instr(block) || 12447ec681f3Smrg nir_instr_prev(instr)->type == nir_instr_type_phi); 124501e04c3fSmrg } 124601e04c3fSmrg 12477ec681f3Smrg validate_instr(instr, state); 12487ec681f3Smrg } 124901e04c3fSmrg 12507ec681f3Smrg validate_assert(state, block->successors[0] != NULL); 12517ec681f3Smrg validate_assert(state, block->successors[0] != block->successors[1]); 12527ec681f3Smrg validate_block_predecessors(block, state); 12537ec681f3Smrg 12547ec681f3Smrg if (!state->impl->structured) { 12557ec681f3Smrg validate_assert(state, nir_block_ends_in_jump(block)); 12567ec681f3Smrg } else if (!nir_block_ends_in_jump(block)) { 125701e04c3fSmrg nir_cf_node *next = nir_cf_node_next(&block->cf_node); 125801e04c3fSmrg if (next == NULL) { 125901e04c3fSmrg switch (state->parent_node->type) { 126001e04c3fSmrg case nir_cf_node_loop: { 126101e04c3fSmrg nir_block *first = nir_loop_first_block(state->loop); 126201e04c3fSmrg validate_assert(state, block->successors[0] == first); 126301e04c3fSmrg /* due to the hack for infinite loops, block->successors[1] may 126401e04c3fSmrg * point to the block after the loop. 126501e04c3fSmrg */ 126601e04c3fSmrg break; 126701e04c3fSmrg } 126801e04c3fSmrg 126901e04c3fSmrg case nir_cf_node_if: { 127001e04c3fSmrg nir_block *after = 127101e04c3fSmrg nir_cf_node_as_block(nir_cf_node_next(state->parent_node)); 127201e04c3fSmrg validate_assert(state, block->successors[0] == after); 127301e04c3fSmrg validate_assert(state, block->successors[1] == NULL); 127401e04c3fSmrg break; 127501e04c3fSmrg } 127601e04c3fSmrg 127701e04c3fSmrg case nir_cf_node_function: 127801e04c3fSmrg validate_assert(state, block->successors[0] == state->impl->end_block); 127901e04c3fSmrg validate_assert(state, block->successors[1] == NULL); 128001e04c3fSmrg break; 128101e04c3fSmrg 128201e04c3fSmrg default: 128301e04c3fSmrg unreachable("unknown control flow node type"); 128401e04c3fSmrg } 128501e04c3fSmrg } else { 128601e04c3fSmrg if (next->type == nir_cf_node_if) { 128701e04c3fSmrg nir_if *if_stmt = nir_cf_node_as_if(next); 128801e04c3fSmrg validate_assert(state, block->successors[0] == 128901e04c3fSmrg nir_if_first_then_block(if_stmt)); 129001e04c3fSmrg validate_assert(state, block->successors[1] == 129101e04c3fSmrg nir_if_first_else_block(if_stmt)); 12927ec681f3Smrg } else if (next->type == nir_cf_node_loop) { 129301e04c3fSmrg nir_loop *loop = nir_cf_node_as_loop(next); 129401e04c3fSmrg validate_assert(state, block->successors[0] == 129501e04c3fSmrg nir_loop_first_block(loop)); 129601e04c3fSmrg validate_assert(state, block->successors[1] == NULL); 12977ec681f3Smrg } else { 12987ec681f3Smrg validate_assert(state, 12997ec681f3Smrg !"Structured NIR cannot have consecutive blocks"); 130001e04c3fSmrg } 130101e04c3fSmrg } 130201e04c3fSmrg } 130301e04c3fSmrg} 130401e04c3fSmrg 13057ec681f3Smrg 13067ec681f3Smrgstatic void 13077ec681f3Smrgvalidate_end_block(nir_block *block, validate_state *state) 13087ec681f3Smrg{ 13097ec681f3Smrg validate_assert(state, block->cf_node.parent == &state->impl->cf_node); 13107ec681f3Smrg 13117ec681f3Smrg exec_list_validate(&block->instr_list); 13127ec681f3Smrg validate_assert(state, exec_list_is_empty(&block->instr_list)); 13137ec681f3Smrg 13147ec681f3Smrg validate_assert(state, block->successors[0] == NULL); 13157ec681f3Smrg validate_assert(state, block->successors[1] == NULL); 13167ec681f3Smrg validate_block_predecessors(block, state); 13177ec681f3Smrg} 13187ec681f3Smrg 131901e04c3fSmrgstatic void 132001e04c3fSmrgvalidate_if(nir_if *if_stmt, validate_state *state) 132101e04c3fSmrg{ 13227ec681f3Smrg validate_assert(state, state->impl->structured); 13237ec681f3Smrg 132401e04c3fSmrg state->if_stmt = if_stmt; 132501e04c3fSmrg 132601e04c3fSmrg validate_assert(state, !exec_node_is_head_sentinel(if_stmt->cf_node.node.prev)); 132701e04c3fSmrg nir_cf_node *prev_node = nir_cf_node_prev(&if_stmt->cf_node); 132801e04c3fSmrg validate_assert(state, prev_node->type == nir_cf_node_block); 132901e04c3fSmrg 133001e04c3fSmrg validate_assert(state, !exec_node_is_tail_sentinel(if_stmt->cf_node.node.next)); 133101e04c3fSmrg nir_cf_node *next_node = nir_cf_node_next(&if_stmt->cf_node); 133201e04c3fSmrg validate_assert(state, next_node->type == nir_cf_node_block); 133301e04c3fSmrg 13347e102996Smaya validate_src(&if_stmt->condition, state, 0, 1); 133501e04c3fSmrg 133601e04c3fSmrg validate_assert(state, !exec_list_is_empty(&if_stmt->then_list)); 133701e04c3fSmrg validate_assert(state, !exec_list_is_empty(&if_stmt->else_list)); 133801e04c3fSmrg 133901e04c3fSmrg nir_cf_node *old_parent = state->parent_node; 134001e04c3fSmrg state->parent_node = &if_stmt->cf_node; 134101e04c3fSmrg 134201e04c3fSmrg foreach_list_typed(nir_cf_node, cf_node, node, &if_stmt->then_list) { 134301e04c3fSmrg validate_cf_node(cf_node, state); 134401e04c3fSmrg } 134501e04c3fSmrg 134601e04c3fSmrg foreach_list_typed(nir_cf_node, cf_node, node, &if_stmt->else_list) { 134701e04c3fSmrg validate_cf_node(cf_node, state); 134801e04c3fSmrg } 134901e04c3fSmrg 135001e04c3fSmrg state->parent_node = old_parent; 135101e04c3fSmrg state->if_stmt = NULL; 135201e04c3fSmrg} 135301e04c3fSmrg 135401e04c3fSmrgstatic void 135501e04c3fSmrgvalidate_loop(nir_loop *loop, validate_state *state) 135601e04c3fSmrg{ 13577ec681f3Smrg validate_assert(state, state->impl->structured); 13587ec681f3Smrg 135901e04c3fSmrg validate_assert(state, !exec_node_is_head_sentinel(loop->cf_node.node.prev)); 136001e04c3fSmrg nir_cf_node *prev_node = nir_cf_node_prev(&loop->cf_node); 136101e04c3fSmrg validate_assert(state, prev_node->type == nir_cf_node_block); 136201e04c3fSmrg 136301e04c3fSmrg validate_assert(state, !exec_node_is_tail_sentinel(loop->cf_node.node.next)); 136401e04c3fSmrg nir_cf_node *next_node = nir_cf_node_next(&loop->cf_node); 136501e04c3fSmrg validate_assert(state, next_node->type == nir_cf_node_block); 136601e04c3fSmrg 136701e04c3fSmrg validate_assert(state, !exec_list_is_empty(&loop->body)); 136801e04c3fSmrg 136901e04c3fSmrg nir_cf_node *old_parent = state->parent_node; 137001e04c3fSmrg state->parent_node = &loop->cf_node; 137101e04c3fSmrg nir_loop *old_loop = state->loop; 137201e04c3fSmrg state->loop = loop; 137301e04c3fSmrg 137401e04c3fSmrg foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) { 137501e04c3fSmrg validate_cf_node(cf_node, state); 137601e04c3fSmrg } 137701e04c3fSmrg 137801e04c3fSmrg state->parent_node = old_parent; 137901e04c3fSmrg state->loop = old_loop; 138001e04c3fSmrg} 138101e04c3fSmrg 138201e04c3fSmrgstatic void 138301e04c3fSmrgvalidate_cf_node(nir_cf_node *node, validate_state *state) 138401e04c3fSmrg{ 138501e04c3fSmrg validate_assert(state, node->parent == state->parent_node); 138601e04c3fSmrg 138701e04c3fSmrg switch (node->type) { 138801e04c3fSmrg case nir_cf_node_block: 138901e04c3fSmrg validate_block(nir_cf_node_as_block(node), state); 139001e04c3fSmrg break; 139101e04c3fSmrg 139201e04c3fSmrg case nir_cf_node_if: 139301e04c3fSmrg validate_if(nir_cf_node_as_if(node), state); 139401e04c3fSmrg break; 139501e04c3fSmrg 139601e04c3fSmrg case nir_cf_node_loop: 139701e04c3fSmrg validate_loop(nir_cf_node_as_loop(node), state); 139801e04c3fSmrg break; 139901e04c3fSmrg 140001e04c3fSmrg default: 140101e04c3fSmrg unreachable("Invalid CF node type"); 140201e04c3fSmrg } 140301e04c3fSmrg} 140401e04c3fSmrg 140501e04c3fSmrgstatic void 14067e102996Smayaprevalidate_reg_decl(nir_register *reg, validate_state *state) 140701e04c3fSmrg{ 14087e102996Smaya validate_assert(state, reg->index < state->impl->reg_alloc); 140901e04c3fSmrg validate_assert(state, !BITSET_TEST(state->regs_found, reg->index)); 14107ec681f3Smrg validate_num_components(state, reg->num_components); 141101e04c3fSmrg BITSET_SET(state->regs_found, reg->index); 141201e04c3fSmrg 141301e04c3fSmrg list_validate(®->uses); 141401e04c3fSmrg list_validate(®->defs); 141501e04c3fSmrg list_validate(®->if_uses); 141601e04c3fSmrg 141701e04c3fSmrg reg_validate_state *reg_state = ralloc(state->regs, reg_validate_state); 14187e102996Smaya reg_state->uses = _mesa_pointer_set_create(reg_state); 14197e102996Smaya reg_state->if_uses = _mesa_pointer_set_create(reg_state); 14207e102996Smaya reg_state->defs = _mesa_pointer_set_create(reg_state); 142101e04c3fSmrg 14227e102996Smaya reg_state->where_defined = state->impl; 142301e04c3fSmrg 142401e04c3fSmrg _mesa_hash_table_insert(state->regs, reg, reg_state); 142501e04c3fSmrg} 142601e04c3fSmrg 142701e04c3fSmrgstatic void 142801e04c3fSmrgpostvalidate_reg_decl(nir_register *reg, validate_state *state) 142901e04c3fSmrg{ 143001e04c3fSmrg struct hash_entry *entry = _mesa_hash_table_search(state->regs, reg); 143101e04c3fSmrg 143201e04c3fSmrg assume(entry); 143301e04c3fSmrg reg_validate_state *reg_state = (reg_validate_state *) entry->data; 143401e04c3fSmrg 143501e04c3fSmrg nir_foreach_use(src, reg) { 143601e04c3fSmrg struct set_entry *entry = _mesa_set_search(reg_state->uses, src); 143701e04c3fSmrg validate_assert(state, entry); 143801e04c3fSmrg _mesa_set_remove(reg_state->uses, entry); 143901e04c3fSmrg } 14407ec681f3Smrg validate_assert(state, reg_state->uses->entries == 0); 144101e04c3fSmrg 144201e04c3fSmrg nir_foreach_if_use(src, reg) { 144301e04c3fSmrg struct set_entry *entry = _mesa_set_search(reg_state->if_uses, src); 144401e04c3fSmrg validate_assert(state, entry); 144501e04c3fSmrg _mesa_set_remove(reg_state->if_uses, entry); 144601e04c3fSmrg } 14477ec681f3Smrg validate_assert(state, reg_state->if_uses->entries == 0); 144801e04c3fSmrg 144901e04c3fSmrg nir_foreach_def(src, reg) { 145001e04c3fSmrg struct set_entry *entry = _mesa_set_search(reg_state->defs, src); 145101e04c3fSmrg validate_assert(state, entry); 145201e04c3fSmrg _mesa_set_remove(reg_state->defs, entry); 145301e04c3fSmrg } 14547ec681f3Smrg validate_assert(state, reg_state->defs->entries == 0); 14557ec681f3Smrg} 145601e04c3fSmrg 14577ec681f3Smrgstatic void 14587ec681f3Smrgvalidate_constant(nir_constant *c, const struct glsl_type *type, 14597ec681f3Smrg validate_state *state) 14607ec681f3Smrg{ 14617ec681f3Smrg if (glsl_type_is_vector_or_scalar(type)) { 14627ec681f3Smrg unsigned num_components = glsl_get_vector_elements(type); 14637ec681f3Smrg unsigned bit_size = glsl_get_bit_size(type); 14647ec681f3Smrg for (unsigned i = 0; i < num_components; i++) 14657ec681f3Smrg validate_const_value(&c->values[i], bit_size, state); 14667ec681f3Smrg for (unsigned i = num_components; i < NIR_MAX_VEC_COMPONENTS; i++) 14677ec681f3Smrg validate_assert(state, c->values[i].u64 == 0); 14687ec681f3Smrg } else { 14697ec681f3Smrg validate_assert(state, c->num_elements == glsl_get_length(type)); 14707ec681f3Smrg if (glsl_type_is_struct_or_ifc(type)) { 14717ec681f3Smrg for (unsigned i = 0; i < c->num_elements; i++) { 14727ec681f3Smrg const struct glsl_type *elem_type = glsl_get_struct_field(type, i); 14737ec681f3Smrg validate_constant(c->elements[i], elem_type, state); 14747ec681f3Smrg } 14757ec681f3Smrg } else if (glsl_type_is_array_or_matrix(type)) { 14767ec681f3Smrg const struct glsl_type *elem_type = glsl_get_array_element(type); 14777ec681f3Smrg for (unsigned i = 0; i < c->num_elements; i++) 14787ec681f3Smrg validate_constant(c->elements[i], elem_type, state); 14797ec681f3Smrg } else { 14807ec681f3Smrg validate_assert(state, !"Invalid type for nir_constant"); 14817ec681f3Smrg } 148201e04c3fSmrg } 148301e04c3fSmrg} 148401e04c3fSmrg 148501e04c3fSmrgstatic void 14867ec681f3Smrgvalidate_var_decl(nir_variable *var, nir_variable_mode valid_modes, 14877ec681f3Smrg validate_state *state) 148801e04c3fSmrg{ 148901e04c3fSmrg state->var = var; 149001e04c3fSmrg 149101e04c3fSmrg /* Must have exactly one mode set */ 149201e04c3fSmrg validate_assert(state, util_is_power_of_two_nonzero(var->data.mode)); 14937ec681f3Smrg validate_assert(state, var->data.mode & valid_modes); 149401e04c3fSmrg 149501e04c3fSmrg if (var->data.compact) { 149601e04c3fSmrg /* The "compact" flag is only valid on arrays of scalars. */ 149701e04c3fSmrg assert(glsl_type_is_array(var->type)); 149801e04c3fSmrg 149901e04c3fSmrg const struct glsl_type *type = glsl_get_array_element(var->type); 15007ec681f3Smrg if (nir_is_arrayed_io(var, state->shader->info.stage)) { 150101e04c3fSmrg assert(glsl_type_is_array(type)); 150201e04c3fSmrg assert(glsl_type_is_scalar(glsl_get_array_element(type))); 150301e04c3fSmrg } else { 150401e04c3fSmrg assert(glsl_type_is_scalar(type)); 150501e04c3fSmrg } 150601e04c3fSmrg } 150701e04c3fSmrg 150801e04c3fSmrg if (var->num_members > 0) { 150901e04c3fSmrg const struct glsl_type *without_array = glsl_without_array(var->type); 15107e102996Smaya validate_assert(state, glsl_type_is_struct_or_ifc(without_array)); 151101e04c3fSmrg validate_assert(state, var->num_members == glsl_get_length(without_array)); 151201e04c3fSmrg validate_assert(state, var->members != NULL); 151301e04c3fSmrg } 151401e04c3fSmrg 15157ec681f3Smrg if (var->data.per_view) 15167ec681f3Smrg validate_assert(state, glsl_type_is_array(var->type)); 15177ec681f3Smrg 15187ec681f3Smrg if (var->constant_initializer) 15197ec681f3Smrg validate_constant(var->constant_initializer, var->type, state); 15207ec681f3Smrg 152101e04c3fSmrg /* 152201e04c3fSmrg * TODO validate some things ir_validate.cpp does (requires more GLSL type 152301e04c3fSmrg * support) 152401e04c3fSmrg */ 152501e04c3fSmrg 152601e04c3fSmrg _mesa_hash_table_insert(state->var_defs, var, 15277ec681f3Smrg valid_modes == nir_var_function_temp ? 15287ec681f3Smrg state->impl : NULL); 152901e04c3fSmrg 153001e04c3fSmrg state->var = NULL; 153101e04c3fSmrg} 153201e04c3fSmrg 153301e04c3fSmrgstatic bool 15347ec681f3Smrgvalidate_ssa_def_dominance(nir_ssa_def *def, void *_state) 153501e04c3fSmrg{ 15367ec681f3Smrg validate_state *state = _state; 153701e04c3fSmrg 15387ec681f3Smrg validate_assert(state, def->index < state->impl->ssa_alloc); 15397ec681f3Smrg validate_assert(state, !BITSET_TEST(state->ssa_defs_found, def->index)); 15407ec681f3Smrg BITSET_SET(state->ssa_defs_found, def->index); 154101e04c3fSmrg 15427ec681f3Smrg return true; 15437ec681f3Smrg} 154401e04c3fSmrg 15457ec681f3Smrgstatic bool 15467ec681f3Smrgvalidate_src_dominance(nir_src *src, void *_state) 15477ec681f3Smrg{ 15487ec681f3Smrg validate_state *state = _state; 15497ec681f3Smrg if (!src->is_ssa) 15507ec681f3Smrg return true; 15517ec681f3Smrg 15527ec681f3Smrg if (src->ssa->parent_instr->block == src->parent_instr->block) { 15537ec681f3Smrg validate_assert(state, src->ssa->index < state->impl->ssa_alloc); 15547ec681f3Smrg validate_assert(state, BITSET_TEST(state->ssa_defs_found, 15557ec681f3Smrg src->ssa->index)); 15567ec681f3Smrg } else { 15577ec681f3Smrg validate_assert(state, nir_block_dominates(src->ssa->parent_instr->block, 15587ec681f3Smrg src->parent_instr->block)); 155901e04c3fSmrg } 15607ec681f3Smrg return true; 15617ec681f3Smrg} 156201e04c3fSmrg 15637ec681f3Smrgstatic void 15647ec681f3Smrgvalidate_ssa_dominance(nir_function_impl *impl, validate_state *state) 15657ec681f3Smrg{ 15667ec681f3Smrg nir_metadata_require(impl, nir_metadata_dominance); 156701e04c3fSmrg 15687ec681f3Smrg nir_foreach_block(block, impl) { 15697ec681f3Smrg state->block = block; 15707ec681f3Smrg nir_foreach_instr(instr, block) { 15717ec681f3Smrg state->instr = instr; 15727ec681f3Smrg if (instr->type == nir_instr_type_phi) { 15737ec681f3Smrg nir_phi_instr *phi = nir_instr_as_phi(instr); 15747ec681f3Smrg nir_foreach_phi_src(src, phi) { 15757ec681f3Smrg validate_assert(state, 15767ec681f3Smrg nir_block_dominates(src->src.ssa->parent_instr->block, 15777ec681f3Smrg src->pred)); 15787ec681f3Smrg } 15797ec681f3Smrg } else { 15807ec681f3Smrg nir_foreach_src(instr, validate_src_dominance, state); 15817ec681f3Smrg } 15827ec681f3Smrg nir_foreach_ssa_def(instr, validate_ssa_def_dominance, state); 15837ec681f3Smrg } 158401e04c3fSmrg } 158501e04c3fSmrg} 158601e04c3fSmrg 158701e04c3fSmrgstatic void 158801e04c3fSmrgvalidate_function_impl(nir_function_impl *impl, validate_state *state) 158901e04c3fSmrg{ 15907ec681f3Smrg /* Resize the ssa_srcs set. It's likely that the size of this set will 15917ec681f3Smrg * never actually hit the number of SSA defs because we remove sources from 15927ec681f3Smrg * the set as we visit them. (It could actually be much larger because 15937ec681f3Smrg * each SSA def can be used more than once.) However, growing it now costs 15947ec681f3Smrg * us very little (the extra memory is already dwarfed by the SSA defs 15957ec681f3Smrg * themselves) and makes collisions much less likely. 15967ec681f3Smrg */ 15977ec681f3Smrg _mesa_set_resize(state->ssa_srcs, impl->ssa_alloc); 15987ec681f3Smrg 159901e04c3fSmrg validate_assert(state, impl->function->impl == impl); 160001e04c3fSmrg validate_assert(state, impl->cf_node.parent == NULL); 160101e04c3fSmrg 160201e04c3fSmrg validate_assert(state, exec_list_is_empty(&impl->end_block->instr_list)); 160301e04c3fSmrg validate_assert(state, impl->end_block->successors[0] == NULL); 160401e04c3fSmrg validate_assert(state, impl->end_block->successors[1] == NULL); 160501e04c3fSmrg 160601e04c3fSmrg state->impl = impl; 160701e04c3fSmrg state->parent_node = &impl->cf_node; 160801e04c3fSmrg 160901e04c3fSmrg exec_list_validate(&impl->locals); 16107ec681f3Smrg nir_foreach_function_temp_variable(var, impl) { 16117ec681f3Smrg validate_var_decl(var, nir_var_function_temp, state); 161201e04c3fSmrg } 161301e04c3fSmrg 16147ec681f3Smrg state->regs_found = reralloc(state->mem_ctx, state->regs_found, 16157ec681f3Smrg BITSET_WORD, BITSET_WORDS(impl->reg_alloc)); 161601e04c3fSmrg memset(state->regs_found, 0, BITSET_WORDS(impl->reg_alloc) * 161701e04c3fSmrg sizeof(BITSET_WORD)); 161801e04c3fSmrg exec_list_validate(&impl->registers); 161901e04c3fSmrg foreach_list_typed(nir_register, reg, node, &impl->registers) { 16207e102996Smaya prevalidate_reg_decl(reg, state); 162101e04c3fSmrg } 162201e04c3fSmrg 16237ec681f3Smrg state->ssa_defs_found = reralloc(state->mem_ctx, state->ssa_defs_found, 16247ec681f3Smrg BITSET_WORD, BITSET_WORDS(impl->ssa_alloc)); 162501e04c3fSmrg memset(state->ssa_defs_found, 0, BITSET_WORDS(impl->ssa_alloc) * 162601e04c3fSmrg sizeof(BITSET_WORD)); 16277ec681f3Smrg 16287ec681f3Smrg _mesa_set_clear(state->blocks, NULL); 16297ec681f3Smrg _mesa_set_resize(state->blocks, impl->num_blocks); 16307ec681f3Smrg collect_blocks(&impl->body, state); 16317ec681f3Smrg _mesa_set_add(state->blocks, impl->end_block); 16327ec681f3Smrg validate_assert(state, !exec_list_is_empty(&impl->body)); 163301e04c3fSmrg foreach_list_typed(nir_cf_node, node, node, &impl->body) { 163401e04c3fSmrg validate_cf_node(node, state); 163501e04c3fSmrg } 16367ec681f3Smrg validate_end_block(impl->end_block, state); 163701e04c3fSmrg 163801e04c3fSmrg foreach_list_typed(nir_register, reg, node, &impl->registers) { 163901e04c3fSmrg postvalidate_reg_decl(reg, state); 164001e04c3fSmrg } 164101e04c3fSmrg 16427ec681f3Smrg validate_assert(state, state->ssa_srcs->entries == 0); 16437ec681f3Smrg _mesa_set_clear(state->ssa_srcs, NULL); 16447ec681f3Smrg 16457ec681f3Smrg static int validate_dominance = -1; 16467ec681f3Smrg if (validate_dominance < 0) { 16477ec681f3Smrg validate_dominance = 16487ec681f3Smrg env_var_as_boolean("NIR_VALIDATE_SSA_DOMINANCE", false); 164901e04c3fSmrg } 16507ec681f3Smrg if (validate_dominance) 16517ec681f3Smrg validate_ssa_dominance(impl, state); 165201e04c3fSmrg} 165301e04c3fSmrg 165401e04c3fSmrgstatic void 165501e04c3fSmrgvalidate_function(nir_function *func, validate_state *state) 165601e04c3fSmrg{ 165701e04c3fSmrg if (func->impl != NULL) { 165801e04c3fSmrg validate_assert(state, func->impl->function == func); 165901e04c3fSmrg validate_function_impl(func->impl, state); 166001e04c3fSmrg } 166101e04c3fSmrg} 166201e04c3fSmrg 166301e04c3fSmrgstatic void 166401e04c3fSmrginit_validate_state(validate_state *state) 166501e04c3fSmrg{ 16667ec681f3Smrg state->mem_ctx = ralloc_context(NULL); 16677ec681f3Smrg state->regs = _mesa_pointer_hash_table_create(state->mem_ctx); 16687ec681f3Smrg state->ssa_srcs = _mesa_pointer_set_create(state->mem_ctx); 166901e04c3fSmrg state->ssa_defs_found = NULL; 167001e04c3fSmrg state->regs_found = NULL; 16717ec681f3Smrg state->blocks = _mesa_pointer_set_create(state->mem_ctx); 16727ec681f3Smrg state->var_defs = _mesa_pointer_hash_table_create(state->mem_ctx); 16737ec681f3Smrg state->errors = _mesa_pointer_hash_table_create(state->mem_ctx); 16747ec681f3Smrg state->shader_gc_list = _mesa_pointer_set_create(state->mem_ctx); 167501e04c3fSmrg 167601e04c3fSmrg state->loop = NULL; 167701e04c3fSmrg state->instr = NULL; 167801e04c3fSmrg state->var = NULL; 167901e04c3fSmrg} 168001e04c3fSmrg 168101e04c3fSmrgstatic void 168201e04c3fSmrgdestroy_validate_state(validate_state *state) 168301e04c3fSmrg{ 16847ec681f3Smrg ralloc_free(state->mem_ctx); 168501e04c3fSmrg} 168601e04c3fSmrg 16877e102996Smayamtx_t fail_dump_mutex = _MTX_INITIALIZER_NP; 16887e102996Smaya 168901e04c3fSmrgstatic void 169001e04c3fSmrgdump_errors(validate_state *state, const char *when) 169101e04c3fSmrg{ 169201e04c3fSmrg struct hash_table *errors = state->errors; 169301e04c3fSmrg 16947e102996Smaya /* Lock around dumping so that we get clean dumps in a multi-threaded 16957e102996Smaya * scenario 16967e102996Smaya */ 16977e102996Smaya mtx_lock(&fail_dump_mutex); 16987e102996Smaya 169901e04c3fSmrg if (when) { 170001e04c3fSmrg fprintf(stderr, "NIR validation failed %s\n", when); 170101e04c3fSmrg fprintf(stderr, "%d errors:\n", _mesa_hash_table_num_entries(errors)); 170201e04c3fSmrg } else { 170301e04c3fSmrg fprintf(stderr, "NIR validation failed with %d errors:\n", 170401e04c3fSmrg _mesa_hash_table_num_entries(errors)); 170501e04c3fSmrg } 170601e04c3fSmrg 170701e04c3fSmrg nir_print_shader_annotated(state->shader, stderr, errors); 170801e04c3fSmrg 170901e04c3fSmrg if (_mesa_hash_table_num_entries(errors) > 0) { 171001e04c3fSmrg fprintf(stderr, "%d additional errors:\n", 171101e04c3fSmrg _mesa_hash_table_num_entries(errors)); 171201e04c3fSmrg hash_table_foreach(errors, entry) { 171301e04c3fSmrg fprintf(stderr, "%s\n", (char *)entry->data); 171401e04c3fSmrg } 171501e04c3fSmrg } 171601e04c3fSmrg 17177e102996Smaya mtx_unlock(&fail_dump_mutex); 17187e102996Smaya 171901e04c3fSmrg abort(); 172001e04c3fSmrg} 172101e04c3fSmrg 172201e04c3fSmrgvoid 172301e04c3fSmrgnir_validate_shader(nir_shader *shader, const char *when) 172401e04c3fSmrg{ 172501e04c3fSmrg static int should_validate = -1; 172601e04c3fSmrg if (should_validate < 0) 172701e04c3fSmrg should_validate = env_var_as_boolean("NIR_VALIDATE", true); 172801e04c3fSmrg if (!should_validate) 172901e04c3fSmrg return; 173001e04c3fSmrg 173101e04c3fSmrg validate_state state; 173201e04c3fSmrg init_validate_state(&state); 173301e04c3fSmrg 17347ec681f3Smrg list_for_each_entry(nir_instr, instr, &shader->gc_list, gc_node) { 17357ec681f3Smrg _mesa_set_add(state.shader_gc_list, instr); 17367ec681f3Smrg } 17377ec681f3Smrg 173801e04c3fSmrg state.shader = shader; 173901e04c3fSmrg 17407ec681f3Smrg nir_variable_mode valid_modes = 17417ec681f3Smrg nir_var_shader_in | 17427ec681f3Smrg nir_var_shader_out | 17437ec681f3Smrg nir_var_shader_temp | 17447ec681f3Smrg nir_var_uniform | 17457ec681f3Smrg nir_var_mem_ubo | 17467ec681f3Smrg nir_var_system_value | 17477ec681f3Smrg nir_var_mem_ssbo | 17487ec681f3Smrg nir_var_mem_shared | 17497ec681f3Smrg nir_var_mem_push_const | 17507ec681f3Smrg nir_var_mem_constant; 17517ec681f3Smrg 17527ec681f3Smrg if (gl_shader_stage_is_callable(shader->info.stage)) 17537ec681f3Smrg valid_modes |= nir_var_shader_call_data; 17547ec681f3Smrg 17557ec681f3Smrg if (shader->info.stage == MESA_SHADER_ANY_HIT || 17567ec681f3Smrg shader->info.stage == MESA_SHADER_CLOSEST_HIT || 17577ec681f3Smrg shader->info.stage == MESA_SHADER_INTERSECTION) 17587ec681f3Smrg valid_modes |= nir_var_ray_hit_attrib; 17597ec681f3Smrg 17607ec681f3Smrg exec_list_validate(&shader->variables); 17617ec681f3Smrg nir_foreach_variable_in_shader(var, shader) 17627ec681f3Smrg validate_var_decl(var, valid_modes, &state); 176301e04c3fSmrg 17647ec681f3Smrg exec_list_validate(&shader->functions); 17657ec681f3Smrg foreach_list_typed(nir_function, func, node, &shader->functions) { 17667ec681f3Smrg validate_function(func, &state); 176701e04c3fSmrg } 176801e04c3fSmrg 17697ec681f3Smrg if (_mesa_hash_table_num_entries(state.errors) > 0) 17707ec681f3Smrg dump_errors(&state, when); 177101e04c3fSmrg 17727ec681f3Smrg destroy_validate_state(&state); 17737ec681f3Smrg} 177401e04c3fSmrg 17757ec681f3Smrgvoid 17767ec681f3Smrgnir_validate_ssa_dominance(nir_shader *shader, const char *when) 17777ec681f3Smrg{ 17787ec681f3Smrg static int should_validate = -1; 17797ec681f3Smrg if (should_validate < 0) 17807ec681f3Smrg should_validate = env_var_as_boolean("NIR_VALIDATE", true); 17817ec681f3Smrg if (!should_validate) 17827ec681f3Smrg return; 178301e04c3fSmrg 17847ec681f3Smrg validate_state state; 17857ec681f3Smrg init_validate_state(&state); 178601e04c3fSmrg 17877ec681f3Smrg state.shader = shader; 17887ec681f3Smrg 17897ec681f3Smrg nir_foreach_function(func, shader) { 17907ec681f3Smrg if (func->impl == NULL) 17917ec681f3Smrg continue; 17927ec681f3Smrg 17937ec681f3Smrg state.ssa_defs_found = reralloc(state.mem_ctx, state.ssa_defs_found, 17947ec681f3Smrg BITSET_WORD, 17957ec681f3Smrg BITSET_WORDS(func->impl->ssa_alloc)); 17967ec681f3Smrg memset(state.ssa_defs_found, 0, BITSET_WORDS(func->impl->ssa_alloc) * 17977ec681f3Smrg sizeof(BITSET_WORD)); 17987ec681f3Smrg 17997ec681f3Smrg state.impl = func->impl; 18007ec681f3Smrg validate_ssa_dominance(func->impl, &state); 180101e04c3fSmrg } 180201e04c3fSmrg 180301e04c3fSmrg if (_mesa_hash_table_num_entries(state.errors) > 0) 180401e04c3fSmrg dump_errors(&state, when); 180501e04c3fSmrg 180601e04c3fSmrg destroy_validate_state(&state); 180701e04c3fSmrg} 180801e04c3fSmrg 180901e04c3fSmrg#endif /* NDEBUG */ 1810