• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2024 Imagination Technologies Ltd.
3  *
4  * SPDX-License-Identifier: MIT
5  */
6 
7 /**
8  * \file pco_validate.c
9  *
10  * \brief PCO validation functions.
11  */
12 
13 #include "pco.h"
14 #include "pco_internal.h"
15 #include "util/bitset.h"
16 #include "util/macros.h"
17 #include "util/ralloc.h"
18 
19 #include <inttypes.h>
20 #include <stdio.h>
21 
22 enum ref_cursor {
23    REF_CURSOR_NONE,
24    REF_CURSOR_INSTR_DEST,
25    REF_CURSOR_INSTR_SRC,
26    REF_CURSOR_IGRP_SRC,
27    REF_CURSOR_IGRP_ISS,
28    REF_CURSOR_IGRP_DEST,
29 };
30 
31 /** Validation state. */
32 struct val_state {
33    const char *when; /** Description of the validation being done. */
34    pco_shader *shader; /** The shader being validated. */
35    pco_func *func; /** Current function being validated. */
36    pco_cf_node *cf_node; /** Current cf node being validated. */
37    pco_igrp *igrp; /** Current instruction group being validated. */
38    enum pco_op_phase phase; /** Phase of the instruction being validated. */
39    pco_instr *instr; /** Current instruction being validated. */
40    pco_ref *ref; /** Current reference being validated. */
41    enum ref_cursor ref_cursor; /** Current reference cursor. */
42 };
43 
44 /**
45  * \brief Asserts a condition, printing an error and aborting on failure.
46  *
47  * \param[in] state Validation state.
48  * \param[in] cond Assertion condition.
49  * \param[in] cond_str Assertion condition string.
50  * \param[in] fmt Format string.
51  */
pco_assert(struct val_state * state,bool cond,const char * cond_str,const char * fmt,...)52 static void pco_assert(struct val_state *state,
53                        bool cond,
54                        const char *cond_str,
55                        const char *fmt,
56                        ...)
57 {
58    if (cond)
59       return;
60 
61    printf("PCO validation failed with assertion \"%s\" - ", cond_str);
62 
63    va_list args;
64    va_start(args, fmt);
65    vprintf(fmt, args);
66    va_end(args);
67 
68    printf(" - while validating");
69 
70    if (state->ref_cursor != REF_CURSOR_NONE) {
71       switch (state->ref_cursor) {
72       case REF_CURSOR_INSTR_DEST:
73          printf(" instr dest #%" PRIuPTR, state->ref - state->instr->dest);
74          break;
75 
76       case REF_CURSOR_INSTR_SRC:
77          printf(" instr src #%" PRIuPTR, state->ref - state->instr->src);
78          break;
79 
80       default:
81          unreachable();
82       }
83 
84       printf(" (");
85       pco_print_ref(state->shader, *state->ref);
86       printf(")");
87    }
88 
89    if (state->cf_node) {
90       printf(" ");
91       pco_print_cf_node_name(state->shader, state->cf_node);
92    }
93 
94    if (state->igrp) {
95       printf(" igrp ");
96       pco_print_igrp(state->shader, state->igrp);
97    }
98 
99    if (state->instr) {
100       printf(" instr ");
101       pco_print_instr(state->shader, state->instr);
102    }
103 
104    if (state->func) {
105       printf(" ");
106       pco_print_cf_node_name(state->shader, &state->func->cf_node);
107    }
108 
109    printf(".\n");
110 
111    pco_print_shader_info(state->shader);
112 
113    abort();
114 }
115 
116 #define PCO_ASSERT(state, cond, fmt, ...) \
117    pco_assert(state, cond, #cond, fmt, ##__VA_ARGS__)
118 
119 /**
120  * \brief Validates SSA assignments and uses.
121  *
122  * \param[in,out] state Validation state.
123  */
pco_validate_ssa(struct val_state * state)124 static void pco_validate_ssa(struct val_state *state)
125 {
126    BITSET_WORD *ssa_writes;
127    pco_foreach_func_in_shader (func, state->shader) {
128       state->func = func;
129 
130       ssa_writes = rzalloc_array_size(NULL,
131                                       sizeof(*ssa_writes),
132                                       BITSET_WORDS(func->next_ssa));
133 
134       /* Ensure sources have been defined before they're used. */
135       state->ref_cursor = REF_CURSOR_INSTR_SRC;
136       pco_foreach_instr_in_func (instr, func) {
137          state->cf_node = &instr->parent_block->cf_node;
138          state->instr = instr;
139          pco_foreach_instr_src_ssa (psrc, instr) {
140             state->ref = psrc;
141             PCO_ASSERT(state,
142                        BITSET_TEST(ssa_writes, psrc->val),
143                        "SSA source used before being defined");
144          }
145 
146          /* Ensure destinations are only defined once. */
147          state->ref_cursor = REF_CURSOR_INSTR_DEST;
148          pco_foreach_instr_dest_ssa (pdest, instr) {
149             state->ref = pdest;
150             PCO_ASSERT(state,
151                        !BITSET_TEST(ssa_writes, pdest->val),
152                        "SSA destination defined to more than once");
153             BITSET_SET(ssa_writes, pdest->val);
154          }
155       }
156 
157       ralloc_free(ssa_writes);
158 
159       state->func = NULL;
160       state->ref = NULL;
161    }
162 }
163 
164 /**
165  * \brief Validates a PCO shader.
166  *
167  * \param[in] shader PCO shader.
168  * \param[in] when When the validation check is being run.
169  */
pco_validate_shader(UNUSED pco_shader * shader,UNUSED const char * when)170 void pco_validate_shader(UNUSED pco_shader *shader, UNUSED const char *when)
171 {
172 #ifndef NDEBUG
173    if (PCO_DEBUG(VAL_SKIP))
174       return;
175 
176    struct val_state state = {
177       .when = when,
178       .shader = shader,
179       .phase = -1,
180    };
181 
182    if (!shader->is_grouped)
183       pco_validate_ssa(&state);
184 
185    puts("finishme: pco_validate_shader");
186 #endif /* NDEBUG */
187 }
188