Home | History | Annotate | Download | only in vc4
      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
     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 
     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