static boolean epilog( struct tgsi_iterate_context *iter ) { struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter; uint file; /* There must be an END instruction somewhere. */ if (ctx->index_of_END == ~0) { report_error( ctx, "Missing END instruction" ); } /* Check if all declared registers were used. */ for (file = TGSI_FILE_NULL; file < TGSI_FILE_COUNT; file++) { uint i; for (i = 0; i < MAX_REGISTERS; i++) { if (is_register_declared( ctx, file, i ) && !is_register_used( ctx, file, i ) && !ctx->regs_ind_used[file]) { report_warning( ctx, "%s[%u]: Register never used", file_names[file], i ); } } } /* Print totals, if any. */ if (ctx->errors || ctx->warnings) debug_printf( "%u errors, %u warnings\n", ctx->errors, ctx->warnings ); return TRUE; }
static boolean iter_declaration( struct tgsi_iterate_context *iter, struct tgsi_full_declaration *decl ) { struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter; uint file; uint i; /* No declarations allowed after the first instruction. */ if (ctx->num_instructions > 0) report_error( ctx, "Instruction expected but declaration found" ); /* Check registers' validity. * Mark the registers as declared. */ file = decl->Declaration.File; if (!check_file_name( ctx, file )) return TRUE; for (i = decl->DeclarationRange.First; i <= decl->DeclarationRange.Last; i++) { if (is_register_declared( ctx, file, i )) report_error( ctx, "%s[%u]: The same register declared more than once", file_names[file], i ); ctx->regs_decl[file][i / BITS_IN_REG_FLAG] |= (1 << (i % BITS_IN_REG_FLAG)); } return TRUE; }
static boolean check_register_usage( struct sanity_check_ctx *ctx, uint file, int index, const char *name, boolean indirect_access ) { if (!check_file_name( ctx, file )) return FALSE; if (indirect_access) { /* Note that 'index' is an offset relative to the value of the * address register. No range checking done here. */ if (!is_any_register_declared( ctx, file )) report_error( ctx, "%s: Undeclared %s register", file_names[file], name ); ctx->regs_ind_used[file] = TRUE; } else { if (index < 0 || index >= MAX_REGISTERS) { report_error( ctx, "%s[%d]: Invalid %s index", file_names[file], index, name ); return FALSE; } if (!is_register_declared( ctx, file, index )) report_error( ctx, "%s[%d]: Undeclared %s register", file_names[file], index, name ); ctx->regs_used[file][index / BITS_IN_REG_FLAG] |= (1 << (index % BITS_IN_REG_FLAG)); } return TRUE; }
static void check_and_declare(struct sanity_check_ctx *ctx, scan_register *reg) { if (is_register_declared( ctx, reg)) report_error( ctx, "%s[%u]: The same register declared more than once", file_names[reg->file], reg->indices[0] ); cso_hash_insert(ctx->regs_decl, scan_register_key(reg), reg); }
static boolean check_register_usage( struct sanity_check_ctx *ctx, scan_register *reg, const char *name, boolean indirect_access ) { if (!check_file_name( ctx, reg->file )) { FREE(reg); return FALSE; } if (indirect_access) { /* Note that 'index' is an offset relative to the value of the * address register. No range checking done here.*/ reg->indices[0] = 0; reg->indices[1] = 0; if (!is_any_register_declared( ctx, reg->file )) report_error( ctx, "%s: Undeclared %s register", file_names[reg->file], name ); if (!is_ind_register_used(ctx, reg)) cso_hash_insert(ctx->regs_ind_used, reg->file, reg); else FREE(reg); } else { if (!is_register_declared( ctx, reg )) { if (reg->dimensions == 2) { report_error( ctx, "%s[%d][%d]: Undeclared %s register", file_names[reg->file], reg->indices[0], reg->indices[1], name ); } else { report_error( ctx, "%s[%d]: Undeclared %s register", file_names[reg->file], reg->indices[0], name ); } } if (!is_register_used( ctx, reg )) cso_hash_insert(ctx->regs_used, scan_register_key(reg), reg); else FREE(reg); } return TRUE; }