From 2800d5e5205e90e6dd07a4f7a7b5424b6b6cc591 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 11 Nov 2010 04:13:08 -0500 Subject: [PATCH] Cleaned up error position reporting. --- mojoshader.c | 62 ++++++++++++++++-------------------------- mojoshader.h | 21 ++++++++++---- mojoshader_assembler.c | 50 +++++++++++++--------------------- mojoshader_internal.h | 6 ---- 4 files changed, 58 insertions(+), 81 deletions(-) diff --git a/mojoshader.c b/mojoshader.c index 56cf9542..2f483846 100644 --- a/mojoshader.c +++ b/mojoshader.c @@ -70,10 +70,10 @@ typedef struct Context MOJOSHADER_malloc malloc; MOJOSHADER_free free; void *malloc_data; + int current_position; const uint32 *orig_tokens; const uint32 *tokens; uint32 tokencount; - MOJOSHADER_parsePhase parse_phase; const MOJOSHADER_swizzle *swizzles; unsigned int swizzles_count; Buffer *output; @@ -368,8 +368,6 @@ static inline int isfail(const Context *ctx) } // isfail -// !!! FIXME: move the errpos calculation into Context, and we can move this -// !!! FIXME: to mojoshader_common.c static void failf(Context *ctx, const char *fmt, ...) ISPRINTF(2,3); static void failf(Context *ctx, const char *fmt, ...) { @@ -377,27 +375,10 @@ static void failf(Context *ctx, const char *fmt, ...) if (ctx->out_of_memory) return; - int errpos = 0; - switch (ctx->parse_phase) - { - case MOJOSHADER_PARSEPHASE_NOTSTARTED: - errpos = -2; - break; - case MOJOSHADER_PARSEPHASE_WORKING: - errpos = (ctx->tokens - ctx->orig_tokens) * sizeof (uint32); - break; - case MOJOSHADER_PARSEPHASE_DONE: - errpos = -1; - break; - default: - assert(0 && "Unexpected value"); - return; - } // switch - // no filename at this level (we pass a NULL to errorlist_add_va()...) va_list ap; va_start(ap, fmt); - errorlist_add_va(ctx->errors, NULL, errpos, fmt, ap); + errorlist_add_va(ctx->errors, NULL, ctx->current_position, fmt, ap); va_end(ap); } // failf @@ -666,6 +647,13 @@ static int allocate_branch_label(Context *ctx) return ctx->assigned_branch_labels++; } // allocate_branch_label +static inline void adjust_token_position(Context *ctx, const int incr) +{ + ctx->tokens += incr; + ctx->tokencount -= incr; + ctx->current_position += incr * sizeof (uint32); +} // adjust_token_position + // D3D stuff that's used in more than just the d3d profile... @@ -5285,8 +5273,8 @@ static int parse_destination_token(Context *ctx, DestArgInfo *info) info->regnum += 6144; } // else if - ctx->tokens++; // swallow token for now, for multiple calls in a row. - ctx->tokencount--; // swallow token for now, for multiple calls in a row. + // swallow token for now, for multiple calls in a row. + adjust_token_position(ctx, 1); if (reserved1 != 0x0) fail(ctx, "Reserved bit #1 in destination token must be zero"); @@ -5517,8 +5505,8 @@ static int parse_source_token(Context *ctx, SourceArgInfo *info) info->swizzle_z = ((info->swizzle >> 4) & 0x3); info->swizzle_w = ((info->swizzle >> 6) & 0x3); - ctx->tokens++; // swallow token for now, for multiple calls in a row. - ctx->tokencount--; // swallow token for now, for multiple calls in a row. + // swallow token for now, for multiple calls in a row. + adjust_token_position(ctx, 1); if (reserved1 != 0x0) fail(ctx, "Reserved bits #1 in source token must be zero"); @@ -5538,8 +5526,8 @@ static int parse_source_token(Context *ctx, SourceArgInfo *info) fail(ctx, "Relative addressing in pixel shader version < 3.0"); const uint32 reltoken = SWAP32(*(ctx->tokens)); - ctx->tokens++; // swallow token for now, for multiple calls in a row. - ctx->tokencount--; // swallow token for now, for multiple calls in a row. + // swallow token for now, for multiple calls in a row. + adjust_token_position(ctx, 1); const int relswiz = (int) ((reltoken >> 16) & 0xFF); info->relative_regnum = (int) (reltoken & 0x7ff); @@ -5756,8 +5744,7 @@ static int parse_args_DCL(Context *ctx) fail(ctx, "Bit #31 in DCL token must be one"); ctx->centroid_allowed = 1; - ctx->tokens++; - ctx->tokencount--; + adjust_token_position(ctx, 1); parse_destination_token(ctx, &ctx->dest_arg); ctx->centroid_allowed = 0; @@ -6648,6 +6635,7 @@ static const Instruction instructions[] = static int parse_instruction_token(Context *ctx) { int retval = 0; + const int start_position = ctx->current_position; const uint32 *start_tokens = ctx->tokens; const uint32 start_tokencount = ctx->tokencount; const uint32 token = SWAP32(*(ctx->tokens)); @@ -6693,8 +6681,7 @@ static int parse_instruction_token(Context *ctx) ctx->predicated = predicated; // Update the context with instruction's arguments. - ctx->tokens++; - ctx->tokencount--; + adjust_token_position(ctx, 1); retval = instruction->parse_args(ctx); if (predicated) @@ -6703,6 +6690,7 @@ static int parse_instruction_token(Context *ctx) // parse_args() moves these forward for convenience...reset them. ctx->tokens = start_tokens; ctx->tokencount = start_tokencount; + ctx->current_position = start_position; if (instruction->state != NULL) instruction->state(ctx); @@ -6985,7 +6973,7 @@ static Context *build_context(const char *profile, ctx->endline = ENDLINE_STR; ctx->endline_len = strlen(ctx->endline); ctx->last_address_reg_component = -1; - ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED; + ctx->current_position = MOJOSHADER_POSITION_BEFORE; ctx->errors = errorlist_create(MallocBridge, FreeBridge, ctx); if (ctx->errors == NULL) @@ -7644,7 +7632,7 @@ const MOJOSHADER_parseData *MOJOSHADER_parse(const char *profile, verify_swizzles(ctx); // Version token always comes first. - ctx->parse_phase = MOJOSHADER_PARSEPHASE_WORKING; + ctx->current_position = 0; rc = parse_version_token(ctx, profile); // drop out now if this definitely isn't bytecode. Saves lots of @@ -7662,8 +7650,7 @@ const MOJOSHADER_parseData *MOJOSHADER_parse(const char *profile, ctx->tokencount = rc; } // if - ctx->tokens += rc; - ctx->tokencount -= rc; + adjust_token_position(ctx, rc); // parse out the rest of the tokens after the version token... while (ctx->tokencount > 0) @@ -7682,11 +7669,10 @@ const MOJOSHADER_parseData *MOJOSHADER_parse(const char *profile, break; } // if - ctx->tokens += rc; - ctx->tokencount -= rc; + adjust_token_position(ctx, rc); } // while - ctx->parse_phase = MOJOSHADER_PARSEPHASE_DONE; + ctx->current_position = MOJOSHADER_POSITION_AFTER; if (!failed) { diff --git a/mojoshader.h b/mojoshader.h index caa02222..d50b81d2 100644 --- a/mojoshader.h +++ b/mojoshader.h @@ -319,6 +319,13 @@ typedef struct MOJOSHADER_symbol } MOJOSHADER_symbol; +/* + * These are used with MOJOSHADER_error as special case positions. + */ +#define MOJOSHADER_POSITION_NONE (-3) +#define MOJOSHADER_POSITION_BEFORE (-2) +#define MOJOSHADER_POSITION_AFTER (-1) + typedef struct MOJOSHADER_error { /* @@ -335,12 +342,14 @@ typedef struct MOJOSHADER_error const char *filename; /* - * Position of error, if there is one. Will be -3 if there was no - * error, -2 if there was an error before processing started, and - * -1 if there was an error during final processing. If >= 0, - * MOJOSHADER_parse() sets this to the byte offset (starting at zero) into - * the bytecode you supplied, and MOJOSHADER_assemble() sets this to a - * a line number in the source code you supplied (starting at one). + * Position of error, if there is one. Will be MOJOSHADER_POSITION_NONE if + * there was no error, MOJOSHADER_POSITION_BEFORE if there was an error + * before processing started, and MOJOSHADER_POSITION_AFTER if there was + * an error during final processing. If >= 0, MOJOSHADER_parse() sets + * this to the byte offset (starting at zero) into the bytecode you + * supplied, and MOJOSHADER_assemble(), MOJOSHADER_parseAst(), and + * MOJOSHADER_compile() sets this to a a line number in the source code + * you supplied (starting at one). */ int error_position; } MOJOSHADER_error; diff --git a/mojoshader_assembler.c b/mojoshader_assembler.c index 0f28f93e..86b1e0bc 100644 --- a/mojoshader_assembler.c +++ b/mojoshader_assembler.c @@ -40,9 +40,10 @@ typedef struct Context MOJOSHADER_malloc malloc; MOJOSHADER_free free; void *malloc_data; + const char *current_file; + int current_position; ErrorList *errors; Preprocessor *preprocessor; - MOJOSHADER_parsePhase parse_phase; MOJOSHADER_shaderType shader_type; uint8 major_ver; uint8 minor_ver; @@ -103,39 +104,16 @@ static void FreeBridge(void *ptr, void *data) } // FreeBridge -// !!! FIXME: move the errpos calculation into Context, and we can move this -// !!! FIXME: to mojoshader_common.c static void failf(Context *ctx, const char *fmt, ...) ISPRINTF(2,3); static void failf(Context *ctx, const char *fmt, ...) { - const char *fname = NULL; - unsigned int linenum = 0; - ctx->isfail = 1; if (ctx->out_of_memory) return; - int errpos = 0; - switch (ctx->parse_phase) - { - case MOJOSHADER_PARSEPHASE_NOTSTARTED: - errpos = -2; - break; - case MOJOSHADER_PARSEPHASE_WORKING: - fname = preprocessor_sourcepos(ctx->preprocessor, &linenum); - errpos = (int) linenum; - break; - case MOJOSHADER_PARSEPHASE_DONE: - errpos = -1; - break; - default: - assert(0 && "Unexpected value"); - return; - } // switch - va_list ap; va_start(ap, fmt); - errorlist_add_va(ctx->errors, fname, errpos, fmt, ap); + errorlist_add_va(ctx->errors, ctx->current_file, ctx->current_position, fmt, ap); va_end(ap); } // failf @@ -197,14 +175,18 @@ static Token nexttoken(Context *ctx) if (preprocessor_outofmemory(ctx->preprocessor)) { - out_of_memory(ctx); + out_of_memory(ctx); // !!! FIXME: this can go; we're bridged now! ctx->tokenval = TOKEN_EOI; ctx->token = NULL; ctx->tokenlen = 0; break; } // if - else if (ctx->tokenval == TOKEN_BAD_CHARS) + unsigned int line; + ctx->current_file = preprocessor_sourcepos(ctx->preprocessor,&line); + ctx->current_position = (int) line; + + if (ctx->tokenval == TOKEN_BAD_CHARS) { fail(ctx, "Bad characters in source file"); continue; @@ -1436,7 +1418,7 @@ static Context *build_context(const char *filename, ctx->malloc = m; ctx->free = f; ctx->malloc_data = d; - ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED; + ctx->current_position = MOJOSHADER_POSITION_BEFORE; const size_t outblk = sizeof (uint32) * 4 * 64; // 64 4-token instrs. ctx->output = buffer_create(outblk, MallocBridge, FreeBridge, ctx); @@ -1642,7 +1624,10 @@ static void output_comments(Context *ctx, const char **comments, return; // make error messages sane if CTAB fails, etc. - ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED; + const char *prev_fname = ctx->current_file; + const int prev_position = ctx->current_position; + ctx->current_file = NULL; + ctx->current_position = MOJOSHADER_POSITION_BEFORE; const char *creator = "MojoShader revision " MOJOSHADER_CHANGESET; if (symbol_count > 0) @@ -1654,7 +1639,8 @@ static void output_comments(Context *ctx, const char **comments, for (i = 0; i < comment_count; i++) output_comment_string(ctx, comments[i]); - ctx->parse_phase = MOJOSHADER_PARSEPHASE_WORKING; + ctx->current_file = prev_fname; + ctx->current_position = prev_position; } // output_comments @@ -1757,7 +1743,6 @@ const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *filename, return &MOJOSHADER_out_of_mem_data; // Version token always comes first. - ctx->parse_phase = MOJOSHADER_PARSEPHASE_WORKING; parse_version_token(ctx); output_comments(ctx, comments, comment_count, symbols, symbol_count); @@ -1766,6 +1751,9 @@ const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *filename, while ((token = nexttoken(ctx)) != TOKEN_EOI) parse_token(ctx, token); + ctx->current_file = NULL; + ctx->current_position = MOJOSHADER_POSITION_AFTER; + output_token(ctx, 0x0000FFFF); // end token always 0x0000FFFF. retval = build_final_assembly(ctx); diff --git a/mojoshader_internal.h b/mojoshader_internal.h index e58dfe8f..4b9c8abd 100644 --- a/mojoshader_internal.h +++ b/mojoshader_internal.h @@ -392,12 +392,6 @@ static inline int scalar_register(const MOJOSHADER_shaderType shader_type, return 0; } // scalar_register -typedef enum -{ - MOJOSHADER_PARSEPHASE_NOTSTARTED, - MOJOSHADER_PARSEPHASE_WORKING, - MOJOSHADER_PARSEPHASE_DONE, -} MOJOSHADER_parsePhase; extern MOJOSHADER_error MOJOSHADER_out_of_mem_error; extern MOJOSHADER_parseData MOJOSHADER_out_of_mem_data;