From 52cc32378c541261d045f160a14ab0cfd27009ad Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 26 Mar 2007 15:46:35 -0600 Subject: Additional error checking for 'return' statements. --- src/mesa/shader/slang/slang_codegen.c | 59 ++++++++++++++++++++++++++++++---- src/mesa/shader/slang/slang_emit.c | 7 ++-- 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 f9dae9f7aa..98596288ce 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 77470aca15..6507cde0c1 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 be2e229b76..c815c9914a 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; -- cgit v1.2.3 From 813a0e11f1eb903883aef18c5cb5c4702dcb6213 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 26 Mar 2007 16:01:58 -0600 Subject: remove debug abort() calls --- src/mesa/shader/slang/slang_codegen.c | 14 ++++++-------- src/mesa/shader/slang/slang_emit.c | 1 - src/mesa/shader/slang/slang_link.c | 7 ++++--- src/mesa/shader/slang/slang_print.c | 2 -- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 98596288ce..c2a33778c6 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -681,11 +681,8 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper, GLuint i; v = _slang_locate_variable(oper->locals, id, GL_TRUE); if (!v) { - printf("var %s not found!\n", (char *) oper->a_id); - _slang_print_var_scope(oper->locals, 6); - - abort(); - break; + _mesa_problem(NULL, "var %s not found!\n", (char *) oper->a_id); + return; } /* look for a substitution */ @@ -1134,7 +1131,8 @@ make_writemask(const char *field) mask |= WRITEMASK_W; break; default: - abort(); + _mesa_problem(NULL, "invalid writemask in make_writemask()"); + return 0; } field++; } @@ -2619,8 +2617,8 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) return new_node0(IR_NOP); default: - printf("Unhandled node type %d\n", oper->type); - abort(); + _mesa_problem(NULL, "bad node type %d in _slang_gen_operation", + oper->type); return new_node0(IR_NOP); } diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 6507cde0c1..109b2df7aa 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -1535,7 +1535,6 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n) default: _mesa_problem(NULL, "Unexpected IR opcode in emit()\n"); - abort(); } return NULL; } diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index 39df256b00..0cad69d410 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -208,10 +208,11 @@ link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog) j = _mesa_add_sampler(shProg->Uniforms, p->Name); break; default: - abort(); + _mesa_problem(NULL, "bad parameter type in link_uniform_vars()"); + return GL_FALSE; } - } + ASSERT(j >= 0); size = p->Size; @@ -544,7 +545,7 @@ _slang_link(GLcontext *ctx, if (!_slang_resolve_attributes(shProg, &shProg->VertexProgram->Base)) { /*goto cleanup;*/ _mesa_problem(ctx, "_slang_resolve_attributes() failed"); - abort(); /* XXX fix */ + return; } } diff --git a/src/mesa/shader/slang/slang_print.c b/src/mesa/shader/slang/slang_print.c index 4be9041c78..c80a6c7e11 100644 --- a/src/mesa/shader/slang/slang_print.c +++ b/src/mesa/shader/slang/slang_print.c @@ -274,10 +274,8 @@ slang_print_tree(const slang_operation *op, int indent) */ } else { - abort(); spaces(indent); printf("DECL %s (anonymous variable!!!!)\n", (char *) op->a_id); - /*abort();*/ } } break; -- cgit v1.2.3 From c042a91b8b202e4c0623e647bda035c715f7c308 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 26 Mar 2007 16:56:45 -0600 Subject: Get rid of SLANG_OPER_GOTO, start rewrite of 'return' handling. --- src/mesa/shader/slang/slang_codegen.c | 94 ++++++++++++------------- src/mesa/shader/slang/slang_compile_operation.h | 3 +- src/mesa/shader/slang/slang_emit.c | 19 ++++- src/mesa/shader/slang/slang_print.c | 5 -- 4 files changed, 65 insertions(+), 56 deletions(-) diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index c2a33778c6..0ca5054ead 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -472,9 +472,9 @@ new_float_literal(const float v[4], GLuint size) * Unconditional jump. */ static slang_ir_node * -new_jump(slang_label *dest) +new_return(slang_label *dest) { - slang_ir_node *n = new_node0(IR_JUMP); + slang_ir_node *n = new_node0(IR_RETURN); assert(dest); if (n) n->Label = dest; @@ -606,6 +606,24 @@ _slang_is_noop(const slang_operation *oper) } +/** + * Recursively search tree for a node of the given type. + */ +static slang_operation * +_slang_find_node_type(slang_operation *oper, slang_operation_type type) +{ + GLuint i; + if (oper->type == type) + return oper; + for (i = 0; i < oper->num_children; i++) { + slang_operation *p = _slang_find_node_type(&oper->children[i], type); + if (p) + return p; + } + return NULL; +} + + /** * Produce inline code for a call to an assembly instruction. * XXX Note: children are passed as asm args in-order, not by name! @@ -749,7 +767,7 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper, slang_operation_copy(&assignOper->children[1], &oper->children[0]); - returnOper->type = SLANG_OPER_RETURN; + returnOper->type = SLANG_OPER_RETURN; /* return w/ no value */ assert(returnOper->num_children == 0); /* do substitutions on the "__retVal = expr" sub-tree */ @@ -1744,22 +1762,7 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) } if (!haveReturnValue) { - /* Convert from: - * return; - * To: - * goto __endOfFunction; - */ - slang_ir_node *n; - slang_operation gotoOp; - slang_operation_construct(&gotoOp); - gotoOp.type = SLANG_OPER_GOTO; - gotoOp.label = A->curFuncEndLabel; - assert(gotoOp.label); - - n = _slang_gen_operation(A, &gotoOp); - /* destroy temp code */ - slang_operation_destruct(&gotoOp); - return n; + return new_return(A->curFuncEndLabel); } else { /* @@ -1767,9 +1770,9 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) * return expr; * To: * __retVal = expr; - * goto __endOfFunction; + * return; // goto __endOfFunction */ - slang_operation *block, *assign, *jump; + slang_operation *assign; slang_atom a_retVal; slang_ir_node *n; @@ -1787,17 +1790,8 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) } #endif - block = slang_operation_new(1); - block->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; - assert(block->locals); - block->locals->outer_scope = oper->locals->outer_scope; - block->num_children = 2; - block->children = slang_operation_new(2); - - /* child[0]: __retVal = expr; */ - assign = &block->children[0]; + assign = slang_operation_new(1); assign->type = SLANG_OPER_ASSIGN; - assign->locals->outer_scope = block->locals; assign->num_children = 2; assign->children = slang_operation_new(2); /* lhs (__retVal) */ @@ -1808,22 +1802,11 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) /* XXX we might be able to avoid this copy someday */ slang_operation_copy(&assign->children[1], &oper->children[0]); - /* child[1]: goto __endOfFunction */ - jump = &block->children[1]; - jump->type = SLANG_OPER_GOTO; - assert(A->curFuncEndLabel); - /* XXX don't call function? */ - jump->label = A->curFuncEndLabel; - assert(jump->label); - -#if 0 /* debug */ - printf("NEW RETURN:\n"); - slang_print_tree(block, 0); -#endif - /* assemble the new code */ - n = _slang_gen_operation(A, block); - slang_operation_delete(block); + n = new_seq(_slang_gen_operation(A, assign), + new_return(A->curFuncEndLabel)); + + slang_operation_delete(assign); return n; } } @@ -2552,8 +2535,6 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) oper, NULL); case SLANG_OPER_RETURN: return _slang_gen_return(A, oper); - case SLANG_OPER_GOTO: - return new_jump(oper->label); case SLANG_OPER_LABEL: return new_label(oper->label); case SLANG_OPER_IDENTIFIER: @@ -2817,6 +2798,23 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun) /* we only really generate code for main, all other functions get * inlined. */ +#if 0 + /* do some basic error checking though */ + if (fun->header.type.specifier.type != SLANG_SPEC_VOID) { + /* check that non-void functions actually return something */ + slang_operation *op + = _slang_find_node_type(fun->body, SLANG_OPER_RETURN); + if (!op) { + slang_info_log_error(A->log, + "function \"%s\" has no return statement", + (char *) fun->header.a_name); + printf( + "function \"%s\" has no return statement\n", + (char *) fun->header.a_name); + return GL_FALSE; + } + } +#endif return GL_TRUE; /* not an error */ } diff --git a/src/mesa/shader/slang/slang_compile_operation.h b/src/mesa/shader/slang/slang_compile_operation.h index 3bed3218a6..b63db04e7e 100644 --- a/src/mesa/shader/slang/slang_compile_operation.h +++ b/src/mesa/shader/slang/slang_compile_operation.h @@ -42,7 +42,6 @@ typedef enum slang_operation_type_ SLANG_OPER_CONTINUE, /* "continue" statement */ SLANG_OPER_DISCARD, /* "discard" (kill fragment) statement */ SLANG_OPER_RETURN, /* "return" [expr] */ - SLANG_OPER_GOTO, /* jump to label */ SLANG_OPER_LABEL, /* a jump target */ SLANG_OPER_EXPRESSION, /* [expr] */ SLANG_OPER_IF, /* "if" [0] then [1] else [2] */ @@ -118,7 +117,7 @@ typedef struct slang_operation_ slang_variable_scope *locals; /**< local vars for scope */ struct slang_function_ *fun; /**< If type == SLANG_OPER_CALL */ struct slang_variable_ *var; /**< If type == slang_oper_identier */ - struct slang_label_ *label; /**< If type == SLANG_OPER_LABEL or GOTO */ + struct slang_label_ *label; /**< If type == SLANG_OPER_LABEL */ } slang_operation; diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 109b2df7aa..92bfb54d80 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -726,6 +726,23 @@ emit_jump(slang_emit_info *emitInfo, slang_ir_node *n) } +static struct prog_instruction * +emit_return(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct prog_instruction *inst; + assert(n); + assert(n->Opcode == IR_RETURN); + assert(n->Label); + inst = new_instruction(emitInfo, OPCODE_BRA /*RET*/); /*XXX TEMPORARY*/ + inst->DstReg.CondMask = COND_TR; /* always branch */ + inst->BranchTarget = _slang_label_get_location(n->Label); + if (inst->BranchTarget < 0) { + _slang_label_add_reference(n->Label, emitInfo->prog->NumInstructions - 1); + } + return inst; +} + + static struct prog_instruction * emit_kill(slang_emit_info *emitInfo) { @@ -1528,7 +1545,7 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n) case IR_END_SUB: return new_instruction(emitInfo, OPCODE_ENDSUB); case IR_RETURN: - return new_instruction(emitInfo, OPCODE_RET); + return emit_return(emitInfo, n); case IR_NOP: return NULL; diff --git a/src/mesa/shader/slang/slang_print.c b/src/mesa/shader/slang/slang_print.c index c80a6c7e11..90e6fe2a96 100644 --- a/src/mesa/shader/slang/slang_print.c +++ b/src/mesa/shader/slang/slang_print.c @@ -308,11 +308,6 @@ slang_print_tree(const slang_operation *op, int indent) slang_print_tree(&op->children[0], indent + 3); break; - case SLANG_OPER_GOTO: - spaces(indent); - printf("GOTO %s\n", (char *) op->a_id); - break; - case SLANG_OPER_LABEL: spaces(indent); printf("LABEL %s\n", (char *) op->a_id); -- cgit v1.2.3 From 037c06846041877fb03890864520daa33b5fa4a9 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 26 Mar 2007 16:58:50 -0600 Subject: special case RET --- src/mesa/shader/prog_print.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c index 3f7ad47e05..3ab004191a 100644 --- a/src/mesa/shader/prog_print.c +++ b/src/mesa/shader/prog_print.c @@ -571,6 +571,13 @@ _mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent, _mesa_printf("CAL %u", inst->BranchTarget); print_comment(inst); break; + case OPCODE_RET: + _mesa_printf("RET (%s%s); # (goto %d)", + condcode_string(inst->DstReg.CondMask), + _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE), + inst->BranchTarget); + print_comment(inst); + break; case OPCODE_IF: if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { /* Use ordinary register */ -- cgit v1.2.3 From 6583429f89df1b6838c5405bd32e5ef30bdf163f Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 26 Mar 2007 17:16:26 -0600 Subject: Get rid of IR_JUMP and related code. --- src/mesa/shader/slang/slang_emit.c | 21 +-------------------- src/mesa/shader/slang/slang_ir.c | 4 ---- src/mesa/shader/slang/slang_ir.h | 2 +- 3 files changed, 2 insertions(+), 25 deletions(-) diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 92bfb54d80..e747a6ef32 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -710,22 +710,6 @@ emit_label(slang_emit_info *emitInfo, const slang_ir_node *n) } -static struct prog_instruction * -emit_jump(slang_emit_info *emitInfo, slang_ir_node *n) -{ - struct prog_instruction *inst; - assert(n); - assert(n->Label); - inst = new_instruction(emitInfo, OPCODE_BRA); - inst->DstReg.CondMask = COND_TR; /* always branch */ - inst->BranchTarget = _slang_label_get_location(n->Label); - if (inst->BranchTarget < 0) { - _slang_label_add_reference(n->Label, emitInfo->prog->NumInstructions - 1); - } - return inst; -} - - static struct prog_instruction * emit_return(slang_emit_info *emitInfo, slang_ir_node *n) { @@ -1517,10 +1501,7 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n) case IR_LABEL: return emit_label(emitInfo, n); - case IR_JUMP: - assert(n); - assert(n->Label); - return emit_jump(emitInfo, n); + case IR_KILL: return emit_kill(emitInfo); diff --git a/src/mesa/shader/slang/slang_ir.c b/src/mesa/shader/slang/slang_ir.c index 14a7b694bd..95b154db68 100644 --- a/src/mesa/shader/slang/slang_ir.c +++ b/src/mesa/shader/slang/slang_ir.c @@ -74,7 +74,6 @@ static const slang_ir_info IrInfo[] = { { IR_SEQ, "IR_SEQ", OPCODE_NOP, 0, 0 }, { IR_SCOPE, "IR_SCOPE", OPCODE_NOP, 0, 0 }, { IR_LABEL, "IR_LABEL", OPCODE_NOP, 0, 0 }, - { IR_JUMP, "IR_JUMP", OPCODE_NOP, 0, 0 }, { IR_IF, "IR_IF", OPCODE_NOP, 0, 0 }, { IR_KILL, "IR_KILL", OPCODE_NOP, 0, 0 }, { IR_COND, "IR_COND", OPCODE_NOP, 0, 0 }, @@ -281,9 +280,6 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent) printf("COND\n"); _slang_print_ir_tree(n->Children[0], indent + 3); break; - case IR_JUMP: - printf("JUMP %s\n", n->Label->Name); - break; case IR_IF: printf("IF \n"); diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h index 2e90409caf..a617a7e173 100644 --- a/src/mesa/shader/slang/slang_ir.h +++ b/src/mesa/shader/slang/slang_ir.h @@ -49,7 +49,7 @@ typedef enum IR_SCOPE, /* new variable scope (one child) */ IR_LABEL, /* target of a jump or cjump */ - IR_JUMP, /* unconditional jump */ + IR_COND, /* conditional expression/predicate */ IR_IF, /* high-level IF/then/else */ -- cgit v1.2.3 From 9878e8ff516486900228429f26b37cb01cd7313f Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 26 Mar 2007 18:46:07 -0600 Subject: Checkpoint: implementing true CAL/RET instructions for subroutine calls. Also, found/fixed a code generation regression: the emit_swizzle() function was always returning NULL. This caused emit_move() to miss its chance at peephole optimization. --- src/mesa/shader/slang/slang_codegen.c | 29 ++++++++++ src/mesa/shader/slang/slang_compile_operation.h | 1 + src/mesa/shader/slang/slang_emit.c | 73 ++++++++++++++++++++----- src/mesa/shader/slang/slang_ir.h | 2 + 4 files changed, 92 insertions(+), 13 deletions(-) diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 0ca5054ead..93b6d9f854 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -468,6 +468,21 @@ new_float_literal(const float v[4], GLuint size) return n; } + +/** + * Inlined subroutine. + */ +static slang_ir_node * +new_inlined_function_call(slang_ir_node *code, slang_label *name) +{ + slang_ir_node *n = new_node1(IR_FUNC, code); + assert(name); + if (n) + n->Label = name; + return n; +} + + /** * Unconditional jump. */ @@ -1092,8 +1107,18 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun, else { /* non-assembly function */ inlined = slang_inline_function_call(A, fun, oper, dest); + if (inlined) { + assert(inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE || + inlined->type == SLANG_OPER_SEQUENCE); + inlined->type = SLANG_OPER_INLINED_CALL; + inlined->fun = fun; + inlined->label = _slang_label_new((char*) fun->header.a_name); + } } + if (!inlined) + return NULL; + /* Replace the function call with the inlined block */ slang_operation_destruct(oper); *oper = *inlined; @@ -2581,6 +2606,7 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) return n; } + case SLANG_OPER_INLINED_CALL: case SLANG_OPER_SEQUENCE: { slang_ir_node *tree = NULL; @@ -2589,6 +2615,9 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) slang_ir_node *n = _slang_gen_operation(A, &oper->children[i]); tree = tree ? new_seq(tree, n) : n; } + if (oper->type == SLANG_OPER_INLINED_CALL) { + tree = new_inlined_function_call(tree, oper->label); + } return tree; } diff --git a/src/mesa/shader/slang/slang_compile_operation.h b/src/mesa/shader/slang/slang_compile_operation.h index b63db04e7e..d497b6f66f 100644 --- a/src/mesa/shader/slang/slang_compile_operation.h +++ b/src/mesa/shader/slang/slang_compile_operation.h @@ -93,6 +93,7 @@ typedef enum slang_operation_type_ SLANG_OPER_NOT, /* "!" [expr] */ SLANG_OPER_SUBSCRIPT, /* [expr] "[" [expr] "]" */ SLANG_OPER_CALL, /* [func name] [param] [param] [...] */ + SLANG_OPER_INLINED_CALL, /* inlined function call */ SLANG_OPER_FIELD, /* i.e.: ".next" or ".xzy" or ".xxx" etc */ SLANG_OPER_POSTINCREMENT, /* [var] "++" */ SLANG_OPER_POSTDECREMENT /* [var] "--" */ diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index e747a6ef32..21b73c2f97 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -62,6 +62,7 @@ typedef struct /* code-gen options */ GLboolean EmitHighLevelInstructions; GLboolean EmitCondCodes; + GLboolean EmitBeginEndSub; GLboolean EmitComments; } slang_emit_info; @@ -203,6 +204,13 @@ new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode) { struct gl_program *prog = emitInfo->prog; struct prog_instruction *inst; + +#if 0 + /* print prev inst */ + if (prog->NumInstructions > 0) { + _mesa_print_instruction(prog->Instructions + prog->NumInstructions - 1); + } +#endif prog->Instructions = _mesa_realloc_instructions(prog->Instructions, prog->NumInstructions, prog->NumInstructions + 1); @@ -710,6 +718,28 @@ emit_label(slang_emit_info *emitInfo, const slang_ir_node *n) } +/** + * Emit code for an inlined function call. + */ +static struct prog_instruction * +emit_func(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct prog_instruction *inst; + assert(n->Label); + if (emitInfo->EmitBeginEndSub) { + inst = new_instruction(emitInfo, OPCODE_BGNSUB); + inst->Comment = _mesa_strdup(n->Label->Name); + } + inst = emit(emitInfo, n->Children[0]); + if (emitInfo->EmitBeginEndSub) { + inst = new_instruction(emitInfo, OPCODE_ENDSUB); + inst->Comment = _mesa_strdup(n->Label->Name); + } + n->Store = n->Children[0]->Store; + return inst; +} + + static struct prog_instruction * emit_return(slang_emit_info *emitInfo, slang_ir_node *n) { @@ -803,14 +833,20 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n) n->Store = n->Children[0]->Store; #if PEEPHOLE_OPTIMIZATIONS - if (inst && _slang_is_temp(emitInfo->vt, n->Children[1]->Store)) { + if (inst && + _slang_is_temp(emitInfo->vt, n->Children[1]->Store) && + (inst->DstReg.File == n->Children[1]->Store->File) && + (inst->DstReg.Index == n->Children[1]->Store->Index)) { /* Peephole optimization: - * Just modify the RHS to put its result into the dest of this - * MOVE operation. Then, this MOVE is a no-op. + * The Right-Hand-Side has its results in a temporary place. + * Modify the RHS (and the prev instruction) to store its results + * in the destination specified by n->Children[0]. + * Then, this MOVE is a no-op. */ - _slang_free_temp(emitInfo->vt, n->Children[1]->Store); + if (n->Children[1]->Opcode != IR_SWIZZLE) + _slang_free_temp(emitInfo->vt, n->Children[1]->Store); *n->Children[1]->Store = *n->Children[0]->Store; - /* fixup the prev (RHS) instruction */ + /* fixup the previous instruction (which stored the RHS result) */ assert(n->Children[0]->Store->Index >= 0); storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask); return inst; @@ -870,11 +906,17 @@ emit_cond(slang_emit_info *emitInfo, slang_ir_node *n) * Need to update condition code register. * Next instruction is typically an IR_IF. */ - if (inst) { - /* set inst's CondUpdate flag */ + if (inst && + n->Children[0]->Store && + inst->DstReg.File == n->Children[0]->Store->File && + inst->DstReg.Index == n->Children[0]->Store->Index) { + /* The previous instruction wrote to the register who's value + * we're testing. Just update that instruction so that the + * condition codes are updated. + */ inst->CondUpdate = GL_TRUE; n->Store = n->Children[0]->Store; - return inst; /* XXX or null? */ + return inst; } else { /* This'll happen for things like "if (i) ..." where no code @@ -1227,8 +1269,9 @@ static struct prog_instruction * emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) { GLuint swizzle; + struct prog_instruction *inst; - (void) emit(emitInfo, n->Children[0]); + inst = emit(emitInfo, n->Children[0]); #ifdef DEBUG { @@ -1246,10 +1289,10 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) n->Store->Index = n->Children[0]->Store->Index; n->Store->Size = swizzle_size(n->Store->Swizzle); #if 0 - printf("Emit Swizzle reg %d chSize %d size %d swz %s\n", + printf("Emit Swizzle %s reg %d chSize %d mySize %d\n", + _mesa_swizzle_string(n->Store->Swizzle, 0, 0), n->Store->Index, n->Children[0]->Store->Size, - n->Store->Size, - _mesa_swizzle_string(n->Store->Swizzle, 0, 0)); + n->Store->Size); #endif /* apply this swizzle to child's swizzle to get composed swizzle */ @@ -1257,7 +1300,7 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) n->Store->Swizzle = swizzle_swizzle(n->Children[0]->Store->Swizzle, swizzle); - return NULL; + return inst; } @@ -1505,6 +1548,9 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n) case IR_KILL: return emit_kill(emitInfo); + case IR_FUNC: + return emit_func(emitInfo, n); + case IR_IF: return emit_if(emitInfo, n); @@ -1553,6 +1599,7 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt, emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions; emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes; + emitInfo.EmitBeginEndSub = 0; /* XXX temporary */ emitInfo.EmitComments = ctx->Shader.EmitComments; (void) emit(&emitInfo, n); diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h index a617a7e173..a9a530aaf8 100644 --- a/src/mesa/shader/slang/slang_ir.h +++ b/src/mesa/shader/slang/slang_ir.h @@ -62,6 +62,8 @@ typedef enum IR_RETURN, /* return from subroutine */ IR_CALL, /* call subroutine */ + IR_FUNC, /* inlined function code */ + IR_LOOP, /* high-level loop-begin / loop-end */ /* Children[0] = loop body */ /* Children[1] = loop tail code, or NULL */ -- cgit v1.2.3 From ae36cfc65eac19281b5ad338e4095008dc69ab21 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 26 Mar 2007 18:47:19 -0600 Subject: s/SUB/BGNSUB/ --- src/mesa/shader/prog_print.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c index 3ab004191a..8fa7ef3d82 100644 --- a/src/mesa/shader/prog_print.c +++ b/src/mesa/shader/prog_print.c @@ -629,7 +629,7 @@ _mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent, break; case OPCODE_BGNSUB: - _mesa_printf("SUB"); + _mesa_printf("BGNSUB"); print_comment(inst); return indent + 3; case OPCODE_ENDSUB: -- cgit v1.2.3