tgsi_sanity.c File Reference

Include dependency graph for tgsi_sanity.c:

Go to the source code of this file.

Data Structures

struct  sanity_check_ctx

Defines

#define BITS_IN_REG_FLAG   (sizeof( reg_flag ) * 8)
#define MAX_REGISTERS   512
#define MAX_REG_FLAGS   ((MAX_REGISTERS + BITS_IN_REG_FLAG - 1) / BITS_IN_REG_FLAG)

Typedefs

typedef uint reg_flag

Functions

static void report_error (struct sanity_check_ctx *ctx, const char *format,...)
static void report_warning (struct sanity_check_ctx *ctx, const char *format,...)
static boolean check_file_name (struct sanity_check_ctx *ctx, uint file)
static boolean is_register_declared (struct sanity_check_ctx *ctx, uint file, int index)
static boolean is_any_register_declared (struct sanity_check_ctx *ctx, uint file)
static boolean is_register_used (struct sanity_check_ctx *ctx, uint file, int index)
static boolean check_register_usage (struct sanity_check_ctx *ctx, uint file, int index, const char *name, boolean indirect_access)
static boolean iter_instruction (struct tgsi_iterate_context *iter, struct tgsi_full_instruction *inst)
static boolean iter_declaration (struct tgsi_iterate_context *iter, struct tgsi_full_declaration *decl)
static boolean iter_immediate (struct tgsi_iterate_context *iter, struct tgsi_full_immediate *imm)
static boolean epilog (struct tgsi_iterate_context *iter)
boolean tgsi_sanity_check (struct tgsi_token *tokens)

Variables

static const char * file_names [TGSI_FILE_COUNT]


Define Documentation

#define BITS_IN_REG_FLAG   (sizeof( reg_flag ) * 8)

Definition at line 36 of file tgsi_sanity.c.

#define MAX_REG_FLAGS   ((MAX_REGISTERS + BITS_IN_REG_FLAG - 1) / BITS_IN_REG_FLAG)

Definition at line 39 of file tgsi_sanity.c.

#define MAX_REGISTERS   512

Definition at line 38 of file tgsi_sanity.c.


Typedef Documentation

typedef uint reg_flag

Definition at line 34 of file tgsi_sanity.c.


Function Documentation

static boolean check_file_name ( struct sanity_check_ctx ctx,
uint  file 
) [static]

Definition at line 89 of file tgsi_sanity.c.

References FALSE, report_error(), TGSI_FILE_COUNT, and TRUE.

00092 {
00093    if (file <= TGSI_FILE_NULL || file >= TGSI_FILE_COUNT) {
00094       report_error( ctx, "(%u): Invalid register file name", file );
00095       return FALSE;
00096    }
00097    return TRUE;
00098 }

static boolean check_register_usage ( struct sanity_check_ctx ctx,
uint  file,
int  index,
const char *  name,
boolean  indirect_access 
) [static]

Definition at line 149 of file tgsi_sanity.c.

References BITS_IN_REG_FLAG, check_file_name(), FALSE, file_names, is_any_register_declared(), is_register_declared(), MAX_REGISTERS, sanity_check_ctx::regs_ind_used, sanity_check_ctx::regs_used, report_error(), and TRUE.

00155 {
00156    if (!check_file_name( ctx, file ))
00157       return FALSE;
00158 
00159    if (indirect_access) {
00160       /* Note that 'index' is an offset relative to the value of the
00161        * address register.  No range checking done here.
00162        */
00163       if (!is_any_register_declared( ctx, file ))
00164          report_error( ctx, "%s: Undeclared %s register", file_names[file], name );
00165       ctx->regs_ind_used[file] = TRUE;
00166    }
00167    else {
00168       if (index < 0 || index >= MAX_REGISTERS) {
00169          report_error( ctx, "%s[%d]: Invalid %s index", file_names[file], index, name );
00170          return FALSE;
00171       }
00172 
00173       if (!is_register_declared( ctx, file, index ))
00174          report_error( ctx, "%s[%d]: Undeclared %s register", file_names[file], index, name );
00175       ctx->regs_used[file][index / BITS_IN_REG_FLAG] |= (1 << (index % BITS_IN_REG_FLAG));
00176    }
00177    return TRUE;
00178 }

static boolean epilog ( struct tgsi_iterate_context iter  )  [static]

Definition at line 309 of file tgsi_sanity.c.

References debug_printf(), sanity_check_ctx::errors, file_names, sanity_check_ctx::index_of_END, is_register_declared(), is_register_used(), MAX_REGISTERS, sanity_check_ctx::regs_ind_used, report_error(), report_warning(), TGSI_FILE_COUNT, TGSI_FILE_NULL, TRUE, and sanity_check_ctx::warnings.

00311 {
00312    struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
00313    uint file;
00314 
00315    /* There must be an END instruction somewhere.
00316     */
00317    if (ctx->index_of_END == ~0) {
00318       report_error( ctx, "Missing END instruction" );
00319    }
00320 
00321    /* Check if all declared registers were used.
00322     */
00323    for (file = TGSI_FILE_NULL; file < TGSI_FILE_COUNT; file++) {
00324       uint i;
00325 
00326       for (i = 0; i < MAX_REGISTERS; i++) {
00327          if (is_register_declared( ctx, file, i ) && !is_register_used( ctx, file, i ) && !ctx->regs_ind_used[file]) {
00328             report_warning( ctx, "%s[%u]: Register never used", file_names[file], i );
00329          }
00330       }
00331    }
00332 
00333    /* Print totals, if any.
00334     */
00335    if (ctx->errors || ctx->warnings)
00336       debug_printf( "%u errors, %u warnings\n", ctx->errors, ctx->warnings );
00337 
00338    return TRUE;
00339 }

static boolean is_any_register_declared ( struct sanity_check_ctx ctx,
uint  file 
) [static]

Definition at line 112 of file tgsi_sanity.c.

References FALSE, MAX_REG_FLAGS, sanity_check_ctx::regs_decl, and TRUE.

00115 {
00116    uint i;
00117 
00118    for (i = 0; i < MAX_REG_FLAGS; i++)
00119       if (ctx->regs_decl[file][i])
00120          return TRUE;
00121    return FALSE;
00122 }

static boolean is_register_declared ( struct sanity_check_ctx ctx,
uint  file,
int  index 
) [static]

Definition at line 101 of file tgsi_sanity.c.

References assert, BITS_IN_REG_FLAG, FALSE, MAX_REGISTERS, sanity_check_ctx::regs_decl, and TRUE.

00105 {
00106    assert( index >= 0 && index < MAX_REGISTERS );
00107 
00108    return (ctx->regs_decl[file][index / BITS_IN_REG_FLAG] & (1 << (index % BITS_IN_REG_FLAG))) ? TRUE : FALSE;
00109 }

static boolean is_register_used ( struct sanity_check_ctx ctx,
uint  file,
int  index 
) [static]

Definition at line 125 of file tgsi_sanity.c.

References assert, BITS_IN_REG_FLAG, FALSE, MAX_REGISTERS, sanity_check_ctx::regs_used, and TRUE.

00129 {
00130    assert( index < MAX_REGISTERS );
00131 
00132    return (ctx->regs_used[file][index / BITS_IN_REG_FLAG] & (1 << (index % BITS_IN_REG_FLAG))) ? TRUE : FALSE;
00133 }

static boolean iter_declaration ( struct tgsi_iterate_context iter,
struct tgsi_full_declaration decl 
) [static]

Definition at line 251 of file tgsi_sanity.c.

References BITS_IN_REG_FLAG, check_file_name(), tgsi_full_declaration::Declaration, tgsi_full_declaration::DeclarationRange, tgsi_declaration::File, file_names, tgsi_declaration_range::First, is_register_declared(), sanity_check_ctx::num_instructions, sanity_check_ctx::regs_decl, report_error(), and TRUE.

00254 {
00255    struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
00256    uint file;
00257    uint i;
00258 
00259    /* No declarations allowed after the first instruction.
00260     */
00261    if (ctx->num_instructions > 0)
00262       report_error( ctx, "Instruction expected but declaration found" );
00263 
00264    /* Check registers' validity.
00265     * Mark the registers as declared.
00266     */
00267    file = decl->Declaration.File;
00268    if (!check_file_name( ctx, file ))
00269       return TRUE;
00270    for (i = decl->DeclarationRange.First; i <= decl->DeclarationRange.Last; i++) {
00271       if (is_register_declared( ctx, file, i ))
00272          report_error( ctx, "%s[%u]: The same register declared more than once", file_names[file], i );
00273       ctx->regs_decl[file][i / BITS_IN_REG_FLAG] |= (1 << (i % BITS_IN_REG_FLAG));
00274    }
00275 
00276    return TRUE;
00277 }

static boolean iter_immediate ( struct tgsi_iterate_context iter,
struct tgsi_full_immediate imm 
) [static]

Definition at line 280 of file tgsi_sanity.c.

References assert, BITS_IN_REG_FLAG, tgsi_immediate::DataType, tgsi_full_immediate::Immediate, MAX_REGISTERS, sanity_check_ctx::num_imms, sanity_check_ctx::num_instructions, sanity_check_ctx::regs_decl, report_error(), TGSI_FILE_IMMEDIATE, TGSI_IMM_FLOAT32, and TRUE.

00283 {
00284    struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
00285 
00286    assert( ctx->num_imms < MAX_REGISTERS );
00287 
00288    /* No immediates allowed after the first instruction.
00289     */
00290    if (ctx->num_instructions > 0)
00291       report_error( ctx, "Instruction expected but immediate found" );
00292 
00293    /* Mark the register as declared.
00294     */
00295    ctx->regs_decl[TGSI_FILE_IMMEDIATE][ctx->num_imms / BITS_IN_REG_FLAG] |= (1 << (ctx->num_imms % BITS_IN_REG_FLAG));
00296    ctx->num_imms++;
00297 
00298    /* Check data type validity.
00299     */
00300    if (imm->Immediate.DataType != TGSI_IMM_FLOAT32) {
00301       report_error( ctx, "(%u): Invalid immediate data type", imm->Immediate.DataType );
00302       return TRUE;
00303    }
00304 
00305    return TRUE;
00306 }

static boolean iter_instruction ( struct tgsi_iterate_context iter,
struct tgsi_full_instruction inst 
) [static]

Definition at line 181 of file tgsi_sanity.c.

References check_register_usage(), tgsi_full_dst_register::DstRegister, FALSE, tgsi_src_register::File, tgsi_dst_register::File, tgsi_full_instruction::FullDstRegisters, tgsi_full_instruction::FullSrcRegisters, tgsi_src_register::Index, tgsi_dst_register::Index, sanity_check_ctx::index_of_END, tgsi_src_register::Indirect, tgsi_full_instruction::Instruction, tgsi_opcode_info::mnemonic, tgsi_opcode_info::num_dst, sanity_check_ctx::num_instructions, tgsi_opcode_info::num_src, tgsi_instruction::NumDstRegs, tgsi_instruction::NumSrcRegs, tgsi_instruction::Opcode, report_error(), report_warning(), tgsi_full_src_register::SrcRegister, tgsi_full_src_register::SrcRegisterInd, TGSI_FILE_ADDRESS, TGSI_FILE_LOOP, tgsi_get_opcode_info(), TGSI_OPCODE_END, and TRUE.

00184 {
00185    struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
00186    const struct tgsi_opcode_info *info;
00187    uint i;
00188 
00189    if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
00190       if (ctx->index_of_END != ~0) {
00191          report_error( ctx, "Too many END instructions" );
00192       }
00193       ctx->index_of_END = ctx->num_instructions;
00194    }
00195 
00196    info = tgsi_get_opcode_info( inst->Instruction.Opcode );
00197    if (info == NULL) {
00198       report_error( ctx, "(%u): Invalid instruction opcode", inst->Instruction.Opcode );
00199       return TRUE;
00200    }
00201 
00202    if (info->num_dst != inst->Instruction.NumDstRegs) {
00203       report_error( ctx, "%s: Invalid number of destination operands, should be %u", info->mnemonic, info->num_dst );
00204    }
00205    if (info->num_src != inst->Instruction.NumSrcRegs) {
00206       report_error( ctx, "%s: Invalid number of source operands, should be %u", info->mnemonic, info->num_src );
00207    }
00208 
00209    /* Check destination and source registers' validity.
00210     * Mark the registers as used.
00211     */
00212    for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
00213       check_register_usage(
00214          ctx,
00215          inst->FullDstRegisters[i].DstRegister.File,
00216          inst->FullDstRegisters[i].DstRegister.Index,
00217          "destination",
00218          FALSE );
00219    }
00220    for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
00221       check_register_usage(
00222          ctx,
00223          inst->FullSrcRegisters[i].SrcRegister.File,
00224          inst->FullSrcRegisters[i].SrcRegister.Index,
00225          "source",
00226          (boolean)inst->FullSrcRegisters[i].SrcRegister.Indirect );
00227       if (inst->FullSrcRegisters[i].SrcRegister.Indirect) {
00228          uint file;
00229          int index;
00230 
00231          file = inst->FullSrcRegisters[i].SrcRegisterInd.File;
00232          index = inst->FullSrcRegisters[i].SrcRegisterInd.Index;
00233          check_register_usage(
00234             ctx,
00235             file,
00236             index,
00237             "indirect",
00238             FALSE );
00239          if (!(file == TGSI_FILE_ADDRESS || file == TGSI_FILE_LOOP) || index != 0) {
00240             report_warning(ctx, "Indirect register neither ADDR[0] nor LOOP[0]");
00241          }
00242       }
00243    }
00244 
00245    ctx->num_instructions++;
00246 
00247    return TRUE;
00248 }

static void report_error ( struct sanity_check_ctx ctx,
const char *  format,
  ... 
) [static]

Definition at line 57 of file tgsi_sanity.c.

References _debug_vprintf(), args, debug_printf(), and sanity_check_ctx::errors.

00061 {
00062    va_list args;
00063 
00064    debug_printf( "Error  : " );
00065    va_start( args, format );
00066    _debug_vprintf( format, args );
00067    va_end( args );
00068    debug_printf( "\n" );
00069    ctx->errors++;
00070 }

static void report_warning ( struct sanity_check_ctx ctx,
const char *  format,
  ... 
) [static]

Definition at line 73 of file tgsi_sanity.c.

References _debug_vprintf(), args, debug_printf(), and sanity_check_ctx::warnings.

00077 {
00078    va_list args;
00079 
00080    debug_printf( "Warning: " );
00081    va_start( args, format );
00082    _debug_vprintf( format, args );
00083    va_end( args );
00084    debug_printf( "\n" );
00085    ctx->warnings++;
00086 }

boolean tgsi_sanity_check ( struct tgsi_token tokens  ) 

Definition at line 342 of file tgsi_sanity.c.

References CALLOC_STRUCT, epilog(), tgsi_iterate_context::epilog, sanity_check_ctx::errors, FALSE, FREE, sanity_check_ctx::index_of_END, sanity_check_ctx::iter, iter_declaration(), iter_immediate(), iter_instruction(), tgsi_iterate_context::iterate_declaration, tgsi_iterate_context::iterate_immediate, tgsi_iterate_context::iterate_instruction, sanity_check_ctx::num_imms, sanity_check_ctx::num_instructions, tgsi_iterate_context::prolog, sanity_check_ctx::regs_decl, sanity_check_ctx::regs_ind_used, sanity_check_ctx::regs_used, tgsi_iterate_shader(), and sanity_check_ctx::warnings.

00344 {
00345    struct sanity_check_ctx *ctx;
00346    boolean ret;
00347    
00348    ctx = CALLOC_STRUCT(sanity_check_ctx);
00349    if(!ctx)
00350       return FALSE;
00351    
00352    ctx->iter.prolog = NULL;
00353    ctx->iter.iterate_instruction = iter_instruction;
00354    ctx->iter.iterate_declaration = iter_declaration;
00355    ctx->iter.iterate_immediate = iter_immediate;
00356    ctx->iter.epilog = epilog;
00357 
00358    memset( ctx->regs_decl, 0, sizeof( ctx->regs_decl ) );
00359    memset( ctx->regs_used, 0, sizeof( ctx->regs_used ) );
00360    memset( ctx->regs_ind_used, 0, sizeof( ctx->regs_ind_used ) );
00361    ctx->num_imms = 0;
00362    ctx->num_instructions = 0;
00363    ctx->index_of_END = ~0;
00364 
00365    ctx->errors = 0;
00366    ctx->warnings = 0;
00367 
00368    ret = tgsi_iterate_shader( tokens, &ctx->iter ) && 
00369          (ctx->errors == 0);
00370  
00371    FREE(ctx);
00372 
00373    return ret;
00374 }


Variable Documentation

const char* file_names[TGSI_FILE_COUNT] [static]

Initial value:

{
   "NULL",
   "CONST",
   "IN",
   "OUT",
   "TEMP",
   "SAMP",
   "ADDR",
   "IMM",
   "LOOP"
}

Definition at line 135 of file tgsi_sanity.c.


Generated on Tue Sep 29 06:25:26 2009 for Gallium3D by  doxygen 1.5.4