1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2014 Intel Corporation 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg * 23b8e80941Smrg * Authors: 24b8e80941Smrg * Connor Abbott (cwabbott0@gmail.com) 25b8e80941Smrg * 26b8e80941Smrg */ 27b8e80941Smrg 28b8e80941Smrg#include "nir.h" 29b8e80941Smrg#include "c11/threads.h" 30b8e80941Smrg#include <assert.h> 31b8e80941Smrg 32b8e80941Smrg/* 33b8e80941Smrg * This file checks for invalid IR indicating a bug somewhere in the compiler. 34b8e80941Smrg */ 35b8e80941Smrg 36b8e80941Smrg/* Since this file is just a pile of asserts, don't bother compiling it if 37b8e80941Smrg * we're not building a debug build. 38b8e80941Smrg */ 39b8e80941Smrg#ifndef NDEBUG 40b8e80941Smrg 41b8e80941Smrg/* 42b8e80941Smrg * Per-register validation state. 43b8e80941Smrg */ 44b8e80941Smrg 45b8e80941Smrgtypedef struct { 46b8e80941Smrg /* 47b8e80941Smrg * equivalent to the uses and defs in nir_register, but built up by the 48b8e80941Smrg * validator. At the end, we verify that the sets have the same entries. 49b8e80941Smrg */ 50b8e80941Smrg struct set *uses, *if_uses, *defs; 51b8e80941Smrg nir_function_impl *where_defined; /* NULL for global registers */ 52b8e80941Smrg} reg_validate_state; 53b8e80941Smrg 54b8e80941Smrgtypedef struct { 55b8e80941Smrg /* 56b8e80941Smrg * equivalent to the uses in nir_ssa_def, but built up by the validator. 57b8e80941Smrg * At the end, we verify that the sets have the same entries. 58b8e80941Smrg */ 59b8e80941Smrg struct set *uses, *if_uses; 60b8e80941Smrg nir_function_impl *where_defined; 61b8e80941Smrg} ssa_def_validate_state; 62b8e80941Smrg 63b8e80941Smrgtypedef struct { 64b8e80941Smrg /* map of register -> validation state (struct above) */ 65b8e80941Smrg struct hash_table *regs; 66b8e80941Smrg 67b8e80941Smrg /* the current shader being validated */ 68b8e80941Smrg nir_shader *shader; 69b8e80941Smrg 70b8e80941Smrg /* the current instruction being validated */ 71b8e80941Smrg nir_instr *instr; 72b8e80941Smrg 73b8e80941Smrg /* the current variable being validated */ 74b8e80941Smrg nir_variable *var; 75b8e80941Smrg 76b8e80941Smrg /* the current basic block being validated */ 77b8e80941Smrg nir_block *block; 78b8e80941Smrg 79b8e80941Smrg /* the current if statement being validated */ 80b8e80941Smrg nir_if *if_stmt; 81b8e80941Smrg 82b8e80941Smrg /* the current loop being visited */ 83b8e80941Smrg nir_loop *loop; 84b8e80941Smrg 85b8e80941Smrg /* the parent of the current cf node being visited */ 86b8e80941Smrg nir_cf_node *parent_node; 87b8e80941Smrg 88b8e80941Smrg /* the current function implementation being validated */ 89b8e80941Smrg nir_function_impl *impl; 90b8e80941Smrg 91b8e80941Smrg /* map of SSA value -> function implementation where it is defined */ 92b8e80941Smrg struct hash_table *ssa_defs; 93b8e80941Smrg 94b8e80941Smrg /* bitset of ssa definitions we have found; used to check uniqueness */ 95b8e80941Smrg BITSET_WORD *ssa_defs_found; 96b8e80941Smrg 97b8e80941Smrg /* bitset of registers we have currently found; used to check uniqueness */ 98b8e80941Smrg BITSET_WORD *regs_found; 99b8e80941Smrg 100b8e80941Smrg /* map of variable -> function implementation where it is defined or NULL 101b8e80941Smrg * if it is a global variable 102b8e80941Smrg */ 103b8e80941Smrg struct hash_table *var_defs; 104b8e80941Smrg 105b8e80941Smrg /* map of instruction/var/etc to failed assert string */ 106b8e80941Smrg struct hash_table *errors; 107b8e80941Smrg} validate_state; 108b8e80941Smrg 109b8e80941Smrgstatic void 110b8e80941Smrglog_error(validate_state *state, const char *cond, const char *file, int line) 111b8e80941Smrg{ 112b8e80941Smrg const void *obj; 113b8e80941Smrg 114b8e80941Smrg if (state->instr) 115b8e80941Smrg obj = state->instr; 116b8e80941Smrg else if (state->var) 117b8e80941Smrg obj = state->var; 118b8e80941Smrg else 119b8e80941Smrg obj = cond; 120b8e80941Smrg 121b8e80941Smrg char *msg = ralloc_asprintf(state->errors, "error: %s (%s:%d)", 122b8e80941Smrg cond, file, line); 123b8e80941Smrg 124b8e80941Smrg _mesa_hash_table_insert(state->errors, obj, msg); 125b8e80941Smrg} 126b8e80941Smrg 127b8e80941Smrg#define validate_assert(state, cond) do { \ 128b8e80941Smrg if (!(cond)) \ 129b8e80941Smrg log_error(state, #cond, __FILE__, __LINE__); \ 130b8e80941Smrg } while (0) 131b8e80941Smrg 132b8e80941Smrgstatic void validate_src(nir_src *src, validate_state *state, 133b8e80941Smrg unsigned bit_sizes, unsigned num_components); 134b8e80941Smrg 135b8e80941Smrgstatic void 136b8e80941Smrgvalidate_reg_src(nir_src *src, validate_state *state, 137b8e80941Smrg unsigned bit_sizes, unsigned num_components) 138b8e80941Smrg{ 139b8e80941Smrg validate_assert(state, src->reg.reg != NULL); 140b8e80941Smrg 141b8e80941Smrg struct hash_entry *entry; 142b8e80941Smrg entry = _mesa_hash_table_search(state->regs, src->reg.reg); 143b8e80941Smrg validate_assert(state, entry); 144b8e80941Smrg 145b8e80941Smrg reg_validate_state *reg_state = (reg_validate_state *) entry->data; 146b8e80941Smrg 147b8e80941Smrg if (state->instr) { 148b8e80941Smrg _mesa_set_add(reg_state->uses, src); 149b8e80941Smrg } else { 150b8e80941Smrg validate_assert(state, state->if_stmt); 151b8e80941Smrg _mesa_set_add(reg_state->if_uses, src); 152b8e80941Smrg } 153b8e80941Smrg 154b8e80941Smrg validate_assert(state, reg_state->where_defined == state->impl && 155b8e80941Smrg "using a register declared in a different function"); 156b8e80941Smrg 157b8e80941Smrg if (bit_sizes) 158b8e80941Smrg validate_assert(state, src->reg.reg->bit_size & bit_sizes); 159b8e80941Smrg if (num_components) 160b8e80941Smrg validate_assert(state, src->reg.reg->num_components == num_components); 161b8e80941Smrg 162b8e80941Smrg validate_assert(state, (src->reg.reg->num_array_elems == 0 || 163b8e80941Smrg src->reg.base_offset < src->reg.reg->num_array_elems) && 164b8e80941Smrg "definitely out-of-bounds array access"); 165b8e80941Smrg 166b8e80941Smrg if (src->reg.indirect) { 167b8e80941Smrg validate_assert(state, src->reg.reg->num_array_elems != 0); 168b8e80941Smrg validate_assert(state, (src->reg.indirect->is_ssa || 169b8e80941Smrg src->reg.indirect->reg.indirect == NULL) && 170b8e80941Smrg "only one level of indirection allowed"); 171b8e80941Smrg validate_src(src->reg.indirect, state, 32, 1); 172b8e80941Smrg } 173b8e80941Smrg} 174b8e80941Smrg 175b8e80941Smrgstatic void 176b8e80941Smrgvalidate_ssa_src(nir_src *src, validate_state *state, 177b8e80941Smrg unsigned bit_sizes, unsigned num_components) 178b8e80941Smrg{ 179b8e80941Smrg validate_assert(state, src->ssa != NULL); 180b8e80941Smrg 181b8e80941Smrg struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, src->ssa); 182b8e80941Smrg 183b8e80941Smrg validate_assert(state, entry); 184b8e80941Smrg 185b8e80941Smrg if (!entry) 186b8e80941Smrg return; 187b8e80941Smrg 188b8e80941Smrg ssa_def_validate_state *def_state = (ssa_def_validate_state *)entry->data; 189b8e80941Smrg 190b8e80941Smrg validate_assert(state, def_state->where_defined == state->impl && 191b8e80941Smrg "using an SSA value defined in a different function"); 192b8e80941Smrg 193b8e80941Smrg if (state->instr) { 194b8e80941Smrg _mesa_set_add(def_state->uses, src); 195b8e80941Smrg } else { 196b8e80941Smrg validate_assert(state, state->if_stmt); 197b8e80941Smrg _mesa_set_add(def_state->if_uses, src); 198b8e80941Smrg } 199b8e80941Smrg 200b8e80941Smrg if (bit_sizes) 201b8e80941Smrg validate_assert(state, src->ssa->bit_size & bit_sizes); 202b8e80941Smrg if (num_components) 203b8e80941Smrg validate_assert(state, src->ssa->num_components == num_components); 204b8e80941Smrg 205b8e80941Smrg /* TODO validate that the use is dominated by the definition */ 206b8e80941Smrg} 207b8e80941Smrg 208b8e80941Smrgstatic void 209b8e80941Smrgvalidate_src(nir_src *src, validate_state *state, 210b8e80941Smrg unsigned bit_sizes, unsigned num_components) 211b8e80941Smrg{ 212b8e80941Smrg if (state->instr) 213b8e80941Smrg validate_assert(state, src->parent_instr == state->instr); 214b8e80941Smrg else 215b8e80941Smrg validate_assert(state, src->parent_if == state->if_stmt); 216b8e80941Smrg 217b8e80941Smrg if (src->is_ssa) 218b8e80941Smrg validate_ssa_src(src, state, bit_sizes, num_components); 219b8e80941Smrg else 220b8e80941Smrg validate_reg_src(src, state, bit_sizes, num_components); 221b8e80941Smrg} 222b8e80941Smrg 223b8e80941Smrgstatic void 224b8e80941Smrgvalidate_alu_src(nir_alu_instr *instr, unsigned index, validate_state *state) 225b8e80941Smrg{ 226b8e80941Smrg nir_alu_src *src = &instr->src[index]; 227b8e80941Smrg 228b8e80941Smrg unsigned num_components = nir_src_num_components(src->src); 229b8e80941Smrg for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++) { 230b8e80941Smrg validate_assert(state, src->swizzle[i] < NIR_MAX_VEC_COMPONENTS); 231b8e80941Smrg 232b8e80941Smrg if (nir_alu_instr_channel_used(instr, index, i)) 233b8e80941Smrg validate_assert(state, src->swizzle[i] < num_components); 234b8e80941Smrg } 235b8e80941Smrg 236b8e80941Smrg validate_src(&src->src, state, 0, 0); 237b8e80941Smrg} 238b8e80941Smrg 239b8e80941Smrgstatic void 240b8e80941Smrgvalidate_reg_dest(nir_reg_dest *dest, validate_state *state, 241b8e80941Smrg unsigned bit_sizes, unsigned num_components) 242b8e80941Smrg{ 243b8e80941Smrg validate_assert(state, dest->reg != NULL); 244b8e80941Smrg 245b8e80941Smrg validate_assert(state, dest->parent_instr == state->instr); 246b8e80941Smrg 247b8e80941Smrg struct hash_entry *entry2; 248b8e80941Smrg entry2 = _mesa_hash_table_search(state->regs, dest->reg); 249b8e80941Smrg 250b8e80941Smrg validate_assert(state, entry2); 251b8e80941Smrg 252b8e80941Smrg reg_validate_state *reg_state = (reg_validate_state *) entry2->data; 253b8e80941Smrg _mesa_set_add(reg_state->defs, dest); 254b8e80941Smrg 255b8e80941Smrg validate_assert(state, reg_state->where_defined == state->impl && 256b8e80941Smrg "writing to a register declared in a different function"); 257b8e80941Smrg 258b8e80941Smrg if (bit_sizes) 259b8e80941Smrg validate_assert(state, dest->reg->bit_size & bit_sizes); 260b8e80941Smrg if (num_components) 261b8e80941Smrg validate_assert(state, dest->reg->num_components == num_components); 262b8e80941Smrg 263b8e80941Smrg validate_assert(state, (dest->reg->num_array_elems == 0 || 264b8e80941Smrg dest->base_offset < dest->reg->num_array_elems) && 265b8e80941Smrg "definitely out-of-bounds array access"); 266b8e80941Smrg 267b8e80941Smrg if (dest->indirect) { 268b8e80941Smrg validate_assert(state, dest->reg->num_array_elems != 0); 269b8e80941Smrg validate_assert(state, (dest->indirect->is_ssa || dest->indirect->reg.indirect == NULL) && 270b8e80941Smrg "only one level of indirection allowed"); 271b8e80941Smrg validate_src(dest->indirect, state, 32, 1); 272b8e80941Smrg } 273b8e80941Smrg} 274b8e80941Smrg 275b8e80941Smrgstatic void 276b8e80941Smrgvalidate_ssa_def(nir_ssa_def *def, validate_state *state) 277b8e80941Smrg{ 278b8e80941Smrg validate_assert(state, def->index < state->impl->ssa_alloc); 279b8e80941Smrg validate_assert(state, !BITSET_TEST(state->ssa_defs_found, def->index)); 280b8e80941Smrg BITSET_SET(state->ssa_defs_found, def->index); 281b8e80941Smrg 282b8e80941Smrg validate_assert(state, def->parent_instr == state->instr); 283b8e80941Smrg 284b8e80941Smrg validate_assert(state, (def->num_components <= 4) || 285b8e80941Smrg (def->num_components == 8) || 286b8e80941Smrg (def->num_components == 16)); 287b8e80941Smrg 288b8e80941Smrg list_validate(&def->uses); 289b8e80941Smrg list_validate(&def->if_uses); 290b8e80941Smrg 291b8e80941Smrg ssa_def_validate_state *def_state = ralloc(state->ssa_defs, 292b8e80941Smrg ssa_def_validate_state); 293b8e80941Smrg def_state->where_defined = state->impl; 294b8e80941Smrg def_state->uses = _mesa_pointer_set_create(def_state); 295b8e80941Smrg def_state->if_uses = _mesa_pointer_set_create(def_state); 296b8e80941Smrg _mesa_hash_table_insert(state->ssa_defs, def, def_state); 297b8e80941Smrg} 298b8e80941Smrg 299b8e80941Smrgstatic void 300b8e80941Smrgvalidate_dest(nir_dest *dest, validate_state *state, 301b8e80941Smrg unsigned bit_sizes, unsigned num_components) 302b8e80941Smrg{ 303b8e80941Smrg if (dest->is_ssa) { 304b8e80941Smrg if (bit_sizes) 305b8e80941Smrg validate_assert(state, dest->ssa.bit_size & bit_sizes); 306b8e80941Smrg if (num_components) 307b8e80941Smrg validate_assert(state, dest->ssa.num_components == num_components); 308b8e80941Smrg validate_ssa_def(&dest->ssa, state); 309b8e80941Smrg } else { 310b8e80941Smrg validate_reg_dest(&dest->reg, state, bit_sizes, num_components); 311b8e80941Smrg } 312b8e80941Smrg} 313b8e80941Smrg 314b8e80941Smrgstatic void 315b8e80941Smrgvalidate_alu_dest(nir_alu_instr *instr, validate_state *state) 316b8e80941Smrg{ 317b8e80941Smrg nir_alu_dest *dest = &instr->dest; 318b8e80941Smrg 319b8e80941Smrg unsigned dest_size = nir_dest_num_components(dest->dest); 320b8e80941Smrg /* 321b8e80941Smrg * validate that the instruction doesn't write to components not in the 322b8e80941Smrg * register/SSA value 323b8e80941Smrg */ 324b8e80941Smrg validate_assert(state, !(dest->write_mask & ~((1 << dest_size) - 1))); 325b8e80941Smrg 326b8e80941Smrg /* validate that saturate is only ever used on instructions with 327b8e80941Smrg * destinations of type float 328b8e80941Smrg */ 329b8e80941Smrg nir_alu_instr *alu = nir_instr_as_alu(state->instr); 330b8e80941Smrg validate_assert(state, 331b8e80941Smrg (nir_alu_type_get_base_type(nir_op_infos[alu->op].output_type) == 332b8e80941Smrg nir_type_float) || 333b8e80941Smrg !dest->saturate); 334b8e80941Smrg 335b8e80941Smrg validate_dest(&dest->dest, state, 0, 0); 336b8e80941Smrg} 337b8e80941Smrg 338b8e80941Smrgstatic void 339b8e80941Smrgvalidate_alu_instr(nir_alu_instr *instr, validate_state *state) 340b8e80941Smrg{ 341b8e80941Smrg validate_assert(state, instr->op < nir_num_opcodes); 342b8e80941Smrg 343b8e80941Smrg unsigned instr_bit_size = 0; 344b8e80941Smrg for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) { 345b8e80941Smrg nir_alu_type src_type = nir_op_infos[instr->op].input_types[i]; 346b8e80941Smrg unsigned src_bit_size = nir_src_bit_size(instr->src[i].src); 347b8e80941Smrg if (nir_alu_type_get_type_size(src_type)) { 348b8e80941Smrg validate_assert(state, src_bit_size == nir_alu_type_get_type_size(src_type)); 349b8e80941Smrg } else if (instr_bit_size) { 350b8e80941Smrg validate_assert(state, src_bit_size == instr_bit_size); 351b8e80941Smrg } else { 352b8e80941Smrg instr_bit_size = src_bit_size; 353b8e80941Smrg } 354b8e80941Smrg 355b8e80941Smrg if (nir_alu_type_get_base_type(src_type) == nir_type_float) { 356b8e80941Smrg /* 8-bit float isn't a thing */ 357b8e80941Smrg validate_assert(state, src_bit_size == 16 || src_bit_size == 32 || 358b8e80941Smrg src_bit_size == 64); 359b8e80941Smrg } 360b8e80941Smrg 361b8e80941Smrg validate_alu_src(instr, i, state); 362b8e80941Smrg } 363b8e80941Smrg 364b8e80941Smrg nir_alu_type dest_type = nir_op_infos[instr->op].output_type; 365b8e80941Smrg unsigned dest_bit_size = nir_dest_bit_size(instr->dest.dest); 366b8e80941Smrg if (nir_alu_type_get_type_size(dest_type)) { 367b8e80941Smrg validate_assert(state, dest_bit_size == nir_alu_type_get_type_size(dest_type)); 368b8e80941Smrg } else if (instr_bit_size) { 369b8e80941Smrg validate_assert(state, dest_bit_size == instr_bit_size); 370b8e80941Smrg } else { 371b8e80941Smrg /* The only unsized thing is the destination so it's vacuously valid */ 372b8e80941Smrg } 373b8e80941Smrg 374b8e80941Smrg if (nir_alu_type_get_base_type(dest_type) == nir_type_float) { 375b8e80941Smrg /* 8-bit float isn't a thing */ 376b8e80941Smrg validate_assert(state, dest_bit_size == 16 || dest_bit_size == 32 || 377b8e80941Smrg dest_bit_size == 64); 378b8e80941Smrg } 379b8e80941Smrg 380b8e80941Smrg validate_alu_dest(instr, state); 381b8e80941Smrg} 382b8e80941Smrg 383b8e80941Smrgstatic void 384b8e80941Smrgvalidate_var_use(nir_variable *var, validate_state *state) 385b8e80941Smrg{ 386b8e80941Smrg struct hash_entry *entry = _mesa_hash_table_search(state->var_defs, var); 387b8e80941Smrg validate_assert(state, entry); 388b8e80941Smrg if (var->data.mode == nir_var_function_temp) 389b8e80941Smrg validate_assert(state, (nir_function_impl *) entry->data == state->impl); 390b8e80941Smrg} 391b8e80941Smrg 392b8e80941Smrgstatic void 393b8e80941Smrgvalidate_deref_instr(nir_deref_instr *instr, validate_state *state) 394b8e80941Smrg{ 395b8e80941Smrg if (instr->deref_type == nir_deref_type_var) { 396b8e80941Smrg /* Variable dereferences are stupid simple. */ 397b8e80941Smrg validate_assert(state, instr->mode == instr->var->data.mode); 398b8e80941Smrg validate_assert(state, instr->type == instr->var->type); 399b8e80941Smrg validate_var_use(instr->var, state); 400b8e80941Smrg } else if (instr->deref_type == nir_deref_type_cast) { 401b8e80941Smrg /* For cast, we simply have to trust the instruction. It's up to 402b8e80941Smrg * lowering passes and front/back-ends to make them sane. 403b8e80941Smrg */ 404b8e80941Smrg validate_src(&instr->parent, state, 0, 0); 405b8e80941Smrg 406b8e80941Smrg /* We just validate that the type and mode are there */ 407b8e80941Smrg validate_assert(state, instr->mode); 408b8e80941Smrg validate_assert(state, instr->type); 409b8e80941Smrg } else { 410b8e80941Smrg /* We require the parent to be SSA. This may be lifted in the future */ 411b8e80941Smrg validate_assert(state, instr->parent.is_ssa); 412b8e80941Smrg 413b8e80941Smrg /* The parent pointer value must have the same number of components 414b8e80941Smrg * as the destination. 415b8e80941Smrg */ 416b8e80941Smrg validate_src(&instr->parent, state, nir_dest_bit_size(instr->dest), 417b8e80941Smrg nir_dest_num_components(instr->dest)); 418b8e80941Smrg 419b8e80941Smrg nir_instr *parent_instr = instr->parent.ssa->parent_instr; 420b8e80941Smrg 421b8e80941Smrg /* The parent must come from another deref instruction */ 422b8e80941Smrg validate_assert(state, parent_instr->type == nir_instr_type_deref); 423b8e80941Smrg 424b8e80941Smrg nir_deref_instr *parent = nir_instr_as_deref(parent_instr); 425b8e80941Smrg 426b8e80941Smrg validate_assert(state, instr->mode == parent->mode); 427b8e80941Smrg 428b8e80941Smrg switch (instr->deref_type) { 429b8e80941Smrg case nir_deref_type_struct: 430b8e80941Smrg validate_assert(state, glsl_type_is_struct_or_ifc(parent->type)); 431b8e80941Smrg validate_assert(state, 432b8e80941Smrg instr->strct.index < glsl_get_length(parent->type)); 433b8e80941Smrg validate_assert(state, instr->type == 434b8e80941Smrg glsl_get_struct_field(parent->type, instr->strct.index)); 435b8e80941Smrg break; 436b8e80941Smrg 437b8e80941Smrg case nir_deref_type_array: 438b8e80941Smrg case nir_deref_type_array_wildcard: 439b8e80941Smrg if (instr->mode == nir_var_mem_ubo || 440b8e80941Smrg instr->mode == nir_var_mem_ssbo || 441b8e80941Smrg instr->mode == nir_var_mem_shared || 442b8e80941Smrg instr->mode == nir_var_mem_global) { 443b8e80941Smrg /* Shared variables and UBO/SSBOs have a bit more relaxed rules 444b8e80941Smrg * because we need to be able to handle array derefs on vectors. 445b8e80941Smrg * Fortunately, nir_lower_io handles these just fine. 446b8e80941Smrg */ 447b8e80941Smrg validate_assert(state, glsl_type_is_array(parent->type) || 448b8e80941Smrg glsl_type_is_matrix(parent->type) || 449b8e80941Smrg glsl_type_is_vector(parent->type)); 450b8e80941Smrg } else { 451b8e80941Smrg /* Most of NIR cannot handle array derefs on vectors */ 452b8e80941Smrg validate_assert(state, glsl_type_is_array(parent->type) || 453b8e80941Smrg glsl_type_is_matrix(parent->type)); 454b8e80941Smrg } 455b8e80941Smrg validate_assert(state, 456b8e80941Smrg instr->type == glsl_get_array_element(parent->type)); 457b8e80941Smrg 458b8e80941Smrg if (instr->deref_type == nir_deref_type_array) { 459b8e80941Smrg validate_src(&instr->arr.index, state, 460b8e80941Smrg nir_dest_bit_size(instr->dest), 1); 461b8e80941Smrg } 462b8e80941Smrg break; 463b8e80941Smrg 464b8e80941Smrg case nir_deref_type_ptr_as_array: 465b8e80941Smrg /* ptr_as_array derefs must have a parent that is either an array, 466b8e80941Smrg * ptr_as_array, or cast. If the parent is a cast, we get the stride 467b8e80941Smrg * information (if any) from the cast deref. 468b8e80941Smrg */ 469b8e80941Smrg validate_assert(state, 470b8e80941Smrg parent->deref_type == nir_deref_type_array || 471b8e80941Smrg parent->deref_type == nir_deref_type_ptr_as_array || 472b8e80941Smrg parent->deref_type == nir_deref_type_cast); 473b8e80941Smrg validate_src(&instr->arr.index, state, 474b8e80941Smrg nir_dest_bit_size(instr->dest), 1); 475b8e80941Smrg break; 476b8e80941Smrg 477b8e80941Smrg default: 478b8e80941Smrg unreachable("Invalid deref instruction type"); 479b8e80941Smrg } 480b8e80941Smrg } 481b8e80941Smrg 482b8e80941Smrg /* We intentionally don't validate the size of the destination because we 483b8e80941Smrg * want to let other compiler components such as SPIR-V decide how big 484b8e80941Smrg * pointers should be. 485b8e80941Smrg */ 486b8e80941Smrg validate_dest(&instr->dest, state, 0, 0); 487b8e80941Smrg 488b8e80941Smrg /* Deref instructions as if conditions don't make sense because if 489b8e80941Smrg * conditions expect well-formed Booleans. If you want to compare with 490b8e80941Smrg * NULL, an explicit comparison operation should be used. 491b8e80941Smrg */ 492b8e80941Smrg validate_assert(state, list_empty(&instr->dest.ssa.if_uses)); 493b8e80941Smrg} 494b8e80941Smrg 495b8e80941Smrgstatic void 496b8e80941Smrgvalidate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state) 497b8e80941Smrg{ 498b8e80941Smrg unsigned dest_bit_size = 0; 499b8e80941Smrg unsigned src_bit_sizes[NIR_INTRINSIC_MAX_INPUTS] = { 0, }; 500b8e80941Smrg switch (instr->intrinsic) { 501b8e80941Smrg case nir_intrinsic_load_param: { 502b8e80941Smrg unsigned param_idx = nir_intrinsic_param_idx(instr); 503b8e80941Smrg validate_assert(state, param_idx < state->impl->function->num_params); 504b8e80941Smrg nir_parameter *param = &state->impl->function->params[param_idx]; 505b8e80941Smrg validate_assert(state, instr->num_components == param->num_components); 506b8e80941Smrg dest_bit_size = param->bit_size; 507b8e80941Smrg break; 508b8e80941Smrg } 509b8e80941Smrg 510b8e80941Smrg case nir_intrinsic_load_deref: { 511b8e80941Smrg nir_deref_instr *src = nir_src_as_deref(instr->src[0]); 512b8e80941Smrg validate_assert(state, glsl_type_is_vector_or_scalar(src->type) || 513b8e80941Smrg (src->mode == nir_var_uniform && 514b8e80941Smrg glsl_get_base_type(src->type) == GLSL_TYPE_SUBROUTINE)); 515b8e80941Smrg validate_assert(state, instr->num_components == 516b8e80941Smrg glsl_get_vector_elements(src->type)); 517b8e80941Smrg dest_bit_size = glsl_get_bit_size(src->type); 518b8e80941Smrg /* Also allow 32-bit boolean load operations */ 519b8e80941Smrg if (glsl_type_is_boolean(src->type)) 520b8e80941Smrg dest_bit_size |= 32; 521b8e80941Smrg break; 522b8e80941Smrg } 523b8e80941Smrg 524b8e80941Smrg case nir_intrinsic_store_deref: { 525b8e80941Smrg nir_deref_instr *dst = nir_src_as_deref(instr->src[0]); 526b8e80941Smrg validate_assert(state, glsl_type_is_vector_or_scalar(dst->type)); 527b8e80941Smrg validate_assert(state, instr->num_components == 528b8e80941Smrg glsl_get_vector_elements(dst->type)); 529b8e80941Smrg src_bit_sizes[1] = glsl_get_bit_size(dst->type); 530b8e80941Smrg /* Also allow 32-bit boolean store operations */ 531b8e80941Smrg if (glsl_type_is_boolean(dst->type)) 532b8e80941Smrg src_bit_sizes[1] |= 32; 533b8e80941Smrg validate_assert(state, (dst->mode & (nir_var_shader_in | 534b8e80941Smrg nir_var_uniform)) == 0); 535b8e80941Smrg validate_assert(state, (nir_intrinsic_write_mask(instr) & ~((1 << instr->num_components) - 1)) == 0); 536b8e80941Smrg break; 537b8e80941Smrg } 538b8e80941Smrg 539b8e80941Smrg case nir_intrinsic_copy_deref: { 540b8e80941Smrg nir_deref_instr *dst = nir_src_as_deref(instr->src[0]); 541b8e80941Smrg nir_deref_instr *src = nir_src_as_deref(instr->src[1]); 542b8e80941Smrg validate_assert(state, glsl_get_bare_type(dst->type) == 543b8e80941Smrg glsl_get_bare_type(src->type)); 544b8e80941Smrg validate_assert(state, (dst->mode & (nir_var_shader_in | 545b8e80941Smrg nir_var_uniform)) == 0); 546b8e80941Smrg break; 547b8e80941Smrg } 548b8e80941Smrg 549b8e80941Smrg default: 550b8e80941Smrg break; 551b8e80941Smrg } 552b8e80941Smrg 553b8e80941Smrg unsigned num_srcs = nir_intrinsic_infos[instr->intrinsic].num_srcs; 554b8e80941Smrg for (unsigned i = 0; i < num_srcs; i++) { 555b8e80941Smrg unsigned components_read = nir_intrinsic_src_components(instr, i); 556b8e80941Smrg 557b8e80941Smrg validate_assert(state, components_read > 0); 558b8e80941Smrg 559b8e80941Smrg validate_src(&instr->src[i], state, src_bit_sizes[i], components_read); 560b8e80941Smrg } 561b8e80941Smrg 562b8e80941Smrg if (nir_intrinsic_infos[instr->intrinsic].has_dest) { 563b8e80941Smrg unsigned components_written = nir_intrinsic_dest_components(instr); 564b8e80941Smrg unsigned bit_sizes = nir_intrinsic_infos[instr->intrinsic].dest_bit_sizes; 565b8e80941Smrg 566b8e80941Smrg validate_assert(state, components_written > 0); 567b8e80941Smrg 568b8e80941Smrg if (dest_bit_size && bit_sizes) 569b8e80941Smrg validate_assert(state, dest_bit_size & bit_sizes); 570b8e80941Smrg else 571b8e80941Smrg dest_bit_size = dest_bit_size ? dest_bit_size : bit_sizes; 572b8e80941Smrg 573b8e80941Smrg validate_dest(&instr->dest, state, dest_bit_size, components_written); 574b8e80941Smrg } 575b8e80941Smrg} 576b8e80941Smrg 577b8e80941Smrgstatic void 578b8e80941Smrgvalidate_tex_instr(nir_tex_instr *instr, validate_state *state) 579b8e80941Smrg{ 580b8e80941Smrg bool src_type_seen[nir_num_tex_src_types]; 581b8e80941Smrg for (unsigned i = 0; i < nir_num_tex_src_types; i++) 582b8e80941Smrg src_type_seen[i] = false; 583b8e80941Smrg 584b8e80941Smrg for (unsigned i = 0; i < instr->num_srcs; i++) { 585b8e80941Smrg validate_assert(state, !src_type_seen[instr->src[i].src_type]); 586b8e80941Smrg src_type_seen[instr->src[i].src_type] = true; 587b8e80941Smrg validate_src(&instr->src[i].src, state, 588b8e80941Smrg 0, nir_tex_instr_src_size(instr, i)); 589b8e80941Smrg 590b8e80941Smrg switch (instr->src[i].src_type) { 591b8e80941Smrg case nir_tex_src_texture_deref: 592b8e80941Smrg case nir_tex_src_sampler_deref: 593b8e80941Smrg validate_assert(state, instr->src[i].src.is_ssa); 594b8e80941Smrg validate_assert(state, 595b8e80941Smrg instr->src[i].src.ssa->parent_instr->type == nir_instr_type_deref); 596b8e80941Smrg break; 597b8e80941Smrg default: 598b8e80941Smrg break; 599b8e80941Smrg } 600b8e80941Smrg } 601b8e80941Smrg 602b8e80941Smrg if (nir_tex_instr_has_explicit_tg4_offsets(instr)) { 603b8e80941Smrg validate_assert(state, instr->op == nir_texop_tg4); 604b8e80941Smrg validate_assert(state, !src_type_seen[nir_tex_src_offset]); 605b8e80941Smrg } 606b8e80941Smrg 607b8e80941Smrg validate_dest(&instr->dest, state, 0, nir_tex_instr_dest_size(instr)); 608b8e80941Smrg} 609b8e80941Smrg 610b8e80941Smrgstatic void 611b8e80941Smrgvalidate_call_instr(nir_call_instr *instr, validate_state *state) 612b8e80941Smrg{ 613b8e80941Smrg validate_assert(state, instr->num_params == instr->callee->num_params); 614b8e80941Smrg 615b8e80941Smrg for (unsigned i = 0; i < instr->num_params; i++) { 616b8e80941Smrg validate_src(&instr->params[i], state, 617b8e80941Smrg instr->callee->params[i].bit_size, 618b8e80941Smrg instr->callee->params[i].num_components); 619b8e80941Smrg } 620b8e80941Smrg} 621b8e80941Smrg 622b8e80941Smrgstatic void 623b8e80941Smrgvalidate_const_value(nir_const_value *val, unsigned bit_size, 624b8e80941Smrg validate_state *state) 625b8e80941Smrg{ 626b8e80941Smrg /* In order for block copies to work properly for things like instruction 627b8e80941Smrg * comparisons and [de]serialization, we require the unused bits of the 628b8e80941Smrg * nir_const_value to be zero. 629b8e80941Smrg */ 630b8e80941Smrg nir_const_value cmp_val; 631b8e80941Smrg memset(&cmp_val, 0, sizeof(cmp_val)); 632b8e80941Smrg switch (bit_size) { 633b8e80941Smrg case 1: 634b8e80941Smrg cmp_val.b = val->b; 635b8e80941Smrg break; 636b8e80941Smrg case 8: 637b8e80941Smrg cmp_val.u8 = val->u8; 638b8e80941Smrg break; 639b8e80941Smrg case 16: 640b8e80941Smrg cmp_val.u16 = val->u16; 641b8e80941Smrg break; 642b8e80941Smrg case 32: 643b8e80941Smrg cmp_val.u32 = val->u32; 644b8e80941Smrg break; 645b8e80941Smrg case 64: 646b8e80941Smrg cmp_val.u64 = val->u64; 647b8e80941Smrg break; 648b8e80941Smrg default: 649b8e80941Smrg validate_assert(state, !"Invalid load_const bit size"); 650b8e80941Smrg } 651b8e80941Smrg validate_assert(state, memcmp(val, &cmp_val, sizeof(cmp_val)) == 0); 652b8e80941Smrg} 653b8e80941Smrg 654b8e80941Smrgstatic void 655b8e80941Smrgvalidate_load_const_instr(nir_load_const_instr *instr, validate_state *state) 656b8e80941Smrg{ 657b8e80941Smrg validate_ssa_def(&instr->def, state); 658b8e80941Smrg 659b8e80941Smrg for (unsigned i = 0; i < instr->def.num_components; i++) 660b8e80941Smrg validate_const_value(&instr->value[i], instr->def.bit_size, state); 661b8e80941Smrg} 662b8e80941Smrg 663b8e80941Smrgstatic void 664b8e80941Smrgvalidate_ssa_undef_instr(nir_ssa_undef_instr *instr, validate_state *state) 665b8e80941Smrg{ 666b8e80941Smrg validate_ssa_def(&instr->def, state); 667b8e80941Smrg} 668b8e80941Smrg 669b8e80941Smrgstatic void 670b8e80941Smrgvalidate_phi_instr(nir_phi_instr *instr, validate_state *state) 671b8e80941Smrg{ 672b8e80941Smrg /* 673b8e80941Smrg * don't validate the sources until we get to them from their predecessor 674b8e80941Smrg * basic blocks, to avoid validating an SSA use before its definition. 675b8e80941Smrg */ 676b8e80941Smrg 677b8e80941Smrg validate_dest(&instr->dest, state, 0, 0); 678b8e80941Smrg 679b8e80941Smrg exec_list_validate(&instr->srcs); 680b8e80941Smrg validate_assert(state, exec_list_length(&instr->srcs) == 681b8e80941Smrg state->block->predecessors->entries); 682b8e80941Smrg} 683b8e80941Smrg 684b8e80941Smrgstatic void 685b8e80941Smrgvalidate_instr(nir_instr *instr, validate_state *state) 686b8e80941Smrg{ 687b8e80941Smrg validate_assert(state, instr->block == state->block); 688b8e80941Smrg 689b8e80941Smrg state->instr = instr; 690b8e80941Smrg 691b8e80941Smrg switch (instr->type) { 692b8e80941Smrg case nir_instr_type_alu: 693b8e80941Smrg validate_alu_instr(nir_instr_as_alu(instr), state); 694b8e80941Smrg break; 695b8e80941Smrg 696b8e80941Smrg case nir_instr_type_deref: 697b8e80941Smrg validate_deref_instr(nir_instr_as_deref(instr), state); 698b8e80941Smrg break; 699b8e80941Smrg 700b8e80941Smrg case nir_instr_type_call: 701b8e80941Smrg validate_call_instr(nir_instr_as_call(instr), state); 702b8e80941Smrg break; 703b8e80941Smrg 704b8e80941Smrg case nir_instr_type_intrinsic: 705b8e80941Smrg validate_intrinsic_instr(nir_instr_as_intrinsic(instr), state); 706b8e80941Smrg break; 707b8e80941Smrg 708b8e80941Smrg case nir_instr_type_tex: 709b8e80941Smrg validate_tex_instr(nir_instr_as_tex(instr), state); 710b8e80941Smrg break; 711b8e80941Smrg 712b8e80941Smrg case nir_instr_type_load_const: 713b8e80941Smrg validate_load_const_instr(nir_instr_as_load_const(instr), state); 714b8e80941Smrg break; 715b8e80941Smrg 716b8e80941Smrg case nir_instr_type_phi: 717b8e80941Smrg validate_phi_instr(nir_instr_as_phi(instr), state); 718b8e80941Smrg break; 719b8e80941Smrg 720b8e80941Smrg case nir_instr_type_ssa_undef: 721b8e80941Smrg validate_ssa_undef_instr(nir_instr_as_ssa_undef(instr), state); 722b8e80941Smrg break; 723b8e80941Smrg 724b8e80941Smrg case nir_instr_type_jump: 725b8e80941Smrg break; 726b8e80941Smrg 727b8e80941Smrg default: 728b8e80941Smrg validate_assert(state, !"Invalid ALU instruction type"); 729b8e80941Smrg break; 730b8e80941Smrg } 731b8e80941Smrg 732b8e80941Smrg state->instr = NULL; 733b8e80941Smrg} 734b8e80941Smrg 735b8e80941Smrgstatic void 736b8e80941Smrgvalidate_phi_src(nir_phi_instr *instr, nir_block *pred, validate_state *state) 737b8e80941Smrg{ 738b8e80941Smrg state->instr = &instr->instr; 739b8e80941Smrg 740b8e80941Smrg validate_assert(state, instr->dest.is_ssa); 741b8e80941Smrg 742b8e80941Smrg exec_list_validate(&instr->srcs); 743b8e80941Smrg nir_foreach_phi_src(src, instr) { 744b8e80941Smrg if (src->pred == pred) { 745b8e80941Smrg validate_assert(state, src->src.is_ssa); 746b8e80941Smrg validate_src(&src->src, state, instr->dest.ssa.bit_size, 747b8e80941Smrg instr->dest.ssa.num_components); 748b8e80941Smrg state->instr = NULL; 749b8e80941Smrg return; 750b8e80941Smrg } 751b8e80941Smrg } 752b8e80941Smrg 753b8e80941Smrg abort(); 754b8e80941Smrg} 755b8e80941Smrg 756b8e80941Smrgstatic void 757b8e80941Smrgvalidate_phi_srcs(nir_block *block, nir_block *succ, validate_state *state) 758b8e80941Smrg{ 759b8e80941Smrg nir_foreach_instr(instr, succ) { 760b8e80941Smrg if (instr->type != nir_instr_type_phi) 761b8e80941Smrg break; 762b8e80941Smrg 763b8e80941Smrg validate_phi_src(nir_instr_as_phi(instr), block, state); 764b8e80941Smrg } 765b8e80941Smrg} 766b8e80941Smrg 767b8e80941Smrgstatic void validate_cf_node(nir_cf_node *node, validate_state *state); 768b8e80941Smrg 769b8e80941Smrgstatic void 770b8e80941Smrgvalidate_block(nir_block *block, validate_state *state) 771b8e80941Smrg{ 772b8e80941Smrg validate_assert(state, block->cf_node.parent == state->parent_node); 773b8e80941Smrg 774b8e80941Smrg state->block = block; 775b8e80941Smrg 776b8e80941Smrg exec_list_validate(&block->instr_list); 777b8e80941Smrg nir_foreach_instr(instr, block) { 778b8e80941Smrg if (instr->type == nir_instr_type_phi) { 779b8e80941Smrg validate_assert(state, instr == nir_block_first_instr(block) || 780b8e80941Smrg nir_instr_prev(instr)->type == nir_instr_type_phi); 781b8e80941Smrg } 782b8e80941Smrg 783b8e80941Smrg if (instr->type == nir_instr_type_jump) { 784b8e80941Smrg validate_assert(state, instr == nir_block_last_instr(block)); 785b8e80941Smrg } 786b8e80941Smrg 787b8e80941Smrg validate_instr(instr, state); 788b8e80941Smrg } 789b8e80941Smrg 790b8e80941Smrg validate_assert(state, block->successors[0] != NULL); 791b8e80941Smrg validate_assert(state, block->successors[0] != block->successors[1]); 792b8e80941Smrg 793b8e80941Smrg for (unsigned i = 0; i < 2; i++) { 794b8e80941Smrg if (block->successors[i] != NULL) { 795b8e80941Smrg struct set_entry *entry = 796b8e80941Smrg _mesa_set_search(block->successors[i]->predecessors, block); 797b8e80941Smrg validate_assert(state, entry); 798b8e80941Smrg 799b8e80941Smrg validate_phi_srcs(block, block->successors[i], state); 800b8e80941Smrg } 801b8e80941Smrg } 802b8e80941Smrg 803b8e80941Smrg set_foreach(block->predecessors, entry) { 804b8e80941Smrg const nir_block *pred = entry->key; 805b8e80941Smrg validate_assert(state, pred->successors[0] == block || 806b8e80941Smrg pred->successors[1] == block); 807b8e80941Smrg } 808b8e80941Smrg 809b8e80941Smrg if (!exec_list_is_empty(&block->instr_list) && 810b8e80941Smrg nir_block_last_instr(block)->type == nir_instr_type_jump) { 811b8e80941Smrg validate_assert(state, block->successors[1] == NULL); 812b8e80941Smrg nir_jump_instr *jump = nir_instr_as_jump(nir_block_last_instr(block)); 813b8e80941Smrg switch (jump->type) { 814b8e80941Smrg case nir_jump_break: { 815b8e80941Smrg nir_block *after = 816b8e80941Smrg nir_cf_node_as_block(nir_cf_node_next(&state->loop->cf_node)); 817b8e80941Smrg validate_assert(state, block->successors[0] == after); 818b8e80941Smrg break; 819b8e80941Smrg } 820b8e80941Smrg 821b8e80941Smrg case nir_jump_continue: { 822b8e80941Smrg nir_block *first = nir_loop_first_block(state->loop); 823b8e80941Smrg validate_assert(state, block->successors[0] == first); 824b8e80941Smrg break; 825b8e80941Smrg } 826b8e80941Smrg 827b8e80941Smrg case nir_jump_return: 828b8e80941Smrg validate_assert(state, block->successors[0] == state->impl->end_block); 829b8e80941Smrg break; 830b8e80941Smrg 831b8e80941Smrg default: 832b8e80941Smrg unreachable("bad jump type"); 833b8e80941Smrg } 834b8e80941Smrg } else { 835b8e80941Smrg nir_cf_node *next = nir_cf_node_next(&block->cf_node); 836b8e80941Smrg if (next == NULL) { 837b8e80941Smrg switch (state->parent_node->type) { 838b8e80941Smrg case nir_cf_node_loop: { 839b8e80941Smrg nir_block *first = nir_loop_first_block(state->loop); 840b8e80941Smrg validate_assert(state, block->successors[0] == first); 841b8e80941Smrg /* due to the hack for infinite loops, block->successors[1] may 842b8e80941Smrg * point to the block after the loop. 843b8e80941Smrg */ 844b8e80941Smrg break; 845b8e80941Smrg } 846b8e80941Smrg 847b8e80941Smrg case nir_cf_node_if: { 848b8e80941Smrg nir_block *after = 849b8e80941Smrg nir_cf_node_as_block(nir_cf_node_next(state->parent_node)); 850b8e80941Smrg validate_assert(state, block->successors[0] == after); 851b8e80941Smrg validate_assert(state, block->successors[1] == NULL); 852b8e80941Smrg break; 853b8e80941Smrg } 854b8e80941Smrg 855b8e80941Smrg case nir_cf_node_function: 856b8e80941Smrg validate_assert(state, block->successors[0] == state->impl->end_block); 857b8e80941Smrg validate_assert(state, block->successors[1] == NULL); 858b8e80941Smrg break; 859b8e80941Smrg 860b8e80941Smrg default: 861b8e80941Smrg unreachable("unknown control flow node type"); 862b8e80941Smrg } 863b8e80941Smrg } else { 864b8e80941Smrg if (next->type == nir_cf_node_if) { 865b8e80941Smrg nir_if *if_stmt = nir_cf_node_as_if(next); 866b8e80941Smrg validate_assert(state, block->successors[0] == 867b8e80941Smrg nir_if_first_then_block(if_stmt)); 868b8e80941Smrg validate_assert(state, block->successors[1] == 869b8e80941Smrg nir_if_first_else_block(if_stmt)); 870b8e80941Smrg } else { 871b8e80941Smrg validate_assert(state, next->type == nir_cf_node_loop); 872b8e80941Smrg nir_loop *loop = nir_cf_node_as_loop(next); 873b8e80941Smrg validate_assert(state, block->successors[0] == 874b8e80941Smrg nir_loop_first_block(loop)); 875b8e80941Smrg validate_assert(state, block->successors[1] == NULL); 876b8e80941Smrg } 877b8e80941Smrg } 878b8e80941Smrg } 879b8e80941Smrg} 880b8e80941Smrg 881b8e80941Smrgstatic void 882b8e80941Smrgvalidate_if(nir_if *if_stmt, validate_state *state) 883b8e80941Smrg{ 884b8e80941Smrg state->if_stmt = if_stmt; 885b8e80941Smrg 886b8e80941Smrg validate_assert(state, !exec_node_is_head_sentinel(if_stmt->cf_node.node.prev)); 887b8e80941Smrg nir_cf_node *prev_node = nir_cf_node_prev(&if_stmt->cf_node); 888b8e80941Smrg validate_assert(state, prev_node->type == nir_cf_node_block); 889b8e80941Smrg 890b8e80941Smrg validate_assert(state, !exec_node_is_tail_sentinel(if_stmt->cf_node.node.next)); 891b8e80941Smrg nir_cf_node *next_node = nir_cf_node_next(&if_stmt->cf_node); 892b8e80941Smrg validate_assert(state, next_node->type == nir_cf_node_block); 893b8e80941Smrg 894b8e80941Smrg validate_src(&if_stmt->condition, state, 0, 1); 895b8e80941Smrg 896b8e80941Smrg validate_assert(state, !exec_list_is_empty(&if_stmt->then_list)); 897b8e80941Smrg validate_assert(state, !exec_list_is_empty(&if_stmt->else_list)); 898b8e80941Smrg 899b8e80941Smrg nir_cf_node *old_parent = state->parent_node; 900b8e80941Smrg state->parent_node = &if_stmt->cf_node; 901b8e80941Smrg 902b8e80941Smrg exec_list_validate(&if_stmt->then_list); 903b8e80941Smrg foreach_list_typed(nir_cf_node, cf_node, node, &if_stmt->then_list) { 904b8e80941Smrg validate_cf_node(cf_node, state); 905b8e80941Smrg } 906b8e80941Smrg 907b8e80941Smrg exec_list_validate(&if_stmt->else_list); 908b8e80941Smrg foreach_list_typed(nir_cf_node, cf_node, node, &if_stmt->else_list) { 909b8e80941Smrg validate_cf_node(cf_node, state); 910b8e80941Smrg } 911b8e80941Smrg 912b8e80941Smrg state->parent_node = old_parent; 913b8e80941Smrg state->if_stmt = NULL; 914b8e80941Smrg} 915b8e80941Smrg 916b8e80941Smrgstatic void 917b8e80941Smrgvalidate_loop(nir_loop *loop, validate_state *state) 918b8e80941Smrg{ 919b8e80941Smrg validate_assert(state, !exec_node_is_head_sentinel(loop->cf_node.node.prev)); 920b8e80941Smrg nir_cf_node *prev_node = nir_cf_node_prev(&loop->cf_node); 921b8e80941Smrg validate_assert(state, prev_node->type == nir_cf_node_block); 922b8e80941Smrg 923b8e80941Smrg validate_assert(state, !exec_node_is_tail_sentinel(loop->cf_node.node.next)); 924b8e80941Smrg nir_cf_node *next_node = nir_cf_node_next(&loop->cf_node); 925b8e80941Smrg validate_assert(state, next_node->type == nir_cf_node_block); 926b8e80941Smrg 927b8e80941Smrg validate_assert(state, !exec_list_is_empty(&loop->body)); 928b8e80941Smrg 929b8e80941Smrg nir_cf_node *old_parent = state->parent_node; 930b8e80941Smrg state->parent_node = &loop->cf_node; 931b8e80941Smrg nir_loop *old_loop = state->loop; 932b8e80941Smrg state->loop = loop; 933b8e80941Smrg 934b8e80941Smrg exec_list_validate(&loop->body); 935b8e80941Smrg foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) { 936b8e80941Smrg validate_cf_node(cf_node, state); 937b8e80941Smrg } 938b8e80941Smrg 939b8e80941Smrg state->parent_node = old_parent; 940b8e80941Smrg state->loop = old_loop; 941b8e80941Smrg} 942b8e80941Smrg 943b8e80941Smrgstatic void 944b8e80941Smrgvalidate_cf_node(nir_cf_node *node, validate_state *state) 945b8e80941Smrg{ 946b8e80941Smrg validate_assert(state, node->parent == state->parent_node); 947b8e80941Smrg 948b8e80941Smrg switch (node->type) { 949b8e80941Smrg case nir_cf_node_block: 950b8e80941Smrg validate_block(nir_cf_node_as_block(node), state); 951b8e80941Smrg break; 952b8e80941Smrg 953b8e80941Smrg case nir_cf_node_if: 954b8e80941Smrg validate_if(nir_cf_node_as_if(node), state); 955b8e80941Smrg break; 956b8e80941Smrg 957b8e80941Smrg case nir_cf_node_loop: 958b8e80941Smrg validate_loop(nir_cf_node_as_loop(node), state); 959b8e80941Smrg break; 960b8e80941Smrg 961b8e80941Smrg default: 962b8e80941Smrg unreachable("Invalid CF node type"); 963b8e80941Smrg } 964b8e80941Smrg} 965b8e80941Smrg 966b8e80941Smrgstatic void 967b8e80941Smrgprevalidate_reg_decl(nir_register *reg, validate_state *state) 968b8e80941Smrg{ 969b8e80941Smrg validate_assert(state, reg->index < state->impl->reg_alloc); 970b8e80941Smrg validate_assert(state, !BITSET_TEST(state->regs_found, reg->index)); 971b8e80941Smrg BITSET_SET(state->regs_found, reg->index); 972b8e80941Smrg 973b8e80941Smrg list_validate(®->uses); 974b8e80941Smrg list_validate(®->defs); 975b8e80941Smrg list_validate(®->if_uses); 976b8e80941Smrg 977b8e80941Smrg reg_validate_state *reg_state = ralloc(state->regs, reg_validate_state); 978b8e80941Smrg reg_state->uses = _mesa_pointer_set_create(reg_state); 979b8e80941Smrg reg_state->if_uses = _mesa_pointer_set_create(reg_state); 980b8e80941Smrg reg_state->defs = _mesa_pointer_set_create(reg_state); 981b8e80941Smrg 982b8e80941Smrg reg_state->where_defined = state->impl; 983b8e80941Smrg 984b8e80941Smrg _mesa_hash_table_insert(state->regs, reg, reg_state); 985b8e80941Smrg} 986b8e80941Smrg 987b8e80941Smrgstatic void 988b8e80941Smrgpostvalidate_reg_decl(nir_register *reg, validate_state *state) 989b8e80941Smrg{ 990b8e80941Smrg struct hash_entry *entry = _mesa_hash_table_search(state->regs, reg); 991b8e80941Smrg 992b8e80941Smrg assume(entry); 993b8e80941Smrg reg_validate_state *reg_state = (reg_validate_state *) entry->data; 994b8e80941Smrg 995b8e80941Smrg nir_foreach_use(src, reg) { 996b8e80941Smrg struct set_entry *entry = _mesa_set_search(reg_state->uses, src); 997b8e80941Smrg validate_assert(state, entry); 998b8e80941Smrg _mesa_set_remove(reg_state->uses, entry); 999b8e80941Smrg } 1000b8e80941Smrg 1001b8e80941Smrg if (reg_state->uses->entries != 0) { 1002b8e80941Smrg printf("extra entries in register uses:\n"); 1003b8e80941Smrg set_foreach(reg_state->uses, entry) 1004b8e80941Smrg printf("%p\n", entry->key); 1005b8e80941Smrg 1006b8e80941Smrg abort(); 1007b8e80941Smrg } 1008b8e80941Smrg 1009b8e80941Smrg nir_foreach_if_use(src, reg) { 1010b8e80941Smrg struct set_entry *entry = _mesa_set_search(reg_state->if_uses, src); 1011b8e80941Smrg validate_assert(state, entry); 1012b8e80941Smrg _mesa_set_remove(reg_state->if_uses, entry); 1013b8e80941Smrg } 1014b8e80941Smrg 1015b8e80941Smrg if (reg_state->if_uses->entries != 0) { 1016b8e80941Smrg printf("extra entries in register if_uses:\n"); 1017b8e80941Smrg set_foreach(reg_state->if_uses, entry) 1018b8e80941Smrg printf("%p\n", entry->key); 1019b8e80941Smrg 1020b8e80941Smrg abort(); 1021b8e80941Smrg } 1022b8e80941Smrg 1023b8e80941Smrg nir_foreach_def(src, reg) { 1024b8e80941Smrg struct set_entry *entry = _mesa_set_search(reg_state->defs, src); 1025b8e80941Smrg validate_assert(state, entry); 1026b8e80941Smrg _mesa_set_remove(reg_state->defs, entry); 1027b8e80941Smrg } 1028b8e80941Smrg 1029b8e80941Smrg if (reg_state->defs->entries != 0) { 1030b8e80941Smrg printf("extra entries in register defs:\n"); 1031b8e80941Smrg set_foreach(reg_state->defs, entry) 1032b8e80941Smrg printf("%p\n", entry->key); 1033b8e80941Smrg 1034b8e80941Smrg abort(); 1035b8e80941Smrg } 1036b8e80941Smrg} 1037b8e80941Smrg 1038b8e80941Smrgstatic void 1039b8e80941Smrgvalidate_var_decl(nir_variable *var, bool is_global, validate_state *state) 1040b8e80941Smrg{ 1041b8e80941Smrg state->var = var; 1042b8e80941Smrg 1043b8e80941Smrg validate_assert(state, is_global == nir_variable_is_global(var)); 1044b8e80941Smrg 1045b8e80941Smrg /* Must have exactly one mode set */ 1046b8e80941Smrg validate_assert(state, util_is_power_of_two_nonzero(var->data.mode)); 1047b8e80941Smrg 1048b8e80941Smrg if (var->data.compact) { 1049b8e80941Smrg /* The "compact" flag is only valid on arrays of scalars. */ 1050b8e80941Smrg assert(glsl_type_is_array(var->type)); 1051b8e80941Smrg 1052b8e80941Smrg const struct glsl_type *type = glsl_get_array_element(var->type); 1053b8e80941Smrg if (nir_is_per_vertex_io(var, state->shader->info.stage)) { 1054b8e80941Smrg assert(glsl_type_is_array(type)); 1055b8e80941Smrg assert(glsl_type_is_scalar(glsl_get_array_element(type))); 1056b8e80941Smrg } else { 1057b8e80941Smrg assert(glsl_type_is_scalar(type)); 1058b8e80941Smrg } 1059b8e80941Smrg } 1060b8e80941Smrg 1061b8e80941Smrg if (var->num_members > 0) { 1062b8e80941Smrg const struct glsl_type *without_array = glsl_without_array(var->type); 1063b8e80941Smrg validate_assert(state, glsl_type_is_struct_or_ifc(without_array)); 1064b8e80941Smrg validate_assert(state, var->num_members == glsl_get_length(without_array)); 1065b8e80941Smrg validate_assert(state, var->members != NULL); 1066b8e80941Smrg } 1067b8e80941Smrg 1068b8e80941Smrg /* 1069b8e80941Smrg * TODO validate some things ir_validate.cpp does (requires more GLSL type 1070b8e80941Smrg * support) 1071b8e80941Smrg */ 1072b8e80941Smrg 1073b8e80941Smrg _mesa_hash_table_insert(state->var_defs, var, 1074b8e80941Smrg is_global ? NULL : state->impl); 1075b8e80941Smrg 1076b8e80941Smrg state->var = NULL; 1077b8e80941Smrg} 1078b8e80941Smrg 1079b8e80941Smrgstatic bool 1080b8e80941Smrgpostvalidate_ssa_def(nir_ssa_def *def, void *void_state) 1081b8e80941Smrg{ 1082b8e80941Smrg validate_state *state = void_state; 1083b8e80941Smrg 1084b8e80941Smrg struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, def); 1085b8e80941Smrg 1086b8e80941Smrg assume(entry); 1087b8e80941Smrg ssa_def_validate_state *def_state = (ssa_def_validate_state *)entry->data; 1088b8e80941Smrg 1089b8e80941Smrg nir_foreach_use(src, def) { 1090b8e80941Smrg struct set_entry *entry = _mesa_set_search(def_state->uses, src); 1091b8e80941Smrg validate_assert(state, entry); 1092b8e80941Smrg _mesa_set_remove(def_state->uses, entry); 1093b8e80941Smrg } 1094b8e80941Smrg 1095b8e80941Smrg if (def_state->uses->entries != 0) { 1096b8e80941Smrg printf("extra entries in SSA def uses:\n"); 1097b8e80941Smrg set_foreach(def_state->uses, entry) 1098b8e80941Smrg printf("%p\n", entry->key); 1099b8e80941Smrg 1100b8e80941Smrg abort(); 1101b8e80941Smrg } 1102b8e80941Smrg 1103b8e80941Smrg nir_foreach_if_use(src, def) { 1104b8e80941Smrg struct set_entry *entry = _mesa_set_search(def_state->if_uses, src); 1105b8e80941Smrg validate_assert(state, entry); 1106b8e80941Smrg _mesa_set_remove(def_state->if_uses, entry); 1107b8e80941Smrg } 1108b8e80941Smrg 1109b8e80941Smrg if (def_state->if_uses->entries != 0) { 1110b8e80941Smrg printf("extra entries in SSA def uses:\n"); 1111b8e80941Smrg set_foreach(def_state->if_uses, entry) 1112b8e80941Smrg printf("%p\n", entry->key); 1113b8e80941Smrg 1114b8e80941Smrg abort(); 1115b8e80941Smrg } 1116b8e80941Smrg 1117b8e80941Smrg return true; 1118b8e80941Smrg} 1119b8e80941Smrg 1120b8e80941Smrgstatic void 1121b8e80941Smrgvalidate_function_impl(nir_function_impl *impl, validate_state *state) 1122b8e80941Smrg{ 1123b8e80941Smrg validate_assert(state, impl->function->impl == impl); 1124b8e80941Smrg validate_assert(state, impl->cf_node.parent == NULL); 1125b8e80941Smrg 1126b8e80941Smrg validate_assert(state, exec_list_is_empty(&impl->end_block->instr_list)); 1127b8e80941Smrg validate_assert(state, impl->end_block->successors[0] == NULL); 1128b8e80941Smrg validate_assert(state, impl->end_block->successors[1] == NULL); 1129b8e80941Smrg 1130b8e80941Smrg state->impl = impl; 1131b8e80941Smrg state->parent_node = &impl->cf_node; 1132b8e80941Smrg 1133b8e80941Smrg exec_list_validate(&impl->locals); 1134b8e80941Smrg nir_foreach_variable(var, &impl->locals) { 1135b8e80941Smrg validate_var_decl(var, false, state); 1136b8e80941Smrg } 1137b8e80941Smrg 1138b8e80941Smrg state->regs_found = realloc(state->regs_found, 1139b8e80941Smrg BITSET_WORDS(impl->reg_alloc) * 1140b8e80941Smrg sizeof(BITSET_WORD)); 1141b8e80941Smrg memset(state->regs_found, 0, BITSET_WORDS(impl->reg_alloc) * 1142b8e80941Smrg sizeof(BITSET_WORD)); 1143b8e80941Smrg exec_list_validate(&impl->registers); 1144b8e80941Smrg foreach_list_typed(nir_register, reg, node, &impl->registers) { 1145b8e80941Smrg prevalidate_reg_decl(reg, state); 1146b8e80941Smrg } 1147b8e80941Smrg 1148b8e80941Smrg state->ssa_defs_found = realloc(state->ssa_defs_found, 1149b8e80941Smrg BITSET_WORDS(impl->ssa_alloc) * 1150b8e80941Smrg sizeof(BITSET_WORD)); 1151b8e80941Smrg memset(state->ssa_defs_found, 0, BITSET_WORDS(impl->ssa_alloc) * 1152b8e80941Smrg sizeof(BITSET_WORD)); 1153b8e80941Smrg exec_list_validate(&impl->body); 1154b8e80941Smrg foreach_list_typed(nir_cf_node, node, node, &impl->body) { 1155b8e80941Smrg validate_cf_node(node, state); 1156b8e80941Smrg } 1157b8e80941Smrg 1158b8e80941Smrg foreach_list_typed(nir_register, reg, node, &impl->registers) { 1159b8e80941Smrg postvalidate_reg_decl(reg, state); 1160b8e80941Smrg } 1161b8e80941Smrg 1162b8e80941Smrg nir_foreach_block(block, impl) { 1163b8e80941Smrg nir_foreach_instr(instr, block) 1164b8e80941Smrg nir_foreach_ssa_def(instr, postvalidate_ssa_def, state); 1165b8e80941Smrg } 1166b8e80941Smrg} 1167b8e80941Smrg 1168b8e80941Smrgstatic void 1169b8e80941Smrgvalidate_function(nir_function *func, validate_state *state) 1170b8e80941Smrg{ 1171b8e80941Smrg if (func->impl != NULL) { 1172b8e80941Smrg validate_assert(state, func->impl->function == func); 1173b8e80941Smrg validate_function_impl(func->impl, state); 1174b8e80941Smrg } 1175b8e80941Smrg} 1176b8e80941Smrg 1177b8e80941Smrgstatic void 1178b8e80941Smrginit_validate_state(validate_state *state) 1179b8e80941Smrg{ 1180b8e80941Smrg state->regs = _mesa_pointer_hash_table_create(NULL); 1181b8e80941Smrg state->ssa_defs = _mesa_pointer_hash_table_create(NULL); 1182b8e80941Smrg state->ssa_defs_found = NULL; 1183b8e80941Smrg state->regs_found = NULL; 1184b8e80941Smrg state->var_defs = _mesa_pointer_hash_table_create(NULL); 1185b8e80941Smrg state->errors = _mesa_pointer_hash_table_create(NULL); 1186b8e80941Smrg 1187b8e80941Smrg state->loop = NULL; 1188b8e80941Smrg state->instr = NULL; 1189b8e80941Smrg state->var = NULL; 1190b8e80941Smrg} 1191b8e80941Smrg 1192b8e80941Smrgstatic void 1193b8e80941Smrgdestroy_validate_state(validate_state *state) 1194b8e80941Smrg{ 1195b8e80941Smrg _mesa_hash_table_destroy(state->regs, NULL); 1196b8e80941Smrg _mesa_hash_table_destroy(state->ssa_defs, NULL); 1197b8e80941Smrg free(state->ssa_defs_found); 1198b8e80941Smrg free(state->regs_found); 1199b8e80941Smrg _mesa_hash_table_destroy(state->var_defs, NULL); 1200b8e80941Smrg _mesa_hash_table_destroy(state->errors, NULL); 1201b8e80941Smrg} 1202b8e80941Smrg 1203b8e80941Smrgmtx_t fail_dump_mutex = _MTX_INITIALIZER_NP; 1204b8e80941Smrg 1205b8e80941Smrgstatic void 1206b8e80941Smrgdump_errors(validate_state *state, const char *when) 1207b8e80941Smrg{ 1208b8e80941Smrg struct hash_table *errors = state->errors; 1209b8e80941Smrg 1210b8e80941Smrg /* Lock around dumping so that we get clean dumps in a multi-threaded 1211b8e80941Smrg * scenario 1212b8e80941Smrg */ 1213b8e80941Smrg mtx_lock(&fail_dump_mutex); 1214b8e80941Smrg 1215b8e80941Smrg if (when) { 1216b8e80941Smrg fprintf(stderr, "NIR validation failed %s\n", when); 1217b8e80941Smrg fprintf(stderr, "%d errors:\n", _mesa_hash_table_num_entries(errors)); 1218b8e80941Smrg } else { 1219b8e80941Smrg fprintf(stderr, "NIR validation failed with %d errors:\n", 1220b8e80941Smrg _mesa_hash_table_num_entries(errors)); 1221b8e80941Smrg } 1222b8e80941Smrg 1223b8e80941Smrg nir_print_shader_annotated(state->shader, stderr, errors); 1224b8e80941Smrg 1225b8e80941Smrg if (_mesa_hash_table_num_entries(errors) > 0) { 1226b8e80941Smrg fprintf(stderr, "%d additional errors:\n", 1227b8e80941Smrg _mesa_hash_table_num_entries(errors)); 1228b8e80941Smrg hash_table_foreach(errors, entry) { 1229b8e80941Smrg fprintf(stderr, "%s\n", (char *)entry->data); 1230b8e80941Smrg } 1231b8e80941Smrg } 1232b8e80941Smrg 1233b8e80941Smrg mtx_unlock(&fail_dump_mutex); 1234b8e80941Smrg 1235b8e80941Smrg abort(); 1236b8e80941Smrg} 1237b8e80941Smrg 1238b8e80941Smrgvoid 1239b8e80941Smrgnir_validate_shader(nir_shader *shader, const char *when) 1240b8e80941Smrg{ 1241b8e80941Smrg static int should_validate = -1; 1242b8e80941Smrg if (should_validate < 0) 1243b8e80941Smrg should_validate = env_var_as_boolean("NIR_VALIDATE", true); 1244b8e80941Smrg if (!should_validate) 1245b8e80941Smrg return; 1246b8e80941Smrg 1247b8e80941Smrg validate_state state; 1248b8e80941Smrg init_validate_state(&state); 1249b8e80941Smrg 1250b8e80941Smrg state.shader = shader; 1251b8e80941Smrg 1252b8e80941Smrg exec_list_validate(&shader->uniforms); 1253b8e80941Smrg nir_foreach_variable(var, &shader->uniforms) { 1254b8e80941Smrg validate_var_decl(var, true, &state); 1255b8e80941Smrg } 1256b8e80941Smrg 1257b8e80941Smrg exec_list_validate(&shader->inputs); 1258b8e80941Smrg nir_foreach_variable(var, &shader->inputs) { 1259b8e80941Smrg validate_var_decl(var, true, &state); 1260b8e80941Smrg } 1261b8e80941Smrg 1262b8e80941Smrg exec_list_validate(&shader->outputs); 1263b8e80941Smrg nir_foreach_variable(var, &shader->outputs) { 1264b8e80941Smrg validate_var_decl(var, true, &state); 1265b8e80941Smrg } 1266b8e80941Smrg 1267b8e80941Smrg exec_list_validate(&shader->shared); 1268b8e80941Smrg nir_foreach_variable(var, &shader->shared) { 1269b8e80941Smrg validate_var_decl(var, true, &state); 1270b8e80941Smrg } 1271b8e80941Smrg 1272b8e80941Smrg exec_list_validate(&shader->globals); 1273b8e80941Smrg nir_foreach_variable(var, &shader->globals) { 1274b8e80941Smrg validate_var_decl(var, true, &state); 1275b8e80941Smrg } 1276b8e80941Smrg 1277b8e80941Smrg exec_list_validate(&shader->system_values); 1278b8e80941Smrg nir_foreach_variable(var, &shader->system_values) { 1279b8e80941Smrg validate_var_decl(var, true, &state); 1280b8e80941Smrg } 1281b8e80941Smrg 1282b8e80941Smrg exec_list_validate(&shader->functions); 1283b8e80941Smrg foreach_list_typed(nir_function, func, node, &shader->functions) { 1284b8e80941Smrg validate_function(func, &state); 1285b8e80941Smrg } 1286b8e80941Smrg 1287b8e80941Smrg if (_mesa_hash_table_num_entries(state.errors) > 0) 1288b8e80941Smrg dump_errors(&state, when); 1289b8e80941Smrg 1290b8e80941Smrg destroy_validate_state(&state); 1291b8e80941Smrg} 1292b8e80941Smrg 1293b8e80941Smrg#endif /* NDEBUG */ 1294