diff options
author | Brian <brian@yutani.localnet.net> | 2007-03-26 15:46:35 -0600 |
---|---|---|
committer | Brian <brian@yutani.localnet.net> | 2007-03-26 15:46:35 -0600 |
commit | 52cc32378c541261d045f160a14ab0cfd27009ad (patch) | |
tree | ee45387ffbe0fdb20ee7ea43e4b6f649f3261caa | |
parent | c3da0bd7dde9febf206efac88bb67e98dfc90baa (diff) |
Additional error checking for 'return' statements.
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 59 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 7 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_typeinfo.h | 1 |
3 files changed, 58 insertions, 9 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index f9dae9f7aa1..98596288cec 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -716,7 +716,7 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper, case SLANG_OPER_RETURN: /* do return replacement here too */ assert(oper->num_children == 0 || oper->num_children == 1); - if (!_slang_is_noop(oper)) { + if (oper->num_children == 1 && !_slang_is_noop(&oper->children[0])) { /* replace: * return expr; * with: @@ -725,6 +725,14 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper, * then do substitutions on the assignment. */ slang_operation *blockOper, *assignOper, *returnOper; + + /* check if function actually has a return type */ + assert(A->CurFunction); + if (A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) { + slang_info_log_error(A->log, "illegal return expression"); + return; + } + blockOper = slang_operation_new(1); blockOper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; blockOper->num_children = 2; @@ -755,6 +763,14 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper, slang_operation_copy(oper, blockOper); slang_operation_destruct(blockOper); } + else { + /* check if return value was expected */ + assert(A->CurFunction); + if (A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) { + slang_info_log_error(A->log, "return statement requires an expression"); + return; + } + } break; case SLANG_OPER_ASSIGN: @@ -806,6 +822,11 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun, slang_variable **substOld; slang_operation **substNew; GLuint substCount, numCopyIn, i; + slang_function *prevFunction; + + /* save / push */ + prevFunction = A->CurFunction; + A->CurFunction = fun; /*assert(oper->type == SLANG_OPER_CALL); (or (matrix) multiply, etc) */ assert(fun->param_count == totalArgs); @@ -1027,6 +1048,10 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun, fun->parameters->num_variables, numArgs); slang_print_tree(top, 0); #endif + + /* pop */ + A->CurFunction = prevFunction; + return top; } @@ -1703,9 +1728,24 @@ _slang_gen_logical_or(slang_assemble_ctx *A, slang_operation *oper) static slang_ir_node * _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) { - if (oper->num_children == 0 || - (oper->num_children == 1 && - oper->children[0].type == SLANG_OPER_VOID)) { + const GLboolean haveReturnValue + = (oper->num_children == 1 && + oper->children[0].type != SLANG_OPER_VOID); + + /* error checking */ + assert(A->CurFunction); + if (haveReturnValue && + A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) { + slang_info_log_error(A->log, "illegal return expression"); + return NULL; + } + else if (!haveReturnValue && + A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) { + slang_info_log_error(A->log, "return statement requires an expression"); + return NULL; + } + + if (!haveReturnValue) { /* Convert from: * return; * To: @@ -1718,7 +1758,6 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) gotoOp.label = A->curFuncEndLabel; assert(gotoOp.label); - /* assemble the new code */ n = _slang_gen_operation(A, &gotoOp); /* destroy temp code */ slang_operation_destruct(&gotoOp); @@ -1743,7 +1782,10 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) { slang_variable *v = _slang_locate_variable(oper->locals, a_retVal, GL_TRUE); - assert(v); + if (!v) { + /* trying to return a value in a void-valued function */ + return NULL; + } } #endif @@ -1843,6 +1885,9 @@ _slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper) _slang_simplify(v->initializer, &A->space, A->atoms); rhs = _slang_gen_operation(A, v->initializer); #endif + if (!rhs) + return NULL; + assert(rhs); init = new_node2(IR_MOVE, var, rhs); /* @@ -2786,6 +2831,8 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun) assert(A->program->Parameters ); assert(A->program->Varying); assert(A->vartable); + A->CurLoop = NULL; + A->CurFunction = fun; /* fold constant expressions, etc. */ _slang_simplify(fun->body, &A->space, A->atoms); diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 77470aca154..6507cde0c17 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -793,11 +793,12 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n) assert(n->Children[1]); inst = emit(emitInfo, n->Children[1]); + if (!n->Children[1]->Store) { + slang_info_log_error(emitInfo->log, "invalid assignment"); + return NULL; + } assert(n->Children[1]->Store->Index >= 0); -#if 0 - assert(!n->Store); -#endif n->Store = n->Children[0]->Store; #if PEEPHOLE_OPTIMIZATIONS diff --git a/src/mesa/shader/slang/slang_typeinfo.h b/src/mesa/shader/slang/slang_typeinfo.h index be2e229b763..c815c9914a9 100644 --- a/src/mesa/shader/slang/slang_typeinfo.h +++ b/src/mesa/shader/slang/slang_typeinfo.h @@ -64,6 +64,7 @@ typedef struct slang_assemble_ctx_ slang_info_log *log; struct slang_label_ *curFuncEndLabel; struct slang_ir_node_ *CurLoop; + struct slang_function_ *CurFunction; } slang_assemble_ctx; |