diff options
author | Brian <brian@yutani.localnet.net> | 2007-05-01 10:22:08 -0600 |
---|---|---|
committer | Brian <brian@yutani.localnet.net> | 2007-05-01 10:22:08 -0600 |
commit | 7559364027eef3d9943d09a03e094400807ecdad (patch) | |
tree | db48a36e3ae3dd0ae497a511b8a1445950bc14b2 | |
parent | 65faf023679988f93da82b4c7ebdc689f2094459 (diff) | |
download | external_mesa3d-7559364027eef3d9943d09a03e094400807ecdad.zip external_mesa3d-7559364027eef3d9943d09a03e094400807ecdad.tar.gz external_mesa3d-7559364027eef3d9943d09a03e094400807ecdad.tar.bz2 |
Rewrite of slang_inline_asm_function() to do full parameter/argument substitution.
We had been taking a short-cut w/ asm inlines by just using parameters in order
rather than doing full formal parameter -> actual argument substitution like
ordinary inlined function calls. This worked in all cases but one: mix() in
which the parameters were used in a different order.
This fixes bug 10821.
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 95 |
1 files changed, 64 insertions, 31 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index c6151f8..cf32b50 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -700,37 +700,6 @@ _slang_find_node_type(slang_operation *oper, slang_operation_type type) } -/** - * Produce inline code for a call to an assembly instruction. - * XXX Note: children are passed as asm args in-order, not by name! - */ -static slang_operation * -slang_inline_asm_function(slang_assemble_ctx *A, - slang_function *fun, slang_operation *oper) -{ - const GLuint numArgs = oper->num_children; - const slang_operation *args = oper->children; - GLuint i; - slang_operation *inlined = slang_operation_new(1); - - /*assert(oper->type == SLANG_OPER_CALL); or vec4_add, etc */ - /* - printf("Inline asm %s\n", (char*) fun->header.a_name); - */ - inlined->type = fun->body->children[0].type; - inlined->a_id = fun->body->children[0].a_id; - inlined->num_children = numArgs; - inlined->children = slang_operation_new(numArgs); - inlined->locals->outer_scope = oper->locals->outer_scope; - - for (i = 0; i < numArgs; i++) { - slang_operation_copy(inlined->children + i, args + i); - } - - return inlined; -} - - static void slang_resolve_variable(slang_operation *oper) { @@ -892,6 +861,70 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper, /** + * Produce inline code for a call to an assembly instruction. + * This is typically used to compile a call to a built-in function like this: + * + * vec4 mix(const vec4 x, const vec4 y, const vec4 a) + * { + * __asm vec4_lrp __retVal, a, y, x; + * } + * + * We basically translate a SLANG_OPER_CALL into a SLANG_OPER_ASM. + */ +static slang_operation * +slang_inline_asm_function(slang_assemble_ctx *A, + slang_function *fun, slang_operation *oper) +{ + const GLuint numArgs = oper->num_children; + GLuint i; + slang_operation *inlined; + const GLboolean haveRetValue = _slang_function_has_return_value(fun); + slang_variable **substOld; + slang_operation **substNew; + + ASSERT(slang_is_asm_function(fun)); + ASSERT(fun->param_count == numArgs + haveRetValue); + + /* + printf("Inline %s as %s\n", + (char*) fun->header.a_name, + (char*) fun->body->children[0].a_id); + */ + + /* + * We'll substitute formal params with actual args in the asm call. + */ + substOld = (slang_variable **) + _slang_alloc(numArgs * sizeof(slang_variable *)); + substNew = (slang_operation **) + _slang_alloc(numArgs * sizeof(slang_operation *)); + for (i = 0; i < numArgs; i++) { + substOld[i] = fun->parameters->variables[i]; + substNew[i] = oper->children + i; + } + + /* make a copy of the code to inline */ + inlined = slang_operation_new(1); + slang_operation_copy(inlined, &fun->body->children[0]); + if (haveRetValue) { + /* get rid of the __retVal child */ + for (i = 0; i < numArgs; i++) { + inlined->children[i] = inlined->children[i + 1]; + } + inlined->num_children--; + } + + /* now do formal->actual substitutions */ + slang_substitute(A, inlined, numArgs, substOld, substNew, GL_FALSE); + + _slang_free(substOld); + _slang_free(substNew); + + return inlined; +} + + +/** * Inline the given function call operation. * Return a new slang_operation that corresponds to the inlined code. */ |