diff options
author | Brian <brian.paul@tungstengraphics.com> | 2007-07-26 15:32:02 -0600 |
---|---|---|
committer | Brian <brian.paul@tungstengraphics.com> | 2007-07-26 15:32:02 -0600 |
commit | e3cef5887540016a6d198598cb50bebe09e3f4cf (patch) | |
tree | 01202fd6cb4a08507540eb4806dc7fdde70e1bf1 /src | |
parent | 9ed040c3c9afe06a8f6b28bc223751e3b2d65fe3 (diff) |
Fix function call bug 11731. Also, fix up IR_CALL/IR_FUNC confusion.
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 27 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 16 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_ir.c | 2 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_ir.h | 2 |
4 files changed, 29 insertions, 18 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index c1664a5ccb..8b2bdd74b5 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -536,7 +536,7 @@ new_not(slang_ir_node *n) static slang_ir_node * new_inlined_function_call(slang_ir_node *code, slang_label *name) { - slang_ir_node *n = new_node1(IR_FUNC, code); + slang_ir_node *n = new_node1(IR_CALL, code); assert(name); if (n) n->Label = name; @@ -1202,17 +1202,29 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun, /* non-assembly function */ inlined = slang_inline_function_call(A, fun, oper, dest); if (inlined && _slang_find_node_type(inlined, SLANG_OPER_RETURN)) { - /* This inlined function has one or more 'return' statements. + slang_operation *callOper; + /* The function we're calling has one or more 'return' statements. * So, we can't truly inline this function because we need to * implement 'return' with RET (and CAL). + * Nevertheless, we performed "inlining" to make a new instance + * of the function body to deal with static register allocation. + * * XXX check if there's one 'return' and if it's the very last * statement in the function - we can optimize that case. */ 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_unique((char*) fun->header.a_name); + if (_slang_function_has_return_value(fun) && !dest) { + assert(inlined->children[0].type == SLANG_OPER_VARIABLE_DECL); + assert(inlined->children[2].type == SLANG_OPER_IDENTIFIER); + callOper = &inlined->children[1]; + } + else { + callOper = inlined; + } + callOper->type = SLANG_OPER_INLINED_CALL; + callOper->fun = fun; + callOper->label = _slang_label_new_unique((char*) fun->header.a_name); } } @@ -1949,8 +1961,7 @@ static slang_ir_node * _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) { const GLboolean haveReturnValue - = (oper->num_children == 1 && - oper->children[0].type != SLANG_OPER_VOID); + = (oper->num_children == 1 && oper->children[0].type != SLANG_OPER_VOID); /* error checking */ assert(A->CurFunction); @@ -1960,7 +1971,7 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) return NULL; } else if (!haveReturnValue && - A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) { + A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) { slang_info_log_error(A->log, "return statement requires an expression"); return NULL; } diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 02c74095a9..fe13f2865c 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -780,16 +780,18 @@ emit_label(slang_emit_info *emitInfo, const slang_ir_node *n) /** - * Emit code for an inlined function call (subroutine). + * Emit code for a function call. + * Note that for each time a function is called, we emit the function's + * body code again because the set of available registers may be different. */ static struct prog_instruction * -emit_func(slang_emit_info *emitInfo, slang_ir_node *n) +emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n) { struct gl_program *progSave; struct prog_instruction *inst; GLuint subroutineId; - assert(n->Opcode == IR_FUNC); + assert(n->Opcode == IR_CALL); assert(n->Label); /* save/push cur program */ @@ -1687,10 +1689,10 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n) case IR_KILL: return emit_kill(emitInfo); - case IR_FUNC: - /* new variable scope for subroutines/function calls*/ + case IR_CALL: + /* new variable scope for subroutines/function calls */ _slang_push_var_table(emitInfo->vt); - inst = emit_func(emitInfo, n); + inst = emit_fcall(emitInfo, n); _slang_pop_var_table(emitInfo->vt); return inst; @@ -1782,7 +1784,7 @@ _slang_resolve_subroutines(slang_emit_info *emitInfo) emitInfo->NumSubroutines = 0; /* Examine CAL instructions. - * At this point, the BranchTarget field of the CAL instructions is + * At this point, the BranchTarget field of the CAL instruction is * the number/id of the subroutine to call (an index into the * emitInfo->Subroutines list). * Translate that into an actual instruction location now. diff --git a/src/mesa/shader/slang/slang_ir.c b/src/mesa/shader/slang/slang_ir.c index a29f302687..92e8d0345e 100644 --- a/src/mesa/shader/slang/slang_ir.c +++ b/src/mesa/shader/slang/slang_ir.c @@ -311,7 +311,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent) printf("RETURN\n"); break; case IR_CALL: - printf("CALL\n"); + printf("CALL %s\n", n->Label->Name); break; case IR_LOOP: diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h index 69db4b5451..c7c0ddbf9a 100644 --- a/src/mesa/shader/slang/slang_ir.h +++ b/src/mesa/shader/slang/slang_ir.h @@ -62,8 +62,6 @@ 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 */ |