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 27static void 28fail_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 36void 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