1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2014 Intel Corporation
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker *
11*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker * Software.
14*61046927SAndroid Build Coastguard Worker *
15*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker *
23*61046927SAndroid Build Coastguard Worker * Authors:
24*61046927SAndroid Build Coastguard Worker * Connor Abbott ([email protected])
25*61046927SAndroid Build Coastguard Worker *
26*61046927SAndroid Build Coastguard Worker */
27*61046927SAndroid Build Coastguard Worker
28*61046927SAndroid Build Coastguard Worker #include <assert.h>
29*61046927SAndroid Build Coastguard Worker #include "c11/threads.h"
30*61046927SAndroid Build Coastguard Worker #include "util/simple_mtx.h"
31*61046927SAndroid Build Coastguard Worker #include "nir.h"
32*61046927SAndroid Build Coastguard Worker #include "nir_xfb_info.h"
33*61046927SAndroid Build Coastguard Worker
34*61046927SAndroid Build Coastguard Worker /*
35*61046927SAndroid Build Coastguard Worker * This file checks for invalid IR indicating a bug somewhere in the compiler.
36*61046927SAndroid Build Coastguard Worker */
37*61046927SAndroid Build Coastguard Worker
38*61046927SAndroid Build Coastguard Worker /* Since this file is just a pile of asserts, don't bother compiling it if
39*61046927SAndroid Build Coastguard Worker * we're not building a debug build.
40*61046927SAndroid Build Coastguard Worker */
41*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
42*61046927SAndroid Build Coastguard Worker
43*61046927SAndroid Build Coastguard Worker typedef struct {
44*61046927SAndroid Build Coastguard Worker void *mem_ctx;
45*61046927SAndroid Build Coastguard Worker
46*61046927SAndroid Build Coastguard Worker /* the current shader being validated */
47*61046927SAndroid Build Coastguard Worker nir_shader *shader;
48*61046927SAndroid Build Coastguard Worker
49*61046927SAndroid Build Coastguard Worker /* the current instruction being validated */
50*61046927SAndroid Build Coastguard Worker nir_instr *instr;
51*61046927SAndroid Build Coastguard Worker
52*61046927SAndroid Build Coastguard Worker /* the current variable being validated */
53*61046927SAndroid Build Coastguard Worker nir_variable *var;
54*61046927SAndroid Build Coastguard Worker
55*61046927SAndroid Build Coastguard Worker /* the current basic block being validated */
56*61046927SAndroid Build Coastguard Worker nir_block *block;
57*61046927SAndroid Build Coastguard Worker
58*61046927SAndroid Build Coastguard Worker /* the current if statement being validated */
59*61046927SAndroid Build Coastguard Worker nir_if *if_stmt;
60*61046927SAndroid Build Coastguard Worker
61*61046927SAndroid Build Coastguard Worker /* the current loop being visited */
62*61046927SAndroid Build Coastguard Worker nir_loop *loop;
63*61046927SAndroid Build Coastguard Worker
64*61046927SAndroid Build Coastguard Worker /* weather the loop continue construct is being visited */
65*61046927SAndroid Build Coastguard Worker bool in_loop_continue_construct;
66*61046927SAndroid Build Coastguard Worker
67*61046927SAndroid Build Coastguard Worker /* the parent of the current cf node being visited */
68*61046927SAndroid Build Coastguard Worker nir_cf_node *parent_node;
69*61046927SAndroid Build Coastguard Worker
70*61046927SAndroid Build Coastguard Worker /* the current function implementation being validated */
71*61046927SAndroid Build Coastguard Worker nir_function_impl *impl;
72*61046927SAndroid Build Coastguard Worker
73*61046927SAndroid Build Coastguard Worker /* Set of all blocks in the list */
74*61046927SAndroid Build Coastguard Worker struct set *blocks;
75*61046927SAndroid Build Coastguard Worker
76*61046927SAndroid Build Coastguard Worker /* Number of tagged nir_src's. This is implicitly the cardinality of the set
77*61046927SAndroid Build Coastguard Worker * of pending nir_src's.
78*61046927SAndroid Build Coastguard Worker */
79*61046927SAndroid Build Coastguard Worker uint32_t nr_tagged_srcs;
80*61046927SAndroid Build Coastguard Worker
81*61046927SAndroid Build Coastguard Worker /* bitset of ssa definitions we have found; used to check uniqueness */
82*61046927SAndroid Build Coastguard Worker BITSET_WORD *ssa_defs_found;
83*61046927SAndroid Build Coastguard Worker
84*61046927SAndroid Build Coastguard Worker /* map of variable -> function implementation where it is defined or NULL
85*61046927SAndroid Build Coastguard Worker * if it is a global variable
86*61046927SAndroid Build Coastguard Worker */
87*61046927SAndroid Build Coastguard Worker struct hash_table *var_defs;
88*61046927SAndroid Build Coastguard Worker
89*61046927SAndroid Build Coastguard Worker /* map of instruction/var/etc to failed assert string */
90*61046927SAndroid Build Coastguard Worker struct hash_table *errors;
91*61046927SAndroid Build Coastguard Worker } validate_state;
92*61046927SAndroid Build Coastguard Worker
93*61046927SAndroid Build Coastguard Worker static void
log_error(validate_state * state,const char * cond,const char * file,int line)94*61046927SAndroid Build Coastguard Worker log_error(validate_state *state, const char *cond, const char *file, int line)
95*61046927SAndroid Build Coastguard Worker {
96*61046927SAndroid Build Coastguard Worker const void *obj;
97*61046927SAndroid Build Coastguard Worker
98*61046927SAndroid Build Coastguard Worker if (state->instr)
99*61046927SAndroid Build Coastguard Worker obj = state->instr;
100*61046927SAndroid Build Coastguard Worker else if (state->var)
101*61046927SAndroid Build Coastguard Worker obj = state->var;
102*61046927SAndroid Build Coastguard Worker else
103*61046927SAndroid Build Coastguard Worker obj = cond;
104*61046927SAndroid Build Coastguard Worker
105*61046927SAndroid Build Coastguard Worker char *msg = ralloc_asprintf(state->errors, "error: %s (%s:%d)",
106*61046927SAndroid Build Coastguard Worker cond, file, line);
107*61046927SAndroid Build Coastguard Worker
108*61046927SAndroid Build Coastguard Worker _mesa_hash_table_insert(state->errors, obj, msg);
109*61046927SAndroid Build Coastguard Worker }
110*61046927SAndroid Build Coastguard Worker
111*61046927SAndroid Build Coastguard Worker static bool
validate_assert_impl(validate_state * state,bool cond,const char * str,const char * file,unsigned line)112*61046927SAndroid Build Coastguard Worker validate_assert_impl(validate_state *state, bool cond, const char *str,
113*61046927SAndroid Build Coastguard Worker const char *file, unsigned line)
114*61046927SAndroid Build Coastguard Worker {
115*61046927SAndroid Build Coastguard Worker if (unlikely(!cond))
116*61046927SAndroid Build Coastguard Worker log_error(state, str, file, line);
117*61046927SAndroid Build Coastguard Worker return cond;
118*61046927SAndroid Build Coastguard Worker }
119*61046927SAndroid Build Coastguard Worker
120*61046927SAndroid Build Coastguard Worker #define validate_assert(state, cond) \
121*61046927SAndroid Build Coastguard Worker validate_assert_impl(state, (cond), #cond, __FILE__, __LINE__)
122*61046927SAndroid Build Coastguard Worker
123*61046927SAndroid Build Coastguard Worker static void
validate_num_components(validate_state * state,unsigned num_components)124*61046927SAndroid Build Coastguard Worker validate_num_components(validate_state *state, unsigned num_components)
125*61046927SAndroid Build Coastguard Worker {
126*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_num_components_valid(num_components));
127*61046927SAndroid Build Coastguard Worker }
128*61046927SAndroid Build Coastguard Worker
129*61046927SAndroid Build Coastguard Worker /* Tag used in nir_src::_parent to indicate that a source has been seen. */
130*61046927SAndroid Build Coastguard Worker #define SRC_TAG_SEEN (0x2)
131*61046927SAndroid Build Coastguard Worker
132*61046927SAndroid Build Coastguard Worker static_assert(SRC_TAG_SEEN == (~NIR_SRC_PARENT_MASK + 1),
133*61046927SAndroid Build Coastguard Worker "Parent pointer tags chosen not to collide");
134*61046927SAndroid Build Coastguard Worker
135*61046927SAndroid Build Coastguard Worker static void
tag_src(nir_src * src,validate_state * state)136*61046927SAndroid Build Coastguard Worker tag_src(nir_src *src, validate_state *state)
137*61046927SAndroid Build Coastguard Worker {
138*61046927SAndroid Build Coastguard Worker /* nir_src only appears once and only in one SSA def use list, since we
139*61046927SAndroid Build Coastguard Worker * mark nir_src's as we go by tagging this pointer.
140*61046927SAndroid Build Coastguard Worker */
141*61046927SAndroid Build Coastguard Worker if (validate_assert(state, (src->_parent & SRC_TAG_SEEN) == 0)) {
142*61046927SAndroid Build Coastguard Worker src->_parent |= SRC_TAG_SEEN;
143*61046927SAndroid Build Coastguard Worker state->nr_tagged_srcs++;
144*61046927SAndroid Build Coastguard Worker }
145*61046927SAndroid Build Coastguard Worker }
146*61046927SAndroid Build Coastguard Worker
147*61046927SAndroid Build Coastguard Worker /* Due to tagging, it's not safe to use nir_src_parent_instr during the main
148*61046927SAndroid Build Coastguard Worker * validate loop. This is a tagging-aware version.
149*61046927SAndroid Build Coastguard Worker */
150*61046927SAndroid Build Coastguard Worker static nir_instr *
src_parent_instr_safe(nir_src * src)151*61046927SAndroid Build Coastguard Worker src_parent_instr_safe(nir_src *src)
152*61046927SAndroid Build Coastguard Worker {
153*61046927SAndroid Build Coastguard Worker uintptr_t untagged = (src->_parent & ~SRC_TAG_SEEN);
154*61046927SAndroid Build Coastguard Worker assert(!(untagged & NIR_SRC_PARENT_IS_IF) && "precondition");
155*61046927SAndroid Build Coastguard Worker return (nir_instr *)untagged;
156*61046927SAndroid Build Coastguard Worker }
157*61046927SAndroid Build Coastguard Worker
158*61046927SAndroid Build Coastguard Worker /*
159*61046927SAndroid Build Coastguard Worker * As we walk SSA defs, we mark every use as seen by tagging the parent pointer.
160*61046927SAndroid Build Coastguard Worker * We need to make sure our use is seen in a use list.
161*61046927SAndroid Build Coastguard Worker *
162*61046927SAndroid Build Coastguard Worker * Then we unmark when we hit the source. This will let us prove that we've
163*61046927SAndroid Build Coastguard Worker * seen all the sources.
164*61046927SAndroid Build Coastguard Worker */
165*61046927SAndroid Build Coastguard Worker static void
validate_src_tag(nir_src * src,validate_state * state)166*61046927SAndroid Build Coastguard Worker validate_src_tag(nir_src *src, validate_state *state)
167*61046927SAndroid Build Coastguard Worker {
168*61046927SAndroid Build Coastguard Worker if (validate_assert(state, src->_parent & SRC_TAG_SEEN)) {
169*61046927SAndroid Build Coastguard Worker src->_parent &= ~SRC_TAG_SEEN;
170*61046927SAndroid Build Coastguard Worker state->nr_tagged_srcs--;
171*61046927SAndroid Build Coastguard Worker }
172*61046927SAndroid Build Coastguard Worker }
173*61046927SAndroid Build Coastguard Worker
174*61046927SAndroid Build Coastguard Worker static void
validate_if_src(nir_src * src,validate_state * state)175*61046927SAndroid Build Coastguard Worker validate_if_src(nir_src *src, validate_state *state)
176*61046927SAndroid Build Coastguard Worker {
177*61046927SAndroid Build Coastguard Worker validate_src_tag(src, state);
178*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_src_parent_if(src) == state->if_stmt);
179*61046927SAndroid Build Coastguard Worker validate_assert(state, src->ssa != NULL);
180*61046927SAndroid Build Coastguard Worker validate_assert(state, src->ssa->num_components == 1);
181*61046927SAndroid Build Coastguard Worker }
182*61046927SAndroid Build Coastguard Worker
183*61046927SAndroid Build Coastguard Worker static void
validate_src(nir_src * src,validate_state * state)184*61046927SAndroid Build Coastguard Worker validate_src(nir_src *src, validate_state *state)
185*61046927SAndroid Build Coastguard Worker {
186*61046927SAndroid Build Coastguard Worker /* Validate the tag first, so that nir_src_parent_instr is valid */
187*61046927SAndroid Build Coastguard Worker validate_src_tag(src, state);
188*61046927SAndroid Build Coastguard Worker
189*61046927SAndroid Build Coastguard Worker /* Source assumed to be instruction, use validate_if_src for if */
190*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_src_parent_instr(src) == state->instr);
191*61046927SAndroid Build Coastguard Worker
192*61046927SAndroid Build Coastguard Worker validate_assert(state, src->ssa != NULL);
193*61046927SAndroid Build Coastguard Worker }
194*61046927SAndroid Build Coastguard Worker
195*61046927SAndroid Build Coastguard Worker static void
validate_sized_src(nir_src * src,validate_state * state,unsigned bit_sizes,unsigned num_components)196*61046927SAndroid Build Coastguard Worker validate_sized_src(nir_src *src, validate_state *state,
197*61046927SAndroid Build Coastguard Worker unsigned bit_sizes, unsigned num_components)
198*61046927SAndroid Build Coastguard Worker {
199*61046927SAndroid Build Coastguard Worker validate_src(src, state);
200*61046927SAndroid Build Coastguard Worker
201*61046927SAndroid Build Coastguard Worker if (bit_sizes)
202*61046927SAndroid Build Coastguard Worker validate_assert(state, src->ssa->bit_size & bit_sizes);
203*61046927SAndroid Build Coastguard Worker if (num_components)
204*61046927SAndroid Build Coastguard Worker validate_assert(state, src->ssa->num_components == num_components);
205*61046927SAndroid Build Coastguard Worker }
206*61046927SAndroid Build Coastguard Worker
207*61046927SAndroid Build Coastguard Worker static void
validate_alu_src(nir_alu_instr * instr,unsigned index,validate_state * state)208*61046927SAndroid Build Coastguard Worker validate_alu_src(nir_alu_instr *instr, unsigned index, validate_state *state)
209*61046927SAndroid Build Coastguard Worker {
210*61046927SAndroid Build Coastguard Worker nir_alu_src *src = &instr->src[index];
211*61046927SAndroid Build Coastguard Worker
212*61046927SAndroid Build Coastguard Worker unsigned num_instr_channels = nir_ssa_alu_instr_src_components(instr, index);
213*61046927SAndroid Build Coastguard Worker unsigned num_components = nir_src_num_components(src->src);
214*61046927SAndroid Build Coastguard Worker
215*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < num_instr_channels; i++) {
216*61046927SAndroid Build Coastguard Worker validate_assert(state, src->swizzle[i] < num_components);
217*61046927SAndroid Build Coastguard Worker }
218*61046927SAndroid Build Coastguard Worker
219*61046927SAndroid Build Coastguard Worker validate_src(&src->src, state);
220*61046927SAndroid Build Coastguard Worker }
221*61046927SAndroid Build Coastguard Worker
222*61046927SAndroid Build Coastguard Worker static void
validate_def(nir_def * def,validate_state * state)223*61046927SAndroid Build Coastguard Worker validate_def(nir_def *def, validate_state *state)
224*61046927SAndroid Build Coastguard Worker {
225*61046927SAndroid Build Coastguard Worker validate_assert(state, def->index < state->impl->ssa_alloc);
226*61046927SAndroid Build Coastguard Worker validate_assert(state, !BITSET_TEST(state->ssa_defs_found, def->index));
227*61046927SAndroid Build Coastguard Worker BITSET_SET(state->ssa_defs_found, def->index);
228*61046927SAndroid Build Coastguard Worker
229*61046927SAndroid Build Coastguard Worker validate_assert(state, def->parent_instr == state->instr);
230*61046927SAndroid Build Coastguard Worker validate_num_components(state, def->num_components);
231*61046927SAndroid Build Coastguard Worker
232*61046927SAndroid Build Coastguard Worker list_validate(&def->uses);
233*61046927SAndroid Build Coastguard Worker nir_foreach_use_including_if(src, def) {
234*61046927SAndroid Build Coastguard Worker /* Check that the def matches. */
235*61046927SAndroid Build Coastguard Worker validate_assert(state, src->ssa == def);
236*61046927SAndroid Build Coastguard Worker
237*61046927SAndroid Build Coastguard Worker /* Check that nir_src's are unique */
238*61046927SAndroid Build Coastguard Worker tag_src(src, state);
239*61046927SAndroid Build Coastguard Worker }
240*61046927SAndroid Build Coastguard Worker }
241*61046927SAndroid Build Coastguard Worker
242*61046927SAndroid Build Coastguard Worker static void
validate_alu_instr(nir_alu_instr * instr,validate_state * state)243*61046927SAndroid Build Coastguard Worker validate_alu_instr(nir_alu_instr *instr, validate_state *state)
244*61046927SAndroid Build Coastguard Worker {
245*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->op < nir_num_opcodes);
246*61046927SAndroid Build Coastguard Worker
247*61046927SAndroid Build Coastguard Worker unsigned instr_bit_size = 0;
248*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
249*61046927SAndroid Build Coastguard Worker nir_alu_type src_type = nir_op_infos[instr->op].input_types[i];
250*61046927SAndroid Build Coastguard Worker unsigned src_bit_size = nir_src_bit_size(instr->src[i].src);
251*61046927SAndroid Build Coastguard Worker if (nir_alu_type_get_type_size(src_type)) {
252*61046927SAndroid Build Coastguard Worker validate_assert(state, src_bit_size == nir_alu_type_get_type_size(src_type));
253*61046927SAndroid Build Coastguard Worker } else if (instr_bit_size) {
254*61046927SAndroid Build Coastguard Worker validate_assert(state, src_bit_size == instr_bit_size);
255*61046927SAndroid Build Coastguard Worker } else {
256*61046927SAndroid Build Coastguard Worker instr_bit_size = src_bit_size;
257*61046927SAndroid Build Coastguard Worker }
258*61046927SAndroid Build Coastguard Worker
259*61046927SAndroid Build Coastguard Worker if (nir_alu_type_get_base_type(src_type) == nir_type_float) {
260*61046927SAndroid Build Coastguard Worker /* 8-bit float isn't a thing */
261*61046927SAndroid Build Coastguard Worker validate_assert(state, src_bit_size == 16 || src_bit_size == 32 ||
262*61046927SAndroid Build Coastguard Worker src_bit_size == 64);
263*61046927SAndroid Build Coastguard Worker }
264*61046927SAndroid Build Coastguard Worker
265*61046927SAndroid Build Coastguard Worker /* In nir_opcodes.py, these are defined to take general uint or int
266*61046927SAndroid Build Coastguard Worker * sources. However, they're really only defined for 32-bit or 64-bit
267*61046927SAndroid Build Coastguard Worker * sources. This seems to be the only place to enforce this
268*61046927SAndroid Build Coastguard Worker * restriction.
269*61046927SAndroid Build Coastguard Worker */
270*61046927SAndroid Build Coastguard Worker switch (instr->op) {
271*61046927SAndroid Build Coastguard Worker case nir_op_ufind_msb:
272*61046927SAndroid Build Coastguard Worker case nir_op_ufind_msb_rev:
273*61046927SAndroid Build Coastguard Worker validate_assert(state, src_bit_size == 32 || src_bit_size == 64);
274*61046927SAndroid Build Coastguard Worker break;
275*61046927SAndroid Build Coastguard Worker
276*61046927SAndroid Build Coastguard Worker default:
277*61046927SAndroid Build Coastguard Worker break;
278*61046927SAndroid Build Coastguard Worker }
279*61046927SAndroid Build Coastguard Worker
280*61046927SAndroid Build Coastguard Worker validate_alu_src(instr, i, state);
281*61046927SAndroid Build Coastguard Worker }
282*61046927SAndroid Build Coastguard Worker
283*61046927SAndroid Build Coastguard Worker nir_alu_type dest_type = nir_op_infos[instr->op].output_type;
284*61046927SAndroid Build Coastguard Worker unsigned dest_bit_size = instr->def.bit_size;
285*61046927SAndroid Build Coastguard Worker if (nir_alu_type_get_type_size(dest_type)) {
286*61046927SAndroid Build Coastguard Worker validate_assert(state, dest_bit_size == nir_alu_type_get_type_size(dest_type));
287*61046927SAndroid Build Coastguard Worker } else if (instr_bit_size) {
288*61046927SAndroid Build Coastguard Worker validate_assert(state, dest_bit_size == instr_bit_size);
289*61046927SAndroid Build Coastguard Worker } else {
290*61046927SAndroid Build Coastguard Worker /* The only unsized thing is the destination so it's vacuously valid */
291*61046927SAndroid Build Coastguard Worker }
292*61046927SAndroid Build Coastguard Worker
293*61046927SAndroid Build Coastguard Worker if (nir_alu_type_get_base_type(dest_type) == nir_type_float) {
294*61046927SAndroid Build Coastguard Worker /* 8-bit float isn't a thing */
295*61046927SAndroid Build Coastguard Worker validate_assert(state, dest_bit_size == 16 || dest_bit_size == 32 ||
296*61046927SAndroid Build Coastguard Worker dest_bit_size == 64);
297*61046927SAndroid Build Coastguard Worker }
298*61046927SAndroid Build Coastguard Worker
299*61046927SAndroid Build Coastguard Worker validate_def(&instr->def, state);
300*61046927SAndroid Build Coastguard Worker }
301*61046927SAndroid Build Coastguard Worker
302*61046927SAndroid Build Coastguard Worker static void
validate_var_use(nir_variable * var,validate_state * state)303*61046927SAndroid Build Coastguard Worker validate_var_use(nir_variable *var, validate_state *state)
304*61046927SAndroid Build Coastguard Worker {
305*61046927SAndroid Build Coastguard Worker struct hash_entry *entry = _mesa_hash_table_search(state->var_defs, var);
306*61046927SAndroid Build Coastguard Worker validate_assert(state, entry);
307*61046927SAndroid Build Coastguard Worker if (entry && var->data.mode == nir_var_function_temp)
308*61046927SAndroid Build Coastguard Worker validate_assert(state, (nir_function_impl *)entry->data == state->impl);
309*61046927SAndroid Build Coastguard Worker }
310*61046927SAndroid Build Coastguard Worker
311*61046927SAndroid Build Coastguard Worker static void
validate_deref_instr(nir_deref_instr * instr,validate_state * state)312*61046927SAndroid Build Coastguard Worker validate_deref_instr(nir_deref_instr *instr, validate_state *state)
313*61046927SAndroid Build Coastguard Worker {
314*61046927SAndroid Build Coastguard Worker if (instr->deref_type == nir_deref_type_var) {
315*61046927SAndroid Build Coastguard Worker /* Variable dereferences are stupid simple. */
316*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->modes == instr->var->data.mode);
317*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->type == instr->var->type);
318*61046927SAndroid Build Coastguard Worker validate_var_use(instr->var, state);
319*61046927SAndroid Build Coastguard Worker } else if (instr->deref_type == nir_deref_type_cast) {
320*61046927SAndroid Build Coastguard Worker /* For cast, we simply have to trust the instruction. It's up to
321*61046927SAndroid Build Coastguard Worker * lowering passes and front/back-ends to make them sane.
322*61046927SAndroid Build Coastguard Worker */
323*61046927SAndroid Build Coastguard Worker validate_src(&instr->parent, state);
324*61046927SAndroid Build Coastguard Worker
325*61046927SAndroid Build Coastguard Worker /* Most variable modes in NIR can only exist by themselves. */
326*61046927SAndroid Build Coastguard Worker if (instr->modes & ~nir_var_mem_generic)
327*61046927SAndroid Build Coastguard Worker validate_assert(state, util_bitcount(instr->modes) == 1);
328*61046927SAndroid Build Coastguard Worker
329*61046927SAndroid Build Coastguard Worker nir_deref_instr *parent = nir_src_as_deref(instr->parent);
330*61046927SAndroid Build Coastguard Worker if (parent) {
331*61046927SAndroid Build Coastguard Worker /* Casts can change the mode but it can't change completely. The new
332*61046927SAndroid Build Coastguard Worker * mode must have some bits in common with the old.
333*61046927SAndroid Build Coastguard Worker */
334*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->modes & parent->modes);
335*61046927SAndroid Build Coastguard Worker } else {
336*61046927SAndroid Build Coastguard Worker /* If our parent isn't a deref, just assert the mode is there */
337*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->modes != 0);
338*61046927SAndroid Build Coastguard Worker }
339*61046927SAndroid Build Coastguard Worker
340*61046927SAndroid Build Coastguard Worker /* We just validate that the type is there */
341*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->type);
342*61046927SAndroid Build Coastguard Worker if (instr->cast.align_mul > 0) {
343*61046927SAndroid Build Coastguard Worker validate_assert(state, util_is_power_of_two_nonzero(instr->cast.align_mul));
344*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->cast.align_offset < instr->cast.align_mul);
345*61046927SAndroid Build Coastguard Worker } else {
346*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->cast.align_offset == 0);
347*61046927SAndroid Build Coastguard Worker }
348*61046927SAndroid Build Coastguard Worker } else {
349*61046927SAndroid Build Coastguard Worker /* The parent pointer value must have the same number of components
350*61046927SAndroid Build Coastguard Worker * as the destination.
351*61046927SAndroid Build Coastguard Worker */
352*61046927SAndroid Build Coastguard Worker validate_sized_src(&instr->parent, state, instr->def.bit_size,
353*61046927SAndroid Build Coastguard Worker instr->def.num_components);
354*61046927SAndroid Build Coastguard Worker
355*61046927SAndroid Build Coastguard Worker nir_instr *parent_instr = instr->parent.ssa->parent_instr;
356*61046927SAndroid Build Coastguard Worker
357*61046927SAndroid Build Coastguard Worker /* The parent must come from another deref instruction */
358*61046927SAndroid Build Coastguard Worker validate_assert(state, parent_instr->type == nir_instr_type_deref);
359*61046927SAndroid Build Coastguard Worker
360*61046927SAndroid Build Coastguard Worker nir_deref_instr *parent = nir_instr_as_deref(parent_instr);
361*61046927SAndroid Build Coastguard Worker
362*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->modes == parent->modes);
363*61046927SAndroid Build Coastguard Worker
364*61046927SAndroid Build Coastguard Worker switch (instr->deref_type) {
365*61046927SAndroid Build Coastguard Worker case nir_deref_type_struct:
366*61046927SAndroid Build Coastguard Worker validate_assert(state, glsl_type_is_struct_or_ifc(parent->type));
367*61046927SAndroid Build Coastguard Worker validate_assert(state,
368*61046927SAndroid Build Coastguard Worker instr->strct.index < glsl_get_length(parent->type));
369*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->type ==
370*61046927SAndroid Build Coastguard Worker glsl_get_struct_field(parent->type, instr->strct.index));
371*61046927SAndroid Build Coastguard Worker break;
372*61046927SAndroid Build Coastguard Worker
373*61046927SAndroid Build Coastguard Worker case nir_deref_type_array:
374*61046927SAndroid Build Coastguard Worker case nir_deref_type_array_wildcard:
375*61046927SAndroid Build Coastguard Worker if (instr->modes & nir_var_vec_indexable_modes) {
376*61046927SAndroid Build Coastguard Worker /* Shared variables and UBO/SSBOs have a bit more relaxed rules
377*61046927SAndroid Build Coastguard Worker * because we need to be able to handle array derefs on vectors.
378*61046927SAndroid Build Coastguard Worker * Fortunately, nir_lower_io handles these just fine.
379*61046927SAndroid Build Coastguard Worker */
380*61046927SAndroid Build Coastguard Worker validate_assert(state, glsl_type_is_array(parent->type) ||
381*61046927SAndroid Build Coastguard Worker glsl_type_is_matrix(parent->type) ||
382*61046927SAndroid Build Coastguard Worker glsl_type_is_vector(parent->type));
383*61046927SAndroid Build Coastguard Worker } else {
384*61046927SAndroid Build Coastguard Worker /* Most of NIR cannot handle array derefs on vectors */
385*61046927SAndroid Build Coastguard Worker validate_assert(state, glsl_type_is_array(parent->type) ||
386*61046927SAndroid Build Coastguard Worker glsl_type_is_matrix(parent->type));
387*61046927SAndroid Build Coastguard Worker }
388*61046927SAndroid Build Coastguard Worker validate_assert(state,
389*61046927SAndroid Build Coastguard Worker instr->type == glsl_get_array_element(parent->type));
390*61046927SAndroid Build Coastguard Worker
391*61046927SAndroid Build Coastguard Worker if (instr->deref_type == nir_deref_type_array) {
392*61046927SAndroid Build Coastguard Worker validate_sized_src(&instr->arr.index, state,
393*61046927SAndroid Build Coastguard Worker instr->def.bit_size, 1);
394*61046927SAndroid Build Coastguard Worker }
395*61046927SAndroid Build Coastguard Worker break;
396*61046927SAndroid Build Coastguard Worker
397*61046927SAndroid Build Coastguard Worker case nir_deref_type_ptr_as_array:
398*61046927SAndroid Build Coastguard Worker /* ptr_as_array derefs must have a parent that is either an array,
399*61046927SAndroid Build Coastguard Worker * ptr_as_array, or cast. If the parent is a cast, we get the stride
400*61046927SAndroid Build Coastguard Worker * information (if any) from the cast deref.
401*61046927SAndroid Build Coastguard Worker */
402*61046927SAndroid Build Coastguard Worker validate_assert(state,
403*61046927SAndroid Build Coastguard Worker parent->deref_type == nir_deref_type_array ||
404*61046927SAndroid Build Coastguard Worker parent->deref_type == nir_deref_type_ptr_as_array ||
405*61046927SAndroid Build Coastguard Worker parent->deref_type == nir_deref_type_cast);
406*61046927SAndroid Build Coastguard Worker validate_sized_src(&instr->arr.index, state,
407*61046927SAndroid Build Coastguard Worker instr->def.bit_size, 1);
408*61046927SAndroid Build Coastguard Worker break;
409*61046927SAndroid Build Coastguard Worker
410*61046927SAndroid Build Coastguard Worker default:
411*61046927SAndroid Build Coastguard Worker unreachable("Invalid deref instruction type");
412*61046927SAndroid Build Coastguard Worker }
413*61046927SAndroid Build Coastguard Worker }
414*61046927SAndroid Build Coastguard Worker
415*61046927SAndroid Build Coastguard Worker /* We intentionally don't validate the size of the destination because we
416*61046927SAndroid Build Coastguard Worker * want to let other compiler components such as SPIR-V decide how big
417*61046927SAndroid Build Coastguard Worker * pointers should be.
418*61046927SAndroid Build Coastguard Worker */
419*61046927SAndroid Build Coastguard Worker validate_def(&instr->def, state);
420*61046927SAndroid Build Coastguard Worker
421*61046927SAndroid Build Coastguard Worker /* Certain modes cannot be used as sources for phi instructions because
422*61046927SAndroid Build Coastguard Worker * way too many passes assume that they can always chase deref chains.
423*61046927SAndroid Build Coastguard Worker */
424*61046927SAndroid Build Coastguard Worker nir_foreach_use_including_if(use, &instr->def) {
425*61046927SAndroid Build Coastguard Worker /* Deref instructions as if conditions don't make sense because if
426*61046927SAndroid Build Coastguard Worker * conditions expect well-formed Booleans. If you want to compare with
427*61046927SAndroid Build Coastguard Worker * NULL, an explicit comparison operation should be used.
428*61046927SAndroid Build Coastguard Worker */
429*61046927SAndroid Build Coastguard Worker if (!validate_assert(state, !nir_src_is_if(use)))
430*61046927SAndroid Build Coastguard Worker continue;
431*61046927SAndroid Build Coastguard Worker
432*61046927SAndroid Build Coastguard Worker if (src_parent_instr_safe(use)->type == nir_instr_type_phi) {
433*61046927SAndroid Build Coastguard Worker validate_assert(state, !(instr->modes & (nir_var_shader_in |
434*61046927SAndroid Build Coastguard Worker nir_var_shader_out |
435*61046927SAndroid Build Coastguard Worker nir_var_shader_out |
436*61046927SAndroid Build Coastguard Worker nir_var_uniform)));
437*61046927SAndroid Build Coastguard Worker }
438*61046927SAndroid Build Coastguard Worker }
439*61046927SAndroid Build Coastguard Worker }
440*61046927SAndroid Build Coastguard Worker
441*61046927SAndroid Build Coastguard Worker static bool
vectorized_intrinsic(nir_intrinsic_instr * intr)442*61046927SAndroid Build Coastguard Worker vectorized_intrinsic(nir_intrinsic_instr *intr)
443*61046927SAndroid Build Coastguard Worker {
444*61046927SAndroid Build Coastguard Worker const nir_intrinsic_info *info = &nir_intrinsic_infos[intr->intrinsic];
445*61046927SAndroid Build Coastguard Worker
446*61046927SAndroid Build Coastguard Worker if (info->dest_components == 0)
447*61046927SAndroid Build Coastguard Worker return true;
448*61046927SAndroid Build Coastguard Worker
449*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < info->num_srcs; i++)
450*61046927SAndroid Build Coastguard Worker if (info->src_components[i] == 0)
451*61046927SAndroid Build Coastguard Worker return true;
452*61046927SAndroid Build Coastguard Worker
453*61046927SAndroid Build Coastguard Worker return false;
454*61046927SAndroid Build Coastguard Worker }
455*61046927SAndroid Build Coastguard Worker
456*61046927SAndroid Build Coastguard Worker /** Returns the image format or PIPE_FORMAT_COUNT for incomplete derefs
457*61046927SAndroid Build Coastguard Worker *
458*61046927SAndroid Build Coastguard Worker * We use PIPE_FORMAT_COUNT for incomplete derefs because PIPE_FORMAT_NONE
459*61046927SAndroid Build Coastguard Worker * indicates that we found the variable but it has no format specified.
460*61046927SAndroid Build Coastguard Worker */
461*61046927SAndroid Build Coastguard Worker static enum pipe_format
image_intrin_format(nir_intrinsic_instr * instr)462*61046927SAndroid Build Coastguard Worker image_intrin_format(nir_intrinsic_instr *instr)
463*61046927SAndroid Build Coastguard Worker {
464*61046927SAndroid Build Coastguard Worker if (nir_intrinsic_format(instr) != PIPE_FORMAT_NONE)
465*61046927SAndroid Build Coastguard Worker return nir_intrinsic_format(instr);
466*61046927SAndroid Build Coastguard Worker
467*61046927SAndroid Build Coastguard Worker /* If this not a deref intrinsic, PIPE_FORMAT_NONE is the best we can do */
468*61046927SAndroid Build Coastguard Worker if (nir_intrinsic_infos[instr->intrinsic].src_components[0] != -1)
469*61046927SAndroid Build Coastguard Worker return PIPE_FORMAT_NONE;
470*61046927SAndroid Build Coastguard Worker
471*61046927SAndroid Build Coastguard Worker nir_variable *var = nir_intrinsic_get_var(instr, 0);
472*61046927SAndroid Build Coastguard Worker if (var == NULL)
473*61046927SAndroid Build Coastguard Worker return PIPE_FORMAT_COUNT;
474*61046927SAndroid Build Coastguard Worker
475*61046927SAndroid Build Coastguard Worker return var->data.image.format;
476*61046927SAndroid Build Coastguard Worker }
477*61046927SAndroid Build Coastguard Worker
478*61046927SAndroid Build Coastguard Worker static void
validate_register_handle(nir_src handle_src,unsigned num_components,unsigned bit_size,validate_state * state)479*61046927SAndroid Build Coastguard Worker validate_register_handle(nir_src handle_src,
480*61046927SAndroid Build Coastguard Worker unsigned num_components,
481*61046927SAndroid Build Coastguard Worker unsigned bit_size,
482*61046927SAndroid Build Coastguard Worker validate_state *state)
483*61046927SAndroid Build Coastguard Worker {
484*61046927SAndroid Build Coastguard Worker nir_def *handle = handle_src.ssa;
485*61046927SAndroid Build Coastguard Worker nir_instr *parent = handle->parent_instr;
486*61046927SAndroid Build Coastguard Worker
487*61046927SAndroid Build Coastguard Worker if (!validate_assert(state, parent->type == nir_instr_type_intrinsic))
488*61046927SAndroid Build Coastguard Worker return;
489*61046927SAndroid Build Coastguard Worker
490*61046927SAndroid Build Coastguard Worker nir_intrinsic_instr *intr = nir_instr_as_intrinsic(parent);
491*61046927SAndroid Build Coastguard Worker if (!validate_assert(state, intr->intrinsic == nir_intrinsic_decl_reg))
492*61046927SAndroid Build Coastguard Worker return;
493*61046927SAndroid Build Coastguard Worker
494*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_intrinsic_num_components(intr) == num_components);
495*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_intrinsic_bit_size(intr) == bit_size);
496*61046927SAndroid Build Coastguard Worker }
497*61046927SAndroid Build Coastguard Worker
498*61046927SAndroid Build Coastguard Worker static void
validate_intrinsic_instr(nir_intrinsic_instr * instr,validate_state * state)499*61046927SAndroid Build Coastguard Worker validate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state)
500*61046927SAndroid Build Coastguard Worker {
501*61046927SAndroid Build Coastguard Worker unsigned dest_bit_size = 0;
502*61046927SAndroid Build Coastguard Worker unsigned src_bit_sizes[NIR_INTRINSIC_MAX_INPUTS] = {
503*61046927SAndroid Build Coastguard Worker 0,
504*61046927SAndroid Build Coastguard Worker };
505*61046927SAndroid Build Coastguard Worker switch (instr->intrinsic) {
506*61046927SAndroid Build Coastguard Worker case nir_intrinsic_decl_reg:
507*61046927SAndroid Build Coastguard Worker assert(state->block == nir_start_block(state->impl));
508*61046927SAndroid Build Coastguard Worker break;
509*61046927SAndroid Build Coastguard Worker
510*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_reg:
511*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_reg_indirect:
512*61046927SAndroid Build Coastguard Worker validate_register_handle(instr->src[0],
513*61046927SAndroid Build Coastguard Worker instr->def.num_components,
514*61046927SAndroid Build Coastguard Worker instr->def.bit_size, state);
515*61046927SAndroid Build Coastguard Worker break;
516*61046927SAndroid Build Coastguard Worker
517*61046927SAndroid Build Coastguard Worker case nir_intrinsic_store_reg:
518*61046927SAndroid Build Coastguard Worker case nir_intrinsic_store_reg_indirect:
519*61046927SAndroid Build Coastguard Worker validate_register_handle(instr->src[1],
520*61046927SAndroid Build Coastguard Worker nir_src_num_components(instr->src[0]),
521*61046927SAndroid Build Coastguard Worker nir_src_bit_size(instr->src[0]), state);
522*61046927SAndroid Build Coastguard Worker break;
523*61046927SAndroid Build Coastguard Worker
524*61046927SAndroid Build Coastguard Worker case nir_intrinsic_convert_alu_types: {
525*61046927SAndroid Build Coastguard Worker nir_alu_type src_type = nir_intrinsic_src_type(instr);
526*61046927SAndroid Build Coastguard Worker nir_alu_type dest_type = nir_intrinsic_dest_type(instr);
527*61046927SAndroid Build Coastguard Worker dest_bit_size = nir_alu_type_get_type_size(dest_type);
528*61046927SAndroid Build Coastguard Worker src_bit_sizes[0] = nir_alu_type_get_type_size(src_type);
529*61046927SAndroid Build Coastguard Worker validate_assert(state, dest_bit_size != 0);
530*61046927SAndroid Build Coastguard Worker validate_assert(state, src_bit_sizes[0] != 0);
531*61046927SAndroid Build Coastguard Worker break;
532*61046927SAndroid Build Coastguard Worker }
533*61046927SAndroid Build Coastguard Worker
534*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_param: {
535*61046927SAndroid Build Coastguard Worker unsigned param_idx = nir_intrinsic_param_idx(instr);
536*61046927SAndroid Build Coastguard Worker validate_assert(state, param_idx < state->impl->function->num_params);
537*61046927SAndroid Build Coastguard Worker nir_parameter *param = &state->impl->function->params[param_idx];
538*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->num_components == param->num_components);
539*61046927SAndroid Build Coastguard Worker dest_bit_size = param->bit_size;
540*61046927SAndroid Build Coastguard Worker break;
541*61046927SAndroid Build Coastguard Worker }
542*61046927SAndroid Build Coastguard Worker
543*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_deref: {
544*61046927SAndroid Build Coastguard Worker nir_deref_instr *src = nir_src_as_deref(instr->src[0]);
545*61046927SAndroid Build Coastguard Worker assert(src);
546*61046927SAndroid Build Coastguard Worker validate_assert(state, glsl_type_is_vector_or_scalar(src->type) ||
547*61046927SAndroid Build Coastguard Worker (src->modes == nir_var_uniform &&
548*61046927SAndroid Build Coastguard Worker glsl_get_base_type(src->type) == GLSL_TYPE_SUBROUTINE));
549*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->num_components ==
550*61046927SAndroid Build Coastguard Worker glsl_get_vector_elements(src->type));
551*61046927SAndroid Build Coastguard Worker dest_bit_size = glsl_get_bit_size(src->type);
552*61046927SAndroid Build Coastguard Worker /* Also allow 32-bit boolean load operations */
553*61046927SAndroid Build Coastguard Worker if (glsl_type_is_boolean(src->type))
554*61046927SAndroid Build Coastguard Worker dest_bit_size |= 32;
555*61046927SAndroid Build Coastguard Worker break;
556*61046927SAndroid Build Coastguard Worker }
557*61046927SAndroid Build Coastguard Worker
558*61046927SAndroid Build Coastguard Worker case nir_intrinsic_store_deref: {
559*61046927SAndroid Build Coastguard Worker nir_deref_instr *dst = nir_src_as_deref(instr->src[0]);
560*61046927SAndroid Build Coastguard Worker assert(dst);
561*61046927SAndroid Build Coastguard Worker validate_assert(state, glsl_type_is_vector_or_scalar(dst->type));
562*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->num_components ==
563*61046927SAndroid Build Coastguard Worker glsl_get_vector_elements(dst->type));
564*61046927SAndroid Build Coastguard Worker src_bit_sizes[1] = glsl_get_bit_size(dst->type);
565*61046927SAndroid Build Coastguard Worker /* Also allow 32-bit boolean store operations */
566*61046927SAndroid Build Coastguard Worker if (glsl_type_is_boolean(dst->type))
567*61046927SAndroid Build Coastguard Worker src_bit_sizes[1] |= 32;
568*61046927SAndroid Build Coastguard Worker validate_assert(state, !nir_deref_mode_may_be(dst, nir_var_read_only_modes));
569*61046927SAndroid Build Coastguard Worker break;
570*61046927SAndroid Build Coastguard Worker }
571*61046927SAndroid Build Coastguard Worker
572*61046927SAndroid Build Coastguard Worker case nir_intrinsic_copy_deref: {
573*61046927SAndroid Build Coastguard Worker nir_deref_instr *dst = nir_src_as_deref(instr->src[0]);
574*61046927SAndroid Build Coastguard Worker nir_deref_instr *src = nir_src_as_deref(instr->src[1]);
575*61046927SAndroid Build Coastguard Worker validate_assert(state, glsl_get_bare_type(dst->type) ==
576*61046927SAndroid Build Coastguard Worker glsl_get_bare_type(src->type));
577*61046927SAndroid Build Coastguard Worker validate_assert(state, !nir_deref_mode_may_be(dst, nir_var_read_only_modes));
578*61046927SAndroid Build Coastguard Worker /* FIXME: now that we track if the var copies were lowered, it would be
579*61046927SAndroid Build Coastguard Worker * good to validate here that no new copy derefs were added. Right now
580*61046927SAndroid Build Coastguard Worker * we can't as there are some specific cases where copies are added even
581*61046927SAndroid Build Coastguard Worker * after the lowering. One example is the Intel compiler, that calls
582*61046927SAndroid Build Coastguard Worker * nir_lower_io_to_temporaries when linking some shader stages.
583*61046927SAndroid Build Coastguard Worker */
584*61046927SAndroid Build Coastguard Worker break;
585*61046927SAndroid Build Coastguard Worker }
586*61046927SAndroid Build Coastguard Worker
587*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_ubo_vec4: {
588*61046927SAndroid Build Coastguard Worker int bit_size = instr->def.bit_size;
589*61046927SAndroid Build Coastguard Worker validate_assert(state, bit_size >= 8);
590*61046927SAndroid Build Coastguard Worker validate_assert(state, (nir_intrinsic_component(instr) +
591*61046927SAndroid Build Coastguard Worker instr->num_components) *
592*61046927SAndroid Build Coastguard Worker (bit_size / 8) <=
593*61046927SAndroid Build Coastguard Worker 16);
594*61046927SAndroid Build Coastguard Worker break;
595*61046927SAndroid Build Coastguard Worker }
596*61046927SAndroid Build Coastguard Worker
597*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_ubo:
598*61046927SAndroid Build Coastguard Worker /* Make sure that the creator didn't forget to set the range_base+range. */
599*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_intrinsic_range(instr) != 0);
600*61046927SAndroid Build Coastguard Worker FALLTHROUGH;
601*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_ssbo:
602*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_shared:
603*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_global:
604*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_global_constant:
605*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_scratch:
606*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_constant:
607*61046927SAndroid Build Coastguard Worker /* These memory load operations must have alignments */
608*61046927SAndroid Build Coastguard Worker validate_assert(state,
609*61046927SAndroid Build Coastguard Worker util_is_power_of_two_nonzero(nir_intrinsic_align_mul(instr)));
610*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_intrinsic_align_offset(instr) <
611*61046927SAndroid Build Coastguard Worker nir_intrinsic_align_mul(instr));
612*61046927SAndroid Build Coastguard Worker FALLTHROUGH;
613*61046927SAndroid Build Coastguard Worker
614*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_uniform:
615*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_input:
616*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_per_primitive_input:
617*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_per_vertex_input:
618*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_interpolated_input:
619*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_output:
620*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_per_vertex_output:
621*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_per_primitive_output:
622*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_push_constant:
623*61046927SAndroid Build Coastguard Worker /* All memory load operations must load at least a byte */
624*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->def.bit_size >= 8);
625*61046927SAndroid Build Coastguard Worker break;
626*61046927SAndroid Build Coastguard Worker
627*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_barycentric_pixel:
628*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_barycentric_centroid:
629*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_barycentric_sample:
630*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_barycentric_at_offset:
631*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_barycentric_at_sample: {
632*61046927SAndroid Build Coastguard Worker enum glsl_interp_mode mode = nir_intrinsic_interp_mode(instr);
633*61046927SAndroid Build Coastguard Worker validate_assert(state,
634*61046927SAndroid Build Coastguard Worker mode == INTERP_MODE_NONE ||
635*61046927SAndroid Build Coastguard Worker mode == INTERP_MODE_SMOOTH ||
636*61046927SAndroid Build Coastguard Worker mode == INTERP_MODE_NOPERSPECTIVE);
637*61046927SAndroid Build Coastguard Worker break;
638*61046927SAndroid Build Coastguard Worker }
639*61046927SAndroid Build Coastguard Worker
640*61046927SAndroid Build Coastguard Worker case nir_intrinsic_store_ssbo:
641*61046927SAndroid Build Coastguard Worker case nir_intrinsic_store_shared:
642*61046927SAndroid Build Coastguard Worker case nir_intrinsic_store_global:
643*61046927SAndroid Build Coastguard Worker case nir_intrinsic_store_scratch:
644*61046927SAndroid Build Coastguard Worker /* These memory store operations must also have alignments */
645*61046927SAndroid Build Coastguard Worker validate_assert(state,
646*61046927SAndroid Build Coastguard Worker util_is_power_of_two_nonzero(nir_intrinsic_align_mul(instr)));
647*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_intrinsic_align_offset(instr) <
648*61046927SAndroid Build Coastguard Worker nir_intrinsic_align_mul(instr));
649*61046927SAndroid Build Coastguard Worker /* All memory store operations must store at least a byte */
650*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_src_bit_size(instr->src[0]) >= 8);
651*61046927SAndroid Build Coastguard Worker break;
652*61046927SAndroid Build Coastguard Worker
653*61046927SAndroid Build Coastguard Worker case nir_intrinsic_store_output:
654*61046927SAndroid Build Coastguard Worker case nir_intrinsic_store_per_vertex_output:
655*61046927SAndroid Build Coastguard Worker if (state->shader->info.stage == MESA_SHADER_FRAGMENT)
656*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_src_bit_size(instr->src[0]) >= 8);
657*61046927SAndroid Build Coastguard Worker else
658*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_src_bit_size(instr->src[0]) >= 16);
659*61046927SAndroid Build Coastguard Worker validate_assert(state,
660*61046927SAndroid Build Coastguard Worker nir_src_bit_size(instr->src[0]) ==
661*61046927SAndroid Build Coastguard Worker nir_alu_type_get_type_size(nir_intrinsic_src_type(instr)));
662*61046927SAndroid Build Coastguard Worker break;
663*61046927SAndroid Build Coastguard Worker
664*61046927SAndroid Build Coastguard Worker case nir_intrinsic_deref_mode_is:
665*61046927SAndroid Build Coastguard Worker case nir_intrinsic_addr_mode_is:
666*61046927SAndroid Build Coastguard Worker validate_assert(state,
667*61046927SAndroid Build Coastguard Worker util_bitcount(nir_intrinsic_memory_modes(instr)) == 1);
668*61046927SAndroid Build Coastguard Worker break;
669*61046927SAndroid Build Coastguard Worker
670*61046927SAndroid Build Coastguard Worker case nir_intrinsic_image_deref_atomic:
671*61046927SAndroid Build Coastguard Worker case nir_intrinsic_image_deref_atomic_swap:
672*61046927SAndroid Build Coastguard Worker case nir_intrinsic_bindless_image_atomic:
673*61046927SAndroid Build Coastguard Worker case nir_intrinsic_bindless_image_atomic_swap:
674*61046927SAndroid Build Coastguard Worker case nir_intrinsic_image_atomic:
675*61046927SAndroid Build Coastguard Worker case nir_intrinsic_image_atomic_swap: {
676*61046927SAndroid Build Coastguard Worker nir_atomic_op op = nir_intrinsic_atomic_op(instr);
677*61046927SAndroid Build Coastguard Worker
678*61046927SAndroid Build Coastguard Worker enum pipe_format format = image_intrin_format(instr);
679*61046927SAndroid Build Coastguard Worker if (format != PIPE_FORMAT_COUNT) {
680*61046927SAndroid Build Coastguard Worker bool allowed = false;
681*61046927SAndroid Build Coastguard Worker bool is_float = (nir_atomic_op_type(op) == nir_type_float);
682*61046927SAndroid Build Coastguard Worker
683*61046927SAndroid Build Coastguard Worker switch (format) {
684*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_R32_FLOAT:
685*61046927SAndroid Build Coastguard Worker allowed = is_float || op == nir_atomic_op_xchg;
686*61046927SAndroid Build Coastguard Worker break;
687*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_R16_FLOAT:
688*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_R64_FLOAT:
689*61046927SAndroid Build Coastguard Worker allowed = op == nir_atomic_op_fmin || op == nir_atomic_op_fmax;
690*61046927SAndroid Build Coastguard Worker break;
691*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_R32_UINT:
692*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_R32_SINT:
693*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_R64_UINT:
694*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_R64_SINT:
695*61046927SAndroid Build Coastguard Worker allowed = !is_float;
696*61046927SAndroid Build Coastguard Worker break;
697*61046927SAndroid Build Coastguard Worker default:
698*61046927SAndroid Build Coastguard Worker break;
699*61046927SAndroid Build Coastguard Worker }
700*61046927SAndroid Build Coastguard Worker
701*61046927SAndroid Build Coastguard Worker validate_assert(state, allowed);
702*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->def.bit_size ==
703*61046927SAndroid Build Coastguard Worker util_format_get_blocksizebits(format));
704*61046927SAndroid Build Coastguard Worker }
705*61046927SAndroid Build Coastguard Worker break;
706*61046927SAndroid Build Coastguard Worker }
707*61046927SAndroid Build Coastguard Worker
708*61046927SAndroid Build Coastguard Worker case nir_intrinsic_store_buffer_amd:
709*61046927SAndroid Build Coastguard Worker if (nir_intrinsic_access(instr) & ACCESS_USES_FORMAT_AMD) {
710*61046927SAndroid Build Coastguard Worker unsigned writemask = nir_intrinsic_write_mask(instr);
711*61046927SAndroid Build Coastguard Worker
712*61046927SAndroid Build Coastguard Worker /* Make sure the writemask is derived from the component count. */
713*61046927SAndroid Build Coastguard Worker validate_assert(state,
714*61046927SAndroid Build Coastguard Worker writemask ==
715*61046927SAndroid Build Coastguard Worker BITFIELD_MASK(nir_src_num_components(instr->src[0])));
716*61046927SAndroid Build Coastguard Worker }
717*61046927SAndroid Build Coastguard Worker break;
718*61046927SAndroid Build Coastguard Worker
719*61046927SAndroid Build Coastguard Worker default:
720*61046927SAndroid Build Coastguard Worker break;
721*61046927SAndroid Build Coastguard Worker }
722*61046927SAndroid Build Coastguard Worker
723*61046927SAndroid Build Coastguard Worker if (instr->num_components > 0)
724*61046927SAndroid Build Coastguard Worker validate_num_components(state, instr->num_components);
725*61046927SAndroid Build Coastguard Worker
726*61046927SAndroid Build Coastguard Worker const nir_intrinsic_info *info = &nir_intrinsic_infos[instr->intrinsic];
727*61046927SAndroid Build Coastguard Worker unsigned num_srcs = info->num_srcs;
728*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < num_srcs; i++) {
729*61046927SAndroid Build Coastguard Worker unsigned components_read = nir_intrinsic_src_components(instr, i);
730*61046927SAndroid Build Coastguard Worker
731*61046927SAndroid Build Coastguard Worker validate_num_components(state, components_read);
732*61046927SAndroid Build Coastguard Worker
733*61046927SAndroid Build Coastguard Worker validate_sized_src(&instr->src[i], state, src_bit_sizes[i], components_read);
734*61046927SAndroid Build Coastguard Worker }
735*61046927SAndroid Build Coastguard Worker
736*61046927SAndroid Build Coastguard Worker if (nir_intrinsic_infos[instr->intrinsic].has_dest) {
737*61046927SAndroid Build Coastguard Worker unsigned components_written = nir_intrinsic_dest_components(instr);
738*61046927SAndroid Build Coastguard Worker unsigned bit_sizes = info->dest_bit_sizes;
739*61046927SAndroid Build Coastguard Worker if (!bit_sizes && info->bit_size_src >= 0)
740*61046927SAndroid Build Coastguard Worker bit_sizes = nir_src_bit_size(instr->src[info->bit_size_src]);
741*61046927SAndroid Build Coastguard Worker
742*61046927SAndroid Build Coastguard Worker validate_num_components(state, components_written);
743*61046927SAndroid Build Coastguard Worker if (dest_bit_size && bit_sizes)
744*61046927SAndroid Build Coastguard Worker validate_assert(state, dest_bit_size & bit_sizes);
745*61046927SAndroid Build Coastguard Worker else
746*61046927SAndroid Build Coastguard Worker dest_bit_size = dest_bit_size ? dest_bit_size : bit_sizes;
747*61046927SAndroid Build Coastguard Worker
748*61046927SAndroid Build Coastguard Worker validate_def(&instr->def, state);
749*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->def.num_components == components_written);
750*61046927SAndroid Build Coastguard Worker
751*61046927SAndroid Build Coastguard Worker if (dest_bit_size)
752*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->def.bit_size & dest_bit_size);
753*61046927SAndroid Build Coastguard Worker }
754*61046927SAndroid Build Coastguard Worker
755*61046927SAndroid Build Coastguard Worker if (!vectorized_intrinsic(instr))
756*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->num_components == 0);
757*61046927SAndroid Build Coastguard Worker
758*61046927SAndroid Build Coastguard Worker if (nir_intrinsic_has_write_mask(instr)) {
759*61046927SAndroid Build Coastguard Worker unsigned component_mask = BITFIELD_MASK(instr->num_components);
760*61046927SAndroid Build Coastguard Worker validate_assert(state, (nir_intrinsic_write_mask(instr) & ~component_mask) == 0);
761*61046927SAndroid Build Coastguard Worker }
762*61046927SAndroid Build Coastguard Worker
763*61046927SAndroid Build Coastguard Worker if (nir_intrinsic_has_io_xfb(instr)) {
764*61046927SAndroid Build Coastguard Worker unsigned used_mask = 0;
765*61046927SAndroid Build Coastguard Worker
766*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; i++) {
767*61046927SAndroid Build Coastguard Worker nir_io_xfb xfb = i < 2 ? nir_intrinsic_io_xfb(instr) : nir_intrinsic_io_xfb2(instr);
768*61046927SAndroid Build Coastguard Worker unsigned xfb_mask = BITFIELD_RANGE(i, xfb.out[i % 2].num_components);
769*61046927SAndroid Build Coastguard Worker
770*61046927SAndroid Build Coastguard Worker /* Each component can be used only once by transform feedback info. */
771*61046927SAndroid Build Coastguard Worker validate_assert(state, (xfb_mask & used_mask) == 0);
772*61046927SAndroid Build Coastguard Worker used_mask |= xfb_mask;
773*61046927SAndroid Build Coastguard Worker }
774*61046927SAndroid Build Coastguard Worker }
775*61046927SAndroid Build Coastguard Worker
776*61046927SAndroid Build Coastguard Worker if (nir_intrinsic_has_io_semantics(instr) &&
777*61046927SAndroid Build Coastguard Worker !nir_intrinsic_infos[instr->intrinsic].has_dest) {
778*61046927SAndroid Build Coastguard Worker nir_io_semantics sem = nir_intrinsic_io_semantics(instr);
779*61046927SAndroid Build Coastguard Worker
780*61046927SAndroid Build Coastguard Worker /* An output that has no effect shouldn't be present in the IR. */
781*61046927SAndroid Build Coastguard Worker validate_assert(state,
782*61046927SAndroid Build Coastguard Worker (nir_slot_is_sysval_output(sem.location, MESA_SHADER_NONE) &&
783*61046927SAndroid Build Coastguard Worker !sem.no_sysval_output) ||
784*61046927SAndroid Build Coastguard Worker (nir_slot_is_varying(sem.location) && !sem.no_varying) ||
785*61046927SAndroid Build Coastguard Worker nir_instr_xfb_write_mask(instr) ||
786*61046927SAndroid Build Coastguard Worker /* TCS can set no_varying and no_sysval_output, meaning
787*61046927SAndroid Build Coastguard Worker * that the output is only read by TCS and not TES.
788*61046927SAndroid Build Coastguard Worker */
789*61046927SAndroid Build Coastguard Worker state->shader->info.stage == MESA_SHADER_TESS_CTRL);
790*61046927SAndroid Build Coastguard Worker validate_assert(state,
791*61046927SAndroid Build Coastguard Worker (!sem.dual_source_blend_index &&
792*61046927SAndroid Build Coastguard Worker !sem.fb_fetch_output) ||
793*61046927SAndroid Build Coastguard Worker state->shader->info.stage == MESA_SHADER_FRAGMENT);
794*61046927SAndroid Build Coastguard Worker validate_assert(state,
795*61046927SAndroid Build Coastguard Worker !sem.gs_streams ||
796*61046927SAndroid Build Coastguard Worker state->shader->info.stage == MESA_SHADER_GEOMETRY);
797*61046927SAndroid Build Coastguard Worker validate_assert(state,
798*61046927SAndroid Build Coastguard Worker !sem.high_dvec2 ||
799*61046927SAndroid Build Coastguard Worker (state->shader->info.stage == MESA_SHADER_VERTEX &&
800*61046927SAndroid Build Coastguard Worker instr->intrinsic == nir_intrinsic_load_input));
801*61046927SAndroid Build Coastguard Worker validate_assert(state,
802*61046927SAndroid Build Coastguard Worker !sem.interp_explicit_strict ||
803*61046927SAndroid Build Coastguard Worker (state->shader->info.stage == MESA_SHADER_FRAGMENT &&
804*61046927SAndroid Build Coastguard Worker instr->intrinsic == nir_intrinsic_load_input_vertex));
805*61046927SAndroid Build Coastguard Worker }
806*61046927SAndroid Build Coastguard Worker }
807*61046927SAndroid Build Coastguard Worker
808*61046927SAndroid Build Coastguard Worker static void
validate_tex_src_texture_deref(nir_tex_instr * instr,validate_state * state,nir_deref_instr * deref)809*61046927SAndroid Build Coastguard Worker validate_tex_src_texture_deref(nir_tex_instr *instr, validate_state *state,
810*61046927SAndroid Build Coastguard Worker nir_deref_instr *deref)
811*61046927SAndroid Build Coastguard Worker {
812*61046927SAndroid Build Coastguard Worker validate_assert(state, glsl_type_is_image(deref->type) ||
813*61046927SAndroid Build Coastguard Worker glsl_type_is_texture(deref->type) ||
814*61046927SAndroid Build Coastguard Worker glsl_type_is_sampler(deref->type));
815*61046927SAndroid Build Coastguard Worker
816*61046927SAndroid Build Coastguard Worker switch (instr->op) {
817*61046927SAndroid Build Coastguard Worker case nir_texop_descriptor_amd:
818*61046927SAndroid Build Coastguard Worker case nir_texop_sampler_descriptor_amd:
819*61046927SAndroid Build Coastguard Worker case nir_texop_custom_border_color_agx:
820*61046927SAndroid Build Coastguard Worker break;
821*61046927SAndroid Build Coastguard Worker case nir_texop_lod:
822*61046927SAndroid Build Coastguard Worker case nir_texop_lod_bias_agx:
823*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_alu_type_get_base_type(instr->dest_type) == nir_type_float);
824*61046927SAndroid Build Coastguard Worker break;
825*61046927SAndroid Build Coastguard Worker case nir_texop_samples_identical:
826*61046927SAndroid Build Coastguard Worker case nir_texop_has_custom_border_color_agx:
827*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_alu_type_get_base_type(instr->dest_type) == nir_type_bool);
828*61046927SAndroid Build Coastguard Worker break;
829*61046927SAndroid Build Coastguard Worker case nir_texop_txs:
830*61046927SAndroid Build Coastguard Worker case nir_texop_texture_samples:
831*61046927SAndroid Build Coastguard Worker case nir_texop_query_levels:
832*61046927SAndroid Build Coastguard Worker case nir_texop_fragment_mask_fetch_amd:
833*61046927SAndroid Build Coastguard Worker case nir_texop_txf_ms_mcs_intel:
834*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_alu_type_get_base_type(instr->dest_type) == nir_type_int ||
835*61046927SAndroid Build Coastguard Worker nir_alu_type_get_base_type(instr->dest_type) == nir_type_uint);
836*61046927SAndroid Build Coastguard Worker break;
837*61046927SAndroid Build Coastguard Worker default:
838*61046927SAndroid Build Coastguard Worker validate_assert(state,
839*61046927SAndroid Build Coastguard Worker glsl_get_sampler_result_type(deref->type) == GLSL_TYPE_VOID ||
840*61046927SAndroid Build Coastguard Worker glsl_base_type_is_integer(glsl_get_sampler_result_type(deref->type)) ==
841*61046927SAndroid Build Coastguard Worker (nir_alu_type_get_base_type(instr->dest_type) == nir_type_int ||
842*61046927SAndroid Build Coastguard Worker nir_alu_type_get_base_type(instr->dest_type) == nir_type_uint));
843*61046927SAndroid Build Coastguard Worker }
844*61046927SAndroid Build Coastguard Worker }
845*61046927SAndroid Build Coastguard Worker
846*61046927SAndroid Build Coastguard Worker static void
validate_tex_instr(nir_tex_instr * instr,validate_state * state)847*61046927SAndroid Build Coastguard Worker validate_tex_instr(nir_tex_instr *instr, validate_state *state)
848*61046927SAndroid Build Coastguard Worker {
849*61046927SAndroid Build Coastguard Worker bool src_type_seen[nir_num_tex_src_types];
850*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < nir_num_tex_src_types; i++)
851*61046927SAndroid Build Coastguard Worker src_type_seen[i] = false;
852*61046927SAndroid Build Coastguard Worker
853*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < instr->num_srcs; i++) {
854*61046927SAndroid Build Coastguard Worker validate_assert(state, !src_type_seen[instr->src[i].src_type]);
855*61046927SAndroid Build Coastguard Worker src_type_seen[instr->src[i].src_type] = true;
856*61046927SAndroid Build Coastguard Worker validate_sized_src(&instr->src[i].src, state,
857*61046927SAndroid Build Coastguard Worker 0, nir_tex_instr_src_size(instr, i));
858*61046927SAndroid Build Coastguard Worker
859*61046927SAndroid Build Coastguard Worker switch (instr->src[i].src_type) {
860*61046927SAndroid Build Coastguard Worker
861*61046927SAndroid Build Coastguard Worker case nir_tex_src_comparator:
862*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->is_shadow);
863*61046927SAndroid Build Coastguard Worker break;
864*61046927SAndroid Build Coastguard Worker
865*61046927SAndroid Build Coastguard Worker case nir_tex_src_bias:
866*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->op == nir_texop_txb ||
867*61046927SAndroid Build Coastguard Worker instr->op == nir_texop_tg4 ||
868*61046927SAndroid Build Coastguard Worker instr->op == nir_texop_lod);
869*61046927SAndroid Build Coastguard Worker break;
870*61046927SAndroid Build Coastguard Worker
871*61046927SAndroid Build Coastguard Worker case nir_tex_src_lod:
872*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->op != nir_texop_tex &&
873*61046927SAndroid Build Coastguard Worker instr->op != nir_texop_txb &&
874*61046927SAndroid Build Coastguard Worker instr->op != nir_texop_txd &&
875*61046927SAndroid Build Coastguard Worker instr->op != nir_texop_lod);
876*61046927SAndroid Build Coastguard Worker break;
877*61046927SAndroid Build Coastguard Worker
878*61046927SAndroid Build Coastguard Worker case nir_tex_src_ddx:
879*61046927SAndroid Build Coastguard Worker case nir_tex_src_ddy:
880*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->op == nir_texop_txd);
881*61046927SAndroid Build Coastguard Worker break;
882*61046927SAndroid Build Coastguard Worker
883*61046927SAndroid Build Coastguard Worker case nir_tex_src_texture_deref: {
884*61046927SAndroid Build Coastguard Worker nir_deref_instr *deref = nir_src_as_deref(instr->src[i].src);
885*61046927SAndroid Build Coastguard Worker if (!validate_assert(state, deref))
886*61046927SAndroid Build Coastguard Worker break;
887*61046927SAndroid Build Coastguard Worker
888*61046927SAndroid Build Coastguard Worker validate_tex_src_texture_deref(instr, state, deref);
889*61046927SAndroid Build Coastguard Worker break;
890*61046927SAndroid Build Coastguard Worker }
891*61046927SAndroid Build Coastguard Worker
892*61046927SAndroid Build Coastguard Worker case nir_tex_src_sampler_deref: {
893*61046927SAndroid Build Coastguard Worker nir_deref_instr *deref = nir_src_as_deref(instr->src[i].src);
894*61046927SAndroid Build Coastguard Worker if (!validate_assert(state, deref))
895*61046927SAndroid Build Coastguard Worker break;
896*61046927SAndroid Build Coastguard Worker
897*61046927SAndroid Build Coastguard Worker validate_assert(state, glsl_type_is_sampler(deref->type));
898*61046927SAndroid Build Coastguard Worker break;
899*61046927SAndroid Build Coastguard Worker }
900*61046927SAndroid Build Coastguard Worker
901*61046927SAndroid Build Coastguard Worker case nir_tex_src_sampler_deref_intrinsic:
902*61046927SAndroid Build Coastguard Worker case nir_tex_src_texture_deref_intrinsic: {
903*61046927SAndroid Build Coastguard Worker nir_intrinsic_instr *intrin =
904*61046927SAndroid Build Coastguard Worker nir_instr_as_intrinsic(instr->src[i].src.ssa->parent_instr);
905*61046927SAndroid Build Coastguard Worker nir_deref_instr *deref =
906*61046927SAndroid Build Coastguard Worker nir_instr_as_deref(intrin->src[0].ssa->parent_instr);
907*61046927SAndroid Build Coastguard Worker if (!validate_assert(state, deref))
908*61046927SAndroid Build Coastguard Worker break;
909*61046927SAndroid Build Coastguard Worker
910*61046927SAndroid Build Coastguard Worker if (instr->src[i].src_type == nir_tex_src_sampler_deref_intrinsic)
911*61046927SAndroid Build Coastguard Worker validate_assert(state, glsl_type_is_sampler(deref->type));
912*61046927SAndroid Build Coastguard Worker else
913*61046927SAndroid Build Coastguard Worker validate_tex_src_texture_deref(instr, state, deref);
914*61046927SAndroid Build Coastguard Worker
915*61046927SAndroid Build Coastguard Worker break;
916*61046927SAndroid Build Coastguard Worker }
917*61046927SAndroid Build Coastguard Worker
918*61046927SAndroid Build Coastguard Worker case nir_tex_src_coord:
919*61046927SAndroid Build Coastguard Worker case nir_tex_src_projector:
920*61046927SAndroid Build Coastguard Worker case nir_tex_src_offset:
921*61046927SAndroid Build Coastguard Worker case nir_tex_src_min_lod:
922*61046927SAndroid Build Coastguard Worker case nir_tex_src_ms_index:
923*61046927SAndroid Build Coastguard Worker case nir_tex_src_texture_offset:
924*61046927SAndroid Build Coastguard Worker case nir_tex_src_sampler_offset:
925*61046927SAndroid Build Coastguard Worker case nir_tex_src_plane:
926*61046927SAndroid Build Coastguard Worker case nir_tex_src_texture_handle:
927*61046927SAndroid Build Coastguard Worker case nir_tex_src_sampler_handle:
928*61046927SAndroid Build Coastguard Worker break;
929*61046927SAndroid Build Coastguard Worker
930*61046927SAndroid Build Coastguard Worker default:
931*61046927SAndroid Build Coastguard Worker break;
932*61046927SAndroid Build Coastguard Worker }
933*61046927SAndroid Build Coastguard Worker }
934*61046927SAndroid Build Coastguard Worker
935*61046927SAndroid Build Coastguard Worker bool msaa = (instr->sampler_dim == GLSL_SAMPLER_DIM_MS ||
936*61046927SAndroid Build Coastguard Worker instr->sampler_dim == GLSL_SAMPLER_DIM_SUBPASS_MS);
937*61046927SAndroid Build Coastguard Worker
938*61046927SAndroid Build Coastguard Worker if (msaa)
939*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->op != nir_texop_txf);
940*61046927SAndroid Build Coastguard Worker else
941*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->op != nir_texop_txf_ms);
942*61046927SAndroid Build Coastguard Worker
943*61046927SAndroid Build Coastguard Worker if (instr->op != nir_texop_tg4)
944*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->component == 0);
945*61046927SAndroid Build Coastguard Worker
946*61046927SAndroid Build Coastguard Worker if (nir_tex_instr_has_explicit_tg4_offsets(instr)) {
947*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->op == nir_texop_tg4);
948*61046927SAndroid Build Coastguard Worker validate_assert(state, !src_type_seen[nir_tex_src_offset]);
949*61046927SAndroid Build Coastguard Worker }
950*61046927SAndroid Build Coastguard Worker
951*61046927SAndroid Build Coastguard Worker if (instr->is_gather_implicit_lod)
952*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->op == nir_texop_tg4);
953*61046927SAndroid Build Coastguard Worker
954*61046927SAndroid Build Coastguard Worker validate_def(&instr->def, state);
955*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->def.num_components ==
956*61046927SAndroid Build Coastguard Worker nir_tex_instr_dest_size(instr));
957*61046927SAndroid Build Coastguard Worker
958*61046927SAndroid Build Coastguard Worker unsigned bit_size = nir_alu_type_get_type_size(instr->dest_type);
959*61046927SAndroid Build Coastguard Worker validate_assert(state,
960*61046927SAndroid Build Coastguard Worker (bit_size ? bit_size : 32) ==
961*61046927SAndroid Build Coastguard Worker instr->def.bit_size);
962*61046927SAndroid Build Coastguard Worker }
963*61046927SAndroid Build Coastguard Worker
964*61046927SAndroid Build Coastguard Worker static void
validate_call_instr(nir_call_instr * instr,validate_state * state)965*61046927SAndroid Build Coastguard Worker validate_call_instr(nir_call_instr *instr, validate_state *state)
966*61046927SAndroid Build Coastguard Worker {
967*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->num_params == instr->callee->num_params);
968*61046927SAndroid Build Coastguard Worker
969*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < instr->num_params; i++) {
970*61046927SAndroid Build Coastguard Worker validate_sized_src(&instr->params[i], state,
971*61046927SAndroid Build Coastguard Worker instr->callee->params[i].bit_size,
972*61046927SAndroid Build Coastguard Worker instr->callee->params[i].num_components);
973*61046927SAndroid Build Coastguard Worker }
974*61046927SAndroid Build Coastguard Worker }
975*61046927SAndroid Build Coastguard Worker
976*61046927SAndroid Build Coastguard Worker static void
validate_const_value(nir_const_value * val,unsigned bit_size,bool is_null_constant,validate_state * state)977*61046927SAndroid Build Coastguard Worker validate_const_value(nir_const_value *val, unsigned bit_size,
978*61046927SAndroid Build Coastguard Worker bool is_null_constant, validate_state *state)
979*61046927SAndroid Build Coastguard Worker {
980*61046927SAndroid Build Coastguard Worker /* In order for block copies to work properly for things like instruction
981*61046927SAndroid Build Coastguard Worker * comparisons and [de]serialization, we require the unused bits of the
982*61046927SAndroid Build Coastguard Worker * nir_const_value to be zero.
983*61046927SAndroid Build Coastguard Worker */
984*61046927SAndroid Build Coastguard Worker nir_const_value cmp_val;
985*61046927SAndroid Build Coastguard Worker memset(&cmp_val, 0, sizeof(cmp_val));
986*61046927SAndroid Build Coastguard Worker if (!is_null_constant) {
987*61046927SAndroid Build Coastguard Worker switch (bit_size) {
988*61046927SAndroid Build Coastguard Worker case 1:
989*61046927SAndroid Build Coastguard Worker cmp_val.b = val->b;
990*61046927SAndroid Build Coastguard Worker break;
991*61046927SAndroid Build Coastguard Worker case 8:
992*61046927SAndroid Build Coastguard Worker cmp_val.u8 = val->u8;
993*61046927SAndroid Build Coastguard Worker break;
994*61046927SAndroid Build Coastguard Worker case 16:
995*61046927SAndroid Build Coastguard Worker cmp_val.u16 = val->u16;
996*61046927SAndroid Build Coastguard Worker break;
997*61046927SAndroid Build Coastguard Worker case 32:
998*61046927SAndroid Build Coastguard Worker cmp_val.u32 = val->u32;
999*61046927SAndroid Build Coastguard Worker break;
1000*61046927SAndroid Build Coastguard Worker case 64:
1001*61046927SAndroid Build Coastguard Worker cmp_val.u64 = val->u64;
1002*61046927SAndroid Build Coastguard Worker break;
1003*61046927SAndroid Build Coastguard Worker default:
1004*61046927SAndroid Build Coastguard Worker validate_assert(state, !"Invalid load_const bit size");
1005*61046927SAndroid Build Coastguard Worker }
1006*61046927SAndroid Build Coastguard Worker }
1007*61046927SAndroid Build Coastguard Worker validate_assert(state, memcmp(val, &cmp_val, sizeof(cmp_val)) == 0);
1008*61046927SAndroid Build Coastguard Worker }
1009*61046927SAndroid Build Coastguard Worker
1010*61046927SAndroid Build Coastguard Worker static void
validate_load_const_instr(nir_load_const_instr * instr,validate_state * state)1011*61046927SAndroid Build Coastguard Worker validate_load_const_instr(nir_load_const_instr *instr, validate_state *state)
1012*61046927SAndroid Build Coastguard Worker {
1013*61046927SAndroid Build Coastguard Worker validate_def(&instr->def, state);
1014*61046927SAndroid Build Coastguard Worker
1015*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < instr->def.num_components; i++)
1016*61046927SAndroid Build Coastguard Worker validate_const_value(&instr->value[i], instr->def.bit_size, false, state);
1017*61046927SAndroid Build Coastguard Worker }
1018*61046927SAndroid Build Coastguard Worker
1019*61046927SAndroid Build Coastguard Worker static void
validate_ssa_undef_instr(nir_undef_instr * instr,validate_state * state)1020*61046927SAndroid Build Coastguard Worker validate_ssa_undef_instr(nir_undef_instr *instr, validate_state *state)
1021*61046927SAndroid Build Coastguard Worker {
1022*61046927SAndroid Build Coastguard Worker validate_def(&instr->def, state);
1023*61046927SAndroid Build Coastguard Worker }
1024*61046927SAndroid Build Coastguard Worker
1025*61046927SAndroid Build Coastguard Worker static void
validate_phi_instr(nir_phi_instr * instr,validate_state * state)1026*61046927SAndroid Build Coastguard Worker validate_phi_instr(nir_phi_instr *instr, validate_state *state)
1027*61046927SAndroid Build Coastguard Worker {
1028*61046927SAndroid Build Coastguard Worker /*
1029*61046927SAndroid Build Coastguard Worker * don't validate the sources until we get to them from their predecessor
1030*61046927SAndroid Build Coastguard Worker * basic blocks, to avoid validating an SSA use before its definition.
1031*61046927SAndroid Build Coastguard Worker */
1032*61046927SAndroid Build Coastguard Worker
1033*61046927SAndroid Build Coastguard Worker validate_def(&instr->def, state);
1034*61046927SAndroid Build Coastguard Worker
1035*61046927SAndroid Build Coastguard Worker exec_list_validate(&instr->srcs);
1036*61046927SAndroid Build Coastguard Worker validate_assert(state, exec_list_length(&instr->srcs) ==
1037*61046927SAndroid Build Coastguard Worker state->block->predecessors->entries);
1038*61046927SAndroid Build Coastguard Worker }
1039*61046927SAndroid Build Coastguard Worker
1040*61046927SAndroid Build Coastguard Worker static void
validate_jump_instr(nir_jump_instr * instr,validate_state * state)1041*61046927SAndroid Build Coastguard Worker validate_jump_instr(nir_jump_instr *instr, validate_state *state)
1042*61046927SAndroid Build Coastguard Worker {
1043*61046927SAndroid Build Coastguard Worker nir_block *block = state->block;
1044*61046927SAndroid Build Coastguard Worker validate_assert(state, &instr->instr == nir_block_last_instr(block));
1045*61046927SAndroid Build Coastguard Worker
1046*61046927SAndroid Build Coastguard Worker switch (instr->type) {
1047*61046927SAndroid Build Coastguard Worker case nir_jump_return:
1048*61046927SAndroid Build Coastguard Worker case nir_jump_halt:
1049*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[0] == state->impl->end_block);
1050*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[1] == NULL);
1051*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->target == NULL);
1052*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->else_target == NULL);
1053*61046927SAndroid Build Coastguard Worker validate_assert(state, !state->in_loop_continue_construct);
1054*61046927SAndroid Build Coastguard Worker break;
1055*61046927SAndroid Build Coastguard Worker
1056*61046927SAndroid Build Coastguard Worker case nir_jump_break:
1057*61046927SAndroid Build Coastguard Worker validate_assert(state, state->impl->structured);
1058*61046927SAndroid Build Coastguard Worker validate_assert(state, state->loop != NULL);
1059*61046927SAndroid Build Coastguard Worker if (state->loop) {
1060*61046927SAndroid Build Coastguard Worker nir_block *after =
1061*61046927SAndroid Build Coastguard Worker nir_cf_node_as_block(nir_cf_node_next(&state->loop->cf_node));
1062*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[0] == after);
1063*61046927SAndroid Build Coastguard Worker }
1064*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[1] == NULL);
1065*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->target == NULL);
1066*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->else_target == NULL);
1067*61046927SAndroid Build Coastguard Worker break;
1068*61046927SAndroid Build Coastguard Worker
1069*61046927SAndroid Build Coastguard Worker case nir_jump_continue:
1070*61046927SAndroid Build Coastguard Worker validate_assert(state, state->impl->structured);
1071*61046927SAndroid Build Coastguard Worker validate_assert(state, state->loop != NULL);
1072*61046927SAndroid Build Coastguard Worker if (state->loop) {
1073*61046927SAndroid Build Coastguard Worker nir_block *cont_block = nir_loop_continue_target(state->loop);
1074*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[0] == cont_block);
1075*61046927SAndroid Build Coastguard Worker }
1076*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[1] == NULL);
1077*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->target == NULL);
1078*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->else_target == NULL);
1079*61046927SAndroid Build Coastguard Worker validate_assert(state, !state->in_loop_continue_construct);
1080*61046927SAndroid Build Coastguard Worker break;
1081*61046927SAndroid Build Coastguard Worker
1082*61046927SAndroid Build Coastguard Worker case nir_jump_goto:
1083*61046927SAndroid Build Coastguard Worker validate_assert(state, !state->impl->structured);
1084*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->target == block->successors[0]);
1085*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->target != NULL);
1086*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->else_target == NULL);
1087*61046927SAndroid Build Coastguard Worker break;
1088*61046927SAndroid Build Coastguard Worker
1089*61046927SAndroid Build Coastguard Worker case nir_jump_goto_if:
1090*61046927SAndroid Build Coastguard Worker validate_assert(state, !state->impl->structured);
1091*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->target == block->successors[1]);
1092*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->else_target == block->successors[0]);
1093*61046927SAndroid Build Coastguard Worker validate_sized_src(&instr->condition, state, 0, 1);
1094*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->target != NULL);
1095*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->else_target != NULL);
1096*61046927SAndroid Build Coastguard Worker break;
1097*61046927SAndroid Build Coastguard Worker
1098*61046927SAndroid Build Coastguard Worker default:
1099*61046927SAndroid Build Coastguard Worker validate_assert(state, !"Invalid jump instruction type");
1100*61046927SAndroid Build Coastguard Worker break;
1101*61046927SAndroid Build Coastguard Worker }
1102*61046927SAndroid Build Coastguard Worker }
1103*61046927SAndroid Build Coastguard Worker
1104*61046927SAndroid Build Coastguard Worker static void
validate_instr(nir_instr * instr,validate_state * state)1105*61046927SAndroid Build Coastguard Worker validate_instr(nir_instr *instr, validate_state *state)
1106*61046927SAndroid Build Coastguard Worker {
1107*61046927SAndroid Build Coastguard Worker validate_assert(state, instr->block == state->block);
1108*61046927SAndroid Build Coastguard Worker
1109*61046927SAndroid Build Coastguard Worker state->instr = instr;
1110*61046927SAndroid Build Coastguard Worker
1111*61046927SAndroid Build Coastguard Worker switch (instr->type) {
1112*61046927SAndroid Build Coastguard Worker case nir_instr_type_alu:
1113*61046927SAndroid Build Coastguard Worker validate_alu_instr(nir_instr_as_alu(instr), state);
1114*61046927SAndroid Build Coastguard Worker break;
1115*61046927SAndroid Build Coastguard Worker
1116*61046927SAndroid Build Coastguard Worker case nir_instr_type_deref:
1117*61046927SAndroid Build Coastguard Worker validate_deref_instr(nir_instr_as_deref(instr), state);
1118*61046927SAndroid Build Coastguard Worker break;
1119*61046927SAndroid Build Coastguard Worker
1120*61046927SAndroid Build Coastguard Worker case nir_instr_type_call:
1121*61046927SAndroid Build Coastguard Worker validate_call_instr(nir_instr_as_call(instr), state);
1122*61046927SAndroid Build Coastguard Worker break;
1123*61046927SAndroid Build Coastguard Worker
1124*61046927SAndroid Build Coastguard Worker case nir_instr_type_intrinsic:
1125*61046927SAndroid Build Coastguard Worker validate_intrinsic_instr(nir_instr_as_intrinsic(instr), state);
1126*61046927SAndroid Build Coastguard Worker break;
1127*61046927SAndroid Build Coastguard Worker
1128*61046927SAndroid Build Coastguard Worker case nir_instr_type_tex:
1129*61046927SAndroid Build Coastguard Worker validate_tex_instr(nir_instr_as_tex(instr), state);
1130*61046927SAndroid Build Coastguard Worker break;
1131*61046927SAndroid Build Coastguard Worker
1132*61046927SAndroid Build Coastguard Worker case nir_instr_type_load_const:
1133*61046927SAndroid Build Coastguard Worker validate_load_const_instr(nir_instr_as_load_const(instr), state);
1134*61046927SAndroid Build Coastguard Worker break;
1135*61046927SAndroid Build Coastguard Worker
1136*61046927SAndroid Build Coastguard Worker case nir_instr_type_phi:
1137*61046927SAndroid Build Coastguard Worker validate_phi_instr(nir_instr_as_phi(instr), state);
1138*61046927SAndroid Build Coastguard Worker break;
1139*61046927SAndroid Build Coastguard Worker
1140*61046927SAndroid Build Coastguard Worker case nir_instr_type_undef:
1141*61046927SAndroid Build Coastguard Worker validate_ssa_undef_instr(nir_instr_as_undef(instr), state);
1142*61046927SAndroid Build Coastguard Worker break;
1143*61046927SAndroid Build Coastguard Worker
1144*61046927SAndroid Build Coastguard Worker case nir_instr_type_jump:
1145*61046927SAndroid Build Coastguard Worker validate_jump_instr(nir_instr_as_jump(instr), state);
1146*61046927SAndroid Build Coastguard Worker break;
1147*61046927SAndroid Build Coastguard Worker
1148*61046927SAndroid Build Coastguard Worker case nir_instr_type_debug_info:
1149*61046927SAndroid Build Coastguard Worker break;
1150*61046927SAndroid Build Coastguard Worker
1151*61046927SAndroid Build Coastguard Worker default:
1152*61046927SAndroid Build Coastguard Worker validate_assert(state, !"Invalid ALU instruction type");
1153*61046927SAndroid Build Coastguard Worker break;
1154*61046927SAndroid Build Coastguard Worker }
1155*61046927SAndroid Build Coastguard Worker
1156*61046927SAndroid Build Coastguard Worker state->instr = NULL;
1157*61046927SAndroid Build Coastguard Worker }
1158*61046927SAndroid Build Coastguard Worker
1159*61046927SAndroid Build Coastguard Worker static void
validate_phi_src(nir_phi_instr * instr,nir_block * pred,validate_state * state)1160*61046927SAndroid Build Coastguard Worker validate_phi_src(nir_phi_instr *instr, nir_block *pred, validate_state *state)
1161*61046927SAndroid Build Coastguard Worker {
1162*61046927SAndroid Build Coastguard Worker state->instr = &instr->instr;
1163*61046927SAndroid Build Coastguard Worker
1164*61046927SAndroid Build Coastguard Worker exec_list_validate(&instr->srcs);
1165*61046927SAndroid Build Coastguard Worker nir_foreach_phi_src(src, instr) {
1166*61046927SAndroid Build Coastguard Worker if (src->pred == pred) {
1167*61046927SAndroid Build Coastguard Worker validate_sized_src(&src->src, state, instr->def.bit_size,
1168*61046927SAndroid Build Coastguard Worker instr->def.num_components);
1169*61046927SAndroid Build Coastguard Worker state->instr = NULL;
1170*61046927SAndroid Build Coastguard Worker return;
1171*61046927SAndroid Build Coastguard Worker }
1172*61046927SAndroid Build Coastguard Worker }
1173*61046927SAndroid Build Coastguard Worker validate_assert(state, !"Phi does not have a source corresponding to one "
1174*61046927SAndroid Build Coastguard Worker "of its predecessor blocks");
1175*61046927SAndroid Build Coastguard Worker }
1176*61046927SAndroid Build Coastguard Worker
1177*61046927SAndroid Build Coastguard Worker static void
validate_phi_srcs(nir_block * block,nir_block * succ,validate_state * state)1178*61046927SAndroid Build Coastguard Worker validate_phi_srcs(nir_block *block, nir_block *succ, validate_state *state)
1179*61046927SAndroid Build Coastguard Worker {
1180*61046927SAndroid Build Coastguard Worker nir_foreach_phi(phi, succ) {
1181*61046927SAndroid Build Coastguard Worker validate_phi_src(phi, block, state);
1182*61046927SAndroid Build Coastguard Worker }
1183*61046927SAndroid Build Coastguard Worker }
1184*61046927SAndroid Build Coastguard Worker
1185*61046927SAndroid Build Coastguard Worker static void
collect_blocks(struct exec_list * cf_list,validate_state * state)1186*61046927SAndroid Build Coastguard Worker collect_blocks(struct exec_list *cf_list, validate_state *state)
1187*61046927SAndroid Build Coastguard Worker {
1188*61046927SAndroid Build Coastguard Worker /* We walk the blocks manually here rather than using nir_foreach_block for
1189*61046927SAndroid Build Coastguard Worker * a few reasons:
1190*61046927SAndroid Build Coastguard Worker *
1191*61046927SAndroid Build Coastguard Worker * 1. We want to call exec_list_validate() on every linked list in the IR
1192*61046927SAndroid Build Coastguard Worker * which means we need to touch every linked and just walking blocks
1193*61046927SAndroid Build Coastguard Worker * with nir_foreach_block() would make that difficult. In particular,
1194*61046927SAndroid Build Coastguard Worker * we want to validate each list before the first time we walk it so
1195*61046927SAndroid Build Coastguard Worker * that we catch broken lists in exec_list_validate() instead of
1196*61046927SAndroid Build Coastguard Worker * getting stuck in a hard-to-debug infinite loop in the validator.
1197*61046927SAndroid Build Coastguard Worker *
1198*61046927SAndroid Build Coastguard Worker * 2. nir_foreach_block() depends on several invariants of the CF node
1199*61046927SAndroid Build Coastguard Worker * hierarchy which nir_validate_shader() is responsible for verifying.
1200*61046927SAndroid Build Coastguard Worker * If we used nir_foreach_block() in nir_validate_shader(), we could
1201*61046927SAndroid Build Coastguard Worker * end up blowing up on a bad list walk instead of throwing the much
1202*61046927SAndroid Build Coastguard Worker * easier to debug validation error.
1203*61046927SAndroid Build Coastguard Worker */
1204*61046927SAndroid Build Coastguard Worker exec_list_validate(cf_list);
1205*61046927SAndroid Build Coastguard Worker foreach_list_typed(nir_cf_node, node, node, cf_list) {
1206*61046927SAndroid Build Coastguard Worker switch (node->type) {
1207*61046927SAndroid Build Coastguard Worker case nir_cf_node_block:
1208*61046927SAndroid Build Coastguard Worker _mesa_set_add(state->blocks, nir_cf_node_as_block(node));
1209*61046927SAndroid Build Coastguard Worker break;
1210*61046927SAndroid Build Coastguard Worker
1211*61046927SAndroid Build Coastguard Worker case nir_cf_node_if:
1212*61046927SAndroid Build Coastguard Worker collect_blocks(&nir_cf_node_as_if(node)->then_list, state);
1213*61046927SAndroid Build Coastguard Worker collect_blocks(&nir_cf_node_as_if(node)->else_list, state);
1214*61046927SAndroid Build Coastguard Worker break;
1215*61046927SAndroid Build Coastguard Worker
1216*61046927SAndroid Build Coastguard Worker case nir_cf_node_loop:
1217*61046927SAndroid Build Coastguard Worker collect_blocks(&nir_cf_node_as_loop(node)->body, state);
1218*61046927SAndroid Build Coastguard Worker collect_blocks(&nir_cf_node_as_loop(node)->continue_list, state);
1219*61046927SAndroid Build Coastguard Worker break;
1220*61046927SAndroid Build Coastguard Worker
1221*61046927SAndroid Build Coastguard Worker default:
1222*61046927SAndroid Build Coastguard Worker unreachable("Invalid CF node type");
1223*61046927SAndroid Build Coastguard Worker }
1224*61046927SAndroid Build Coastguard Worker }
1225*61046927SAndroid Build Coastguard Worker }
1226*61046927SAndroid Build Coastguard Worker
1227*61046927SAndroid Build Coastguard Worker static void
collect_blocks_pdfs(nir_function_impl * impl,nir_block * block,uint32_t * count,validate_state * state)1228*61046927SAndroid Build Coastguard Worker collect_blocks_pdfs(nir_function_impl *impl, nir_block *block,
1229*61046927SAndroid Build Coastguard Worker uint32_t *count, validate_state *state)
1230*61046927SAndroid Build Coastguard Worker {
1231*61046927SAndroid Build Coastguard Worker if (block == impl->end_block)
1232*61046927SAndroid Build Coastguard Worker return;
1233*61046927SAndroid Build Coastguard Worker
1234*61046927SAndroid Build Coastguard Worker if (_mesa_set_search(state->blocks, block))
1235*61046927SAndroid Build Coastguard Worker return;
1236*61046927SAndroid Build Coastguard Worker
1237*61046927SAndroid Build Coastguard Worker _mesa_set_add(state->blocks, block);
1238*61046927SAndroid Build Coastguard Worker
1239*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < ARRAY_SIZE(block->successors); i++) {
1240*61046927SAndroid Build Coastguard Worker if (block->successors[i] != NULL)
1241*61046927SAndroid Build Coastguard Worker collect_blocks_pdfs(impl, block->successors[i], count, state);
1242*61046927SAndroid Build Coastguard Worker }
1243*61046927SAndroid Build Coastguard Worker
1244*61046927SAndroid Build Coastguard Worker /* Assert that the blocks are indexed in reverse PDFS order */
1245*61046927SAndroid Build Coastguard Worker validate_assert(state, block->index == --(*count));
1246*61046927SAndroid Build Coastguard Worker }
1247*61046927SAndroid Build Coastguard Worker
1248*61046927SAndroid Build Coastguard Worker static void
collect_unstructured_blocks(nir_function_impl * impl,validate_state * state)1249*61046927SAndroid Build Coastguard Worker collect_unstructured_blocks(nir_function_impl *impl, validate_state *state)
1250*61046927SAndroid Build Coastguard Worker {
1251*61046927SAndroid Build Coastguard Worker exec_list_validate(&impl->body);
1252*61046927SAndroid Build Coastguard Worker
1253*61046927SAndroid Build Coastguard Worker /* Assert that the blocks are properly indexed */
1254*61046927SAndroid Build Coastguard Worker uint32_t count = 0;
1255*61046927SAndroid Build Coastguard Worker foreach_list_typed(nir_cf_node, node, node, &impl->body) {
1256*61046927SAndroid Build Coastguard Worker nir_block *block = nir_cf_node_as_block(node);
1257*61046927SAndroid Build Coastguard Worker validate_assert(state, block->index == count++);
1258*61046927SAndroid Build Coastguard Worker }
1259*61046927SAndroid Build Coastguard Worker validate_assert(state, impl->end_block->index == count);
1260*61046927SAndroid Build Coastguard Worker
1261*61046927SAndroid Build Coastguard Worker collect_blocks_pdfs(impl, nir_start_block(impl), &count, state);
1262*61046927SAndroid Build Coastguard Worker }
1263*61046927SAndroid Build Coastguard Worker
1264*61046927SAndroid Build Coastguard Worker static void validate_cf_node(nir_cf_node *node, validate_state *state);
1265*61046927SAndroid Build Coastguard Worker
1266*61046927SAndroid Build Coastguard Worker static void
validate_block_predecessors(nir_block * block,validate_state * state)1267*61046927SAndroid Build Coastguard Worker validate_block_predecessors(nir_block *block, validate_state *state)
1268*61046927SAndroid Build Coastguard Worker {
1269*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 2; i++) {
1270*61046927SAndroid Build Coastguard Worker if (block->successors[i] == NULL)
1271*61046927SAndroid Build Coastguard Worker continue;
1272*61046927SAndroid Build Coastguard Worker
1273*61046927SAndroid Build Coastguard Worker /* The block has to exist in the nir_function_impl */
1274*61046927SAndroid Build Coastguard Worker validate_assert(state, _mesa_set_search(state->blocks,
1275*61046927SAndroid Build Coastguard Worker block->successors[i]));
1276*61046927SAndroid Build Coastguard Worker
1277*61046927SAndroid Build Coastguard Worker /* And we have to be in our successor's predecessors set */
1278*61046927SAndroid Build Coastguard Worker validate_assert(state,
1279*61046927SAndroid Build Coastguard Worker _mesa_set_search(block->successors[i]->predecessors, block));
1280*61046927SAndroid Build Coastguard Worker
1281*61046927SAndroid Build Coastguard Worker validate_phi_srcs(block, block->successors[i], state);
1282*61046927SAndroid Build Coastguard Worker }
1283*61046927SAndroid Build Coastguard Worker
1284*61046927SAndroid Build Coastguard Worker /* The start block cannot have any predecessors */
1285*61046927SAndroid Build Coastguard Worker if (block == nir_start_block(state->impl))
1286*61046927SAndroid Build Coastguard Worker validate_assert(state, block->predecessors->entries == 0);
1287*61046927SAndroid Build Coastguard Worker
1288*61046927SAndroid Build Coastguard Worker set_foreach(block->predecessors, entry) {
1289*61046927SAndroid Build Coastguard Worker const nir_block *pred = entry->key;
1290*61046927SAndroid Build Coastguard Worker validate_assert(state, _mesa_set_search(state->blocks, pred));
1291*61046927SAndroid Build Coastguard Worker validate_assert(state, pred->successors[0] == block ||
1292*61046927SAndroid Build Coastguard Worker pred->successors[1] == block);
1293*61046927SAndroid Build Coastguard Worker }
1294*61046927SAndroid Build Coastguard Worker }
1295*61046927SAndroid Build Coastguard Worker
1296*61046927SAndroid Build Coastguard Worker static void
validate_block(nir_block * block,validate_state * state)1297*61046927SAndroid Build Coastguard Worker validate_block(nir_block *block, validate_state *state)
1298*61046927SAndroid Build Coastguard Worker {
1299*61046927SAndroid Build Coastguard Worker validate_assert(state, block->cf_node.parent == state->parent_node);
1300*61046927SAndroid Build Coastguard Worker
1301*61046927SAndroid Build Coastguard Worker state->block = block;
1302*61046927SAndroid Build Coastguard Worker
1303*61046927SAndroid Build Coastguard Worker exec_list_validate(&block->instr_list);
1304*61046927SAndroid Build Coastguard Worker nir_foreach_instr(instr, block) {
1305*61046927SAndroid Build Coastguard Worker if (instr->type == nir_instr_type_phi) {
1306*61046927SAndroid Build Coastguard Worker validate_assert(state, instr == nir_block_first_instr(block) ||
1307*61046927SAndroid Build Coastguard Worker nir_instr_prev(instr)->type == nir_instr_type_phi);
1308*61046927SAndroid Build Coastguard Worker }
1309*61046927SAndroid Build Coastguard Worker
1310*61046927SAndroid Build Coastguard Worker validate_instr(instr, state);
1311*61046927SAndroid Build Coastguard Worker }
1312*61046927SAndroid Build Coastguard Worker
1313*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[0] != NULL);
1314*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[0] != block->successors[1]);
1315*61046927SAndroid Build Coastguard Worker validate_block_predecessors(block, state);
1316*61046927SAndroid Build Coastguard Worker
1317*61046927SAndroid Build Coastguard Worker if (!state->impl->structured) {
1318*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_block_ends_in_jump(block));
1319*61046927SAndroid Build Coastguard Worker } else if (!nir_block_ends_in_jump(block)) {
1320*61046927SAndroid Build Coastguard Worker nir_cf_node *next = nir_cf_node_next(&block->cf_node);
1321*61046927SAndroid Build Coastguard Worker if (next == NULL) {
1322*61046927SAndroid Build Coastguard Worker switch (state->parent_node->type) {
1323*61046927SAndroid Build Coastguard Worker case nir_cf_node_loop: {
1324*61046927SAndroid Build Coastguard Worker if (block == nir_loop_last_block(state->loop)) {
1325*61046927SAndroid Build Coastguard Worker nir_block *cont = nir_loop_continue_target(state->loop);
1326*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[0] == cont);
1327*61046927SAndroid Build Coastguard Worker } else {
1328*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_loop_has_continue_construct(state->loop) &&
1329*61046927SAndroid Build Coastguard Worker block == nir_loop_last_continue_block(state->loop));
1330*61046927SAndroid Build Coastguard Worker nir_block *head = nir_loop_first_block(state->loop);
1331*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[0] == head);
1332*61046927SAndroid Build Coastguard Worker }
1333*61046927SAndroid Build Coastguard Worker /* due to the hack for infinite loops, block->successors[1] may
1334*61046927SAndroid Build Coastguard Worker * point to the block after the loop.
1335*61046927SAndroid Build Coastguard Worker */
1336*61046927SAndroid Build Coastguard Worker break;
1337*61046927SAndroid Build Coastguard Worker }
1338*61046927SAndroid Build Coastguard Worker
1339*61046927SAndroid Build Coastguard Worker case nir_cf_node_if: {
1340*61046927SAndroid Build Coastguard Worker nir_block *after =
1341*61046927SAndroid Build Coastguard Worker nir_cf_node_as_block(nir_cf_node_next(state->parent_node));
1342*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[0] == after);
1343*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[1] == NULL);
1344*61046927SAndroid Build Coastguard Worker break;
1345*61046927SAndroid Build Coastguard Worker }
1346*61046927SAndroid Build Coastguard Worker
1347*61046927SAndroid Build Coastguard Worker case nir_cf_node_function:
1348*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[0] == state->impl->end_block);
1349*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[1] == NULL);
1350*61046927SAndroid Build Coastguard Worker break;
1351*61046927SAndroid Build Coastguard Worker
1352*61046927SAndroid Build Coastguard Worker default:
1353*61046927SAndroid Build Coastguard Worker unreachable("unknown control flow node type");
1354*61046927SAndroid Build Coastguard Worker }
1355*61046927SAndroid Build Coastguard Worker } else {
1356*61046927SAndroid Build Coastguard Worker if (next->type == nir_cf_node_if) {
1357*61046927SAndroid Build Coastguard Worker nir_if *if_stmt = nir_cf_node_as_if(next);
1358*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[0] ==
1359*61046927SAndroid Build Coastguard Worker nir_if_first_then_block(if_stmt));
1360*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[1] ==
1361*61046927SAndroid Build Coastguard Worker nir_if_first_else_block(if_stmt));
1362*61046927SAndroid Build Coastguard Worker } else if (next->type == nir_cf_node_loop) {
1363*61046927SAndroid Build Coastguard Worker nir_loop *loop = nir_cf_node_as_loop(next);
1364*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[0] ==
1365*61046927SAndroid Build Coastguard Worker nir_loop_first_block(loop));
1366*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[1] == NULL);
1367*61046927SAndroid Build Coastguard Worker } else {
1368*61046927SAndroid Build Coastguard Worker validate_assert(state,
1369*61046927SAndroid Build Coastguard Worker !"Structured NIR cannot have consecutive blocks");
1370*61046927SAndroid Build Coastguard Worker }
1371*61046927SAndroid Build Coastguard Worker }
1372*61046927SAndroid Build Coastguard Worker }
1373*61046927SAndroid Build Coastguard Worker }
1374*61046927SAndroid Build Coastguard Worker
1375*61046927SAndroid Build Coastguard Worker static void
validate_end_block(nir_block * block,validate_state * state)1376*61046927SAndroid Build Coastguard Worker validate_end_block(nir_block *block, validate_state *state)
1377*61046927SAndroid Build Coastguard Worker {
1378*61046927SAndroid Build Coastguard Worker validate_assert(state, block->cf_node.parent == &state->impl->cf_node);
1379*61046927SAndroid Build Coastguard Worker
1380*61046927SAndroid Build Coastguard Worker exec_list_validate(&block->instr_list);
1381*61046927SAndroid Build Coastguard Worker validate_assert(state, exec_list_is_empty(&block->instr_list));
1382*61046927SAndroid Build Coastguard Worker
1383*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[0] == NULL);
1384*61046927SAndroid Build Coastguard Worker validate_assert(state, block->successors[1] == NULL);
1385*61046927SAndroid Build Coastguard Worker validate_block_predecessors(block, state);
1386*61046927SAndroid Build Coastguard Worker }
1387*61046927SAndroid Build Coastguard Worker
1388*61046927SAndroid Build Coastguard Worker static void
validate_if(nir_if * if_stmt,validate_state * state)1389*61046927SAndroid Build Coastguard Worker validate_if(nir_if *if_stmt, validate_state *state)
1390*61046927SAndroid Build Coastguard Worker {
1391*61046927SAndroid Build Coastguard Worker validate_assert(state, state->impl->structured);
1392*61046927SAndroid Build Coastguard Worker
1393*61046927SAndroid Build Coastguard Worker state->if_stmt = if_stmt;
1394*61046927SAndroid Build Coastguard Worker
1395*61046927SAndroid Build Coastguard Worker validate_assert(state, !exec_node_is_head_sentinel(if_stmt->cf_node.node.prev));
1396*61046927SAndroid Build Coastguard Worker nir_cf_node *prev_node = nir_cf_node_prev(&if_stmt->cf_node);
1397*61046927SAndroid Build Coastguard Worker validate_assert(state, prev_node->type == nir_cf_node_block);
1398*61046927SAndroid Build Coastguard Worker
1399*61046927SAndroid Build Coastguard Worker validate_assert(state, !exec_node_is_tail_sentinel(if_stmt->cf_node.node.next));
1400*61046927SAndroid Build Coastguard Worker nir_cf_node *next_node = nir_cf_node_next(&if_stmt->cf_node);
1401*61046927SAndroid Build Coastguard Worker validate_assert(state, next_node->type == nir_cf_node_block);
1402*61046927SAndroid Build Coastguard Worker
1403*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_src_is_if(&if_stmt->condition));
1404*61046927SAndroid Build Coastguard Worker validate_if_src(&if_stmt->condition, state);
1405*61046927SAndroid Build Coastguard Worker
1406*61046927SAndroid Build Coastguard Worker validate_assert(state, !exec_list_is_empty(&if_stmt->then_list));
1407*61046927SAndroid Build Coastguard Worker validate_assert(state, !exec_list_is_empty(&if_stmt->else_list));
1408*61046927SAndroid Build Coastguard Worker
1409*61046927SAndroid Build Coastguard Worker nir_cf_node *old_parent = state->parent_node;
1410*61046927SAndroid Build Coastguard Worker state->parent_node = &if_stmt->cf_node;
1411*61046927SAndroid Build Coastguard Worker
1412*61046927SAndroid Build Coastguard Worker foreach_list_typed(nir_cf_node, cf_node, node, &if_stmt->then_list) {
1413*61046927SAndroid Build Coastguard Worker validate_cf_node(cf_node, state);
1414*61046927SAndroid Build Coastguard Worker }
1415*61046927SAndroid Build Coastguard Worker
1416*61046927SAndroid Build Coastguard Worker foreach_list_typed(nir_cf_node, cf_node, node, &if_stmt->else_list) {
1417*61046927SAndroid Build Coastguard Worker validate_cf_node(cf_node, state);
1418*61046927SAndroid Build Coastguard Worker }
1419*61046927SAndroid Build Coastguard Worker
1420*61046927SAndroid Build Coastguard Worker state->parent_node = old_parent;
1421*61046927SAndroid Build Coastguard Worker state->if_stmt = NULL;
1422*61046927SAndroid Build Coastguard Worker }
1423*61046927SAndroid Build Coastguard Worker
1424*61046927SAndroid Build Coastguard Worker static void
validate_loop(nir_loop * loop,validate_state * state)1425*61046927SAndroid Build Coastguard Worker validate_loop(nir_loop *loop, validate_state *state)
1426*61046927SAndroid Build Coastguard Worker {
1427*61046927SAndroid Build Coastguard Worker validate_assert(state, state->impl->structured);
1428*61046927SAndroid Build Coastguard Worker
1429*61046927SAndroid Build Coastguard Worker validate_assert(state, !exec_node_is_head_sentinel(loop->cf_node.node.prev));
1430*61046927SAndroid Build Coastguard Worker nir_cf_node *prev_node = nir_cf_node_prev(&loop->cf_node);
1431*61046927SAndroid Build Coastguard Worker validate_assert(state, prev_node->type == nir_cf_node_block);
1432*61046927SAndroid Build Coastguard Worker
1433*61046927SAndroid Build Coastguard Worker validate_assert(state, !exec_node_is_tail_sentinel(loop->cf_node.node.next));
1434*61046927SAndroid Build Coastguard Worker nir_cf_node *next_node = nir_cf_node_next(&loop->cf_node);
1435*61046927SAndroid Build Coastguard Worker validate_assert(state, next_node->type == nir_cf_node_block);
1436*61046927SAndroid Build Coastguard Worker
1437*61046927SAndroid Build Coastguard Worker validate_assert(state, !exec_list_is_empty(&loop->body));
1438*61046927SAndroid Build Coastguard Worker
1439*61046927SAndroid Build Coastguard Worker nir_cf_node *old_parent = state->parent_node;
1440*61046927SAndroid Build Coastguard Worker state->parent_node = &loop->cf_node;
1441*61046927SAndroid Build Coastguard Worker nir_loop *old_loop = state->loop;
1442*61046927SAndroid Build Coastguard Worker bool old_continue_construct = state->in_loop_continue_construct;
1443*61046927SAndroid Build Coastguard Worker state->loop = loop;
1444*61046927SAndroid Build Coastguard Worker state->in_loop_continue_construct = false;
1445*61046927SAndroid Build Coastguard Worker
1446*61046927SAndroid Build Coastguard Worker foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) {
1447*61046927SAndroid Build Coastguard Worker validate_cf_node(cf_node, state);
1448*61046927SAndroid Build Coastguard Worker }
1449*61046927SAndroid Build Coastguard Worker state->in_loop_continue_construct = true;
1450*61046927SAndroid Build Coastguard Worker foreach_list_typed(nir_cf_node, cf_node, node, &loop->continue_list) {
1451*61046927SAndroid Build Coastguard Worker validate_cf_node(cf_node, state);
1452*61046927SAndroid Build Coastguard Worker }
1453*61046927SAndroid Build Coastguard Worker state->in_loop_continue_construct = false;
1454*61046927SAndroid Build Coastguard Worker state->parent_node = old_parent;
1455*61046927SAndroid Build Coastguard Worker state->loop = old_loop;
1456*61046927SAndroid Build Coastguard Worker state->in_loop_continue_construct = old_continue_construct;
1457*61046927SAndroid Build Coastguard Worker }
1458*61046927SAndroid Build Coastguard Worker
1459*61046927SAndroid Build Coastguard Worker static void
validate_cf_node(nir_cf_node * node,validate_state * state)1460*61046927SAndroid Build Coastguard Worker validate_cf_node(nir_cf_node *node, validate_state *state)
1461*61046927SAndroid Build Coastguard Worker {
1462*61046927SAndroid Build Coastguard Worker validate_assert(state, node->parent == state->parent_node);
1463*61046927SAndroid Build Coastguard Worker
1464*61046927SAndroid Build Coastguard Worker switch (node->type) {
1465*61046927SAndroid Build Coastguard Worker case nir_cf_node_block:
1466*61046927SAndroid Build Coastguard Worker validate_block(nir_cf_node_as_block(node), state);
1467*61046927SAndroid Build Coastguard Worker break;
1468*61046927SAndroid Build Coastguard Worker
1469*61046927SAndroid Build Coastguard Worker case nir_cf_node_if:
1470*61046927SAndroid Build Coastguard Worker validate_if(nir_cf_node_as_if(node), state);
1471*61046927SAndroid Build Coastguard Worker break;
1472*61046927SAndroid Build Coastguard Worker
1473*61046927SAndroid Build Coastguard Worker case nir_cf_node_loop:
1474*61046927SAndroid Build Coastguard Worker validate_loop(nir_cf_node_as_loop(node), state);
1475*61046927SAndroid Build Coastguard Worker break;
1476*61046927SAndroid Build Coastguard Worker
1477*61046927SAndroid Build Coastguard Worker default:
1478*61046927SAndroid Build Coastguard Worker unreachable("Invalid CF node type");
1479*61046927SAndroid Build Coastguard Worker }
1480*61046927SAndroid Build Coastguard Worker }
1481*61046927SAndroid Build Coastguard Worker
1482*61046927SAndroid Build Coastguard Worker static void
validate_constant(nir_constant * c,const struct glsl_type * type,validate_state * state)1483*61046927SAndroid Build Coastguard Worker validate_constant(nir_constant *c, const struct glsl_type *type,
1484*61046927SAndroid Build Coastguard Worker validate_state *state)
1485*61046927SAndroid Build Coastguard Worker {
1486*61046927SAndroid Build Coastguard Worker if (glsl_type_is_vector_or_scalar(type)) {
1487*61046927SAndroid Build Coastguard Worker unsigned num_components = glsl_get_vector_elements(type);
1488*61046927SAndroid Build Coastguard Worker unsigned bit_size = glsl_get_bit_size(type);
1489*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < num_components; i++)
1490*61046927SAndroid Build Coastguard Worker validate_const_value(&c->values[i], bit_size, c->is_null_constant, state);
1491*61046927SAndroid Build Coastguard Worker for (unsigned i = num_components; i < NIR_MAX_VEC_COMPONENTS; i++)
1492*61046927SAndroid Build Coastguard Worker validate_assert(state, c->values[i].u64 == 0);
1493*61046927SAndroid Build Coastguard Worker } else {
1494*61046927SAndroid Build Coastguard Worker validate_assert(state, c->num_elements == glsl_get_length(type));
1495*61046927SAndroid Build Coastguard Worker if (glsl_type_is_struct_or_ifc(type)) {
1496*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < c->num_elements; i++) {
1497*61046927SAndroid Build Coastguard Worker const struct glsl_type *elem_type = glsl_get_struct_field(type, i);
1498*61046927SAndroid Build Coastguard Worker validate_constant(c->elements[i], elem_type, state);
1499*61046927SAndroid Build Coastguard Worker validate_assert(state, !c->is_null_constant || c->elements[i]->is_null_constant);
1500*61046927SAndroid Build Coastguard Worker }
1501*61046927SAndroid Build Coastguard Worker } else if (glsl_type_is_array_or_matrix(type)) {
1502*61046927SAndroid Build Coastguard Worker const struct glsl_type *elem_type = glsl_get_array_element(type);
1503*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < c->num_elements; i++) {
1504*61046927SAndroid Build Coastguard Worker validate_constant(c->elements[i], elem_type, state);
1505*61046927SAndroid Build Coastguard Worker validate_assert(state, !c->is_null_constant || c->elements[i]->is_null_constant);
1506*61046927SAndroid Build Coastguard Worker }
1507*61046927SAndroid Build Coastguard Worker } else {
1508*61046927SAndroid Build Coastguard Worker validate_assert(state, !"Invalid type for nir_constant");
1509*61046927SAndroid Build Coastguard Worker }
1510*61046927SAndroid Build Coastguard Worker }
1511*61046927SAndroid Build Coastguard Worker }
1512*61046927SAndroid Build Coastguard Worker
1513*61046927SAndroid Build Coastguard Worker static void
validate_var_decl(nir_variable * var,nir_variable_mode valid_modes,validate_state * state)1514*61046927SAndroid Build Coastguard Worker validate_var_decl(nir_variable *var, nir_variable_mode valid_modes,
1515*61046927SAndroid Build Coastguard Worker validate_state *state)
1516*61046927SAndroid Build Coastguard Worker {
1517*61046927SAndroid Build Coastguard Worker state->var = var;
1518*61046927SAndroid Build Coastguard Worker
1519*61046927SAndroid Build Coastguard Worker /* Must have exactly one mode set */
1520*61046927SAndroid Build Coastguard Worker validate_assert(state, util_is_power_of_two_nonzero(var->data.mode));
1521*61046927SAndroid Build Coastguard Worker validate_assert(state, var->data.mode & valid_modes);
1522*61046927SAndroid Build Coastguard Worker
1523*61046927SAndroid Build Coastguard Worker if (var->data.compact) {
1524*61046927SAndroid Build Coastguard Worker /* The "compact" flag is only valid on arrays of scalars. */
1525*61046927SAndroid Build Coastguard Worker assert(glsl_type_is_array(var->type));
1526*61046927SAndroid Build Coastguard Worker
1527*61046927SAndroid Build Coastguard Worker const struct glsl_type *type = glsl_get_array_element(var->type);
1528*61046927SAndroid Build Coastguard Worker if (nir_is_arrayed_io(var, state->shader->info.stage)) {
1529*61046927SAndroid Build Coastguard Worker if (var->data.per_view) {
1530*61046927SAndroid Build Coastguard Worker assert(glsl_type_is_array(type));
1531*61046927SAndroid Build Coastguard Worker type = glsl_get_array_element(type);
1532*61046927SAndroid Build Coastguard Worker }
1533*61046927SAndroid Build Coastguard Worker assert(glsl_type_is_array(type));
1534*61046927SAndroid Build Coastguard Worker assert(glsl_type_is_scalar(glsl_get_array_element(type)));
1535*61046927SAndroid Build Coastguard Worker } else {
1536*61046927SAndroid Build Coastguard Worker assert(glsl_type_is_scalar(type));
1537*61046927SAndroid Build Coastguard Worker }
1538*61046927SAndroid Build Coastguard Worker }
1539*61046927SAndroid Build Coastguard Worker
1540*61046927SAndroid Build Coastguard Worker if (var->num_members > 0) {
1541*61046927SAndroid Build Coastguard Worker const struct glsl_type *without_array = glsl_without_array(var->type);
1542*61046927SAndroid Build Coastguard Worker validate_assert(state, glsl_type_is_struct_or_ifc(without_array));
1543*61046927SAndroid Build Coastguard Worker validate_assert(state, var->num_members == glsl_get_length(without_array));
1544*61046927SAndroid Build Coastguard Worker validate_assert(state, var->members != NULL);
1545*61046927SAndroid Build Coastguard Worker }
1546*61046927SAndroid Build Coastguard Worker
1547*61046927SAndroid Build Coastguard Worker if (var->data.per_view)
1548*61046927SAndroid Build Coastguard Worker validate_assert(state, glsl_type_is_array(var->type));
1549*61046927SAndroid Build Coastguard Worker
1550*61046927SAndroid Build Coastguard Worker if (var->constant_initializer)
1551*61046927SAndroid Build Coastguard Worker validate_constant(var->constant_initializer, var->type, state);
1552*61046927SAndroid Build Coastguard Worker
1553*61046927SAndroid Build Coastguard Worker if (var->data.mode == nir_var_image) {
1554*61046927SAndroid Build Coastguard Worker validate_assert(state, !var->data.bindless);
1555*61046927SAndroid Build Coastguard Worker validate_assert(state, glsl_type_is_image(glsl_without_array(var->type)));
1556*61046927SAndroid Build Coastguard Worker }
1557*61046927SAndroid Build Coastguard Worker
1558*61046927SAndroid Build Coastguard Worker if (var->data.per_vertex)
1559*61046927SAndroid Build Coastguard Worker validate_assert(state, state->shader->info.stage == MESA_SHADER_FRAGMENT);
1560*61046927SAndroid Build Coastguard Worker
1561*61046927SAndroid Build Coastguard Worker /*
1562*61046927SAndroid Build Coastguard Worker * TODO validate some things ir_validate.cpp does (requires more GLSL type
1563*61046927SAndroid Build Coastguard Worker * support)
1564*61046927SAndroid Build Coastguard Worker */
1565*61046927SAndroid Build Coastguard Worker
1566*61046927SAndroid Build Coastguard Worker _mesa_hash_table_insert(state->var_defs, var,
1567*61046927SAndroid Build Coastguard Worker valid_modes == nir_var_function_temp ? state->impl : NULL);
1568*61046927SAndroid Build Coastguard Worker
1569*61046927SAndroid Build Coastguard Worker state->var = NULL;
1570*61046927SAndroid Build Coastguard Worker }
1571*61046927SAndroid Build Coastguard Worker
1572*61046927SAndroid Build Coastguard Worker static bool
validate_ssa_def_dominance(nir_def * def,void * _state)1573*61046927SAndroid Build Coastguard Worker validate_ssa_def_dominance(nir_def *def, void *_state)
1574*61046927SAndroid Build Coastguard Worker {
1575*61046927SAndroid Build Coastguard Worker validate_state *state = _state;
1576*61046927SAndroid Build Coastguard Worker
1577*61046927SAndroid Build Coastguard Worker validate_assert(state, def->index < state->impl->ssa_alloc);
1578*61046927SAndroid Build Coastguard Worker validate_assert(state, !BITSET_TEST(state->ssa_defs_found, def->index));
1579*61046927SAndroid Build Coastguard Worker BITSET_SET(state->ssa_defs_found, def->index);
1580*61046927SAndroid Build Coastguard Worker
1581*61046927SAndroid Build Coastguard Worker return true;
1582*61046927SAndroid Build Coastguard Worker }
1583*61046927SAndroid Build Coastguard Worker
1584*61046927SAndroid Build Coastguard Worker static bool
validate_src_dominance(nir_src * src,void * _state)1585*61046927SAndroid Build Coastguard Worker validate_src_dominance(nir_src *src, void *_state)
1586*61046927SAndroid Build Coastguard Worker {
1587*61046927SAndroid Build Coastguard Worker validate_state *state = _state;
1588*61046927SAndroid Build Coastguard Worker
1589*61046927SAndroid Build Coastguard Worker if (src->ssa->parent_instr->block == nir_src_parent_instr(src)->block) {
1590*61046927SAndroid Build Coastguard Worker validate_assert(state, src->ssa->index < state->impl->ssa_alloc);
1591*61046927SAndroid Build Coastguard Worker validate_assert(state, BITSET_TEST(state->ssa_defs_found,
1592*61046927SAndroid Build Coastguard Worker src->ssa->index));
1593*61046927SAndroid Build Coastguard Worker } else {
1594*61046927SAndroid Build Coastguard Worker validate_assert(state, nir_block_dominates(src->ssa->parent_instr->block,
1595*61046927SAndroid Build Coastguard Worker nir_src_parent_instr(src)->block));
1596*61046927SAndroid Build Coastguard Worker }
1597*61046927SAndroid Build Coastguard Worker return true;
1598*61046927SAndroid Build Coastguard Worker }
1599*61046927SAndroid Build Coastguard Worker
1600*61046927SAndroid Build Coastguard Worker static void
validate_ssa_dominance(nir_function_impl * impl,validate_state * state)1601*61046927SAndroid Build Coastguard Worker validate_ssa_dominance(nir_function_impl *impl, validate_state *state)
1602*61046927SAndroid Build Coastguard Worker {
1603*61046927SAndroid Build Coastguard Worker nir_metadata_require(impl, nir_metadata_dominance);
1604*61046927SAndroid Build Coastguard Worker
1605*61046927SAndroid Build Coastguard Worker nir_foreach_block(block, impl) {
1606*61046927SAndroid Build Coastguard Worker state->block = block;
1607*61046927SAndroid Build Coastguard Worker nir_foreach_instr(instr, block) {
1608*61046927SAndroid Build Coastguard Worker state->instr = instr;
1609*61046927SAndroid Build Coastguard Worker if (instr->type == nir_instr_type_phi) {
1610*61046927SAndroid Build Coastguard Worker nir_phi_instr *phi = nir_instr_as_phi(instr);
1611*61046927SAndroid Build Coastguard Worker nir_foreach_phi_src(src, phi) {
1612*61046927SAndroid Build Coastguard Worker validate_assert(state,
1613*61046927SAndroid Build Coastguard Worker nir_block_dominates(src->src.ssa->parent_instr->block,
1614*61046927SAndroid Build Coastguard Worker src->pred));
1615*61046927SAndroid Build Coastguard Worker }
1616*61046927SAndroid Build Coastguard Worker } else {
1617*61046927SAndroid Build Coastguard Worker nir_foreach_src(instr, validate_src_dominance, state);
1618*61046927SAndroid Build Coastguard Worker }
1619*61046927SAndroid Build Coastguard Worker nir_foreach_def(instr, validate_ssa_def_dominance, state);
1620*61046927SAndroid Build Coastguard Worker }
1621*61046927SAndroid Build Coastguard Worker }
1622*61046927SAndroid Build Coastguard Worker }
1623*61046927SAndroid Build Coastguard Worker
1624*61046927SAndroid Build Coastguard Worker static void
validate_function_impl(nir_function_impl * impl,validate_state * state)1625*61046927SAndroid Build Coastguard Worker validate_function_impl(nir_function_impl *impl, validate_state *state)
1626*61046927SAndroid Build Coastguard Worker {
1627*61046927SAndroid Build Coastguard Worker validate_assert(state, impl->function->impl == impl);
1628*61046927SAndroid Build Coastguard Worker validate_assert(state, impl->cf_node.parent == NULL);
1629*61046927SAndroid Build Coastguard Worker
1630*61046927SAndroid Build Coastguard Worker if (impl->preamble) {
1631*61046927SAndroid Build Coastguard Worker validate_assert(state, impl->function->is_entrypoint);
1632*61046927SAndroid Build Coastguard Worker validate_assert(state, impl->preamble->is_preamble);
1633*61046927SAndroid Build Coastguard Worker }
1634*61046927SAndroid Build Coastguard Worker
1635*61046927SAndroid Build Coastguard Worker validate_assert(state, exec_list_is_empty(&impl->end_block->instr_list));
1636*61046927SAndroid Build Coastguard Worker validate_assert(state, impl->end_block->successors[0] == NULL);
1637*61046927SAndroid Build Coastguard Worker validate_assert(state, impl->end_block->successors[1] == NULL);
1638*61046927SAndroid Build Coastguard Worker
1639*61046927SAndroid Build Coastguard Worker state->impl = impl;
1640*61046927SAndroid Build Coastguard Worker state->parent_node = &impl->cf_node;
1641*61046927SAndroid Build Coastguard Worker
1642*61046927SAndroid Build Coastguard Worker exec_list_validate(&impl->locals);
1643*61046927SAndroid Build Coastguard Worker nir_foreach_function_temp_variable(var, impl) {
1644*61046927SAndroid Build Coastguard Worker validate_var_decl(var, nir_var_function_temp, state);
1645*61046927SAndroid Build Coastguard Worker }
1646*61046927SAndroid Build Coastguard Worker
1647*61046927SAndroid Build Coastguard Worker state->ssa_defs_found = reralloc(state->mem_ctx, state->ssa_defs_found,
1648*61046927SAndroid Build Coastguard Worker BITSET_WORD, BITSET_WORDS(impl->ssa_alloc));
1649*61046927SAndroid Build Coastguard Worker memset(state->ssa_defs_found, 0, BITSET_WORDS(impl->ssa_alloc) * sizeof(BITSET_WORD));
1650*61046927SAndroid Build Coastguard Worker
1651*61046927SAndroid Build Coastguard Worker _mesa_set_clear(state->blocks, NULL);
1652*61046927SAndroid Build Coastguard Worker _mesa_set_resize(state->blocks, impl->num_blocks);
1653*61046927SAndroid Build Coastguard Worker if (impl->structured)
1654*61046927SAndroid Build Coastguard Worker collect_blocks(&impl->body, state);
1655*61046927SAndroid Build Coastguard Worker else
1656*61046927SAndroid Build Coastguard Worker collect_unstructured_blocks(impl, state);
1657*61046927SAndroid Build Coastguard Worker _mesa_set_add(state->blocks, impl->end_block);
1658*61046927SAndroid Build Coastguard Worker validate_assert(state, !exec_list_is_empty(&impl->body));
1659*61046927SAndroid Build Coastguard Worker foreach_list_typed(nir_cf_node, node, node, &impl->body) {
1660*61046927SAndroid Build Coastguard Worker validate_cf_node(node, state);
1661*61046927SAndroid Build Coastguard Worker }
1662*61046927SAndroid Build Coastguard Worker validate_end_block(impl->end_block, state);
1663*61046927SAndroid Build Coastguard Worker
1664*61046927SAndroid Build Coastguard Worker /* We must have seen every source by now. This also means that we've untagged
1665*61046927SAndroid Build Coastguard Worker * every source, so we have valid (unaugmented) NIR once again.
1666*61046927SAndroid Build Coastguard Worker */
1667*61046927SAndroid Build Coastguard Worker validate_assert(state, state->nr_tagged_srcs == 0);
1668*61046927SAndroid Build Coastguard Worker
1669*61046927SAndroid Build Coastguard Worker static int validate_dominance = -1;
1670*61046927SAndroid Build Coastguard Worker if (validate_dominance < 0) {
1671*61046927SAndroid Build Coastguard Worker validate_dominance =
1672*61046927SAndroid Build Coastguard Worker NIR_DEBUG(VALIDATE_SSA_DOMINANCE);
1673*61046927SAndroid Build Coastguard Worker }
1674*61046927SAndroid Build Coastguard Worker if (validate_dominance) {
1675*61046927SAndroid Build Coastguard Worker memset(state->ssa_defs_found, 0, BITSET_WORDS(impl->ssa_alloc) * sizeof(BITSET_WORD));
1676*61046927SAndroid Build Coastguard Worker validate_ssa_dominance(impl, state);
1677*61046927SAndroid Build Coastguard Worker }
1678*61046927SAndroid Build Coastguard Worker }
1679*61046927SAndroid Build Coastguard Worker
1680*61046927SAndroid Build Coastguard Worker static void
validate_function(nir_function * func,validate_state * state)1681*61046927SAndroid Build Coastguard Worker validate_function(nir_function *func, validate_state *state)
1682*61046927SAndroid Build Coastguard Worker {
1683*61046927SAndroid Build Coastguard Worker if (func->impl != NULL) {
1684*61046927SAndroid Build Coastguard Worker validate_assert(state, func->impl->function == func);
1685*61046927SAndroid Build Coastguard Worker validate_function_impl(func->impl, state);
1686*61046927SAndroid Build Coastguard Worker }
1687*61046927SAndroid Build Coastguard Worker }
1688*61046927SAndroid Build Coastguard Worker
1689*61046927SAndroid Build Coastguard Worker static void
init_validate_state(validate_state * state)1690*61046927SAndroid Build Coastguard Worker init_validate_state(validate_state *state)
1691*61046927SAndroid Build Coastguard Worker {
1692*61046927SAndroid Build Coastguard Worker state->mem_ctx = ralloc_context(NULL);
1693*61046927SAndroid Build Coastguard Worker state->ssa_defs_found = NULL;
1694*61046927SAndroid Build Coastguard Worker state->blocks = _mesa_pointer_set_create(state->mem_ctx);
1695*61046927SAndroid Build Coastguard Worker state->var_defs = _mesa_pointer_hash_table_create(state->mem_ctx);
1696*61046927SAndroid Build Coastguard Worker state->errors = _mesa_pointer_hash_table_create(state->mem_ctx);
1697*61046927SAndroid Build Coastguard Worker state->nr_tagged_srcs = 0;
1698*61046927SAndroid Build Coastguard Worker
1699*61046927SAndroid Build Coastguard Worker state->loop = NULL;
1700*61046927SAndroid Build Coastguard Worker state->in_loop_continue_construct = false;
1701*61046927SAndroid Build Coastguard Worker state->instr = NULL;
1702*61046927SAndroid Build Coastguard Worker state->var = NULL;
1703*61046927SAndroid Build Coastguard Worker }
1704*61046927SAndroid Build Coastguard Worker
1705*61046927SAndroid Build Coastguard Worker static void
destroy_validate_state(validate_state * state)1706*61046927SAndroid Build Coastguard Worker destroy_validate_state(validate_state *state)
1707*61046927SAndroid Build Coastguard Worker {
1708*61046927SAndroid Build Coastguard Worker ralloc_free(state->mem_ctx);
1709*61046927SAndroid Build Coastguard Worker }
1710*61046927SAndroid Build Coastguard Worker
1711*61046927SAndroid Build Coastguard Worker simple_mtx_t fail_dump_mutex = SIMPLE_MTX_INITIALIZER;
1712*61046927SAndroid Build Coastguard Worker
1713*61046927SAndroid Build Coastguard Worker static void
dump_errors(validate_state * state,const char * when)1714*61046927SAndroid Build Coastguard Worker dump_errors(validate_state *state, const char *when)
1715*61046927SAndroid Build Coastguard Worker {
1716*61046927SAndroid Build Coastguard Worker struct hash_table *errors = state->errors;
1717*61046927SAndroid Build Coastguard Worker
1718*61046927SAndroid Build Coastguard Worker /* Lock around dumping so that we get clean dumps in a multi-threaded
1719*61046927SAndroid Build Coastguard Worker * scenario
1720*61046927SAndroid Build Coastguard Worker */
1721*61046927SAndroid Build Coastguard Worker simple_mtx_lock(&fail_dump_mutex);
1722*61046927SAndroid Build Coastguard Worker
1723*61046927SAndroid Build Coastguard Worker if (when) {
1724*61046927SAndroid Build Coastguard Worker fprintf(stderr, "NIR validation failed %s\n", when);
1725*61046927SAndroid Build Coastguard Worker fprintf(stderr, "%d errors:\n", _mesa_hash_table_num_entries(errors));
1726*61046927SAndroid Build Coastguard Worker } else {
1727*61046927SAndroid Build Coastguard Worker fprintf(stderr, "NIR validation failed with %d errors:\n",
1728*61046927SAndroid Build Coastguard Worker _mesa_hash_table_num_entries(errors));
1729*61046927SAndroid Build Coastguard Worker }
1730*61046927SAndroid Build Coastguard Worker
1731*61046927SAndroid Build Coastguard Worker nir_print_shader_annotated(state->shader, stderr, errors);
1732*61046927SAndroid Build Coastguard Worker
1733*61046927SAndroid Build Coastguard Worker if (_mesa_hash_table_num_entries(errors) > 0) {
1734*61046927SAndroid Build Coastguard Worker fprintf(stderr, "%d additional errors:\n",
1735*61046927SAndroid Build Coastguard Worker _mesa_hash_table_num_entries(errors));
1736*61046927SAndroid Build Coastguard Worker hash_table_foreach(errors, entry) {
1737*61046927SAndroid Build Coastguard Worker fprintf(stderr, "%s\n", (char *)entry->data);
1738*61046927SAndroid Build Coastguard Worker }
1739*61046927SAndroid Build Coastguard Worker }
1740*61046927SAndroid Build Coastguard Worker
1741*61046927SAndroid Build Coastguard Worker simple_mtx_unlock(&fail_dump_mutex);
1742*61046927SAndroid Build Coastguard Worker
1743*61046927SAndroid Build Coastguard Worker abort();
1744*61046927SAndroid Build Coastguard Worker }
1745*61046927SAndroid Build Coastguard Worker
1746*61046927SAndroid Build Coastguard Worker void
nir_validate_shader(nir_shader * shader,const char * when)1747*61046927SAndroid Build Coastguard Worker nir_validate_shader(nir_shader *shader, const char *when)
1748*61046927SAndroid Build Coastguard Worker {
1749*61046927SAndroid Build Coastguard Worker if (NIR_DEBUG(NOVALIDATE))
1750*61046927SAndroid Build Coastguard Worker return;
1751*61046927SAndroid Build Coastguard Worker
1752*61046927SAndroid Build Coastguard Worker validate_state state;
1753*61046927SAndroid Build Coastguard Worker init_validate_state(&state);
1754*61046927SAndroid Build Coastguard Worker
1755*61046927SAndroid Build Coastguard Worker state.shader = shader;
1756*61046927SAndroid Build Coastguard Worker
1757*61046927SAndroid Build Coastguard Worker nir_variable_mode valid_modes =
1758*61046927SAndroid Build Coastguard Worker nir_var_shader_in |
1759*61046927SAndroid Build Coastguard Worker nir_var_shader_out |
1760*61046927SAndroid Build Coastguard Worker nir_var_shader_temp |
1761*61046927SAndroid Build Coastguard Worker nir_var_uniform |
1762*61046927SAndroid Build Coastguard Worker nir_var_mem_ubo |
1763*61046927SAndroid Build Coastguard Worker nir_var_system_value |
1764*61046927SAndroid Build Coastguard Worker nir_var_mem_ssbo |
1765*61046927SAndroid Build Coastguard Worker nir_var_mem_shared |
1766*61046927SAndroid Build Coastguard Worker nir_var_mem_global |
1767*61046927SAndroid Build Coastguard Worker nir_var_mem_push_const |
1768*61046927SAndroid Build Coastguard Worker nir_var_mem_constant |
1769*61046927SAndroid Build Coastguard Worker nir_var_image;
1770*61046927SAndroid Build Coastguard Worker
1771*61046927SAndroid Build Coastguard Worker if (gl_shader_stage_is_callable(shader->info.stage))
1772*61046927SAndroid Build Coastguard Worker valid_modes |= nir_var_shader_call_data;
1773*61046927SAndroid Build Coastguard Worker
1774*61046927SAndroid Build Coastguard Worker if (shader->info.stage == MESA_SHADER_ANY_HIT ||
1775*61046927SAndroid Build Coastguard Worker shader->info.stage == MESA_SHADER_CLOSEST_HIT ||
1776*61046927SAndroid Build Coastguard Worker shader->info.stage == MESA_SHADER_INTERSECTION)
1777*61046927SAndroid Build Coastguard Worker valid_modes |= nir_var_ray_hit_attrib;
1778*61046927SAndroid Build Coastguard Worker
1779*61046927SAndroid Build Coastguard Worker if (shader->info.stage == MESA_SHADER_TASK ||
1780*61046927SAndroid Build Coastguard Worker shader->info.stage == MESA_SHADER_MESH)
1781*61046927SAndroid Build Coastguard Worker valid_modes |= nir_var_mem_task_payload;
1782*61046927SAndroid Build Coastguard Worker
1783*61046927SAndroid Build Coastguard Worker if (shader->info.stage == MESA_SHADER_COMPUTE)
1784*61046927SAndroid Build Coastguard Worker valid_modes |= nir_var_mem_node_payload |
1785*61046927SAndroid Build Coastguard Worker nir_var_mem_node_payload_in;
1786*61046927SAndroid Build Coastguard Worker
1787*61046927SAndroid Build Coastguard Worker exec_list_validate(&shader->variables);
1788*61046927SAndroid Build Coastguard Worker nir_foreach_variable_in_shader(var, shader)
1789*61046927SAndroid Build Coastguard Worker validate_var_decl(var, valid_modes, &state);
1790*61046927SAndroid Build Coastguard Worker
1791*61046927SAndroid Build Coastguard Worker exec_list_validate(&shader->functions);
1792*61046927SAndroid Build Coastguard Worker foreach_list_typed(nir_function, func, node, &shader->functions) {
1793*61046927SAndroid Build Coastguard Worker validate_function(func, &state);
1794*61046927SAndroid Build Coastguard Worker }
1795*61046927SAndroid Build Coastguard Worker
1796*61046927SAndroid Build Coastguard Worker if (shader->xfb_info != NULL) {
1797*61046927SAndroid Build Coastguard Worker /* At least validate that, if nir_shader::xfb_info exists, the shader
1798*61046927SAndroid Build Coastguard Worker * has real transform feedback going on.
1799*61046927SAndroid Build Coastguard Worker */
1800*61046927SAndroid Build Coastguard Worker validate_assert(&state, shader->info.stage == MESA_SHADER_VERTEX ||
1801*61046927SAndroid Build Coastguard Worker shader->info.stage == MESA_SHADER_TESS_EVAL ||
1802*61046927SAndroid Build Coastguard Worker shader->info.stage == MESA_SHADER_GEOMETRY);
1803*61046927SAndroid Build Coastguard Worker validate_assert(&state, shader->xfb_info->buffers_written != 0);
1804*61046927SAndroid Build Coastguard Worker validate_assert(&state, shader->xfb_info->streams_written != 0);
1805*61046927SAndroid Build Coastguard Worker validate_assert(&state, shader->xfb_info->output_count > 0);
1806*61046927SAndroid Build Coastguard Worker }
1807*61046927SAndroid Build Coastguard Worker
1808*61046927SAndroid Build Coastguard Worker if (_mesa_hash_table_num_entries(state.errors) > 0)
1809*61046927SAndroid Build Coastguard Worker dump_errors(&state, when);
1810*61046927SAndroid Build Coastguard Worker
1811*61046927SAndroid Build Coastguard Worker destroy_validate_state(&state);
1812*61046927SAndroid Build Coastguard Worker }
1813*61046927SAndroid Build Coastguard Worker
1814*61046927SAndroid Build Coastguard Worker void
nir_validate_ssa_dominance(nir_shader * shader,const char * when)1815*61046927SAndroid Build Coastguard Worker nir_validate_ssa_dominance(nir_shader *shader, const char *when)
1816*61046927SAndroid Build Coastguard Worker {
1817*61046927SAndroid Build Coastguard Worker if (NIR_DEBUG(NOVALIDATE))
1818*61046927SAndroid Build Coastguard Worker return;
1819*61046927SAndroid Build Coastguard Worker
1820*61046927SAndroid Build Coastguard Worker validate_state state;
1821*61046927SAndroid Build Coastguard Worker init_validate_state(&state);
1822*61046927SAndroid Build Coastguard Worker
1823*61046927SAndroid Build Coastguard Worker state.shader = shader;
1824*61046927SAndroid Build Coastguard Worker
1825*61046927SAndroid Build Coastguard Worker nir_foreach_function_impl(impl, shader) {
1826*61046927SAndroid Build Coastguard Worker state.ssa_defs_found = reralloc(state.mem_ctx, state.ssa_defs_found,
1827*61046927SAndroid Build Coastguard Worker BITSET_WORD,
1828*61046927SAndroid Build Coastguard Worker BITSET_WORDS(impl->ssa_alloc));
1829*61046927SAndroid Build Coastguard Worker memset(state.ssa_defs_found, 0, BITSET_WORDS(impl->ssa_alloc) * sizeof(BITSET_WORD));
1830*61046927SAndroid Build Coastguard Worker
1831*61046927SAndroid Build Coastguard Worker state.impl = impl;
1832*61046927SAndroid Build Coastguard Worker validate_ssa_dominance(impl, &state);
1833*61046927SAndroid Build Coastguard Worker }
1834*61046927SAndroid Build Coastguard Worker
1835*61046927SAndroid Build Coastguard Worker if (_mesa_hash_table_num_entries(state.errors) > 0)
1836*61046927SAndroid Build Coastguard Worker dump_errors(&state, when);
1837*61046927SAndroid Build Coastguard Worker
1838*61046927SAndroid Build Coastguard Worker destroy_validate_state(&state);
1839*61046927SAndroid Build Coastguard Worker }
1840*61046927SAndroid Build Coastguard Worker
1841*61046927SAndroid Build Coastguard Worker #endif /* NDEBUG */
1842