1 /*
2  * Copyright © 2016 Broadcom Limited
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "vc4_qir.h"
25 #include "vc4_qpu.h"
26 
27 static void
fail_instr(struct vc4_compile * c,struct qinst * inst,const char * msg)28 fail_instr(struct vc4_compile *c, struct qinst *inst, const char *msg)
29 {
30         fprintf(stderr, "qir_validate: %s: ", msg);
31         qir_dump_inst(c, inst);
32         fprintf(stderr, "\n");
33         abort();
34 }
35 
qir_validate(struct vc4_compile * c)36 void qir_validate(struct vc4_compile *c)
37 {
38         bool already_assigned[c->num_temps];
39         memset(&already_assigned, 0, sizeof(already_assigned));
40 
41         /* We don't want to do validation in release builds, but we want to
42          * keep compiling the validation code to make sure it doesn't get
43          * broken.
44          */
45 #ifndef DEBUG
46         return;
47 #endif
48 
49         for (int i = 0; i < c->num_temps; i++) {
50                 struct qinst *def = c->defs[i];
51 
52                 if (def && def->cond != QPU_COND_ALWAYS)
53                         fail_instr(c, def, "SSA def with condition");
54         }
55 
56         qir_for_each_inst_inorder(inst, c) {
57                 switch (inst->dst.file) {
58                 case QFILE_TEMP:
59                         if (inst->dst.index >= c->num_temps)
60                                 fail_instr(c, inst, "bad temp index");
61 
62                         if (c->defs[inst->dst.index] &&
63                             already_assigned[inst->dst.index]) {
64                                 fail_instr(c, inst, "Re-assignment of SSA value");
65                         }
66                         already_assigned[inst->dst.index] = true;
67                         break;
68 
69                 case QFILE_NULL:
70                 case QFILE_VPM:
71                 case QFILE_TLB_COLOR_WRITE:
72                 case QFILE_TLB_COLOR_WRITE_MS:
73                 case QFILE_TLB_Z_WRITE:
74                 case QFILE_TLB_STENCIL_SETUP:
75                         break;
76 
77                 case QFILE_VARY:
78                 case QFILE_UNIF:
79                 case QFILE_FRAG_X:
80                 case QFILE_FRAG_Y:
81                 case QFILE_FRAG_REV_FLAG:
82                 case QFILE_QPU_ELEMENT:
83                 case QFILE_SMALL_IMM:
84                 case QFILE_LOAD_IMM:
85                         fail_instr(c, inst, "Bad dest file");
86                         break;
87 
88                 case QFILE_TEX_S:
89                 case QFILE_TEX_T:
90                 case QFILE_TEX_R:
91                 case QFILE_TEX_B:
92                         if (inst->src[qir_get_tex_uniform_src(inst)].file !=
93                             QFILE_UNIF) {
94                                 fail_instr(c, inst,
95                                            "tex op missing implicit uniform");
96                         }
97                         break;
98 
99                 case QFILE_TEX_S_DIRECT:
100                         if (inst->op != QOP_ADD) {
101                                 fail_instr(c, inst,
102                                            "kernel validation requires that "
103                                            "direct texture lookups use an ADD");
104                         }
105                         break;
106                 }
107 
108                 for (int i = 0; i < qir_get_nsrc(inst); i++) {
109                         struct qreg src = inst->src[i];
110 
111                         switch (src.file) {
112                         case QFILE_TEMP:
113                                 if (src.index >= c->num_temps)
114                                         fail_instr(c, inst, "bad temp index");
115                                 break;
116 
117                         case QFILE_VARY:
118                         case QFILE_UNIF:
119                         case QFILE_VPM:
120                         case QFILE_LOAD_IMM:
121                         case QFILE_QPU_ELEMENT:
122                                 break;
123 
124                         case QFILE_SMALL_IMM:
125                                 if (qpu_encode_small_immediate(src.index) == ~0)
126                                         fail_instr(c, inst, "bad small immediate");
127                                 break;
128 
129                         case QFILE_FRAG_X:
130                         case QFILE_FRAG_Y:
131                         case QFILE_FRAG_REV_FLAG:
132                                 if (c->stage != QSTAGE_FRAG)
133                                         fail_instr(c, inst, "frag access in VS/CS");
134                                 break;
135 
136                         case QFILE_NULL:
137                         case QFILE_TLB_COLOR_WRITE:
138                         case QFILE_TLB_COLOR_WRITE_MS:
139                         case QFILE_TLB_Z_WRITE:
140                         case QFILE_TLB_STENCIL_SETUP:
141                         case QFILE_TEX_S_DIRECT:
142                         case QFILE_TEX_S:
143                         case QFILE_TEX_T:
144                         case QFILE_TEX_R:
145                         case QFILE_TEX_B:
146                                 fail_instr(c, inst, "Bad src file");
147                                 break;
148                         }
149                 }
150         }
151 }
152