summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader/slang/slang_codegen.c
diff options
context:
space:
mode:
authorBrian <[email protected]>2007-05-01 10:22:08 -0600
committerBrian <[email protected]>2007-05-01 10:22:08 -0600
commit7559364027eef3d9943d09a03e094400807ecdad (patch)
treedb48a36e3ae3dd0ae497a511b8a1445950bc14b2 /src/mesa/shader/slang/slang_codegen.c
parent65faf023679988f93da82b4c7ebdc689f2094459 (diff)
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.
Diffstat (limited to 'src/mesa/shader/slang/slang_codegen.c')
-rw-r--r--src/mesa/shader/slang/slang_codegen.c95
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 c6151f8feaa..cf32b501a62 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.
*/